fix(tray): Re-activation

This commit is contained in:
Michael Carlberg 2016-12-14 11:34:09 +01:00
parent 8c3f40db5b
commit b11a662d81
5 changed files with 83 additions and 55 deletions

View File

@ -96,7 +96,7 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
void acquire_selection();
void notify_clients();
void notify_clients_delayed(chrono::seconds delay = 1s);
void notify_clients_delayed();
void track_selection_owner(xcb_window_t owner);
void process_docking_request(xcb_window_t win);
@ -157,6 +157,10 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
bool m_restacked{false};
std::mutex m_mtx;
chrono::time_point<chrono::system_clock, chrono::milliseconds> m_drawtime;
bool m_firstactivation{true};
};
POLYBAR_NS_END

View File

@ -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<decltype(path)>(path)), m_barname(forward<decltype(bar)>(bar)) {
: m_logger(logger), m_xrm(xrm), m_file(forward<string>(path)), m_barname(forward<string>(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>(string_util::trim(move(line), ' ')), '"')};
m_sections[section].emplace_hint(it, move(key), move(value));
}

View File

@ -120,10 +120,8 @@ void eventloop::stop() {
* Enqueue event
*/
bool eventloop::enqueue(event&& evt) {
uint8_t type{static_cast<uint8_t>(evt.type)};
if (!m_queue.enqueue(move(evt))) {
m_log.warn("Failed to enqueue event (%d)", static_cast<uint8_t>(type));
m_log.warn("Failed to enqueue event");
return false;
}

View File

@ -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<string>(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<string>(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<string>(value), needle), needle);
}
/**

View File

@ -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<chrono::milliseconds>(now);
m_log.info("Redraw tray container (id=%s) %lu", m_connection.id(m_tray),
chrono::duration_cast<chrono::microseconds>(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<xcb_window_t>();
m_othermanager = XCB_NONE;
;
xcb_window_t owner;
try {
owner = m_connection.get_selection_owner(m_atom).owner<xcb_window_t>();
} 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<xcb_window_t>();
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);