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}; } /**