From b11a662d81b4700f9a812b52402fa1e844c84393 Mon Sep 17 00:00:00 2001 From: Michael Carlberg Date: Wed, 14 Dec 2016 11:34:09 +0100 Subject: [PATCH] fix(tray): Re-activation --- include/x11/tray_manager.hpp | 6 ++- src/components/config.cpp | 7 ++- src/components/eventloop.cpp | 4 +- src/utils/string.cpp | 29 +++++++----- src/x11/tray_manager.cpp | 92 ++++++++++++++++++++++-------------- 5 files changed, 83 insertions(+), 55 deletions(-) diff --git a/include/x11/tray_manager.hpp b/include/x11/tray_manager.hpp index 73bda873..5e6fe0b4 100644 --- a/include/x11/tray_manager.hpp +++ b/include/x11/tray_manager.hpp @@ -96,7 +96,7 @@ class tray_manager : public xpp::event::sink m_drawtime; + + bool m_firstactivation{true}; }; POLYBAR_NS_END diff --git a/src/components/config.cpp b/src/components/config.cpp index 6d66742c..2613c733 100644 --- a/src/components/config.cpp +++ b/src/components/config.cpp @@ -26,7 +26,7 @@ config::make_type config::make(string path, string bar) { * Construct config object */ config::config(const logger& logger, const xresource_manager& xrm, string&& path, string&& bar) - : m_logger(logger), m_xrm(xrm), m_file(forward(path)), m_barname(forward(bar)) { + : m_logger(logger), m_xrm(xrm), m_file(forward(path)), m_barname(forward(bar)) { if (!file_util::exists(m_file)) { throw application_error("Could not find config file: " + m_file); } @@ -78,7 +78,7 @@ void config::warn_deprecated(const string& section, const string& key, string re * Parse key/value pairs from the configuration file */ void config::parse_file() { - std::ifstream in(m_file.c_str()); + std::ifstream in(m_file); string line; string section; uint32_t lineno{0}; @@ -117,8 +117,7 @@ void config::parse_file() { line.erase(0, equal_pos + 1); } - string value{string_util::trim(string_util::trim(move(line), ' '), '"')}; - + string value{string_util::trim(forward(string_util::trim(move(line), ' ')), '"')}; m_sections[section].emplace_hint(it, move(key), move(value)); } diff --git a/src/components/eventloop.cpp b/src/components/eventloop.cpp index 3a9cce64..f05a8686 100644 --- a/src/components/eventloop.cpp +++ b/src/components/eventloop.cpp @@ -120,10 +120,8 @@ void eventloop::stop() { * Enqueue event */ bool eventloop::enqueue(event&& evt) { - uint8_t type{static_cast(evt.type)}; - if (!m_queue.enqueue(move(evt))) { - m_log.warn("Failed to enqueue event (%d)", static_cast(type)); + m_log.warn("Failed to enqueue event"); return false; } diff --git a/src/utils/string.cpp b/src/utils/string.cpp index e94154b5..2b51108e 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -122,30 +122,37 @@ namespace string_util { /** * Remove needle from the start of the string */ - string ltrim(string&& haystack, const char& needle) { - string str(haystack); - while (str[0] == needle) { - str.erase(0, 1); + string ltrim(string&& value, const char& needle) { + if (value.empty()) { + return ""; } - return str; + while (*value.begin() == needle) { + value.erase(0, 1); + } + return forward(value); } /** * Remove needle from the end of the string */ - string rtrim(string&& haystack, const char& needle) { - string str(haystack); - while (str[str.length() - 1] == needle) { - str.erase(str.length() - 1, 1); + string rtrim(string&& value, const char& needle) { + if (value.empty()) { + return ""; } - return str; + while (*(value.end() - 1) == needle) { + value.erase(value.length() - 1, 1); + } + return forward(value); } /** * Remove needle from the start and end of the string */ string trim(string&& value, const char& needle) { - return rtrim(ltrim(move(value), needle), needle); + if (value.empty()) { + return ""; + } + return rtrim(ltrim(forward(value), needle), needle); } /** diff --git a/src/x11/tray_manager.cpp b/src/x11/tray_manager.cpp index fd046993..efd8ceeb 100644 --- a/src/x11/tray_manager.cpp +++ b/src/x11/tray_manager.cpp @@ -51,12 +51,15 @@ tray_manager::make_type tray_manager::make() { } tray_manager::tray_manager(connection& conn, signal_emitter& emitter, const logger& logger) - : m_connection(conn), m_sig(emitter), m_log(logger) {} + : m_connection(conn), m_sig(emitter), m_log(logger) { + m_connection.attach_sink(this, SINK_PRIORITY_TRAY); +} tray_manager::~tray_manager() { if (m_delaythread.joinable()) { m_delaythread.join(); } + m_connection.detach_sink(this, SINK_PRIORITY_TRAY); deactivate(); } @@ -198,7 +201,6 @@ void tray_manager::activate() { m_opts.running = true; m_sig.attach(this); - m_connection.attach_sink(this, SINK_PRIORITY_TRAY); try { create_window(); @@ -221,13 +223,16 @@ void tray_manager::activate() { // notify clients waiting for a manager. acquire_selection(); - // Notify pending tray clients - notify_clients(); - // Send delayed notification - if (m_othermanager != XCB_NONE && m_othermanager != m_tray) { + if (!m_firstactivation) { notify_clients_delayed(); + } else if (m_othermanager != XCB_NONE && m_othermanager != m_tray) { + notify_clients_delayed(); + } else { + notify_clients(); } + + m_firstactivation = false; } /** @@ -243,7 +248,6 @@ void tray_manager::deactivate(bool clear_selection) { m_opts.running = false; m_sig.detach(this); - m_connection.detach_sink(this, SINK_PRIORITY_TRAY); if (!m_connection.connection_has_error() && clear_selection && m_acquired_selection) { m_log.trace("tray: Unset selection owner"); @@ -506,7 +510,15 @@ void tray_manager::refresh_window() { * Redraw window */ void tray_manager::redraw_window(bool realloc_bg) { - m_log.info("Redraw tray container (id=%s)", m_connection.id(m_tray)); + chrono::system_clock::time_point now{chrono::system_clock::now()}; + + if (!realloc_bg && now - 24ms < m_drawtime) { + return m_log.trace("tray: Ignoring redraw (throttled)"); + } + + m_drawtime = chrono::time_point_cast(now); + m_log.info("Redraw tray container (id=%s) %lu", m_connection.id(m_tray), + chrono::duration_cast(chrono::system_clock::now().time_since_epoch())); reconfigure_bg(realloc_bg); refresh_window(); } @@ -669,23 +681,34 @@ void tray_manager::set_tray_colors() { * Acquire the systray selection */ void tray_manager::acquire_selection() { - auto reply = m_connection.get_selection_owner_unchecked(m_atom); - auto owner = reply.owner(); + m_othermanager = XCB_NONE; + ; + xcb_window_t owner; + + try { + owner = m_connection.get_selection_owner(m_atom).owner(); + } catch (const exception& err) { + return; + } if (owner == m_tray) { - m_log.info("tray: Already managing the systray selection"); - } else if ((m_othermanager = owner) != XCB_NONE) { - m_log.info("Replacing selection manager %s", m_connection.id(owner)); - } else { - m_log.trace("tray: Change selection owner to %s", m_connection.id(m_tray)); - m_connection.set_selection_owner_checked(m_tray, m_atom, XCB_CURRENT_TIME); - - if (m_connection.get_selection_owner_unchecked(m_atom)->owner != m_tray) { - throw application_error("Failed to get control of the systray selection"); - } - - m_acquired_selection = false; + m_log.trace("tray: Already managing the systray selection"); + m_acquired_selection = true; + return; } + + if ((m_othermanager = owner) != XCB_NONE) { + m_log.info("Replacing selection manager %s", m_connection.id(owner)); + } + + m_log.trace("tray: Change selection owner to %s", m_connection.id(m_tray)); + m_connection.set_selection_owner_checked(m_tray, m_atom, XCB_CURRENT_TIME); + + if (m_connection.get_selection_owner_unchecked(m_atom)->owner != m_tray) { + throw application_error("Failed to get control of the systray selection"); + } + + m_acquired_selection = true; } /** @@ -705,16 +728,14 @@ void tray_manager::notify_clients() { /** * Send delayed notification to pending clients */ -void tray_manager::notify_clients_delayed(chrono::seconds delay) { - if (!m_activated) { - return; - } else if (m_delaythread.joinable()) { +void tray_manager::notify_clients_delayed() { + if (m_delaythread.joinable()) { m_delaythread.join(); } - m_delaythread = thread([this](auto&& delay) { - this_thread::sleep_for(delay); + m_delaythread = thread([this]() { + this_thread::sleep_for(1s); notify_clients(); - }, move(delay)); + }); } /** @@ -722,7 +743,7 @@ void tray_manager::notify_clients_delayed(chrono::seconds delay) { * If it gets destroyed or goes away we can reactivate the tray_manager */ void tray_manager::track_selection_owner(xcb_window_t owner) { - if (owner) { + if (owner != XCB_NONE) { m_log.trace("tray: Listen for events on the new selection window"); const uint32_t mask{XCB_CW_EVENT_MASK}; const uint32_t values[]{XCB_EVENT_MASK_STRUCTURE_NOTIFY}; @@ -987,11 +1008,11 @@ void tray_manager::handle(const evt::selection_clear& evt) { try { m_log.warn("Lost systray selection, deactivating..."); - m_othermanager = m_connection.get_selection_owner(m_atom)->owner; + m_othermanager = m_connection.get_selection_owner(m_atom).owner(); track_selection_owner(m_othermanager); } catch (const exception& err) { m_log.err("Failed to get systray selection owner"); - m_othermanager = 0; + m_othermanager = XCB_NONE; } deactivate(false); @@ -1053,10 +1074,9 @@ void tray_manager::handle(const evt::reparent_notify& evt) { void tray_manager::handle(const evt::destroy_notify& evt) { if (m_activated && evt->window == m_tray) { deactivate(); - } else if (!m_activated && evt->window == m_othermanager && evt->window != m_tray) { - m_log.trace("tray: Received destroy_notify"); - // m_log.info("Tray selection available... re-activating"); - // activate(); + } else if (!m_activated && evt->window == m_othermanager) { + m_log.info("Tray selection available... re-activating"); + activate(); } else if (m_activated && is_embedded(evt->window)) { m_log.trace("tray: Received destroy_notify for client, remove..."); remove_client(evt->window);