restack: Add bottom restacking strategy

For now this is the same as the generic one
This commit is contained in:
patrick96 2023-05-15 13:49:32 +02:00 committed by Patrick Ziegler
parent 59acb4150b
commit b11a2ff653
5 changed files with 82 additions and 32 deletions

View File

@ -8,7 +8,12 @@
POLYBAR_NS POLYBAR_NS
namespace restack_util { namespace restack_util {
using params = std::pair<xcb_window_t, xcb_stack_mode_t>;
void restack_relative(connection& conn, xcb_window_t win, xcb_window_t sibling, xcb_stack_mode_t stack_mode); void restack_relative(connection& conn, xcb_window_t win, xcb_window_t sibling, xcb_stack_mode_t stack_mode);
bool are_siblings(connection& conn, xcb_window_t win, xcb_window_t sibling);
params get_bottom_params(connection& conn, xcb_window_t bar_window);
params get_generic_params(connection& conn, xcb_window_t bar_window);
} }
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -480,8 +480,11 @@ void bar::toggle() {
} }
/** /**
* Move the bar window above defined sibling * Move the bar window above/below defined sibling in the X window stack.
* in the X window stack *
* How the sibling is determined depends on the wm-restack setting.
*
* This is meant to resolve polybar appearing above other windows (especially in fullscreen).
*/ */
void bar::restack_window() { void bar::restack_window() {
string wm_restack; string wm_restack;
@ -492,15 +495,15 @@ void bar::restack_window() {
return; return;
} }
xcb_window_t bar_window = m_opts.x_data.window;
xcb_window_t restack_sibling = XCB_NONE; xcb_window_t restack_sibling = XCB_NONE;
xcb_stack_mode_t stack_mode = XCB_STACK_MODE_ABOVE; xcb_stack_mode_t stack_mode = XCB_STACK_MODE_ABOVE;
if (wm_restack == "generic") { if (wm_restack == "generic") {
auto children = m_connection.query_tree(m_connection.root()).children(); std::tie(restack_sibling, stack_mode) = restack_util::get_bottom_params(m_connection, bar_window);
if (children.begin() != children.end() && *children.begin() != m_opts.x_data.window) { } else if (wm_restack == "bottom") {
restack_sibling = *children.begin(); std::tie(restack_sibling, stack_mode) = restack_util::get_bottom_params(m_connection, bar_window);
stack_mode = XCB_STACK_MODE_BELOW;
}
} else if (wm_restack == "bspwm") { } else if (wm_restack == "bspwm") {
restack_sibling = bspwm_util::get_restack_sibling(m_connection, m_opts.monitor); restack_sibling = bspwm_util::get_restack_sibling(m_connection, m_opts.monitor);
#if ENABLE_I3 #if ENABLE_I3
@ -517,13 +520,13 @@ void bar::restack_window() {
if (restack_sibling != XCB_NONE) { if (restack_sibling != XCB_NONE) {
try { try {
restack_util::restack_relative(m_connection, m_opts.x_data.window, restack_sibling, stack_mode); restack_util::restack_relative(m_connection, bar_window, restack_sibling, stack_mode);
m_log.info("Successfully restacked bar window"); m_log.info("Successfully restacked bar window");
} catch (const exception& err) { } catch (const exception& err) {
m_log.err("Failed to restack bar window (err=%s)", err.what()); m_log.err("Failed to restack bar window (err=%s)", err.what());
} }
} else if (!wm_restack.empty()) { } else if (!wm_restack.empty()) {
m_log.err("Failed to restack bar window"); m_log.err("Failed to restack bar window: No suitable sibling window for restacking was found");
} }
} }

View File

@ -36,10 +36,7 @@ vector<xcb_window_t> root_windows(connection& conn) {
} }
/** /**
* Restack given window relative to the bspwm root window * Returns window against which to restack.
* 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) { xcb_window_t get_restack_sibling(connection& conn, const monitor_t& mon) {
for (auto&& root : root_windows(conn)) { for (auto&& root : root_windows(conn)) {

View File

@ -66,10 +66,7 @@ namespace i3_util {
} }
/** /**
* Restack given window relative to the i3 root window * Returns window against which to restack.
* defined for the given monitor
*
* Fixes the issue with always-on-top window's
*/ */
xcb_window_t get_restack_sibling(connection& conn) { xcb_window_t get_restack_sibling(connection& conn) {
return root_window(conn); return root_window(conn);

View File

@ -3,7 +3,10 @@
POLYBAR_NS POLYBAR_NS
namespace restack_util { namespace restack_util {
/**
static constexpr params NONE_PARAMS = {XCB_NONE, XCB_STACK_MODE_ABOVE};
/**
* Restacks the given window relative to a given sibling with some stack order (above, below) * Restacks the given window relative to a given sibling with some stack order (above, below)
* *
* Both windows need to be siblings (have the same parent window). * Both windows need to be siblings (have the same parent window).
@ -13,11 +16,56 @@ namespace restack_util {
* @param stack_mode The restacking mode (above, below) * @param stack_mode The restacking mode (above, below)
* @throw Some xpp error if restacking fails * @throw Some xpp error if restacking fails
*/ */
void restack_relative(connection& conn, xcb_window_t win, xcb_window_t sibling, xcb_stack_mode_t stack_mode) { void restack_relative(connection& conn, xcb_window_t win, xcb_window_t sibling, xcb_stack_mode_t stack_mode) {
const unsigned int value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE; const unsigned int value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
const std::array<uint32_t, 2> value_list = {sibling, stack_mode}; const std::array<uint32_t, 2> value_list = {sibling, stack_mode};
conn.configure_window_checked(win, value_mask, value_list.data()); conn.configure_window_checked(win, value_mask, value_list.data());
}
} }
/**
* @return true iff the two given windows are sibings (are different windows and have same parent).
*/
bool are_siblings(connection& conn, xcb_window_t win, xcb_window_t sibling) {
if (win == XCB_NONE || sibling == XCB_NONE || win == sibling) {
return false;
}
auto win_tree = conn.query_tree(win);
auto sibling_tree = conn.query_tree(sibling);
return win_tree->parent == sibling_tree->parent;
}
/**
* "bottom" restack strategy.
*
* Moves the bar window to the bottom of the window stack
*/
std::pair<xcb_window_t, xcb_stack_mode_t> get_bottom_params(connection& conn, xcb_window_t bar_window) {
auto children = conn.query_tree(conn.root()).children();
if (children.begin() != children.end() && *children.begin() != bar_window) {
return {*children.begin(), XCB_STACK_MODE_BELOW};
}
return NONE_PARAMS;
}
/**
* Generic restack stratgey.
*
* Tries to provide the best WM-agnostic restacking.
*
* Currently tries to the following stratgies in order:
* * bottom
*/
std::pair<xcb_window_t, xcb_stack_mode_t> get_generic_params(connection& conn, xcb_window_t bar_window) {
auto [sibling, mode] = get_bottom_params(conn, bar_window);
if (are_siblings(conn, bar_window, sibling)) {
return {sibling, mode};
}
return NONE_PARAMS;
}
} // namespace restack_util
POLYBAR_NS_END POLYBAR_NS_END