From 59acb4150b93de56d53ba2ab82d1562352644079 Mon Sep 17 00:00:00 2001 From: patrick96 Date: Mon, 15 May 2023 13:22:38 +0200 Subject: [PATCH] Clean up restacking code Restacking algorithms now only need to provide the sibling window and stacking mode. --- include/utils/bspwm.hpp | 2 +- include/utils/i3.hpp | 2 +- src/components/bar.cpp | 30 +++--- src/utils/bspwm.cpp | 225 ++++++++++++++++++++-------------------- src/utils/i3.cpp | 10 +- 5 files changed, 130 insertions(+), 139 deletions(-) diff --git a/include/utils/bspwm.hpp b/include/utils/bspwm.hpp index 075e2566..8499b011 100644 --- a/include/utils/bspwm.hpp +++ b/include/utils/bspwm.hpp @@ -25,7 +25,7 @@ namespace bspwm_util { }; vector root_windows(connection& conn); - bool restack_to_root(connection& conn, const monitor_t& mon, const xcb_window_t win); + xcb_window_t get_restack_sibling(connection& conn, const monitor_t& mon); string get_socket_path(); diff --git a/include/utils/i3.hpp b/include/utils/i3.hpp index 9ce255c9..b43805e2 100644 --- a/include/utils/i3.hpp +++ b/include/utils/i3.hpp @@ -19,7 +19,7 @@ namespace i3_util { shared_ptr focused_workspace(const connection_t&); vector root_windows(connection& conn, const string& output_name = ""); - bool restack_to_root(connection& conn, const xcb_window_t win); + xcb_window_t get_restack_sibling(connection& conn); } namespace { diff --git a/src/components/bar.cpp b/src/components/bar.cpp index 46da6f61..fb02b158 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -11,9 +11,9 @@ #include "events/signal_emitter.hpp" #include "tags/dispatch.hpp" #include "utils/bspwm.hpp" -#include "utils/restack.hpp" #include "utils/color.hpp" #include "utils/math.hpp" +#include "utils/restack.hpp" #include "utils/string.hpp" #include "utils/units.hpp" #include "x11/atoms.hpp" @@ -492,23 +492,20 @@ void bar::restack_window() { return; } - auto restacked = false; + xcb_window_t restack_sibling = XCB_NONE; + xcb_stack_mode_t stack_mode = XCB_STACK_MODE_ABOVE; if (wm_restack == "generic") { - try { - auto children = m_connection.query_tree(m_connection.root()).children(); - if (children.begin() != children.end() && *children.begin() != m_opts.x_data.window) { - restack_util::restack_relative(m_connection, m_opts.x_data.window, *children.begin(), XCB_STACK_MODE_BELOW); - } - restacked = true; - } catch (const exception& err) { - m_log.err("Failed to restack bar window (err=%s)", err.what()); + 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; } } else if (wm_restack == "bspwm") { - restacked = bspwm_util::restack_to_root(m_connection, m_opts.monitor, m_opts.x_data.window); + restack_sibling = bspwm_util::get_restack_sibling(m_connection, m_opts.monitor); #if ENABLE_I3 } else if (wm_restack == "i3" && m_opts.override_redirect) { - restacked = i3_util::restack_to_root(m_connection, m_opts.x_data.window); + restack_sibling = i3_util::get_restack_sibling(m_connection); } else if (wm_restack == "i3" && !m_opts.override_redirect) { m_log.warn("Ignoring restack of i3 window (not needed when `override-redirect = false`)"); wm_restack.clear(); @@ -518,8 +515,13 @@ void bar::restack_window() { wm_restack.clear(); } - if (restacked) { - m_log.info("Successfully restacked bar window"); + if (restack_sibling != XCB_NONE) { + try { + restack_util::restack_relative(m_connection, m_opts.x_data.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"); } diff --git a/src/utils/bspwm.cpp b/src/utils/bspwm.cpp index 8b66e76a..310e8cce 100644 --- a/src/utils/bspwm.cpp +++ b/src/utils/bspwm.cpp @@ -5,148 +5,143 @@ #include "errors.hpp" #include "utils/env.hpp" #include "x11/connection.hpp" +#include "x11/ewmh.hpp" POLYBAR_NS namespace bspwm_util { - /** - * Get all bspwm root windows - */ - vector root_windows(connection& conn) { - vector roots; - auto children = conn.query_tree(conn.root()).children(); +/** + * Get all bspwm root windows + */ +vector root_windows(connection& conn) { + vector roots; + 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; + for (auto it = children.begin(); it != children.end(); it++) { + xcb_icccm_get_wm_class_reply_t reply{}; + reply.class_name = reply.instance_name = nullptr; - 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); - } - } - - if (reply.class_name != nullptr || reply.instance_name != nullptr) { - xcb_icccm_get_wm_class_reply_wipe(&reply); + 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); } } - return roots; + if (reply.class_name != nullptr || reply.instance_name != nullptr) { + xcb_icccm_get_wm_class_reply_wipe(&reply); + } } - /** - * Restack given window relative to the bspwm root window - * for the given monitor. - * - * Fixes the issue with always-on-top window's - */ - bool restack_to_root(connection& conn, const monitor_t& mon, const xcb_window_t win) { - for (auto&& root : root_windows(conn)) { - auto geom = conn.get_geometry(root); + return roots; +} - if (mon->x != geom->x || mon->y != geom->y) { - continue; - } - if (mon->w != geom->width || mon->h != geom->height) { - continue; - } +/** + * Restack given window relative to the bspwm root window + * for the given monitor. + * + * Fixes the issue with always-on-top window's + */ +xcb_window_t get_restack_sibling(connection& conn, const monitor_t& mon) { + for (auto&& root : root_windows(conn)) { + auto geom = conn.get_geometry(root); - const unsigned int value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE; - const unsigned int value_list[2]{root, XCB_STACK_MODE_ABOVE}; - - conn.configure_window_checked(win, value_mask, value_list); - conn.flush(); - - return true; + if (mon->x != geom->x || mon->y != geom->y) { + continue; + } + if (mon->w != geom->width || mon->h != geom->height) { + continue; } - return false; + return root; } - /** - * Get path to the bspwm socket by the following order - * - * 1. Value of environment variable BSPWM_SOCKET - * 2. Value built from the bspwm socket path template - * 3. Value of the macro BSPWM_SOCKET_PATH - */ - string get_socket_path() { - string env_path; + return XCB_NONE; +} - if (!(env_path = env_util::get("BSPWM_SOCKET")).empty()) { - return env_path; - } +/** + * Get path to the bspwm socket by the following order + * + * 1. Value of environment variable BSPWM_SOCKET + * 2. Value built from the bspwm socket path template + * 3. Value of the macro BSPWM_SOCKET_PATH + */ +string get_socket_path() { + string env_path; - struct sockaddr_un sa {}; - char* host = nullptr; - int dsp = 0; - int scr = 0; - - if (xcb_parse_display(nullptr, &host, &dsp, &scr) == 0) { - return BSPWM_SOCKET_PATH; - } - - snprintf(sa.sun_path, sizeof(sa.sun_path), "/tmp/bspwm%s_%i_%i-socket", host, dsp, scr); - free(host); - - return sa.sun_path; + if (!(env_path = env_util::get("BSPWM_SOCKET")).empty()) { + return env_path; } - /** - * Generate a payload object with properly formatted data - * ready to be sent to the bspwm ipc controller - */ - payload_t make_payload(const string& cmd) { - payload_t payload{new payload_t::element_type{}}; - auto size = sizeof(payload->data); - int offset = 0; - int chars = 0; + struct sockaddr_un sa {}; + char* host = nullptr; + int dsp = 0; + int scr = 0; - for (auto&& word : string_util::split(cmd, ' ')) { - chars = snprintf(payload->data + offset, size - offset, "%s%c", word.c_str(), 0); - payload->len += chars; - offset += chars; - } - - return payload; + if (xcb_parse_display(nullptr, &host, &dsp, &scr) == 0) { + return BSPWM_SOCKET_PATH; } - /** - * Create an ipc socket connection - * - * Example usage: - * @code cpp - * auto ipc = make_connection(); - * ipc->send(make_payload("desktop -f eDP-1:^1")); - * @endcode - */ - connection_t make_connection() { - return socket_util::make_unix_connection(get_socket_path()); + snprintf(sa.sun_path, sizeof(sa.sun_path), "/tmp/bspwm%s_%i_%i-socket", host, dsp, scr); + free(host); + + return sa.sun_path; +} + +/** + * Generate a payload object with properly formatted data + * ready to be sent to the bspwm ipc controller + */ +payload_t make_payload(const string& cmd) { + payload_t payload{new payload_t::element_type{}}; + auto size = sizeof(payload->data); + int offset = 0; + int chars = 0; + + for (auto&& word : string_util::split(cmd, ' ')) { + chars = snprintf(payload->data + offset, size - offset, "%s%c", word.c_str(), 0); + payload->len += chars; + offset += chars; } - /** - * Create a connection and subscribe to events - * on the bspwm socket - * - * Example usage: - * @code cpp - * auto ipc = make_subscriber(); - * - * while (!ipc->poll(POLLHUP, 0)) { - * ssize_t bytes_received = 0; - * auto data = ipc->receive(BUFSIZ-1, bytes_received, 0); - * std::cout << data << std::endl; - * } - * @endcode - */ - connection_t make_subscriber() { - auto conn = make_connection(); - auto payload = make_payload("subscribe report"); - if (conn->send(payload->data, payload->len, 0) == 0) { - throw system_error("Failed to initialize subscriber"); - } - return conn; + return payload; +} + +/** + * Create an ipc socket connection + * + * Example usage: + * @code cpp + * auto ipc = make_connection(); + * ipc->send(make_payload("desktop -f eDP-1:^1")); + * @endcode + */ +connection_t make_connection() { + return socket_util::make_unix_connection(get_socket_path()); +} + +/** + * Create a connection and subscribe to events + * on the bspwm socket + * + * Example usage: + * @code cpp + * auto ipc = make_subscriber(); + * + * while (!ipc->poll(POLLHUP, 0)) { + * ssize_t bytes_received = 0; + * auto data = ipc->receive(BUFSIZ-1, bytes_received, 0); + * std::cout << data << std::endl; + * } + * @endcode + */ +connection_t make_subscriber() { + auto conn = make_connection(); + auto payload = make_payload("subscribe report"); + if (conn->send(payload->data, payload->len, 0) == 0) { + throw system_error("Failed to initialize subscriber"); } + return conn; +} } // namespace bspwm_util POLYBAR_NS_END diff --git a/src/utils/i3.cpp b/src/utils/i3.cpp index 0a576436..6c2c7b1f 100644 --- a/src/utils/i3.cpp +++ b/src/utils/i3.cpp @@ -71,14 +71,8 @@ namespace i3_util { * * Fixes the issue with always-on-top window's */ - bool restack_to_root(connection& conn, const xcb_window_t win) { - const unsigned int value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE; - const unsigned int value_list[2]{root_window(conn), XCB_STACK_MODE_ABOVE}; - if (value_list[0] != XCB_NONE) { - conn.configure_window_checked(win, value_mask, value_list); - return true; - } - return false; + xcb_window_t get_restack_sibling(connection& conn) { + return root_window(conn); } } // namespace i3_util