From c9752598a578f05772a9b15e6de2b92d99c6dc3a Mon Sep 17 00:00:00 2001
From: patrick96
Date: Sun, 8 Oct 2023 20:36:33 +0200
Subject: [PATCH] fix(bspwm): Restack against topmost root window.
The ewmh strategy has to be dropped because the
`_NET_SUPPORTING_WM_CHECK` window may (at least in bspwm) appear
anywhere in the window stack.
To fix the overlapping monitors issue in #2873, we simply restack
against the topmost of these root windows.
Fixes #2972
Fixes #2873 (again)
---
CHANGELOG.md | 2 +-
include/utils/bspwm.hpp | 34 +++++++++---------------
src/components/bar.cpp | 2 +-
src/utils/bspwm.cpp | 59 +++++++++++++----------------------------
4 files changed, 33 insertions(+), 64 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5a29bfce..a7dd4813 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -52,7 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Changed fuzzy match option on i3 and bspwm modules to find longest match instead of the first match ([`#2831`](https://github.com/polybar/polybar/pull/2831), [`#2829`](https://github.com/polybar/polybar/issues/2829)) by [@Ron0Studios](https://github.com/ron0studios/).
- `wm-restack`
- `generic`: Is now a best effort combination of other restacking strategies. First tries `ewmh` and then the `bottom` strategy ([`#2961`](https://github.com/polybar/polybar/pull/2961))
- - `bspwm`: First tries the `ewmh` strategy before falling back to its old behavior ([`#2961`](https://github.com/polybar/polybar/pull/2961))
+ - `bspwm`: Will restack above the topmost bspwm root window instead of the root window associated with the monitor polybar is on ([`#3019`](https://github.com/polybar/polybar/pull/3019))
### Fixed
- Waiting for double click interval on modules that don't have a double click action ([`#2663`](https://github.com/polybar/polybar/issues/2663), [`#2695`](https://github.com/polybar/polybar/pull/2695))
diff --git a/include/utils/bspwm.hpp b/include/utils/bspwm.hpp
index cdd26a38..e36ef2a2 100644
--- a/include/utils/bspwm.hpp
+++ b/include/utils/bspwm.hpp
@@ -1,38 +1,30 @@
#pragma once
-#include
-#include
-
#include "common.hpp"
-#include "settings.hpp"
#include "utils/restack.hpp"
#include "utils/socket.hpp"
-#include "utils/string.hpp"
-#include "x11/extensions/randr.hpp"
-#include "x11/window.hpp"
POLYBAR_NS
class connection;
namespace bspwm_util {
- struct payload;
- using connection_t = unique_ptr;
- using payload_t = unique_ptr;
+using connection_t = unique_ptr;
- struct payload {
- char data[BUFSIZ]{'\0'};
- size_t len = 0;
- };
+struct payload {
+ char data[BUFSIZ]{'\0'};
+ size_t len = 0;
+};
- vector root_windows(connection& conn);
- restack_util::params get_restack_params(connection& conn, const monitor_t& mon, xcb_window_t bar_window);
+using payload_t = unique_ptr;
- string get_socket_path();
+restack_util::params get_restack_params(connection& conn);
- payload_t make_payload(const string& cmd);
- connection_t make_connection();
- connection_t make_subscriber();
-}
+string get_socket_path();
+
+payload_t make_payload(const string& cmd);
+connection_t make_connection();
+connection_t make_subscriber();
+} // namespace bspwm_util
POLYBAR_NS_END
diff --git a/src/components/bar.cpp b/src/components/bar.cpp
index a973cb12..cacf2fb3 100644
--- a/src/components/bar.cpp
+++ b/src/components/bar.cpp
@@ -506,7 +506,7 @@ void bar::restack_window() {
} else if (wm_restack == "bottom") {
restack_params = restack_util::get_bottom_params(m_connection, bar_window);
} else if (wm_restack == "bspwm") {
- restack_params = bspwm_util::get_restack_params(m_connection, m_opts.monitor, bar_window);
+ restack_params = bspwm_util::get_restack_params(m_connection);
#if ENABLE_I3
} else if (wm_restack == "i3" && m_opts.override_redirect) {
restack_params = i3_util::get_restack_params(m_connection);
diff --git a/src/utils/bspwm.cpp b/src/utils/bspwm.cpp
index 9d05a138..7e2ec7ed 100644
--- a/src/utils/bspwm.cpp
+++ b/src/utils/bspwm.cpp
@@ -1,64 +1,41 @@
#include "utils/bspwm.hpp"
#include
+#include
#include "errors.hpp"
#include "utils/env.hpp"
+#include "utils/string.hpp"
#include "x11/connection.hpp"
-#include "x11/ewmh.hpp"
+#include "x11/icccm.hpp"
POLYBAR_NS
namespace bspwm_util {
/**
- * Get all bspwm root windows
+ * Returns window against which to restack.
+ *
+ * Bspwm creates one root window per monitor with a `WM_CLASS` value of `root\0Bspwm` and the window taking up the
+ * entire monitor.
+ * For overlapping monitors, stacking polybar above the root window for its monitor, but below the root window for an
+ * overlapping monitor, may cause the upper root window to obstruct polybar, at least in terms of receiving mouse
+ * clicks. Because of that, we simply restack polybar above the topmost root window.
*/
-vector root_windows(connection& conn) {
- vector roots;
+restack_util::params get_restack_params(connection& conn) {
auto children = conn.query_tree(conn.root()).children();
- for (auto it = children.begin(); it != children.end(); it++) {
- xcb_icccm_get_wm_class_reply_t reply{};
- reply.class_name = reply.instance_name = nullptr;
+ xcb_window_t top_root = XCB_NONE;
- if (xcb_icccm_get_wm_class_reply(conn, xcb_icccm_get_wm_class(conn, *it), &reply, nullptr)) {
- if (string_util::compare("Bspwm", reply.class_name) && string_util::compare("root", reply.instance_name)) {
- roots.emplace_back(*it);
- }
- }
+ // Iteration happens from bottom to top
+ for (xcb_window_t wid : children) {
+ auto [instance_name, class_name] = icccm_util::get_wm_class(conn, wid);
- if (reply.class_name != nullptr || reply.instance_name != nullptr) {
- xcb_icccm_get_wm_class_reply_wipe(&reply);
+ if (string_util::compare("root", instance_name) && string_util::compare("Bspwm", class_name)) {
+ top_root = wid;
}
}
- return roots;
-}
-
-/**
- * Returns window against which to restack.
- */
-restack_util::params get_restack_params(connection& conn, const monitor_t& mon, xcb_window_t bar_window) {
- auto ewmh_params = restack_util::get_ewmh_params(conn);
-
- if (restack_util::are_siblings(conn, bar_window, ewmh_params.first)) {
- return ewmh_params;
- }
-
- for (auto&& root : root_windows(conn)) {
- auto geom = conn.get_geometry(root);
-
- if (mon->x != geom->x || mon->y != geom->y) {
- continue;
- }
- if (mon->w != geom->width || mon->h != geom->height) {
- continue;
- }
-
- return {root, XCB_STACK_MODE_ABOVE};
- }
-
- return restack_util::NONE_PARAMS;
+ return {top_root, XCB_STACK_MODE_ABOVE};
}
/**