tray: Store clients in unique_ptr
This commit is contained in:
parent
0c223ae2bb
commit
5c38d5cb17
@ -17,14 +17,11 @@ POLYBAR_NS
|
|||||||
// fwd declarations
|
// fwd declarations
|
||||||
class connection;
|
class connection;
|
||||||
|
|
||||||
class tray_client : public non_copyable_mixin {
|
class tray_client : public non_copyable_mixin, public non_movable_mixin {
|
||||||
public:
|
public:
|
||||||
explicit tray_client(const logger& log, connection& conn, xcb_window_t tray, xcb_window_t win, size s);
|
explicit tray_client(const logger& log, connection& conn, xcb_window_t tray, xcb_window_t win, size s);
|
||||||
~tray_client();
|
~tray_client();
|
||||||
|
|
||||||
tray_client(tray_client&&);
|
|
||||||
tray_client& operator=(tray_client&&);
|
|
||||||
|
|
||||||
string name() const;
|
string name() const;
|
||||||
|
|
||||||
unsigned int width() const;
|
unsigned int width() const;
|
||||||
|
@ -120,6 +120,7 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::client_message, e
|
|||||||
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);
|
void remove_client(const tray_client& client);
|
||||||
void remove_client(xcb_window_t win);
|
void remove_client(xcb_window_t win);
|
||||||
|
void clean_clients();
|
||||||
bool change_visibility(bool visible);
|
bool change_visibility(bool visible);
|
||||||
|
|
||||||
void handle(const evt::expose& evt) override;
|
void handle(const evt::expose& evt) override;
|
||||||
@ -141,7 +142,7 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::client_message, e
|
|||||||
connection& m_connection;
|
connection& m_connection;
|
||||||
signal_emitter& m_sig;
|
signal_emitter& m_sig;
|
||||||
const logger& m_log;
|
const logger& m_log;
|
||||||
vector<tray_client> m_clients;
|
vector<unique_ptr<tray_client>> m_clients;
|
||||||
|
|
||||||
tray_settings m_opts{};
|
tray_settings m_opts{};
|
||||||
const bar_settings& m_bar_opts;
|
const bar_settings& m_bar_opts;
|
||||||
|
@ -840,6 +840,7 @@ void bar::handle(const evt::button_press& evt) {
|
|||||||
*/
|
*/
|
||||||
void bar::handle(const evt::expose& evt) {
|
void bar::handle(const evt::expose& evt) {
|
||||||
if (evt->window == m_opts.x_data.window && evt->count == 0) {
|
if (evt->window == m_opts.x_data.window && evt->count == 0) {
|
||||||
|
// TODO
|
||||||
// if (m_tray->running()) {
|
// if (m_tray->running()) {
|
||||||
// broadcast_visibility();
|
// broadcast_visibility();
|
||||||
// }
|
// }
|
||||||
|
@ -69,31 +69,6 @@ tray_client::~tray_client() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tray_client::tray_client(tray_client&& c) : m_log(c.m_log), m_connection(c.m_connection) {
|
|
||||||
std::swap(m_name, c.m_name);
|
|
||||||
std::swap(m_wrapper, c.m_wrapper);
|
|
||||||
std::swap(m_client, c.m_client);
|
|
||||||
std::swap(m_xembed_supported, c.m_xembed_supported);
|
|
||||||
std::swap(m_xembed, c.m_xembed);
|
|
||||||
std::swap(m_mapped, c.m_mapped);
|
|
||||||
std::swap(m_hidden, c.m_hidden);
|
|
||||||
std::swap(m_size, c.m_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
tray_client& tray_client::operator=(tray_client&& c) {
|
|
||||||
m_log = c.m_log;
|
|
||||||
m_connection = c.m_connection;
|
|
||||||
std::swap(m_name, c.m_name);
|
|
||||||
std::swap(m_wrapper, c.m_wrapper);
|
|
||||||
std::swap(m_client, c.m_client);
|
|
||||||
std::swap(m_xembed_supported, c.m_xembed_supported);
|
|
||||||
std::swap(m_xembed, c.m_xembed);
|
|
||||||
std::swap(m_mapped, c.m_mapped);
|
|
||||||
std::swap(m_hidden, c.m_hidden);
|
|
||||||
std::swap(m_size, c.m_size);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
string tray_client::name() const {
|
string tray_client::name() const {
|
||||||
return "tray_client(" + m_connection.id(m_client) + ", " + m_name + ")";
|
return "tray_client(" + m_connection.id(m_client) + ", " + m_name + ")";
|
||||||
}
|
}
|
||||||
|
@ -270,18 +270,27 @@ void tray_manager::reconfigure_clients() {
|
|||||||
|
|
||||||
int x = calculate_x() + m_opts.spacing;
|
int x = calculate_x() + m_opts.spacing;
|
||||||
|
|
||||||
for (auto it = m_clients.rbegin(); it != m_clients.rend(); it++) {
|
bool has_error = false;
|
||||||
|
|
||||||
|
for (auto& client : m_clients) {
|
||||||
try {
|
try {
|
||||||
it->ensure_state();
|
client->ensure_state();
|
||||||
// TODO skip if the client isn't mapped
|
|
||||||
it->reconfigure(x, calculate_client_y());
|
if (client->mapped()) {
|
||||||
|
client->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) {
|
||||||
m_log.err("Failed to reconfigure %s, removing ... (%s)", it->name(), err.what());
|
m_log.err("Failed to reconfigure %s, removing ... (%s)", client->name(), err.what());
|
||||||
remove_client(*it);
|
client.reset();
|
||||||
|
has_error = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_error) {
|
||||||
|
clean_clients();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -296,11 +305,11 @@ void tray_manager::refresh_window() {
|
|||||||
|
|
||||||
for (auto& client : m_clients) {
|
for (auto& client : m_clients) {
|
||||||
try {
|
try {
|
||||||
if (client.mapped()) {
|
if (client->mapped()) {
|
||||||
client.clear_window();
|
client->clear_window();
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
m_log.err("tray: Failed to clear %s (%s)", client.name(), e.what());
|
m_log.err("tray: Failed to clear %s (%s)", client->name(), e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,24 +443,24 @@ void tray_manager::process_docking_request(xcb_window_t win) {
|
|||||||
m_log.info("tray: Processing docking request from '%s' (%s)", ewmh_util::get_wm_name(win), m_connection.id(win));
|
m_log.info("tray: Processing docking request from '%s' (%s)", ewmh_util::get_wm_name(win), m_connection.id(win));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tray_client client(m_log, m_connection, m_opts.selection_owner, win, m_opts.client_size);
|
auto client = make_unique<tray_client>(m_log, m_connection, m_opts.selection_owner, win, m_opts.client_size);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
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());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
client.update_client_attributes();
|
client->update_client_attributes();
|
||||||
|
|
||||||
client.reparent();
|
client->reparent();
|
||||||
|
|
||||||
client.add_to_save_set();
|
client->add_to_save_set();
|
||||||
|
|
||||||
client.notify_xembed();
|
client->notify_xembed();
|
||||||
|
|
||||||
client.ensure_state();
|
client->ensure_state();
|
||||||
|
|
||||||
m_clients.emplace_back(std::move(client));
|
m_clients.emplace_back(std::move(client));
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
@ -475,7 +484,7 @@ unsigned tray_manager::calculate_w() const {
|
|||||||
unsigned width = m_opts.spacing;
|
unsigned width = m_opts.spacing;
|
||||||
unsigned count{0};
|
unsigned count{0};
|
||||||
for (auto& client : m_clients) {
|
for (auto& client : m_clients) {
|
||||||
if (client.mapped()) {
|
if (client->mapped()) {
|
||||||
count++;
|
count++;
|
||||||
width += m_opts.spacing + m_opts.client_size.w;
|
width += m_opts.spacing + m_opts.client_size.w;
|
||||||
}
|
}
|
||||||
@ -504,12 +513,12 @@ bool tray_manager::is_embedded(const xcb_window_t& win) {
|
|||||||
*/
|
*/
|
||||||
tray_client* tray_manager::find_client(const xcb_window_t& win) {
|
tray_client* tray_manager::find_client(const xcb_window_t& win) {
|
||||||
auto client = std::find_if(m_clients.begin(), m_clients.end(),
|
auto client = std::find_if(m_clients.begin(), m_clients.end(),
|
||||||
[win](const auto& client) { return client.match(win) || client.embedder() == win; });
|
[win](const auto& client) { return client->match(win) || client->embedder() == win; });
|
||||||
|
|
||||||
if (client == m_clients.end()) {
|
if (client == m_clients.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
return &(*client);
|
return client->get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,13 +535,25 @@ void tray_manager::remove_client(const tray_client& client) {
|
|||||||
void tray_manager::remove_client(xcb_window_t win) {
|
void tray_manager::remove_client(xcb_window_t win) {
|
||||||
auto old_size = m_clients.size();
|
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); }));
|
||||||
|
|
||||||
if (old_size != m_clients.size()) {
|
if (old_size != m_clients.size()) {
|
||||||
tray_manager::reconfigure();
|
tray_manager::reconfigure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all null pointers from client list.
|
||||||
|
*
|
||||||
|
* Removing clients is often done in two steps:
|
||||||
|
* 1. When removing a client during iteration, the unique_ptr is reset.
|
||||||
|
* 2. Afterwards all null pointers are removed from the list.
|
||||||
|
*/
|
||||||
|
void tray_manager::clean_clients() {
|
||||||
|
m_clients.erase(
|
||||||
|
std::remove_if(m_clients.begin(), m_clients.end(), [](const auto& client) { return client.get() == nullptr; }));
|
||||||
|
}
|
||||||
|
|
||||||
bool tray_manager::change_visibility(bool visible) {
|
bool tray_manager::change_visibility(bool visible) {
|
||||||
if (!is_active() || m_hidden == !visible) {
|
if (!is_active() || m_hidden == !visible) {
|
||||||
return false;
|
return false;
|
||||||
@ -543,8 +564,8 @@ bool tray_manager::change_visibility(bool visible) {
|
|||||||
m_hidden = !visible;
|
m_hidden = !visible;
|
||||||
|
|
||||||
for (auto& client : m_clients) {
|
for (auto& client : m_clients) {
|
||||||
client.hidden(m_hidden);
|
client->hidden(m_hidden);
|
||||||
client.ensure_state();
|
client->ensure_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_hidden) {
|
if (!m_hidden) {
|
||||||
|
Loading…
Reference in New Issue
Block a user