tray: Fix tray not updating after (un)map_notify

The issue was that the event was for the wrapper window and that the
tray_client's move constructors didn't correctly copy over all data and
so when the m_clients vector grew, it corrupted the state of all
existing clients.
This commit is contained in:
patrick96 2022-09-03 22:34:00 +02:00
parent 1127792ccf
commit 901183a60a
No known key found for this signature in database
GPG Key ID: 521E5E03AEBCA1A7
3 changed files with 31 additions and 18 deletions

View File

@ -64,7 +64,8 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
public signal_receiver<SIGN_PRIORITY_TRAY, signals::ui::update_background, public signal_receiver<SIGN_PRIORITY_TRAY, signals::ui::update_background,
signals::ui_tray::tray_pos_change, signals::ui_tray::tray_visibility> { signals::ui_tray::tray_pos_change, signals::ui_tray::tray_visibility> {
public: public:
explicit tray_manager(connection& conn, signal_emitter& emitter, const logger& logger, const bar_settings& bar_opts, on_update on_update); explicit tray_manager(connection& conn, signal_emitter& emitter, const logger& logger, const bar_settings& bar_opts,
on_update on_update);
~tray_manager(); ~tray_manager();
@ -108,7 +109,7 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
void update_width(); void update_width();
bool is_embedded(const xcb_window_t& win) const; bool is_embedded(const xcb_window_t& win);
tray_client* find_client(const xcb_window_t& win); tray_client* find_client(const xcb_window_t& win);
void remove_client(const tray_client& client, bool reconfigure = true); void remove_client(const tray_client& client, bool reconfigure = true);
void remove_client(xcb_window_t win, bool reconfigure = true); void remove_client(xcb_window_t win, bool reconfigure = true);

View File

@ -68,9 +68,14 @@ tray_client::~tray_client() {
} }
} }
tray_client::tray_client(tray_client&& c) : m_log(c.m_log), m_connection(c.m_connection), m_size(c.m_size) { tray_client::tray_client(tray_client&& c) : m_log(c.m_log), m_connection(c.m_connection) {
std::swap(m_wrapper, c.m_wrapper); std::swap(m_wrapper, c.m_wrapper);
std::swap(m_client, c.m_client); 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) { tray_client& tray_client::operator=(tray_client&& c) {
@ -78,6 +83,10 @@ tray_client& tray_client::operator=(tray_client&& c) {
m_connection = c.m_connection; m_connection = c.m_connection;
std::swap(m_wrapper, c.m_wrapper); std::swap(m_wrapper, c.m_wrapper);
std::swap(m_client, c.m_client); 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); std::swap(m_size, c.m_size);
return *this; return *this;
} }
@ -196,7 +205,7 @@ void tray_client::ensure_state() const {
} }
m_log.trace("tray(%s): ensure_state (hidden=%i, mapped=%i, should_be_mapped=%i)", m_connection.id(client()), m_hidden, m_log.trace("tray(%s): ensure_state (hidden=%i, mapped=%i, should_be_mapped=%i)", m_connection.id(client()), m_hidden,
mapped(), should_be_mapped); m_mapped, should_be_mapped);
if (should_be_mapped) { if (should_be_mapped) {
m_log.trace("tray(%s): Map client", m_connection.id(client())); m_log.trace("tray(%s): Map client", m_connection.id(client()));

View File

@ -449,23 +449,26 @@ int tray_manager::calculate_client_y() {
} }
/** /**
* Check if the given window is embedded * Check if the given window is embedded.
*
* The given window ID can be the ID of the wrapper or the embedded window
*/ */
bool tray_manager::is_embedded(const xcb_window_t& win) const { bool tray_manager::is_embedded(const xcb_window_t& win) {
return m_clients.end() != return find_client(win) != nullptr;
std::find_if(m_clients.begin(), m_clients.end(), [win](const auto& client) { return client.match(win); });
} }
/** /**
* Find tray client by window * Find tray client object from the wrapper or embedded window
*/ */
tray_client* tray_manager::find_client(const xcb_window_t& win) { tray_client* tray_manager::find_client(const xcb_window_t& win) {
for (auto& client : m_clients) { auto client = std::find_if(m_clients.begin(), m_clients.end(),
if (client.match(win)) { [win](const auto& client) { return client.match(win) || client.embedder() == win; });
return &client;
} if (client == m_clients.end()) {
}
return nullptr; return nullptr;
} else {
return &(*client);
}
} }
/** /**
@ -667,7 +670,7 @@ void tray_manager::handle(const evt::reparent_notify& evt) {
} }
if (evt->parent != client->embedder()) { if (evt->parent != client->embedder()) {
m_log.trace("tray: Received reparent_notify for client, remove..."); m_log.info("tray: Received reparent_notify for client, remove...");
remove_client(*client); remove_client(*client);
} }
} }
@ -680,7 +683,7 @@ void tray_manager::handle(const evt::destroy_notify& evt) {
m_log.info("Systray selection unmanaged... re-activating"); m_log.info("Systray selection unmanaged... re-activating");
activate(); activate();
} else if (m_activated && is_embedded(evt->window)) { } else if (m_activated && is_embedded(evt->window)) {
m_log.trace("tray: Received destroy_notify for client, remove..."); m_log.info("tray: Received destroy_notify for client, remove...");
remove_client(evt->window); remove_client(evt->window);
redraw_window(); redraw_window();
} }
@ -694,7 +697,7 @@ void tray_manager::handle(const evt::map_notify& evt) {
m_log.trace("tray: Received map_notify"); m_log.trace("tray: Received map_notify");
m_log.trace("tray: Update container mapped flag"); m_log.trace("tray: Update container mapped flag");
redraw_window(); redraw_window();
} else if (is_embedded(evt->window)) { // TODO FIXME evt->window points to the wrapper window } else if (is_embedded(evt->window)) {
m_log.trace("tray: Received map_notify"); m_log.trace("tray: Received map_notify");
m_log.trace("tray: Set client mapped"); m_log.trace("tray: Set client mapped");
auto client = find_client(evt->window); auto client = find_client(evt->window);
@ -710,7 +713,7 @@ void tray_manager::handle(const evt::map_notify& evt) {
* Event callback : XCB_UNMAP_NOTIFY * Event callback : XCB_UNMAP_NOTIFY
*/ */
void tray_manager::handle(const evt::unmap_notify& evt) { void tray_manager::handle(const evt::unmap_notify& evt) {
if (m_activated && is_embedded(evt->window)) { // TODO FIXME evt->window points to the wrapper window if (m_activated && is_embedded(evt->window)) {
m_log.trace("tray: Received unmap_notify"); m_log.trace("tray: Received unmap_notify");
m_log.trace("tray: Set client unmapped"); m_log.trace("tray: Set client unmapped");
auto client = find_client(evt->window); auto client = find_client(evt->window);