fix(tray): Re-activation
This commit is contained in:
parent
8c3f40db5b
commit
b11a662d81
@ -96,7 +96,7 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
|
|||||||
|
|
||||||
void acquire_selection();
|
void acquire_selection();
|
||||||
void notify_clients();
|
void notify_clients();
|
||||||
void notify_clients_delayed(chrono::seconds delay = 1s);
|
void notify_clients_delayed();
|
||||||
|
|
||||||
void track_selection_owner(xcb_window_t owner);
|
void track_selection_owner(xcb_window_t owner);
|
||||||
void process_docking_request(xcb_window_t win);
|
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};
|
bool m_restacked{false};
|
||||||
|
|
||||||
std::mutex m_mtx;
|
std::mutex m_mtx;
|
||||||
|
|
||||||
|
chrono::time_point<chrono::system_clock, chrono::milliseconds> m_drawtime;
|
||||||
|
|
||||||
|
bool m_firstactivation{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -26,7 +26,7 @@ config::make_type config::make(string path, string bar) {
|
|||||||
* Construct config object
|
* Construct config object
|
||||||
*/
|
*/
|
||||||
config::config(const logger& logger, const xresource_manager& xrm, string&& path, string&& bar)
|
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)) {
|
if (!file_util::exists(m_file)) {
|
||||||
throw application_error("Could not find config file: " + 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
|
* Parse key/value pairs from the configuration file
|
||||||
*/
|
*/
|
||||||
void config::parse_file() {
|
void config::parse_file() {
|
||||||
std::ifstream in(m_file.c_str());
|
std::ifstream in(m_file);
|
||||||
string line;
|
string line;
|
||||||
string section;
|
string section;
|
||||||
uint32_t lineno{0};
|
uint32_t lineno{0};
|
||||||
@ -117,8 +117,7 @@ void config::parse_file() {
|
|||||||
line.erase(0, equal_pos + 1);
|
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));
|
m_sections[section].emplace_hint(it, move(key), move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,10 +120,8 @@ void eventloop::stop() {
|
|||||||
* Enqueue event
|
* Enqueue event
|
||||||
*/
|
*/
|
||||||
bool eventloop::enqueue(event&& evt) {
|
bool eventloop::enqueue(event&& evt) {
|
||||||
uint8_t type{static_cast<uint8_t>(evt.type)};
|
|
||||||
|
|
||||||
if (!m_queue.enqueue(move(evt))) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,30 +122,37 @@ namespace string_util {
|
|||||||
/**
|
/**
|
||||||
* Remove needle from the start of the string
|
* Remove needle from the start of the string
|
||||||
*/
|
*/
|
||||||
string ltrim(string&& haystack, const char& needle) {
|
string ltrim(string&& value, const char& needle) {
|
||||||
string str(haystack);
|
if (value.empty()) {
|
||||||
while (str[0] == needle) {
|
return "";
|
||||||
str.erase(0, 1);
|
|
||||||
}
|
}
|
||||||
return str;
|
while (*value.begin() == needle) {
|
||||||
|
value.erase(0, 1);
|
||||||
|
}
|
||||||
|
return forward<string>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove needle from the end of the string
|
* Remove needle from the end of the string
|
||||||
*/
|
*/
|
||||||
string rtrim(string&& haystack, const char& needle) {
|
string rtrim(string&& value, const char& needle) {
|
||||||
string str(haystack);
|
if (value.empty()) {
|
||||||
while (str[str.length() - 1] == needle) {
|
return "";
|
||||||
str.erase(str.length() - 1, 1);
|
|
||||||
}
|
}
|
||||||
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
|
* Remove needle from the start and end of the string
|
||||||
*/
|
*/
|
||||||
string trim(string&& value, const char& needle) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,12 +51,15 @@ tray_manager::make_type tray_manager::make() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tray_manager::tray_manager(connection& conn, signal_emitter& emitter, const logger& logger)
|
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() {
|
tray_manager::~tray_manager() {
|
||||||
if (m_delaythread.joinable()) {
|
if (m_delaythread.joinable()) {
|
||||||
m_delaythread.join();
|
m_delaythread.join();
|
||||||
}
|
}
|
||||||
|
m_connection.detach_sink(this, SINK_PRIORITY_TRAY);
|
||||||
deactivate();
|
deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +201,6 @@ void tray_manager::activate() {
|
|||||||
m_opts.running = true;
|
m_opts.running = true;
|
||||||
|
|
||||||
m_sig.attach(this);
|
m_sig.attach(this);
|
||||||
m_connection.attach_sink(this, SINK_PRIORITY_TRAY);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
create_window();
|
create_window();
|
||||||
@ -221,13 +223,16 @@ void tray_manager::activate() {
|
|||||||
// notify clients waiting for a manager.
|
// notify clients waiting for a manager.
|
||||||
acquire_selection();
|
acquire_selection();
|
||||||
|
|
||||||
// Notify pending tray clients
|
|
||||||
notify_clients();
|
|
||||||
|
|
||||||
// Send delayed notification
|
// Send delayed notification
|
||||||
if (m_othermanager != XCB_NONE && m_othermanager != m_tray) {
|
if (!m_firstactivation) {
|
||||||
notify_clients_delayed();
|
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_opts.running = false;
|
||||||
|
|
||||||
m_sig.detach(this);
|
m_sig.detach(this);
|
||||||
m_connection.detach_sink(this, SINK_PRIORITY_TRAY);
|
|
||||||
|
|
||||||
if (!m_connection.connection_has_error() && clear_selection && m_acquired_selection) {
|
if (!m_connection.connection_has_error() && clear_selection && m_acquired_selection) {
|
||||||
m_log.trace("tray: Unset selection owner");
|
m_log.trace("tray: Unset selection owner");
|
||||||
@ -506,7 +510,15 @@ void tray_manager::refresh_window() {
|
|||||||
* Redraw window
|
* Redraw window
|
||||||
*/
|
*/
|
||||||
void tray_manager::redraw_window(bool realloc_bg) {
|
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);
|
reconfigure_bg(realloc_bg);
|
||||||
refresh_window();
|
refresh_window();
|
||||||
}
|
}
|
||||||
@ -669,14 +681,26 @@ void tray_manager::set_tray_colors() {
|
|||||||
* Acquire the systray selection
|
* Acquire the systray selection
|
||||||
*/
|
*/
|
||||||
void tray_manager::acquire_selection() {
|
void tray_manager::acquire_selection() {
|
||||||
auto reply = m_connection.get_selection_owner_unchecked(m_atom);
|
m_othermanager = XCB_NONE;
|
||||||
auto owner = reply.owner<xcb_window_t>();
|
;
|
||||||
|
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) {
|
if (owner == m_tray) {
|
||||||
m_log.info("tray: Already managing the systray selection");
|
m_log.trace("tray: Already managing the systray selection");
|
||||||
} else if ((m_othermanager = owner) != XCB_NONE) {
|
m_acquired_selection = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_othermanager = owner) != XCB_NONE) {
|
||||||
m_log.info("Replacing selection manager %s", m_connection.id(owner));
|
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_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);
|
m_connection.set_selection_owner_checked(m_tray, m_atom, XCB_CURRENT_TIME);
|
||||||
|
|
||||||
@ -684,8 +708,7 @@ void tray_manager::acquire_selection() {
|
|||||||
throw application_error("Failed to get control of the systray selection");
|
throw application_error("Failed to get control of the systray selection");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_acquired_selection = false;
|
m_acquired_selection = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -705,16 +728,14 @@ void tray_manager::notify_clients() {
|
|||||||
/**
|
/**
|
||||||
* Send delayed notification to pending clients
|
* Send delayed notification to pending clients
|
||||||
*/
|
*/
|
||||||
void tray_manager::notify_clients_delayed(chrono::seconds delay) {
|
void tray_manager::notify_clients_delayed() {
|
||||||
if (!m_activated) {
|
if (m_delaythread.joinable()) {
|
||||||
return;
|
|
||||||
} else if (m_delaythread.joinable()) {
|
|
||||||
m_delaythread.join();
|
m_delaythread.join();
|
||||||
}
|
}
|
||||||
m_delaythread = thread([this](auto&& delay) {
|
m_delaythread = thread([this]() {
|
||||||
this_thread::sleep_for(delay);
|
this_thread::sleep_for(1s);
|
||||||
notify_clients();
|
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
|
* If it gets destroyed or goes away we can reactivate the tray_manager
|
||||||
*/
|
*/
|
||||||
void tray_manager::track_selection_owner(xcb_window_t owner) {
|
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");
|
m_log.trace("tray: Listen for events on the new selection window");
|
||||||
const uint32_t mask{XCB_CW_EVENT_MASK};
|
const uint32_t mask{XCB_CW_EVENT_MASK};
|
||||||
const uint32_t values[]{XCB_EVENT_MASK_STRUCTURE_NOTIFY};
|
const uint32_t values[]{XCB_EVENT_MASK_STRUCTURE_NOTIFY};
|
||||||
@ -987,11 +1008,11 @@ void tray_manager::handle(const evt::selection_clear& evt) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
m_log.warn("Lost systray selection, deactivating...");
|
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);
|
track_selection_owner(m_othermanager);
|
||||||
} catch (const exception& err) {
|
} catch (const exception& err) {
|
||||||
m_log.err("Failed to get systray selection owner");
|
m_log.err("Failed to get systray selection owner");
|
||||||
m_othermanager = 0;
|
m_othermanager = XCB_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
deactivate(false);
|
deactivate(false);
|
||||||
@ -1053,10 +1074,9 @@ void tray_manager::handle(const evt::reparent_notify& evt) {
|
|||||||
void tray_manager::handle(const evt::destroy_notify& evt) {
|
void tray_manager::handle(const evt::destroy_notify& evt) {
|
||||||
if (m_activated && evt->window == m_tray) {
|
if (m_activated && evt->window == m_tray) {
|
||||||
deactivate();
|
deactivate();
|
||||||
} else if (!m_activated && evt->window == m_othermanager && evt->window != m_tray) {
|
} else if (!m_activated && evt->window == m_othermanager) {
|
||||||
m_log.trace("tray: Received destroy_notify");
|
m_log.info("Tray selection available... re-activating");
|
||||||
// m_log.info("Tray selection available... 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.trace("tray: Received destroy_notify for client, remove...");
|
||||||
remove_client(evt->window);
|
remove_client(evt->window);
|
||||||
|
Loading…
Reference in New Issue
Block a user