From b11a2ff65363171555364fb3752a39f96c83ed5f Mon Sep 17 00:00:00 2001
From: patrick96
Date: Mon, 15 May 2023 13:49:32 +0200
Subject: [PATCH] restack: Add bottom restacking strategy
For now this is the same as the generic one
---
include/utils/restack.hpp | 5 +++
src/components/bar.cpp | 21 ++++++-----
src/utils/bspwm.cpp | 5 +--
src/utils/i3.cpp | 5 +--
src/utils/restack.cpp | 78 +++++++++++++++++++++++++++++++--------
5 files changed, 82 insertions(+), 32 deletions(-)
diff --git a/include/utils/restack.hpp b/include/utils/restack.hpp
index bf3eaca8..7fdb98a8 100644
--- a/include/utils/restack.hpp
+++ b/include/utils/restack.hpp
@@ -8,7 +8,12 @@
POLYBAR_NS
namespace restack_util {
+ using params = std::pair;
+
void restack_relative(connection& conn, xcb_window_t win, xcb_window_t sibling, xcb_stack_mode_t stack_mode);
+ bool are_siblings(connection& conn, xcb_window_t win, xcb_window_t sibling);
+ params get_bottom_params(connection& conn, xcb_window_t bar_window);
+ params get_generic_params(connection& conn, xcb_window_t bar_window);
}
POLYBAR_NS_END
diff --git a/src/components/bar.cpp b/src/components/bar.cpp
index fb02b158..22c730ba 100644
--- a/src/components/bar.cpp
+++ b/src/components/bar.cpp
@@ -480,8 +480,11 @@ void bar::toggle() {
}
/**
- * Move the bar window above defined sibling
- * in the X window stack
+ * Move the bar window above/below defined sibling in the X window stack.
+ *
+ * How the sibling is determined depends on the wm-restack setting.
+ *
+ * This is meant to resolve polybar appearing above other windows (especially in fullscreen).
*/
void bar::restack_window() {
string wm_restack;
@@ -492,15 +495,15 @@ void bar::restack_window() {
return;
}
+ xcb_window_t bar_window = m_opts.x_data.window;
+
xcb_window_t restack_sibling = XCB_NONE;
xcb_stack_mode_t stack_mode = XCB_STACK_MODE_ABOVE;
if (wm_restack == "generic") {
- auto children = m_connection.query_tree(m_connection.root()).children();
- if (children.begin() != children.end() && *children.begin() != m_opts.x_data.window) {
- restack_sibling = *children.begin();
- stack_mode = XCB_STACK_MODE_BELOW;
- }
+ std::tie(restack_sibling, stack_mode) = restack_util::get_bottom_params(m_connection, bar_window);
+ } else if (wm_restack == "bottom") {
+ std::tie(restack_sibling, stack_mode) = restack_util::get_bottom_params(m_connection, bar_window);
} else if (wm_restack == "bspwm") {
restack_sibling = bspwm_util::get_restack_sibling(m_connection, m_opts.monitor);
#if ENABLE_I3
@@ -517,13 +520,13 @@ void bar::restack_window() {
if (restack_sibling != XCB_NONE) {
try {
- restack_util::restack_relative(m_connection, m_opts.x_data.window, restack_sibling, stack_mode);
+ restack_util::restack_relative(m_connection, bar_window, restack_sibling, stack_mode);
m_log.info("Successfully restacked bar window");
} catch (const exception& err) {
m_log.err("Failed to restack bar window (err=%s)", err.what());
}
} else if (!wm_restack.empty()) {
- m_log.err("Failed to restack bar window");
+ m_log.err("Failed to restack bar window: No suitable sibling window for restacking was found");
}
}
diff --git a/src/utils/bspwm.cpp b/src/utils/bspwm.cpp
index 310e8cce..9a3a9885 100644
--- a/src/utils/bspwm.cpp
+++ b/src/utils/bspwm.cpp
@@ -36,10 +36,7 @@ vector root_windows(connection& conn) {
}
/**
- * Restack given window relative to the bspwm root window
- * for the given monitor.
- *
- * Fixes the issue with always-on-top window's
+ * Returns window against which to restack.
*/
xcb_window_t get_restack_sibling(connection& conn, const monitor_t& mon) {
for (auto&& root : root_windows(conn)) {
diff --git a/src/utils/i3.cpp b/src/utils/i3.cpp
index 6c2c7b1f..b532edf7 100644
--- a/src/utils/i3.cpp
+++ b/src/utils/i3.cpp
@@ -66,10 +66,7 @@ namespace i3_util {
}
/**
- * Restack given window relative to the i3 root window
- * defined for the given monitor
- *
- * Fixes the issue with always-on-top window's
+ * Returns window against which to restack.
*/
xcb_window_t get_restack_sibling(connection& conn) {
return root_window(conn);
diff --git a/src/utils/restack.cpp b/src/utils/restack.cpp
index af3cb7e3..7f4962a4 100644
--- a/src/utils/restack.cpp
+++ b/src/utils/restack.cpp
@@ -3,21 +3,69 @@
POLYBAR_NS
namespace restack_util {
- /**
- * Restacks the given window relative to a given sibling with some stack order (above, below)
- *
- * Both windows need to be siblings (have the same parent window).
- *
- * @param win The window to restack
- * @param sibling The window relative to which restacking happens
- * @param stack_mode The restacking mode (above, below)
- * @throw Some xpp error if restacking fails
- */
- void restack_relative(connection& conn, xcb_window_t win, xcb_window_t sibling, xcb_stack_mode_t stack_mode) {
- const unsigned int value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
- const std::array value_list = {sibling, stack_mode};
- conn.configure_window_checked(win, value_mask, value_list.data());
- }
+
+static constexpr params NONE_PARAMS = {XCB_NONE, XCB_STACK_MODE_ABOVE};
+
+/**
+ * Restacks the given window relative to a given sibling with some stack order (above, below)
+ *
+ * Both windows need to be siblings (have the same parent window).
+ *
+ * @param win The window to restack
+ * @param sibling The window relative to which restacking happens
+ * @param stack_mode The restacking mode (above, below)
+ * @throw Some xpp error if restacking fails
+ */
+void restack_relative(connection& conn, xcb_window_t win, xcb_window_t sibling, xcb_stack_mode_t stack_mode) {
+ const unsigned int value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
+ const std::array value_list = {sibling, stack_mode};
+ conn.configure_window_checked(win, value_mask, value_list.data());
}
+/**
+ * @return true iff the two given windows are sibings (are different windows and have same parent).
+ */
+bool are_siblings(connection& conn, xcb_window_t win, xcb_window_t sibling) {
+ if (win == XCB_NONE || sibling == XCB_NONE || win == sibling) {
+ return false;
+ }
+
+ auto win_tree = conn.query_tree(win);
+ auto sibling_tree = conn.query_tree(sibling);
+ return win_tree->parent == sibling_tree->parent;
+}
+
+/**
+ * "bottom" restack strategy.
+ *
+ * Moves the bar window to the bottom of the window stack
+ */
+std::pair get_bottom_params(connection& conn, xcb_window_t bar_window) {
+ auto children = conn.query_tree(conn.root()).children();
+ if (children.begin() != children.end() && *children.begin() != bar_window) {
+ return {*children.begin(), XCB_STACK_MODE_BELOW};
+ }
+
+ return NONE_PARAMS;
+}
+
+/**
+ * Generic restack stratgey.
+ *
+ * Tries to provide the best WM-agnostic restacking.
+ *
+ * Currently tries to the following stratgies in order:
+ * * bottom
+ */
+std::pair get_generic_params(connection& conn, xcb_window_t bar_window) {
+ auto [sibling, mode] = get_bottom_params(conn, bar_window);
+
+ if (are_siblings(conn, bar_window, sibling)) {
+ return {sibling, mode};
+ }
+
+ return NONE_PARAMS;
+}
+} // namespace restack_util
+
POLYBAR_NS_END