fix: Support negative struts

Fixed #2642
This commit is contained in:
patrick96 2022-03-14 23:47:05 +01:00 committed by Patrick Ziegler
parent 705845e5d3
commit 4556a4a7a8
5 changed files with 63 additions and 36 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Fixed ### Fixed
- `format-offset` being ignored ([`#2643`](https://github.com/polybar/polybar/pull/2643)) - `format-offset` being ignored ([`#2643`](https://github.com/polybar/polybar/pull/2643))
- Negative struts (`margin-bottom`, `margin-top`) being ignored ([`#2642`](https://github.com/polybar/polybar/issues/2642), [`#2644`](https://github.com/polybar/polybar/pull/2644))
## [3.6.1] - 2022-03-05 ## [3.6.1] - 2022-03-05
### Build ### Build

View File

@ -59,6 +59,11 @@ static inline mousebtn mousebtn_get_double(mousebtn btn) {
} }
} }
/**
* Order of values for _NET_WM_STRUT_PARTIAL
*
* https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html#idm45381391268672
*/
enum class strut { enum class strut {
LEFT = 0, LEFT = 0,
RIGHT, RIGHT,
@ -132,13 +137,6 @@ struct percentage_with_offset {
extent_val offset{ZERO_PX_EXTENT}; extent_val offset{ZERO_PX_EXTENT};
}; };
struct edge_values {
unsigned int left{0U};
unsigned int right{0U};
unsigned int top{0U};
unsigned int bottom{0U};
};
struct radius { struct radius {
double top_left{0.0}; double top_left{0.0};
double top_right{0.0}; double top_right{0.0};
@ -173,7 +171,7 @@ struct bar_settings {
monitor_t monitor{}; monitor_t monitor{};
bool monitor_strict{false}; bool monitor_strict{false};
bool monitor_exact{true}; bool monitor_exact{true};
edge origin{edge::TOP}; bool bottom{false};
struct size size { struct size size {
1U, 1U 1U, 1U
}; };
@ -185,7 +183,10 @@ struct bar_settings {
position offset{0, 0}; position offset{0, 0};
side_values padding{ZERO_SPACE, ZERO_SPACE}; side_values padding{ZERO_SPACE, ZERO_SPACE};
side_values module_margin{ZERO_SPACE, ZERO_SPACE}; side_values module_margin{ZERO_SPACE, ZERO_SPACE};
edge_values strut{0U, 0U, 0U, 0U}; struct {
int top;
int bottom;
} strut{0, 0};
rgba background{0xFF000000}; rgba background{0xFF000000};
rgba foreground{0xFFFFFFFF}; rgba foreground{0xFFFFFFFF};

View File

@ -2,6 +2,7 @@
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_aux.h> #include <xcb/xcb_aux.h>
#include <xpp/window.hpp> #include <xpp/window.hpp>
#include "common.hpp" #include "common.hpp"
@ -17,7 +18,7 @@ class window : public xpp::window<connection&> {
window reconfigure_geom(unsigned short int w, unsigned short int h, short int x = 0, short int y = 0); window reconfigure_geom(unsigned short int w, unsigned short int h, short int x = 0, short int y = 0);
window reconfigure_pos(short int x, short int y); window reconfigure_pos(short int x, short int y);
window reconfigure_struts(unsigned short int w, unsigned short int h, short int x, bool bottom = false); window reconfigure_struts(uint32_t w, uint32_t strut, uint32_t x, bool bottom = false);
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -191,7 +191,7 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
// Load configuration values // Load configuration values
m_opts.origin = m_conf.get(bs, "bottom", false) ? edge::BOTTOM : edge::TOP; m_opts.bottom = m_conf.get(bs, "bottom", m_opts.bottom);
m_opts.spacing = m_conf.get(bs, "spacing", m_opts.spacing); m_opts.spacing = m_conf.get(bs, "spacing", m_opts.spacing);
m_opts.separator = drawtypes::load_optional_label(m_conf, bs, "separator", ""); m_opts.separator = drawtypes::load_optional_label(m_conf, bs, "separator", "");
m_opts.locale = m_conf.get(bs, "locale", ""s); m_opts.locale = m_conf.get(bs, "locale", ""s);
@ -221,10 +221,8 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
// Load values used to adjust the struts atom // Load values used to adjust the struts atom
auto margin_top = m_conf.get("global/wm", "margin-top", percentage_with_offset{}); auto margin_top = m_conf.get("global/wm", "margin-top", percentage_with_offset{});
auto margin_bottom = m_conf.get("global/wm", "margin-bottom", percentage_with_offset{}); auto margin_bottom = m_conf.get("global/wm", "margin-bottom", percentage_with_offset{});
m_opts.strut.top = m_opts.strut.top = units_utils::percentage_with_offset_to_pixel(margin_top, m_opts.monitor->h, m_opts.dpi_y);
units_utils::percentage_with_offset_to_pixel_nonnegative(margin_top, m_opts.monitor->h, m_opts.dpi_y); m_opts.strut.bottom = units_utils::percentage_with_offset_to_pixel(margin_bottom, m_opts.monitor->h, m_opts.dpi_y);
m_opts.strut.bottom =
units_utils::percentage_with_offset_to_pixel_nonnegative(margin_bottom, m_opts.monitor->h, m_opts.dpi_y);
// Load commands used for fallback click handlers // Load commands used for fallback click handlers
vector<action> actions; vector<action> actions;
@ -329,7 +327,7 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
m_opts.size.h += m_opts.borders[edge::TOP].size; m_opts.size.h += m_opts.borders[edge::TOP].size;
m_opts.size.h += m_opts.borders[edge::BOTTOM].size; m_opts.size.h += m_opts.borders[edge::BOTTOM].size;
if (m_opts.origin == edge::BOTTOM) { if (m_opts.bottom) {
m_opts.pos.y = m_opts.monitor->y + m_opts.monitor->h - m_opts.size.h - m_opts.offset.y; m_opts.pos.y = m_opts.monitor->y + m_opts.monitor->h - m_opts.size.h - m_opts.offset.y;
} }
@ -556,23 +554,41 @@ void bar::reconfigure_pos() {
*/ */
void bar::reconfigure_struts() { void bar::reconfigure_struts() {
auto geom = m_connection.get_geometry(m_screen->root()); auto geom = m_connection.get_geometry(m_screen->root());
auto w = m_opts.size.w + m_opts.offset.x; int h = m_opts.size.h + m_opts.offset.y;
auto h = m_opts.size.h + m_opts.offset.y;
if (m_opts.origin == edge::BOTTOM) { // Apply user-defined margins
if (m_opts.bottom) {
h += m_opts.strut.top; h += m_opts.strut.top;
} else { } else {
h += m_opts.strut.bottom; h += m_opts.strut.bottom;
} }
if (m_opts.origin == edge::BOTTOM && m_opts.monitor->y + m_opts.monitor->h < geom->height) { h = std::max(h, 0);
h += geom->height - (m_opts.monitor->y + m_opts.monitor->h);
} else if (m_opts.origin != edge::BOTTOM) { int correction = 0;
h += m_opts.monitor->y;
// Only apply correction if any space is requested
if (h > 0) {
/*
* Strut coordinates have to be relative to root window and not any monitor.
* If any monitor is not aligned at the top or bottom
*/
if (m_opts.bottom) {
/*
* For bottom-algined bars, the correction is the number of pixels between
* the root window's bottom edge and the monitor's bottom edge
*/
correction = geom->height - (m_opts.monitor->y + m_opts.monitor->h);
} else {
// For top-aligned bars, we simply add the monitor's y-position
correction = m_opts.monitor->y;
}
correction = std::max(correction, 0);
} }
window win{m_connection, m_opts.window}; window win{m_connection, m_opts.window};
win.reconfigure_struts(w, h, m_opts.pos.x, m_opts.origin == edge::BOTTOM); win.reconfigure_struts(m_opts.size.w, h + correction, m_opts.pos.x, m_opts.bottom);
} }
/** /**

View File

@ -1,9 +1,10 @@
#include "x11/window.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "utils/memory.hpp" #include "utils/memory.hpp"
#include "x11/atoms.hpp" #include "x11/atoms.hpp"
#include "x11/connection.hpp" #include "x11/connection.hpp"
#include "x11/extensions/randr.hpp" #include "x11/extensions/randr.hpp"
#include "x11/window.hpp"
POLYBAR_NS POLYBAR_NS
@ -45,24 +46,31 @@ window window::reconfigure_pos(short int x, short int y) {
/** /**
* Reconfigure the windows ewmh strut * Reconfigure the windows ewmh strut
*
* Ref: https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html#idm45381391268672
*
* @param w Width of the bar window
* @param strut Size of the reserved space. Height of the window, corrected for unaligned monitors
* @param x The absolute x-position of the bar window (top-left corner)
* @param bottom Whether the bar is at the bottom of the screen
*/ */
window window::reconfigure_struts(unsigned short int w, unsigned short int h, short int x, bool bottom) { window window::reconfigure_struts(uint32_t w, uint32_t strut, uint32_t x, bool bottom) {
unsigned int none{0}; std::array<uint32_t, 12> values{};
unsigned int values[12]{none};
if (bottom) { if (bottom) {
values[static_cast<int>(strut::BOTTOM)] = h; values[to_integral(strut::BOTTOM)] = strut;
values[static_cast<int>(strut::BOTTOM_START_X)] = x; values[to_integral(strut::BOTTOM_START_X)] = x;
values[static_cast<int>(strut::BOTTOM_END_X)] = x + w - 1; values[to_integral(strut::BOTTOM_END_X)] = x + w - 1;
} else { } else {
values[static_cast<int>(strut::TOP)] = h; values[to_integral(strut::TOP)] = strut;
values[static_cast<int>(strut::TOP_START_X)] = x; values[to_integral(strut::TOP_START_X)] = x;
values[static_cast<int>(strut::TOP_END_X)] = x + w - 1; values[to_integral(strut::TOP_END_X)] = x + w - 1;
} }
connection().change_property_checked(XCB_PROP_MODE_REPLACE, *this, _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, 4, values);
connection().change_property_checked( connection().change_property_checked(
XCB_PROP_MODE_REPLACE, *this, _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32, 12, values); XCB_PROP_MODE_REPLACE, *this, _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, 4, values.data());
connection().change_property_checked(
XCB_PROP_MODE_REPLACE, *this, _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32, 12, values.data());
return *this; return *this;
} }