feat: Restack-to-root

Fixes the issue where the bar window is being
drawn on top of fullscreen window's
This commit is contained in:
Michael Carlberg 2016-10-11 18:53:51 +02:00
parent dac5a3c804
commit e1b6238564
4 changed files with 86 additions and 0 deletions

View File

@ -414,6 +414,17 @@ The configuration syntax is based on the `ini` file format.
; left
; right
tray-position = right
; Restack the bar window and put it above the
; selected window manager's root
;
; Fixes the issue where the bar is being drawn
; on top of fullscreen window's
;
; Currently supported WM's:
; bspwm
; Default: none
wm-restack = bspwm
~~~
### Modules

View File

@ -30,6 +30,8 @@ modules-right = volume cpu ram clock
tray-position = right
wm-restack = bspwm
[module/label]
type = custom/text
content = %{F#f90f59}Example%{F#ff} configuration

View File

@ -17,6 +17,7 @@
#include "components/x11/window.hpp"
#include "components/x11/xlib.hpp"
#include "components/x11/xutils.hpp"
#include "utils/bspwm.hpp"
#include "utils/math.hpp"
#include "utils/string.hpp"
#include "utils/threading.hpp"
@ -275,6 +276,23 @@ class bar : public xpp::event::sink<evt::button_press> {
m_connection.map_window_checked(m_window);
}
// }}}
// Restack window and put it above defined WM's root {{{
try {
auto wm_restack = m_conf.get<string>(bs, "wm-restack");
if (wm_restack == "bspwm") {
if (bspwm_util::restack_above_root(m_connection, m_bar.monitor, m_window))
m_log.info("Successfully restacked window above Bspwm root");
else
m_log.err("Failed to restack bar window above Bspwm root");
} else {
m_log.warn("Unsupported wm-restack option '%s'", wm_restack);
}
} catch (const key_error& err) {
}
// }}}
// Create graphic contexts {{{

View File

@ -1,8 +1,12 @@
#pragma once
#include <xcb/xcb.h>
#include <xcb/xcb_icccm.h>
#include "common.hpp"
#include "components/x11/connection.hpp"
#include "components/x11/randr.hpp"
#include "components/x11/window.hpp"
#include "config.hpp"
#include "utils/socket.hpp"
#include "utils/string.hpp"
@ -22,6 +26,57 @@ namespace bspwm_util {
size_t len = 0;
};
/**
* Get all bspwm root windows
*/
auto root_windows(connection& conn) {
vector<xcb_window_t> roots;
auto children = conn.query_tree(conn.screen()->root).children();
for (auto it = children.begin(); it != children.end(); it++) {
auto cookie = xcb_icccm_get_wm_class(conn, *it);
xcb_icccm_get_wm_class_reply_t reply;
if (xcb_icccm_get_wm_class_reply(conn, cookie, &reply, nullptr) == 0)
continue;
if (!string_util::compare("Bspwm", reply.class_name) ||
!string_util::compare("root", reply.instance_name))
continue;
roots.emplace_back(*it);
}
return roots;
}
/**
* Restack given window above the bspwm root window
* for the given monitor.
*
* Fixes the issue with always-on-top window's
*/
bool restack_above_root(connection& conn, const monitor_t& mon, const xcb_window_t win) {
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;
const uint32_t value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
const uint32_t value_list[2]{root, XCB_STACK_MODE_ABOVE};
conn.configure_window_checked(win, value_mask, value_list);
conn.flush();
return true;
}
return false;
}
/**
* Get path to the bspwm socket by the following order
*