diff --git a/include/components/types.hpp b/include/components/types.hpp index 8a140c58..1538efd6 100644 --- a/include/components/types.hpp +++ b/include/components/types.hpp @@ -28,6 +28,13 @@ enum class strut { BOTTOM_END_X, }; +struct strut_margins { + uint16_t t; + uint16_t b; + uint16_t l; + uint16_t r; +}; + struct bar_settings { bar_settings() = default; @@ -65,6 +72,8 @@ struct bar_settings { int16_t vertical_mid{0}; + strut_margins margins; + string geom() { char buffer[32]{ '\0', diff --git a/include/x11/window.hpp b/include/x11/window.hpp index cb5e411c..3b4379b8 100644 --- a/include/x11/window.hpp +++ b/include/x11/window.hpp @@ -2,6 +2,7 @@ #include "common.hpp" #include "x11/connection.hpp" +#include "x11/randr.hpp" LEMONBUDDY_NS @@ -19,6 +20,7 @@ class window : public xpp::window { window reconfigure_geom(uint16_t w, uint16_t h, int16_t x = 0, int16_t y = 0); window reconfigure_pos(int16_t x, int16_t y); + window reconfigure_struts(const monitor_t& mon, uint16_t w, uint16_t h, int16_t x, int16_t y, bool bottom = false); void redraw(); }; diff --git a/src/components/bar.cpp b/src/components/bar.cpp index f93ee1f1..7b024117 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -108,6 +108,11 @@ void bar::bootstrap(bool nodraw) { // {{{ GET_CONFIG_VALUE(bs, m_opts.module_margin_left, "module-margin-left"); GET_CONFIG_VALUE(bs, m_opts.module_margin_right, "module-margin-right"); + m_opts.margins.l = m_conf.get("global/wm", "margin-left", 0); + m_opts.margins.r = m_conf.get("global/wm", "margin-right", 0); + m_opts.margins.t = m_conf.get("global/wm", "margin-top", 0); + m_opts.margins.b = m_conf.get("global/wm", "margin-bottom", 0); + // }}} // Set the WM_NAME value {{{ // Required early for --print-wmname @@ -141,8 +146,8 @@ void bar::bootstrap(bool nodraw) { // {{{ create_gcontexts(); create_rootpixmap(); restack_window(); - map_window(); set_wmhints(); + map_window(); // m_log.trace("bar: Listen to X RandR events"); // m_connection.select_input(m_window, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); @@ -718,6 +723,11 @@ void bar::restack_window() { // {{{ void bar::map_window() { // {{{ try { m_window.map_checked(); + + auto w = m_opts.width + m_opts.offset_x; + auto h = m_opts.height + m_opts.offset_y; + + m_window.reconfigure_struts(m_opts.monitor, w, h, m_opts.x, m_opts.y, m_opts.bottom); m_window.reconfigure_pos(m_opts.x, m_opts.y); } catch (const exception& err) { m_log.err("Failed to map bar window"); @@ -751,48 +761,8 @@ void bar::set_wmhints() { // {{{ wm_util::set_wmpid(m_connection, m_window, getpid()); m_log.trace("bar: Set _NET_WM_STRUT / _NET_WM_STRUT_PARTIAL"); - { - uint32_t none{0}; - uint32_t strut[12]{none}; - - auto mt = m_conf.get("global/wm", "margin-top", 0); - auto mb = m_conf.get("global/wm", "margin-bottom", 0); - auto ml = m_conf.get("global/wm", "margin-left", 0); - auto mr = m_conf.get("global/wm", "margin-right", 0); - - auto geom = m_connection.get_geometry(m_screen->root); - auto base_x = geom->x + m_opts.monitor->x; - auto max_x = base_x + m_opts.monitor->w; - auto height = m_opts.height + m_opts.offset_y; - auto width = m_opts.width + m_opts.offset_x; - auto start_x = base_x + m_opts.offset_x - ml; - auto end_x = base_x + width - m_opts.offset_x + mr; - - // clang-format off - if (m_opts.bottom) { - auto base_y = geom->y + geom->height - m_opts.monitor->h - m_opts.monitor->y; - - strut[static_cast(strut::BOTTOM)] = - math_util::cap(base_y + height + mt, base_y, base_y + m_opts.monitor->h); - strut[static_cast(strut::BOTTOM_START_X)] = - math_util::cap(start_x, base_x, max_x); - strut[static_cast(strut::BOTTOM_END_X)] = - math_util::cap(end_x, base_x, max_x); - } else { - auto base_y = geom->y + m_opts.monitor->y; - - strut[static_cast(strut::TOP)] = - math_util::cap(base_y + height + mb, base_y, base_y + m_opts.monitor->h); - strut[static_cast(strut::TOP_START_X)] = - math_util::cap(start_x, base_x, max_x); - strut[static_cast(strut::TOP_END_X)] = - math_util::cap(end_x, base_x, max_x); - } - - m_connection.change_property(XCB_PROP_MODE_REPLACE, m_window, _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, 4, strut); - m_connection.change_property(XCB_PROP_MODE_REPLACE, m_window, _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32, 12, strut); - // clang-format on - } + m_window.reconfigure_struts(m_opts.monitor, m_opts.width + m_opts.offset_x, m_opts.height + m_opts.offset_y, m_opts.x, + m_opts.y, m_opts.bottom); } // }}} /** diff --git a/src/x11/window.cpp b/src/x11/window.cpp index 2c53eb16..a4495805 100644 --- a/src/x11/window.cpp +++ b/src/x11/window.cpp @@ -1,8 +1,12 @@ #include +#include "utils/math.hpp" +#include "x11/atoms.hpp" #include "x11/window.hpp" #include "x11/xutils.hpp" +#include "components/types.hpp" + LEMONBUDDY_NS window window::create_checked(int16_t x, int16_t y, uint16_t w, uint16_t h) { @@ -53,7 +57,7 @@ window window::reconfigure_geom(uint16_t w, uint16_t h, int16_t x, int16_t y) { window window::reconfigure_pos(int16_t x, int16_t y) { uint32_t mask = 0; - uint32_t values[7]; + uint32_t values[2]; xcb_params_configure_window_t params; XCB_AUX_ADD_PARAM(&mask, ¶ms, x, x); @@ -65,6 +69,36 @@ window window::reconfigure_pos(int16_t x, int16_t y) { return *this; } +window window::reconfigure_struts(const monitor_t& mon, uint16_t w, uint16_t h, int16_t x, int16_t y, bool bottom) { + auto& conn = connection(); + auto root = conn.screen()->root; + auto geom = conn.get_geometry(root); + + uint32_t none{0}; + uint32_t strut[12]{none}; + + auto bx = geom->x + mon->x; + auto x1 = bx + x; + auto x2 = bx + x + w; + + if (bottom) { + auto by = geom->y + geom->height - mon->h - mon->y; + strut[static_cast(strut::BOTTOM)] = math_util::cap(by + h + y, 0, by + mon->h); + strut[static_cast(strut::BOTTOM_START_X)] = math_util::cap(x1, bx, bx + mon->w); + strut[static_cast(strut::BOTTOM_END_X)] = math_util::cap(x2, bx, bx + mon->w); + } else { + auto by = geom->y + mon->y; + strut[static_cast(strut::TOP)] = math_util::cap(by + h + y, 0, by + mon->h); + strut[static_cast(strut::TOP_START_X)] = math_util::cap(x1, bx, bx + mon->w); + strut[static_cast(strut::TOP_END_X)] = math_util::cap(x2, bx, bx + mon->w); + } + + conn.change_property(XCB_PROP_MODE_REPLACE, *this, _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, 4, strut); + conn.change_property(XCB_PROP_MODE_REPLACE, *this, _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32, 12, strut); + + return *this; +} + void window::redraw() { xutils::visibility_notify(connection(), *this, XCB_VISIBILITY_FULLY_OBSCURED); xutils::visibility_notify(connection(), *this, XCB_VISIBILITY_UNOBSCURED);