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
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);
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

View File

@ -480,8 +480,11 @@ void bar::toggle() {
}
/**
* Move the bar window above defined sibling
* in the X window stack
* Move the bar window above/below defined sibling 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() {
string wm_restack;
@ -492,15 +495,15 @@ void bar::restack_window() {
return;
}
xcb_window_t bar_window = m_opts.x_data.window;
xcb_window_t restack_sibling = XCB_NONE;
xcb_stack_mode_t stack_mode = XCB_STACK_MODE_ABOVE;
if (wm_restack == "generic") {
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;
}
std::tie(restack_sibling, stack_mode) = restack_util::get_bottom_params(m_connection, bar_window);
} else if (wm_restack == "bottom") {
std::tie(restack_sibling, stack_mode) = restack_util::get_bottom_params(m_connection, bar_window);
} else if (wm_restack == "bspwm") {
restack_sibling = bspwm_util::get_restack_sibling(m_connection, m_opts.monitor);
#if ENABLE_I3
@ -517,13 +520,13 @@ void bar::restack_window() {
if (restack_sibling != XCB_NONE) {
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");
} 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");
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
* for the given monitor.
*
* Fixes the issue with always-on-top window's
* Returns window against which to restack.
*/
xcb_window_t get_restack_sibling(connection& conn, const monitor_t& mon) {
for (auto&& root : root_windows(conn)) {

View File

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

View File

@ -3,21 +3,69 @@
POLYBAR_NS
namespace restack_util {
/**
* 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).
*
* @param win The window to restack
* @param sibling The window relative to which restacking happens
* @param stack_mode The restacking mode (above, below)
* @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) {
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};
conn.configure_window_checked(win, value_mask, value_list.data());
}
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)
*
* Both windows need to be siblings (have the same parent window).
*
* @param win The window to restack
* @param sibling The window relative to which restacking happens
* @param stack_mode The restacking mode (above, below)
* @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) {
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};
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