tray: Cleanup client state handling
This commit is contained in:
parent
5fd62edfca
commit
63c6b13cbf
@ -40,6 +40,8 @@ class tray_client : public non_copyable_mixin {
|
|||||||
|
|
||||||
void hidden(bool state);
|
void hidden(bool state);
|
||||||
|
|
||||||
|
bool should_be_mapped() const;
|
||||||
|
|
||||||
xcb_window_t embedder() const;
|
xcb_window_t embedder() const;
|
||||||
xcb_window_t client() const;
|
xcb_window_t client() const;
|
||||||
|
|
||||||
@ -97,9 +99,14 @@ class tray_client : public non_copyable_mixin {
|
|||||||
*/
|
*/
|
||||||
xembed::info m_xembed;
|
xembed::info m_xembed;
|
||||||
|
|
||||||
// TODO
|
/**
|
||||||
|
* Whether the wrapper window is currently mapped.
|
||||||
|
*/
|
||||||
bool m_mapped{false};
|
bool m_mapped{false};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the
|
||||||
|
*/
|
||||||
bool m_hidden{false};
|
bool m_hidden{false};
|
||||||
|
|
||||||
size m_size;
|
size m_size;
|
||||||
|
@ -58,9 +58,9 @@ struct tray_settings {
|
|||||||
|
|
||||||
using on_update = std::function<void(void)>;
|
using on_update = std::function<void(void)>;
|
||||||
|
|
||||||
class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify, evt::client_message,
|
class tray_manager : public xpp::event::sink<evt::expose, evt::client_message, evt::configure_request,
|
||||||
evt::configure_request, evt::resize_request, evt::selection_clear, evt::property_notify,
|
evt::resize_request, evt::selection_clear, evt::property_notify, evt::reparent_notify,
|
||||||
evt::reparent_notify, evt::destroy_notify, evt::map_notify, evt::unmap_notify>,
|
evt::destroy_notify, evt::map_notify, evt::unmap_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:
|
||||||
@ -81,6 +81,8 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
|
|||||||
bool is_inactive() const;
|
bool is_inactive() const;
|
||||||
bool is_waiting() const;
|
bool is_waiting() const;
|
||||||
|
|
||||||
|
bool is_visible() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void reconfigure_window();
|
void reconfigure_window();
|
||||||
void reconfigure_clients();
|
void reconfigure_clients();
|
||||||
@ -115,12 +117,11 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
|
|||||||
|
|
||||||
bool is_embedded(const xcb_window_t& win);
|
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);
|
||||||
void remove_client(xcb_window_t win, bool reconfigure = true);
|
void remove_client(xcb_window_t win);
|
||||||
bool change_visibility(bool visible);
|
bool change_visibility(bool visible);
|
||||||
|
|
||||||
void handle(const evt::expose& evt) override;
|
void handle(const evt::expose& evt) override;
|
||||||
void handle(const evt::visibility_notify& evt) override;
|
|
||||||
void handle(const evt::client_message& evt) override;
|
void handle(const evt::client_message& evt) override;
|
||||||
void handle(const evt::configure_request& evt) override;
|
void handle(const evt::configure_request& evt) override;
|
||||||
void handle(const evt::resize_request& evt) override;
|
void handle(const evt::resize_request& evt) override;
|
||||||
|
@ -167,6 +167,21 @@ void tray_client::hidden(bool state) {
|
|||||||
m_hidden = state;
|
m_hidden = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the current state indicates the client should be mapped.
|
||||||
|
*/
|
||||||
|
bool tray_client::should_be_mapped() const {
|
||||||
|
if (m_hidden) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_xembed_supported()) {
|
||||||
|
return m_xembed.is_mapped();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
xcb_window_t tray_client::embedder() const {
|
xcb_window_t tray_client::embedder() const {
|
||||||
return m_wrapper;
|
return m_wrapper;
|
||||||
}
|
}
|
||||||
@ -209,22 +224,15 @@ void tray_client::add_to_save_set() const {
|
|||||||
* Make sure that the window mapping state is correct
|
* Make sure that the window mapping state is correct
|
||||||
*/
|
*/
|
||||||
void tray_client::ensure_state() const {
|
void tray_client::ensure_state() const {
|
||||||
bool should_be_mapped = true;
|
bool new_state = should_be_mapped();
|
||||||
|
|
||||||
if (is_xembed_supported()) {
|
if (new_state == m_mapped) {
|
||||||
should_be_mapped = m_xembed.is_mapped();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_hidden) {
|
m_log.trace("%s: ensure_state (hidden=%i, mapped=%i, should_be_mapped=%i)", name(), m_hidden, m_mapped, new_state);
|
||||||
should_be_mapped = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO can we stop here if should_be_mapped == m_mapped?
|
if (new_state) {
|
||||||
|
|
||||||
m_log.trace(
|
|
||||||
"%s: ensure_state (hidden=%i, mapped=%i, should_be_mapped=%i)", name(), m_hidden, m_mapped, should_be_mapped);
|
|
||||||
|
|
||||||
if (should_be_mapped) {
|
|
||||||
m_log.trace("%s: Map client", name());
|
m_log.trace("%s: Map client", name());
|
||||||
m_connection.map_window_checked(embedder());
|
m_connection.map_window_checked(embedder());
|
||||||
m_connection.map_window_checked(client());
|
m_connection.map_window_checked(client());
|
||||||
|
@ -115,6 +115,10 @@ bool tray_manager::is_waiting() const {
|
|||||||
return m_state == state::WAITING;
|
return m_state == state::WAITING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tray_manager::is_visible() const {
|
||||||
|
return is_active() && !m_hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activate systray management
|
* Activate systray management
|
||||||
*/
|
*/
|
||||||
@ -268,13 +272,13 @@ void tray_manager::reconfigure_clients() {
|
|||||||
for (auto it = m_clients.rbegin(); it != m_clients.rend(); it++) {
|
for (auto it = m_clients.rbegin(); it != m_clients.rend(); it++) {
|
||||||
try {
|
try {
|
||||||
it->ensure_state();
|
it->ensure_state();
|
||||||
|
// TODO skip if the client isn't mapped
|
||||||
it->reconfigure(x, calculate_client_y());
|
it->reconfigure(x, calculate_client_y());
|
||||||
|
|
||||||
x += m_opts.client_size.w + m_opts.spacing;
|
x += m_opts.client_size.w + m_opts.spacing;
|
||||||
} catch (const xpp::x::error::window& err) {
|
} catch (const xpp::x::error::window& err) {
|
||||||
// TODO print error
|
|
||||||
m_log.err("Failed to reconfigure %s, removing ... (%s)", it->name(), err.what());
|
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
|
* Refresh the bar window by clearing it along with each client window
|
||||||
*/
|
*/
|
||||||
void tray_manager::refresh_window() {
|
void tray_manager::refresh_window() {
|
||||||
// TODO create method that checks is_active and !m_hidden
|
if (!is_visible()) {
|
||||||
if (!is_active() || m_hidden) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,19 +505,19 @@ tray_client* tray_manager::find_client(const xcb_window_t& win) {
|
|||||||
/**
|
/**
|
||||||
* Remove tray client
|
* Remove tray client
|
||||||
*/
|
*/
|
||||||
void tray_manager::remove_client(const tray_client& client, bool reconfigure) {
|
void tray_manager::remove_client(const tray_client& client) {
|
||||||
remove_client(client.client(), reconfigure);
|
remove_client(client.client());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove tray client by window
|
* 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(
|
m_clients.erase(
|
||||||
std::remove_if(m_clients.begin(), m_clients.end(), [win](const auto& client) { return client.match(win); }));
|
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 (old_size != m_clients.size()) {
|
||||||
if (reconfigure) {
|
|
||||||
tray_manager::reconfigure();
|
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
|
* Event callback : XCB_CLIENT_MESSAGE
|
||||||
*/
|
*/
|
||||||
@ -669,14 +661,11 @@ void tray_manager::handle(const evt::property_notify& evt) {
|
|||||||
client->query_xembed();
|
client->query_xembed();
|
||||||
} catch (const xpp::x::error::window& err) {
|
} catch (const xpp::x::error::window& err) {
|
||||||
m_log.err("Failed to query _XEMBED_INFO, removing %s ... (%s)", client->name(), err.what());
|
m_log.err("Failed to query _XEMBED_INFO, removing %s ... (%s)", client->name(), err.what());
|
||||||
remove_client(*client, true);
|
remove_client(*client);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO only reconfigure if should_be_mapped changed
|
client->ensure_state();
|
||||||
if (client->get_xembed().is_mapped()) {
|
|
||||||
reconfigure();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -723,6 +712,12 @@ void tray_manager::handle(const evt::map_notify& evt) {
|
|||||||
redraw_window();
|
redraw_window();
|
||||||
} else if (is_embedded(evt->window)) {
|
} else if (is_embedded(evt->window)) {
|
||||||
auto client = find_client(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());
|
m_log.trace("%s: Received map_notify", client->name());
|
||||||
|
|
||||||
if (!client->mapped()) {
|
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) {
|
void tray_manager::handle(const evt::unmap_notify& evt) {
|
||||||
if (is_active() && is_embedded(evt->window)) {
|
if (is_active() && is_embedded(evt->window)) {
|
||||||
auto client = find_client(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());
|
m_log.trace("%s: Received unmap_notify", client->name());
|
||||||
|
|
||||||
if (client->mapped()) {
|
if (client->mapped()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user