From ba0e4780268cf504852a39d9a83f35b9b36b2831 Mon Sep 17 00:00:00 2001
From: patrick96
Date: Sun, 27 Feb 2022 21:36:16 +0100
Subject: [PATCH] Cleanup tray position handling
---
include/events/signal.hpp | 3 -
include/events/signal_fwd.hpp | 1 -
include/x11/tray_client.hpp | 5 +-
include/x11/tray_manager.hpp | 44 +++++++++--
src/components/bar.cpp | 4 +-
src/x11/tray_client.cpp | 15 ++--
src/x11/tray_manager.cpp | 135 +++++++++++++++++-----------------
7 files changed, 116 insertions(+), 91 deletions(-)
diff --git a/include/events/signal.hpp b/include/events/signal.hpp
index f54f0684..3299f075 100644
--- a/include/events/signal.hpp
+++ b/include/events/signal.hpp
@@ -101,9 +101,6 @@ namespace signals {
} // namespace ui
namespace ui_tray {
- struct mapped_clients : public detail::value_signal {
- using base_type::base_type;
- };
struct tray_width_change : public detail::value_signal {
using base_type::base_type;
};
diff --git a/include/events/signal_fwd.hpp b/include/events/signal_fwd.hpp
index 0e422b21..7895a99b 100644
--- a/include/events/signal_fwd.hpp
+++ b/include/events/signal_fwd.hpp
@@ -35,7 +35,6 @@ namespace signals {
struct update_geometry;
} // namespace ui
namespace ui_tray {
- struct mapped_clients;
struct tray_width_change;
struct tray_pos_change;
}
diff --git a/include/x11/tray_client.hpp b/include/x11/tray_client.hpp
index eb2593fa..3a4fcaee 100644
--- a/include/x11/tray_client.hpp
+++ b/include/x11/tray_client.hpp
@@ -13,7 +13,7 @@ class connection;
class tray_client {
public:
- explicit tray_client(connection& conn, xcb_window_t win, unsigned int w, unsigned int h);
+ explicit tray_client(connection& conn, xcb_window_t win, size s);
tray_client(const tray_client& c) = delete;
tray_client& operator=(tray_client& c) = delete;
@@ -55,8 +55,7 @@ class tray_client {
bool m_mapped{false};
- unsigned int m_width;
- unsigned int m_height;
+ size m_size;
};
POLYBAR_NS_END
diff --git a/include/x11/tray_manager.hpp b/include/x11/tray_manager.hpp
index cf60488a..6c093e2d 100644
--- a/include/x11/tray_manager.hpp
+++ b/include/x11/tray_manager.hpp
@@ -43,14 +43,41 @@ struct tray_settings {
alignment align{alignment::NONE};
bool running{false};
- int orig_x{0};
- int orig_y{0};
- unsigned int configured_w{0U};
- unsigned int configured_slots{0U};
- unsigned int width{0U};
+ /**
+ * Tray window position.
+ *
+ * Relative to the bar window
+ * TODO make relative to inner area
+ */
+ position pos{0, 0};
+
+ /**
+ * Tray offset in pixels.
+ */
+ position offset{0, 0};
+
+ /**
+ * Current dimensions of the tray window.
+ */
+ size win_size{0, 0};
+
+ /**
+ * Dimensions for client windows.
+ */
+ size client_size{0, 0};
+
+ /**
+ * Number of clients currently mapped.
+ */
+ int num_clients{0};
+
+ // This is the width of the bar window
+ // TODO directly read from bar_settings
unsigned int width_max{0U};
- unsigned int height{0U};
- unsigned int height_fill{0U};
+
+ /**
+ * Number of pixels added between tray icons
+ */
unsigned int spacing{0U};
rgba background{};
rgba foreground{};
@@ -116,7 +143,8 @@ class tray_manager : public xpp::event::sink find_client(const xcb_window_t& win) const;
void remove_client(shared_ptr& client, bool reconfigure = true);
void remove_client(xcb_window_t win, bool reconfigure = true);
- unsigned int mapped_clients() const;
+ int mapped_clients() const;
+ bool has_mapped_clients() const;
void handle(const evt::expose& evt) override;
void handle(const evt::visibility_notify& evt) override;
diff --git a/src/components/bar.cpp b/src/components/bar.cpp
index 2c06674f..fada7501 100644
--- a/src/components/bar.cpp
+++ b/src/components/bar.cpp
@@ -393,9 +393,9 @@ void bar::parse(string&& data, bool force) {
auto rect = m_opts.inner_area();
- if (m_tray && !m_tray->settings().detached && m_tray->settings().configured_slots && !m_tray->settings().adaptive) {
+ if (m_tray && !m_tray->settings().detached && m_tray->settings().num_clients > 0 && !m_tray->settings().adaptive) {
auto trayalign = m_tray->settings().align;
- auto traywidth = m_tray->settings().configured_w;
+ auto traywidth = m_tray->settings().win_size.w;
if (trayalign == alignment::LEFT) {
rect.x += traywidth;
rect.width -= traywidth;
diff --git a/src/x11/tray_client.cpp b/src/x11/tray_client.cpp
index e9fee279..89fdf638 100644
--- a/src/x11/tray_client.cpp
+++ b/src/x11/tray_client.cpp
@@ -8,19 +8,18 @@
POLYBAR_NS
-tray_client::tray_client(connection& conn, xcb_window_t win, unsigned int w, unsigned int h)
- : m_connection(conn), m_window(win), m_width(w), m_height(h) {}
+tray_client::tray_client(connection& conn, xcb_window_t win, size s) : m_connection(conn), m_window(win), m_size(s) {}
tray_client::~tray_client() {
xembed::unembed(m_connection, window(), m_connection.root());
}
unsigned int tray_client::width() const {
- return m_width;
+ return m_size.w;
}
unsigned int tray_client::height() const {
- return m_height;
+ return m_size.h;
}
void tray_client::clear_window() const {
@@ -92,8 +91,8 @@ void tray_client::reconfigure(int x, int y) const {
unsigned int configure_values[7];
xcb_params_configure_window_t configure_params{};
- XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, width, m_width);
- XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, height, m_height);
+ XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, width, m_size.w);
+ XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, height, m_size.h);
XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, x, x);
XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, y, y);
@@ -113,8 +112,8 @@ void tray_client::configure_notify(int x, int y) const {
notify.above_sibling = 0;
notify.x = x;
notify.y = y;
- notify.width = m_width;
- notify.height = m_height;
+ notify.width = m_size.w;
+ notify.height = m_size.h;
notify.border_width = 0;
unsigned int mask{XCB_EVENT_MASK_STRUCTURE_NOTIFY};
diff --git a/src/x11/tray_manager.cpp b/src/x11/tray_manager.cpp
index c23ae7ba..e181daae 100644
--- a/src/x11/tray_manager.cpp
+++ b/src/x11/tray_manager.cpp
@@ -92,46 +92,40 @@ void tray_manager::setup() {
return;
}
- m_opts.detached = conf.get(bs, "tray-detached", false);
- m_opts.height = m_bar_opts.size.h;
- m_opts.height -= m_bar_opts.borders.at(edge::BOTTOM).size;
- m_opts.height -= m_bar_opts.borders.at(edge::TOP).size;
- m_opts.height_fill = m_opts.height;
+ auto inner_area = m_bar_opts.inner_area();
+ m_opts.win_size.w = 0;
+ m_opts.win_size.h = inner_area.height;
- if (m_opts.height % 2 != 0) {
- m_opts.height--;
- }
+ m_opts.detached = conf.get(bs, "tray-detached", false);
+ unsigned int client_height = inner_area.height;
auto maxsize = conf.get(bs, "tray-maxsize", 16);
- if (m_opts.height > maxsize) {
- m_opts.spacing += (m_opts.height - maxsize) / 2;
- m_opts.height = maxsize;
+ if (client_height > maxsize) {
+ m_opts.spacing += (client_height - maxsize) / 2;
+ client_height = maxsize;
}
m_opts.width_max = m_bar_opts.size.w;
- m_opts.width = m_opts.height;
- m_opts.orig_y = m_bar_opts.borders.at(edge::TOP).size;
+ m_opts.client_size = {client_height, client_height};
// Apply user-defined scaling
auto scale = conf.get(bs, "tray-scale", 1.0);
- m_opts.width *= scale;
- m_opts.height_fill *= scale;
+ m_opts.client_size.w *= scale;
+ m_opts.win_size.h *= scale;
- auto inner_area = m_bar_opts.inner_area();
-
- switch (m_opts.align) {
- case alignment::NONE:
- break;
- case alignment::LEFT:
- m_opts.orig_x = inner_area.x;
- break;
- case alignment::CENTER:
- m_opts.orig_x = inner_area.x + inner_area.width / 2 - m_opts.width / 2;
- break;
- case alignment::RIGHT:
- m_opts.orig_x = inner_area.x + inner_area.width;
- break;
- }
+ m_opts.pos.x = inner_area.x + [&]() -> int {
+ switch (m_opts.align) {
+ case alignment::LEFT:
+ return 0;
+ case alignment::CENTER:
+ return inner_area.width / 2 - m_opts.client_size.w / 2;
+ case alignment::RIGHT:
+ return inner_area.width;
+ default:
+ return 0;
+ }
+ }();
+ m_opts.pos.y = inner_area.y;
if (conf.has(bs, "tray-transparent")) {
m_log.warn("tray-transparent is deprecated, the tray always uses pseudo-transparency. Please remove it.");
@@ -164,10 +158,13 @@ void tray_manager::setup() {
max_y = inner_area.height;
}
- m_opts.orig_x += units_utils::percentage_with_offset_to_pixel(offset_x, max_x, m_bar_opts.dpi_x);
- m_opts.orig_y += units_utils::percentage_with_offset_to_pixel(offset_y, max_y, m_bar_opts.dpi_y);
+ m_opts.offset.x = units_utils::percentage_with_offset_to_pixel(offset_x, max_x, m_bar_opts.dpi_x);
+ m_opts.offset.y = units_utils::percentage_with_offset_to_pixel(offset_y, max_y, m_bar_opts.dpi_y);
- m_opts.bar_window = bar_opts.window;
+ m_opts.pos.x += m_opts.offset.x;
+ m_opts.pos.y += m_opts.offset.y;
+
+ m_opts.bar_window = m_bar_opts.window;
// Activate the tray manager
query_atom();
@@ -264,8 +261,8 @@ void tray_manager::deactivate(bool clear_selection) {
m_tray = 0;
m_pixmap = 0;
m_gc = 0;
- m_opts.configured_w = 0;
- m_opts.configured_slots = 0;
+ m_opts.win_size.w = 0;
+ m_opts.num_clients = 0;
m_acquired_selection = false;
m_mapped = false;
@@ -299,7 +296,7 @@ void tray_manager::reconfigure() {
m_log.err("Failed to reconfigure tray background (%s)", err.what());
}
- m_opts.configured_slots = mapped_clients();
+ m_opts.num_clients = mapped_clients();
guard.unlock();
refresh_window();
m_connection.flush();
@@ -318,17 +315,17 @@ void tray_manager::reconfigure_window() {
return;
}
- auto clients = mapped_clients();
- if (!clients && m_mapped) {
+ bool has_clients = has_mapped_clients();
+ if (!has_clients && m_mapped) {
m_log.trace("tray: Reconfigure window / unmap");
m_connection.unmap_window_checked(m_tray);
- } else if (clients && !m_mapped && !m_hidden) {
+ } else if (has_clients && !m_mapped && !m_hidden) {
m_log.trace("tray: Reconfigure window / map");
m_connection.map_window_checked(m_tray);
}
auto width = calculate_w();
- auto x = calculate_x(width);
+ m_opts.win_size.w = width;
if (m_opts.transparent) {
xcb_rectangle_t rect{0, 0, calculate_w(), calculate_h()};
@@ -336,6 +333,7 @@ void tray_manager::reconfigure_window() {
}
if (width > 0) {
+ auto x = calculate_x(width);
m_log.trace("tray: New window values, width=%d, x=%d", width, x);
unsigned int mask = 0;
@@ -347,8 +345,6 @@ void tray_manager::reconfigure_window() {
connection::pack_values(mask, ¶ms, values);
m_connection.configure_window_checked(m_tray, mask, values);
}
-
- m_opts.configured_w = width;
}
/**
@@ -366,7 +362,7 @@ void tray_manager::reconfigure_clients() {
client->ensure_state();
client->reconfigure(x, calculate_client_y());
- x += m_opts.width + m_opts.spacing;
+ x += m_opts.client_size.w + m_opts.spacing;
} catch (const xpp::x::error::window& err) {
remove_client(client, false);
}
@@ -441,10 +437,10 @@ void tray_manager::refresh_window() {
m_connection.flush();
- if (!mapped_clients()) {
- m_opts.configured_w = 0;
+ if (has_mapped_clients()) {
+ m_opts.win_size.w = width;
} else {
- m_opts.configured_w = width;
+ m_opts.win_size.w = 0;
}
}
@@ -696,7 +692,7 @@ void tray_manager::track_selection_owner(xcb_window_t owner) {
void tray_manager::process_docking_request(xcb_window_t win) {
m_log.info("Processing docking request from '%s' (%s)", ewmh_util::get_wm_name(win), m_connection.id(win));
- m_clients.emplace_back(std::make_shared(m_connection, win, m_opts.width, m_opts.height));
+ m_clients.emplace_back(std::make_shared(m_connection, win, m_opts.client_size));
auto& client = m_clients.back();
try {
@@ -753,11 +749,11 @@ void tray_manager::process_docking_request(xcb_window_t win) {
* Calculate x position of tray window
*/
int tray_manager::calculate_x(unsigned int width) const {
- auto x = m_opts.orig_x;
+ auto x = m_opts.pos.x;
if (m_opts.align == alignment::RIGHT) {
- x -= ((m_opts.width + m_opts.spacing) * m_clients.size() + m_opts.spacing);
+ x -= ((m_opts.client_size.w + m_opts.spacing) * m_clients.size() + m_opts.spacing);
} else if (m_opts.align == alignment::CENTER) {
- x -= (width / 2) - (m_opts.width / 2);
+ x -= (width / 2) - (m_opts.client_size.w / 2);
}
return x;
}
@@ -766,7 +762,7 @@ int tray_manager::calculate_x(unsigned int width) const {
* Calculate y position of tray window
*/
int tray_manager::calculate_y() const {
- return m_opts.orig_y;
+ return m_opts.pos.y;
}
/**
@@ -778,7 +774,7 @@ unsigned short int tray_manager::calculate_w() const {
for (auto&& client : m_clients) {
if (client->mapped()) {
count++;
- width += m_opts.spacing + m_opts.width;
+ width += m_opts.spacing + m_opts.client_size.w;
}
}
return count ? width : 0;
@@ -788,7 +784,7 @@ unsigned short int tray_manager::calculate_w() const {
* Calculate height of tray window
*/
unsigned short int tray_manager::calculate_h() const {
- return m_opts.height_fill;
+ return m_opts.win_size.h;
}
/**
@@ -797,7 +793,7 @@ unsigned short int tray_manager::calculate_h() const {
int tray_manager::calculate_client_x(const xcb_window_t& win) {
for (unsigned int i = 0; i < m_clients.size(); i++) {
if (m_clients[i]->match(win)) {
- return m_opts.spacing + m_opts.width * i;
+ return m_opts.spacing + m_opts.client_size.w * i;
}
}
return m_opts.spacing;
@@ -807,7 +803,7 @@ int tray_manager::calculate_client_x(const xcb_window_t& win) {
* Calculate y position of client window
*/
int tray_manager::calculate_client_y() {
- return (m_opts.height_fill - m_opts.height) / 2;
+ return (m_opts.win_size.h - m_opts.client_size.h) / 2;
}
/**
@@ -852,8 +848,8 @@ void tray_manager::remove_client(xcb_window_t win, bool reconfigure) {
/**
* Get number of mapped clients
*/
-unsigned int tray_manager::mapped_clients() const {
- unsigned int mapped_clients = 0;
+int tray_manager::mapped_clients() const {
+ int mapped_clients = 0;
for (auto&& client : m_clients) {
if (client->mapped()) {
@@ -864,6 +860,16 @@ unsigned int tray_manager::mapped_clients() const {
return mapped_clients;
}
+bool tray_manager::has_mapped_clients() const {
+ for (auto&& client : m_clients) {
+ if (client->mapped()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/**
* Event callback : XCB_EXPOSE
*/
@@ -1052,11 +1058,9 @@ void tray_manager::handle(const evt::map_notify& evt) {
m_log.trace("tray: Received map_notify");
m_log.trace("tray: Set client mapped");
find_client(evt->window)->mapped(true);
- unsigned int clientcount{mapped_clients()};
- if (clientcount > m_opts.configured_slots) {
+ if (mapped_clients() > m_opts.num_clients) {
reconfigure();
}
- m_sig.emit(signals::ui_tray::mapped_clients{move(clientcount)});
}
}
@@ -1072,7 +1076,6 @@ void tray_manager::handle(const evt::unmap_notify& evt) {
m_log.trace("tray: Received unmap_notify");
m_log.trace("tray: Set client unmapped");
find_client(evt->window)->mapped(false);
- m_sig.emit(signals::ui_tray::mapped_clients{mapped_clients()});
}
}
@@ -1083,7 +1086,7 @@ void tray_manager::handle(const evt::unmap_notify& evt) {
*/
bool tray_manager::on(const signals::ui::visibility_change& evt) {
bool visible{evt.cast()};
- unsigned int clients{mapped_clients()};
+ bool has_clients = has_mapped_clients();
m_log.trace("tray: visibility_change (state=%i, activated=%i, mapped=%i, hidden=%i)", visible,
static_cast(m_activated), static_cast(m_mapped), static_cast(m_hidden));
@@ -1092,11 +1095,11 @@ bool tray_manager::on(const signals::ui::visibility_change& evt) {
if (!m_activated) {
return false;
- } else if (!m_hidden && !m_mapped && clients) {
+ } else if (!m_hidden && !m_mapped && has_clients) {
m_connection.map_window(m_tray);
- } else if ((!clients || m_hidden) && m_mapped) {
+ } else if ((!has_clients || m_hidden) && m_mapped) {
m_connection.unmap_window(m_tray);
- } else if (m_mapped && !m_hidden && clients) {
+ } else if (m_mapped && !m_hidden && has_clients) {
redraw_window();
}
@@ -1120,7 +1123,7 @@ bool tray_manager::on(const signals::ui::update_background&) {
}
bool tray_manager::on(const signals::ui_tray::tray_pos_change& evt) {
- m_opts.orig_x = m_bar_opts.inner_area(true).x + evt.cast();
+ m_opts.pos.x = m_bar_opts.inner_area(true).x + evt.cast();
reconfigure_window();
return true;