#include #include #include "common.hpp" #include "settings.hpp" #include "utils/i3.hpp" #include "utils/socket.hpp" #include "utils/string.hpp" #include "x11/connection.hpp" #include "x11/ewmh.hpp" #include "x11/icccm.hpp" POLYBAR_NS namespace i3_util { /** * Get all workspaces for given output */ vector> workspaces(const connection_t& conn, const string& output, const bool show_urgent) { vector> result; for (auto&& ws : conn.get_workspaces()) { if (output.empty() || ws->output == output || (show_urgent && ws->urgent)) { result.emplace_back(forward(ws)); } } return result; } /** * Get currently focused workspace */ shared_ptr focused_workspace(const connection_t& conn) { for (auto&& ws : conn.get_workspaces()) { if (ws->focused) { return ws; } } return nullptr; } /** * Get main root window */ xcb_window_t root_window(connection& conn) { auto children = conn.query_tree(conn.screen()->root).children(); const auto wm_name = [&](xcb_connection_t* conn, xcb_window_t win) -> string { string title; if (!(title = ewmh_util::get_wm_name(win)).empty()) { return title; } else if (!(title = icccm_util::get_wm_name(conn, win)).empty()) { return title; } else { return ""; } }; for (auto it = children.begin(); it != children.end(); it++) { if (wm_name(conn, *it) == "i3") { return *it; } } return XCB_NONE; } /** * Restack given window relative to the i3 root window * defined for the given monitor * * 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; } } POLYBAR_NS_END