From 5c38d5cb17203dee2c1e1fba78a8b434695a0118 Mon Sep 17 00:00:00 2001
From: patrick96
Date: Sat, 24 Sep 2022 13:20:02 +0200
Subject: [PATCH] tray: Store clients in unique_ptr
---
include/x11/tray_client.hpp | 5 +--
include/x11/tray_manager.hpp | 3 +-
src/components/bar.cpp | 1 +
src/x11/tray_client.cpp | 25 --------------
src/x11/tray_manager.cpp | 67 +++++++++++++++++++++++-------------
5 files changed, 48 insertions(+), 53 deletions(-)
diff --git a/include/x11/tray_client.hpp b/include/x11/tray_client.hpp
index ec9d4109..eb1a9189 100644
--- a/include/x11/tray_client.hpp
+++ b/include/x11/tray_client.hpp
@@ -17,14 +17,11 @@ POLYBAR_NS
// fwd declarations
class connection;
-class tray_client : public non_copyable_mixin {
+class tray_client : public non_copyable_mixin, public non_movable_mixin {
public:
explicit tray_client(const logger& log, connection& conn, xcb_window_t tray, xcb_window_t win, size s);
~tray_client();
- tray_client(tray_client&&);
- tray_client& operator=(tray_client&&);
-
string name() const;
unsigned int width() const;
diff --git a/include/x11/tray_manager.hpp b/include/x11/tray_manager.hpp
index 7d96e2d2..ead438ff 100644
--- a/include/x11/tray_manager.hpp
+++ b/include/x11/tray_manager.hpp
@@ -120,6 +120,7 @@ class tray_manager : public xpp::event::sink m_clients;
+ vector> m_clients;
tray_settings m_opts{};
const bar_settings& m_bar_opts;
diff --git a/src/components/bar.cpp b/src/components/bar.cpp
index 49a8c5d6..e060baaa 100644
--- a/src/components/bar.cpp
+++ b/src/components/bar.cpp
@@ -840,6 +840,7 @@ void bar::handle(const evt::button_press& evt) {
*/
void bar::handle(const evt::expose& evt) {
if (evt->window == m_opts.x_data.window && evt->count == 0) {
+ // TODO
// if (m_tray->running()) {
// broadcast_visibility();
// }
diff --git a/src/x11/tray_client.cpp b/src/x11/tray_client.cpp
index d405e47f..b13d0d07 100644
--- a/src/x11/tray_client.cpp
+++ b/src/x11/tray_client.cpp
@@ -69,31 +69,6 @@ tray_client::~tray_client() {
}
}
-tray_client::tray_client(tray_client&& c) : m_log(c.m_log), m_connection(c.m_connection) {
- std::swap(m_name, c.m_name);
- std::swap(m_wrapper, c.m_wrapper);
- std::swap(m_client, c.m_client);
- std::swap(m_xembed_supported, c.m_xembed_supported);
- std::swap(m_xembed, c.m_xembed);
- std::swap(m_mapped, c.m_mapped);
- std::swap(m_hidden, c.m_hidden);
- std::swap(m_size, c.m_size);
-}
-
-tray_client& tray_client::operator=(tray_client&& c) {
- m_log = c.m_log;
- m_connection = c.m_connection;
- std::swap(m_name, c.m_name);
- std::swap(m_wrapper, c.m_wrapper);
- std::swap(m_client, c.m_client);
- std::swap(m_xembed_supported, c.m_xembed_supported);
- std::swap(m_xembed, c.m_xembed);
- std::swap(m_mapped, c.m_mapped);
- std::swap(m_hidden, c.m_hidden);
- std::swap(m_size, c.m_size);
- return *this;
-}
-
string tray_client::name() const {
return "tray_client(" + m_connection.id(m_client) + ", " + m_name + ")";
}
diff --git a/src/x11/tray_manager.cpp b/src/x11/tray_manager.cpp
index 1dc7c1b1..4916dc68 100644
--- a/src/x11/tray_manager.cpp
+++ b/src/x11/tray_manager.cpp
@@ -270,18 +270,27 @@ void tray_manager::reconfigure_clients() {
int x = calculate_x() + m_opts.spacing;
- for (auto it = m_clients.rbegin(); it != m_clients.rend(); it++) {
+ bool has_error = false;
+
+ for (auto& client : m_clients) {
try {
- it->ensure_state();
- // TODO skip if the client isn't mapped
- it->reconfigure(x, calculate_client_y());
+ client->ensure_state();
+
+ if (client->mapped()) {
+ client->reconfigure(x, calculate_client_y());
+ }
x += m_opts.client_size.w + m_opts.spacing;
} catch (const xpp::x::error::window& err) {
- m_log.err("Failed to reconfigure %s, removing ... (%s)", it->name(), err.what());
- remove_client(*it);
+ m_log.err("Failed to reconfigure %s, removing ... (%s)", client->name(), err.what());
+ client.reset();
+ has_error = true;
}
}
+
+ if (has_error) {
+ clean_clients();
+ }
}
/**
@@ -296,11 +305,11 @@ void tray_manager::refresh_window() {
for (auto& client : m_clients) {
try {
- if (client.mapped()) {
- client.clear_window();
+ if (client->mapped()) {
+ client->clear_window();
}
} catch (const std::exception& e) {
- m_log.err("tray: Failed to clear %s (%s)", client.name(), e.what());
+ m_log.err("tray: Failed to clear %s (%s)", client->name(), e.what());
}
}
@@ -434,24 +443,24 @@ void tray_manager::process_docking_request(xcb_window_t win) {
m_log.info("tray: Processing docking request from '%s' (%s)", ewmh_util::get_wm_name(win), m_connection.id(win));
try {
- tray_client client(m_log, m_connection, m_opts.selection_owner, win, m_opts.client_size);
+ auto client = make_unique(m_log, m_connection, m_opts.selection_owner, win, m_opts.client_size);
try {
- client.query_xembed();
+ client->query_xembed();
} catch (const xpp::x::error::window& err) {
- m_log.err("Failed to query _XEMBED_INFO, removing %s ... (%s)", client.name(), err.what());
+ m_log.err("Failed to query _XEMBED_INFO, removing %s ... (%s)", client->name(), err.what());
return;
}
- client.update_client_attributes();
+ client->update_client_attributes();
- client.reparent();
+ client->reparent();
- client.add_to_save_set();
+ client->add_to_save_set();
- client.notify_xembed();
+ client->notify_xembed();
- client.ensure_state();
+ client->ensure_state();
m_clients.emplace_back(std::move(client));
} catch (const std::exception& err) {
@@ -475,7 +484,7 @@ unsigned tray_manager::calculate_w() const {
unsigned width = m_opts.spacing;
unsigned count{0};
for (auto& client : m_clients) {
- if (client.mapped()) {
+ if (client->mapped()) {
count++;
width += m_opts.spacing + m_opts.client_size.w;
}
@@ -504,12 +513,12 @@ bool tray_manager::is_embedded(const xcb_window_t& win) {
*/
tray_client* tray_manager::find_client(const xcb_window_t& win) {
auto client = std::find_if(m_clients.begin(), m_clients.end(),
- [win](const auto& client) { return client.match(win) || client.embedder() == win; });
+ [win](const auto& client) { return client->match(win) || client->embedder() == win; });
if (client == m_clients.end()) {
return nullptr;
} else {
- return &(*client);
+ return client->get();
}
}
@@ -526,13 +535,25 @@ void tray_manager::remove_client(const tray_client& client) {
void tray_manager::remove_client(xcb_window_t win) {
auto old_size = m_clients.size();
m_clients.erase(
- std::remove_if(m_clients.begin(), m_clients.end(), [win](const auto& client) { return client.match(win); }));
+ std::remove_if(m_clients.begin(), m_clients.end(), [win](const auto& client) { return client->match(win); }));
if (old_size != m_clients.size()) {
tray_manager::reconfigure();
}
}
+/**
+ * Remove all null pointers from client list.
+ *
+ * Removing clients is often done in two steps:
+ * 1. When removing a client during iteration, the unique_ptr is reset.
+ * 2. Afterwards all null pointers are removed from the list.
+ */
+void tray_manager::clean_clients() {
+ m_clients.erase(
+ std::remove_if(m_clients.begin(), m_clients.end(), [](const auto& client) { return client.get() == nullptr; }));
+}
+
bool tray_manager::change_visibility(bool visible) {
if (!is_active() || m_hidden == !visible) {
return false;
@@ -543,8 +564,8 @@ bool tray_manager::change_visibility(bool visible) {
m_hidden = !visible;
for (auto& client : m_clients) {
- client.hidden(m_hidden);
- client.ensure_state();
+ client->hidden(m_hidden);
+ client->ensure_state();
}
if (!m_hidden) {