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