diff --git a/include/x11/tray_client.hpp b/include/x11/tray_client.hpp index 84fa44f8..ec9d4109 100644 --- a/include/x11/tray_client.hpp +++ b/include/x11/tray_client.hpp @@ -40,6 +40,8 @@ class tray_client : public non_copyable_mixin { void hidden(bool state); + bool should_be_mapped() const; + xcb_window_t embedder() const; xcb_window_t client() const; @@ -97,9 +99,14 @@ class tray_client : public non_copyable_mixin { */ xembed::info m_xembed; - // TODO + /** + * Whether the wrapper window is currently mapped. + */ bool m_mapped{false}; + /** + * Whether the + */ bool m_hidden{false}; size m_size; diff --git a/include/x11/tray_manager.hpp b/include/x11/tray_manager.hpp index 9b7c1cff..391390f7 100644 --- a/include/x11/tray_manager.hpp +++ b/include/x11/tray_manager.hpp @@ -58,9 +58,9 @@ struct tray_settings { using on_update = std::function; -class tray_manager : public xpp::event::sink, +class tray_manager : public xpp::event::sink, public signal_receiver { public: @@ -81,6 +81,8 @@ class tray_manager : public xpp::event::sinkensure_state(); + // TODO skip if the client isn't mapped it->reconfigure(x, calculate_client_y()); x += m_opts.client_size.w + m_opts.spacing; } catch (const xpp::x::error::window& err) { - // TODO print error m_log.err("Failed to reconfigure %s, removing ... (%s)", it->name(), err.what()); - remove_client(*it, false); + remove_client(*it); } } } @@ -283,8 +287,7 @@ void tray_manager::reconfigure_clients() { * Refresh the bar window by clearing it along with each client window */ void tray_manager::refresh_window() { - // TODO create method that checks is_active and !m_hidden - if (!is_active() || m_hidden) { + if (!is_visible()) { return; } @@ -502,19 +505,19 @@ tray_client* tray_manager::find_client(const xcb_window_t& win) { /** * Remove tray client */ -void tray_manager::remove_client(const tray_client& client, bool reconfigure) { - remove_client(client.client(), reconfigure); +void tray_manager::remove_client(const tray_client& client) { + remove_client(client.client()); } /** * Remove tray client by window */ -void tray_manager::remove_client(xcb_window_t win, bool reconfigure) { +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); })); - // TODO remove param. Reconfigure if clients were deleted - if (reconfigure) { + if (old_size != m_clients.size()) { tray_manager::reconfigure(); } } @@ -551,17 +554,6 @@ void tray_manager::handle(const evt::expose& evt) { } } -/** - * Event callback : XCB_VISIBILITY_NOTIFY - */ -void tray_manager::handle(const evt::visibility_notify& evt) { - // TODO for which windows is this important? - if (is_active() && !m_clients.empty()) { - m_log.trace("tray: Received visibility_notify for %s", m_connection.id(evt->window)); - reconfigure_window(); - } -} - /** * Event callback : XCB_CLIENT_MESSAGE */ @@ -669,14 +661,11 @@ void tray_manager::handle(const evt::property_notify& evt) { 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()); - remove_client(*client, true); + remove_client(*client); return; } - // TODO only reconfigure if should_be_mapped changed - if (client->get_xembed().is_mapped()) { - reconfigure(); - } + client->ensure_state(); } /** @@ -723,6 +712,12 @@ void tray_manager::handle(const evt::map_notify& evt) { redraw_window(); } else if (is_embedded(evt->window)) { auto client = find_client(evt->window); + + // If we received a notification on the wrapped window, we don't want to do anything. + if (client->embedder() != evt->window) { + return; + } + m_log.trace("%s: Received map_notify", client->name()); if (!client->mapped()) { @@ -738,6 +733,12 @@ void tray_manager::handle(const evt::map_notify& evt) { void tray_manager::handle(const evt::unmap_notify& evt) { if (is_active() && is_embedded(evt->window)) { auto client = find_client(evt->window); + + // If we received a notification on the wrapped window, we don't want to do anything. + if (client->embedder() != evt->window) { + return; + } + m_log.trace("%s: Received unmap_notify", client->name()); if (client->mapped()) {