tray: Cleanup

This commit is contained in:
patrick96 2022-10-31 23:21:00 +01:00
parent ca25b5685c
commit f5d16891dd
No known key found for this signature in database
GPG Key ID: 521E5E03AEBCA1A7
7 changed files with 287 additions and 270 deletions

View File

@ -22,7 +22,7 @@ namespace modules {
private: private:
static constexpr const char* TAG_TRAY{"<tray>"}; static constexpr const char* TAG_TRAY{"<tray>"};
tray_manager m_tray; tray::manager m_tray;
}; };
} // namespace modules } // namespace modules
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -20,11 +20,13 @@ POLYBAR_NS
// fwd declarations // fwd declarations
class connection; class connection;
class tray_client : public non_copyable_mixin, public non_movable_mixin { namespace tray {
class client : public non_copyable_mixin, public non_movable_mixin {
public: public:
explicit tray_client( explicit client(
const logger& log, connection& conn, xcb_window_t parent, xcb_window_t win, size s, uint32_t desired_background); const logger& log, connection& conn, xcb_window_t parent, xcb_window_t win, size s, uint32_t desired_background);
~tray_client(); ~client();
string name() const; string name() const;
@ -44,7 +46,7 @@ class tray_client : public non_copyable_mixin, public non_movable_mixin {
bool should_be_mapped() const; bool should_be_mapped() const;
xcb_window_t embedder() const; xcb_window_t embedder() const;
xcb_window_t client() const; xcb_window_t client_window() const;
void query_xembed(); void query_xembed();
bool is_xembed_supported() const; bool is_xembed_supported() const;
@ -63,7 +65,6 @@ class tray_client : public non_copyable_mixin, public non_movable_mixin {
protected: protected:
void observe_background(); void observe_background();
protected:
const logger& m_log; const logger& m_log;
connection& m_connection; connection& m_connection;
@ -103,7 +104,7 @@ class tray_client : public non_copyable_mixin, public non_movable_mixin {
* *
* Only valid if m_xembed_supported == true * Only valid if m_xembed_supported == true
*/ */
xembed::info m_xembed; xembed::info m_xembed{};
/** /**
* Whether the wrapper window is currently mapped. * Whether the wrapper window is currently mapped.
@ -125,4 +126,6 @@ class tray_client : public non_copyable_mixin, public non_movable_mixin {
unique_ptr<cairo::xcb_surface> m_surface; unique_ptr<cairo::xcb_surface> m_surface;
}; };
} // namespace tray
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -25,14 +25,16 @@
POLYBAR_NS POLYBAR_NS
namespace chrono = std::chrono;
using namespace std::chrono_literals;
using std::atomic;
// fwd declarations // fwd declarations
class connection; class connection;
class bg_slice; class bg_slice;
namespace tray {
namespace chrono = std::chrono;
using namespace std::chrono_literals;
using std::atomic;
struct tray_settings { struct tray_settings {
/** /**
* Dimensions for client windows. * Dimensions for client windows.
@ -56,16 +58,16 @@ 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::client_message, evt::configure_request, class manager : public xpp::event::sink<evt::expose, evt::client_message, evt::configure_request, evt::resize_request,
evt::resize_request, evt::selection_clear, evt::property_notify, evt::reparent_notify, evt::selection_clear, evt::property_notify, evt::reparent_notify, evt::destroy_notify,
evt::destroy_notify, evt::map_notify, evt::unmap_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:
explicit tray_manager(connection& conn, signal_emitter& emitter, const logger& logger, const bar_settings& bar_opts, explicit manager(connection& conn, signal_emitter& emitter, const logger& logger, const bar_settings& bar_opts,
on_update on_update); on_update on_update);
~tray_manager(); ~manager() override;
unsigned get_width() const; unsigned get_width() const;
@ -115,8 +117,8 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::client_message, e
void update_width(); void update_width();
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); client* find_client(const xcb_window_t& win);
void remove_client(const tray_client& client); void remove_client(const client& client);
void remove_client(xcb_window_t win); void remove_client(xcb_window_t win);
void clean_clients(); void clean_clients();
bool change_visibility(bool visible); bool change_visibility(bool visible);
@ -140,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<unique_ptr<tray_client>> m_clients; vector<unique_ptr<client>> m_clients;
tray_settings m_opts{}; tray_settings m_opts{};
const bar_settings& m_bar_opts; const bar_settings& m_bar_opts;
@ -200,4 +202,6 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::client_message, e
bool m_firstactivation{true}; bool m_firstactivation{true};
}; };
} // namespace tray
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -35,7 +35,7 @@ namespace xembed {
class info { class info {
public: public:
void set(uint32_t* data); void set(const uint32_t* data);
uint32_t get_version() const; uint32_t get_version() const;
uint32_t get_flags() const; uint32_t get_flags() const;

View File

@ -11,6 +11,8 @@
POLYBAR_NS POLYBAR_NS
namespace tray {
/* /*
* TODO proper background of wrapper window * TODO proper background of wrapper window
* *
@ -20,7 +22,7 @@ POLYBAR_NS
* 2. Use pseudo-transparency when activated (make sure the depths match) * 2. Use pseudo-transparency when activated (make sure the depths match)
* 3. Use background color * 3. Use background color
*/ */
tray_client::tray_client( client::client(
const logger& log, connection& conn, xcb_window_t parent, xcb_window_t win, size s, uint32_t desired_background) const logger& log, connection& conn, xcb_window_t parent, xcb_window_t win, size s, uint32_t desired_background)
: m_log(log) : m_log(log)
, m_connection(conn) , m_connection(conn)
@ -88,7 +90,7 @@ tray_client::tray_client(
xcb_params_gc_t params{}; xcb_params_gc_t params{};
uint32_t mask = 0; uint32_t mask = 0;
XCB_AUX_ADD_PARAM(&mask, &params, graphics_exposures, 1); XCB_AUX_ADD_PARAM(&mask, &params, graphics_exposures, 1);
std::array<uint32_t, 32> values; std::array<uint32_t, 32> values{};
connection::pack_values(mask, &params, values); connection::pack_values(mask, &params, values);
m_connection.create_gc_checked(gc, pixmap, mask, values.data()); m_connection.create_gc_checked(gc, pixmap, mask, values.data());
} catch (const std::exception& err) { } catch (const std::exception& err) {
@ -108,7 +110,7 @@ tray_client::tray_client(
observe_background(); observe_background();
} }
tray_client::~tray_client() { client::~client() {
if (m_client != XCB_NONE) { if (m_client != XCB_NONE) {
xembed::unembed(m_connection, m_client, m_connection.root()); xembed::unembed(m_connection, m_client, m_connection.root());
} }
@ -118,19 +120,19 @@ tray_client::~tray_client() {
} }
} }
string tray_client::name() const { string client::name() const {
return "tray_client(" + m_connection.id(m_client) + ", " + m_name + ")"; return "client(" + m_connection.id(m_client) + ", " + m_name + ")";
} }
unsigned int tray_client::width() const { unsigned int client::width() const {
return m_size.w; return m_size.w;
} }
unsigned int tray_client::height() const { unsigned int client::height() const {
return m_size.h; return m_size.h;
} }
void tray_client::clear_window() const { void client::clear_window() const {
if (!mapped()) { if (!mapped()) {
return; return;
} }
@ -141,19 +143,20 @@ void tray_client::clear_window() const {
auto send_visibility = [&](uint8_t state) { auto send_visibility = [&](uint8_t state) {
xcb_visibility_notify_event_t evt{}; xcb_visibility_notify_event_t evt{};
evt.response_type = XCB_VISIBILITY_NOTIFY; evt.response_type = XCB_VISIBILITY_NOTIFY;
evt.window = client(); evt.window = client_window();
evt.state = state; evt.state = state;
m_connection.send_event_checked(true, client(), XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char*>(&evt)); m_connection.send_event_checked(
true, client_window(), XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char*>(&evt));
}; };
send_visibility(XCB_VISIBILITY_FULLY_OBSCURED); send_visibility(XCB_VISIBILITY_FULLY_OBSCURED);
send_visibility(XCB_VISIBILITY_UNOBSCURED); send_visibility(XCB_VISIBILITY_UNOBSCURED);
m_connection.clear_area_checked(1, client(), 0, 0, width(), height()); m_connection.clear_area_checked(1, client_window(), 0, 0, width(), height());
} }
void tray_client::update_client_attributes() const { void client::update_client_attributes() const {
uint32_t configure_mask = 0; uint32_t configure_mask = 0;
std::array<uint32_t, 32> configure_values{}; std::array<uint32_t, 32> configure_values{};
xcb_params_cw_t configure_params{}; xcb_params_cw_t configure_params{};
@ -164,32 +167,32 @@ void tray_client::update_client_attributes() const {
connection::pack_values(configure_mask, &configure_params, configure_values); connection::pack_values(configure_mask, &configure_params, configure_values);
m_log.trace("%s: Update client window", name()); m_log.trace("%s: Update client window", name());
m_connection.change_window_attributes_checked(client(), configure_mask, configure_values.data()); m_connection.change_window_attributes_checked(client_window(), configure_mask, configure_values.data());
} }
void tray_client::reparent() const { void client::reparent() const {
m_log.trace("%s: Reparent client", name()); m_log.trace("%s: Reparent client", name());
m_connection.reparent_window_checked(client(), embedder(), 0, 0); m_connection.reparent_window_checked(client_window(), embedder(), 0, 0);
} }
/** /**
* Is this the client for the given client window * Is this the client for the given client window
*/ */
bool tray_client::match(const xcb_window_t& win) const { bool client::match(const xcb_window_t& win) const {
return win == m_client; return win == m_client;
} }
/** /**
* Get client window mapped state * Get client window mapped state
*/ */
bool tray_client::mapped() const { bool client::mapped() const {
return m_mapped; return m_mapped;
} }
/** /**
* Set client window mapped state * Set client window mapped state
*/ */
void tray_client::mapped(bool state) { void client::mapped(bool state) {
if (m_mapped != state) { if (m_mapped != state) {
m_log.trace("%s: set mapped: %i", name(), state); m_log.trace("%s: set mapped: %i", name(), state);
m_mapped = state; m_mapped = state;
@ -201,14 +204,14 @@ void tray_client::mapped(bool state) {
* *
* Use this to trigger a mapping/unmapping * Use this to trigger a mapping/unmapping
*/ */
void tray_client::hidden(bool state) { void client::hidden(bool state) {
m_hidden = state; m_hidden = state;
} }
/** /**
* Whether the current state indicates the client should be mapped. * Whether the current state indicates the client should be mapped.
*/ */
bool tray_client::should_be_mapped() const { bool client::should_be_mapped() const {
if (m_hidden) { if (m_hidden) {
return false; return false;
} }
@ -220,15 +223,15 @@ bool tray_client::should_be_mapped() const {
return true; return true;
} }
xcb_window_t tray_client::embedder() const { xcb_window_t client::embedder() const {
return m_wrapper; return m_wrapper;
} }
xcb_window_t tray_client::client() const { xcb_window_t client::client_window() const {
return m_client; return m_client;
} }
void tray_client::query_xembed() { void client::query_xembed() {
m_xembed_supported = xembed::query(m_connection, m_client, m_xembed); m_xembed_supported = xembed::query(m_connection, m_client, m_xembed);
if (is_xembed_supported()) { if (is_xembed_supported()) {
@ -238,30 +241,30 @@ void tray_client::query_xembed() {
} }
} }
bool tray_client::is_xembed_supported() const { bool client::is_xembed_supported() const {
return m_xembed_supported; return m_xembed_supported;
} }
const xembed::info& tray_client::get_xembed() const { const xembed::info& client::get_xembed() const {
return m_xembed; return m_xembed;
} }
void tray_client::notify_xembed() const { void client::notify_xembed() const {
if (is_xembed_supported()) { if (is_xembed_supported()) {
m_log.trace("%s: Send embedded notification to client", name()); m_log.trace("%s: Send embedded notification to client", name());
xembed::notify_embedded(m_connection, client(), embedder(), m_xembed.get_version()); xembed::notify_embedded(m_connection, client_window(), embedder(), m_xembed.get_version());
} }
} }
void tray_client::add_to_save_set() const { void client::add_to_save_set() const {
m_log.trace("%s: Add client window to the save set", name()); m_log.trace("%s: Add client window to the save set", name());
m_connection.change_save_set_checked(XCB_SET_MODE_INSERT, client()); m_connection.change_save_set_checked(XCB_SET_MODE_INSERT, client_window());
} }
/** /**
* 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 client::ensure_state() const {
bool new_state = should_be_mapped(); bool new_state = should_be_mapped();
if (new_state == m_mapped) { if (new_state == m_mapped) {
@ -273,10 +276,10 @@ void tray_client::ensure_state() const {
if (new_state) { if (new_state) {
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_window());
} else { } else {
m_log.trace("%s: Unmap client", name()); m_log.trace("%s: Unmap client", name());
m_connection.unmap_window_checked(client()); m_connection.unmap_window_checked(client_window());
m_connection.unmap_window_checked(embedder()); m_connection.unmap_window_checked(embedder());
} }
} }
@ -284,7 +287,7 @@ void tray_client::ensure_state() const {
/** /**
* Configure window position * Configure window position
*/ */
void tray_client::set_position(int x, int y) { void client::set_position(int x, int y) {
m_log.trace("%s: moving to (%d, %d)", name(), x, y); m_log.trace("%s: moving to (%d, %d)", name(), x, y);
position new_pos{x, y}; position new_pos{x, y};
@ -312,12 +315,12 @@ void tray_client::set_position(int x, int y) {
XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, x, 0); XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, x, 0);
XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, y, 0); XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, y, 0);
connection::pack_values(configure_mask, &configure_params, configure_values); connection::pack_values(configure_mask, &configure_params, configure_values);
m_connection.configure_window_checked(client(), configure_mask, configure_values.data()); m_connection.configure_window_checked(client_window(), configure_mask, configure_values.data());
// TODO // TODO
xcb_size_hints_t size_hints{}; xcb_size_hints_t size_hints{};
xcb_icccm_size_hints_set_size(&size_hints, false, m_size.w, m_size.h); xcb_icccm_size_hints_set_size(&size_hints, false, m_size.w, m_size.h);
xcb_icccm_set_wm_size_hints(m_connection, client(), XCB_ATOM_WM_NORMAL_HINTS, &size_hints); xcb_icccm_set_wm_size_hints(m_connection, client_window(), XCB_ATOM_WM_NORMAL_HINTS, &size_hints);
// The position has changed, we need a new background slice. // The position has changed, we need a new background slice.
observe_background(); observe_background();
@ -326,11 +329,11 @@ void tray_client::set_position(int x, int y) {
/** /**
* Respond to client resize/move requests * Respond to client resize/move requests
*/ */
void tray_client::configure_notify() const { void client::configure_notify() const {
xcb_configure_notify_event_t notify; xcb_configure_notify_event_t notify;
notify.response_type = XCB_CONFIGURE_NOTIFY; notify.response_type = XCB_CONFIGURE_NOTIFY;
notify.event = client(); notify.event = client_window();
notify.window = client(); notify.window = client_window();
notify.override_redirect = false; notify.override_redirect = false;
notify.above_sibling = 0; notify.above_sibling = 0;
notify.x = 0; notify.x = 0;
@ -340,13 +343,13 @@ void tray_client::configure_notify() const {
notify.border_width = 0; notify.border_width = 0;
unsigned int mask{XCB_EVENT_MASK_STRUCTURE_NOTIFY}; unsigned int mask{XCB_EVENT_MASK_STRUCTURE_NOTIFY};
m_connection.send_event_checked(false, client(), mask, reinterpret_cast<const char*>(&notify)); m_connection.send_event_checked(false, client_window(), mask, reinterpret_cast<const char*>(&notify));
} }
/** /**
* Redraw background using the observed background slice. * Redraw background using the observed background slice.
*/ */
void tray_client::update_bg() const { void client::update_bg() const {
m_log.trace("%s: Update background", name()); m_log.trace("%s: Update background", name());
// Composite background slice with background color. // Composite background slice with background color.
@ -363,11 +366,13 @@ void tray_client::update_bg() const {
m_connection.flush(); m_connection.flush();
} }
void tray_client::observe_background() { void client::observe_background() {
xcb_rectangle_t rect{0, 0, static_cast<uint16_t>(m_size.w), static_cast<uint16_t>(m_size.h)}; xcb_rectangle_t rect{0, 0, static_cast<uint16_t>(m_size.w), static_cast<uint16_t>(m_size.h)};
m_bg_slice = m_background_manager.observe(rect, embedder()); m_bg_slice = m_background_manager.observe(rect, embedder());
update_bg(); update_bg();
} }
} // namespace tray
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -3,6 +3,7 @@
#include <xcb/xcb_image.h> #include <xcb/xcb_image.h>
#include <thread> #include <thread>
#include <utility>
#include "cairo/context.hpp" #include "cairo/context.hpp"
#include "cairo/surface.hpp" #include "cairo/surface.hpp"
@ -50,13 +51,15 @@
POLYBAR_NS POLYBAR_NS
tray_manager::tray_manager( namespace tray {
manager::manager(
connection& conn, signal_emitter& emitter, const logger& logger, const bar_settings& bar_opts, on_update on_update) connection& conn, signal_emitter& emitter, const logger& logger, const bar_settings& bar_opts, on_update on_update)
: m_connection(conn), m_sig(emitter), m_log(logger), m_bar_opts(bar_opts), m_on_update(on_update) { : m_connection(conn), m_sig(emitter), m_log(logger), m_bar_opts(bar_opts), m_on_update(std::move(on_update)) {
m_connection.attach_sink(this, SINK_PRIORITY_TRAY); m_connection.attach_sink(this, SINK_PRIORITY_TRAY);
} }
tray_manager::~tray_manager() { manager::~manager() {
if (m_delaythread.joinable()) { if (m_delaythread.joinable()) {
m_delaythread.join(); m_delaythread.join();
} }
@ -64,7 +67,7 @@ tray_manager::~tray_manager() {
deactivate(); deactivate();
} }
void tray_manager::setup(const config& conf, const string& section_name) { void manager::setup(const config& conf, const string& section_name) {
unsigned client_height = m_bar_opts.inner_area().height; unsigned client_height = m_bar_opts.inner_area().height;
// Add user-defined padding // Add user-defined padding
@ -101,30 +104,30 @@ void tray_manager::setup(const config& conf, const string& section_name) {
activate(); activate();
} }
unsigned tray_manager::get_width() const { unsigned manager::get_width() const {
return m_tray_width; return m_tray_width;
} }
bool tray_manager::is_active() const { bool manager::is_active() const {
return m_state == state::ACTIVE; return m_state == state::ACTIVE;
} }
bool tray_manager::is_inactive() const { bool manager::is_inactive() const {
return m_state == state::INACTIVE; return m_state == state::INACTIVE;
} }
bool tray_manager::is_waiting() const { bool manager::is_waiting() const {
return m_state == state::WAITING; return m_state == state::WAITING;
} }
bool tray_manager::is_visible() const { bool manager::is_visible() const {
return is_active() && !m_hidden; return is_active() && !m_hidden;
} }
/** /**
* Activate systray management * Activate systray management
*/ */
void tray_manager::activate() { void manager::activate() {
if (is_active()) { if (is_active()) {
return; return;
} }
@ -173,7 +176,7 @@ void tray_manager::activate() {
* *
* @param other window id for current selection owner * @param other window id for current selection owner
*/ */
void tray_manager::wait_for_selection(xcb_window_t other) { void manager::wait_for_selection(xcb_window_t other) {
if (is_waiting() || other == XCB_NONE) { if (is_waiting() || other == XCB_NONE) {
return; return;
} }
@ -198,7 +201,7 @@ void tray_manager::wait_for_selection(xcb_window_t other) {
/** /**
* Deactivate systray management * Deactivate systray management
*/ */
void tray_manager::deactivate() { void manager::deactivate() {
if (is_inactive()) { if (is_inactive()) {
return; return;
} }
@ -228,7 +231,7 @@ void tray_manager::deactivate() {
/** /**
* Reconfigure tray * Reconfigure tray
*/ */
void tray_manager::reconfigure() { void manager::reconfigure() {
if (!m_opts.selection_owner) { if (!m_opts.selection_owner) {
return; return;
} }
@ -249,7 +252,7 @@ void tray_manager::reconfigure() {
* *
* TODO should we call update_width directly? * TODO should we call update_width directly?
*/ */
void tray_manager::reconfigure_window() { void manager::reconfigure_window() {
m_log.trace("tray: Reconfigure window (hidden=%i, clients=%i)", m_hidden, m_clients.size()); m_log.trace("tray: Reconfigure window (hidden=%i, clients=%i)", m_hidden, m_clients.size());
update_width(); update_width();
} }
@ -257,7 +260,7 @@ void tray_manager::reconfigure_window() {
/** /**
* TODO make sure this is always called when m_clients changes * TODO make sure this is always called when m_clients changes
*/ */
void tray_manager::update_width() { void manager::update_width() {
unsigned new_width = calculate_w(); unsigned new_width = calculate_w();
if (m_tray_width != new_width) { if (m_tray_width != new_width) {
m_tray_width = new_width; m_tray_width = new_width;
@ -269,7 +272,7 @@ void tray_manager::update_width() {
/** /**
* Reconfigure clients * Reconfigure clients
*/ */
void tray_manager::reconfigure_clients() { void manager::reconfigure_clients() {
m_log.trace("tray: Reconfigure clients"); m_log.trace("tray: Reconfigure clients");
int x = calculate_x() + m_opts.spacing; int x = calculate_x() + m_opts.spacing;
@ -300,7 +303,7 @@ void tray_manager::reconfigure_clients() {
/** /**
* Redraw client windows. * Redraw client windows.
*/ */
void tray_manager::redraw_clients() { void manager::redraw_clients() {
if (!is_visible()) { if (!is_visible()) {
return; return;
} }
@ -323,7 +326,7 @@ void tray_manager::redraw_clients() {
/** /**
* Find the systray selection atom * Find the systray selection atom
*/ */
void tray_manager::query_atom() { void manager::query_atom() {
m_log.trace("tray: Find systray selection atom for the default screen"); m_log.trace("tray: Find systray selection atom for the default screen");
string name{"_NET_SYSTEM_TRAY_S" + to_string(m_connection.default_screen())}; string name{"_NET_SYSTEM_TRAY_S" + to_string(m_connection.default_screen())};
auto reply = m_connection.intern_atom(false, name.length(), name.c_str()); auto reply = m_connection.intern_atom(false, name.length(), name.c_str());
@ -333,7 +336,7 @@ void tray_manager::query_atom() {
/** /**
* Set color atom used by clients when determing icon theme * Set color atom used by clients when determing icon theme
*/ */
void tray_manager::set_tray_colors() { void manager::set_tray_colors() {
m_log.trace("tray: Set _NET_SYSTEM_TRAY_COLORS to 0x%08x", m_opts.foreground); m_log.trace("tray: Set _NET_SYSTEM_TRAY_COLORS to 0x%08x", m_opts.foreground);
auto r = m_opts.foreground.red_i(); auto r = m_opts.foreground.red_i();
@ -344,21 +347,21 @@ void tray_manager::set_tray_colors() {
const uint16_t g16 = (g << 8) | g; const uint16_t g16 = (g << 8) | g;
const uint16_t b16 = (b << 8) | b; const uint16_t b16 = (b << 8) | b;
const uint32_t colors[12] = { const array<uint32_t, 12> colors = {
r16, g16, b16, // normal r16, g16, b16, // normal
r16, g16, b16, // error r16, g16, b16, // error
r16, g16, b16, // warning r16, g16, b16, // warning
r16, g16, b16, // success r16, g16, b16, // success
}; };
m_connection.change_property( m_connection.change_property(XCB_PROP_MODE_REPLACE, m_opts.selection_owner, _NET_SYSTEM_TRAY_COLORS,
XCB_PROP_MODE_REPLACE, m_opts.selection_owner, _NET_SYSTEM_TRAY_COLORS, XCB_ATOM_CARDINAL, 32, 12, colors); XCB_ATOM_CARDINAL, 32, colors.size(), colors.data());
} }
/** /**
* Set the _NET_SYSTEM_TRAY_ORIENTATION atom * Set the _NET_SYSTEM_TRAY_ORIENTATION atom
*/ */
void tray_manager::set_tray_orientation() { void manager::set_tray_orientation() {
const uint32_t orientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ; const uint32_t orientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
m_log.trace("tray: Set _NET_SYSTEM_TRAY_ORIENTATION to 0x%x", orientation); m_log.trace("tray: Set _NET_SYSTEM_TRAY_ORIENTATION to 0x%x", orientation);
m_connection.change_property_checked(XCB_PROP_MODE_REPLACE, m_opts.selection_owner, _NET_SYSTEM_TRAY_ORIENTATION, m_connection.change_property_checked(XCB_PROP_MODE_REPLACE, m_opts.selection_owner, _NET_SYSTEM_TRAY_ORIENTATION,
@ -366,7 +369,7 @@ void tray_manager::set_tray_orientation() {
} }
// TODO remove // TODO remove
void tray_manager::set_tray_visual() { void manager::set_tray_visual() {
// TODO use bar visual // TODO use bar visual
const uint32_t visualid = m_connection.visual_type(XCB_VISUAL_CLASS_TRUE_COLOR, 32)->visual_id; const uint32_t visualid = m_connection.visual_type(XCB_VISUAL_CLASS_TRUE_COLOR, 32)->visual_id;
m_log.trace("tray: Set _NET_SYSTEM_TRAY_VISUAL to 0x%x", visualid); m_log.trace("tray: Set _NET_SYSTEM_TRAY_VISUAL to 0x%x", visualid);
@ -380,7 +383,7 @@ void tray_manager::set_tray_visual() {
* @param other_owner is set to the current owner if the function fails * @param other_owner is set to the current owner if the function fails
* @returns Whether we acquired the selection * @returns Whether we acquired the selection
*/ */
bool tray_manager::acquire_selection(xcb_window_t& other_owner) { bool manager::acquire_selection(xcb_window_t& other_owner) {
other_owner = XCB_NONE; other_owner = XCB_NONE;
xcb_window_t owner = m_connection.get_selection_owner(m_atom).owner(); xcb_window_t owner = m_connection.get_selection_owner(m_atom).owner();
@ -404,7 +407,7 @@ bool tray_manager::acquire_selection(xcb_window_t& other_owner) {
/** /**
* Notify pending clients about the new systray MANAGER * Notify pending clients about the new systray MANAGER
*/ */
void tray_manager::notify_clients() { void manager::notify_clients() {
if (is_active()) { if (is_active()) {
m_log.info("tray: Notifying pending tray clients"); m_log.info("tray: Notifying pending tray clients");
auto message = m_connection.make_client_message(MANAGER, m_connection.root()); auto message = m_connection.make_client_message(MANAGER, m_connection.root());
@ -418,7 +421,7 @@ void tray_manager::notify_clients() {
/** /**
* Send delayed notification to pending clients * Send delayed notification to pending clients
*/ */
void tray_manager::notify_clients_delayed() { void manager::notify_clients_delayed() {
if (m_delaythread.joinable()) { if (m_delaythread.joinable()) {
m_delaythread.join(); m_delaythread.join();
} }
@ -432,42 +435,42 @@ void tray_manager::notify_clients_delayed() {
* Track changes to the given selection owner * Track changes to the given selection owner
* 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 manager::track_selection_owner(xcb_window_t owner) {
if (owner != XCB_NONE) { if (owner != XCB_NONE) {
const unsigned mask{XCB_CW_EVENT_MASK}; const uint32_t mask{XCB_CW_EVENT_MASK};
const unsigned values[]{XCB_EVENT_MASK_STRUCTURE_NOTIFY}; const uint32_t value{XCB_EVENT_MASK_STRUCTURE_NOTIFY};
m_connection.change_window_attributes(owner, mask, values); m_connection.change_window_attributes(owner, mask, &value);
} }
} }
/** /**
* Process client docking request * Process client docking request
*/ */
void tray_manager::process_docking_request(xcb_window_t win) { void 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 {
auto client = make_unique<tray_client>( auto cl = make_unique<client>(
m_log, m_connection, m_opts.selection_owner, win, m_opts.client_size, m_bar_opts.background.value()); m_log, m_connection, m_opts.selection_owner, win, m_opts.client_size, m_bar_opts.background.value());
try { try {
client->query_xembed(); cl->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)", cl->name(), err.what());
return; return;
} }
client->update_client_attributes(); cl->update_client_attributes();
client->reparent(); cl->reparent();
client->add_to_save_set(); cl->add_to_save_set();
client->ensure_state(); cl->ensure_state();
client->notify_xembed(); cl->notify_xembed();
m_clients.emplace_back(std::move(client)); m_clients.emplace_back(std::move(cl));
} catch (const std::exception& err) { } catch (const std::exception& err) {
m_log.err("tray: Failed to setup tray client removing... (%s)", err.what()); m_log.err("tray: Failed to setup tray client removing... (%s)", err.what());
return; return;
@ -477,18 +480,18 @@ void tray_manager::process_docking_request(xcb_window_t win) {
/** /**
* Calculate x position of tray window * Calculate x position of tray window
*/ */
int tray_manager::calculate_x() const { int manager::calculate_x() const {
return m_bar_opts.inner_area(false).x + m_pos.x; return m_bar_opts.inner_area(false).x + m_pos.x;
} }
int tray_manager::calculate_y() const { int manager::calculate_y() const {
return m_bar_opts.inner_area(false).y + m_pos.y; return m_bar_opts.inner_area(false).y + m_pos.y;
} }
unsigned tray_manager::calculate_w() const { unsigned 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 (const 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;
@ -500,7 +503,7 @@ unsigned tray_manager::calculate_w() const {
/** /**
* Calculate y position of client window * Calculate y position of client window
*/ */
int tray_manager::calculate_client_y() { int manager::calculate_client_y() {
return (m_bar_opts.inner_area(true).height - m_opts.client_size.h) / 2; return (m_bar_opts.inner_area(true).height - m_opts.client_size.h) / 2;
} }
@ -509,14 +512,14 @@ int tray_manager::calculate_client_y() {
* *
* The given window ID can be the ID of the wrapper or the embedded window * The given window ID can be the ID of the wrapper or the embedded window
*/ */
bool tray_manager::is_embedded(const xcb_window_t& win) { bool manager::is_embedded(const xcb_window_t& win) {
return find_client(win) != nullptr; return find_client(win) != nullptr;
} }
/** /**
* Find tray client object from the wrapper or embedded window * Find tray client object from the wrapper or embedded window
*/ */
tray_client* tray_manager::find_client(const xcb_window_t& win) { client* 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; });
@ -530,20 +533,20 @@ 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) { void manager::remove_client(const client& c) {
remove_client(client.client()); remove_client(c.client_window());
} }
/** /**
* Remove tray client by window * Remove tray client by window
*/ */
void tray_manager::remove_client(xcb_window_t win) { void 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(); manager::reconfigure();
} }
} }
@ -554,12 +557,12 @@ void tray_manager::remove_client(xcb_window_t win) {
* 1. When removing a client during iteration, the unique_ptr is reset. * 1. When removing a client during iteration, the unique_ptr is reset.
* 2. Afterwards all null pointers are removed from the list. * 2. Afterwards all null pointers are removed from the list.
*/ */
void tray_manager::clean_clients() { void manager::clean_clients() {
m_clients.erase( m_clients.erase(
std::remove_if(m_clients.begin(), m_clients.end(), [](const auto& client) { return client.get() == nullptr; })); std::remove_if(m_clients.begin(), m_clients.end(), [](const auto& client) { return client.get() == nullptr; }));
} }
bool tray_manager::change_visibility(bool visible) { bool manager::change_visibility(bool visible) {
if (!is_active() || m_hidden == !visible) { if (!is_active() || m_hidden == !visible) {
return false; return false;
} }
@ -585,7 +588,7 @@ bool tray_manager::change_visibility(bool visible) {
/** /**
* Event callback : XCB_EXPOSE * Event callback : XCB_EXPOSE
*/ */
void tray_manager::handle(const evt::expose& evt) { void manager::handle(const evt::expose& evt) {
if (is_active() && !m_clients.empty() && evt->count == 0) { if (is_active() && !m_clients.empty() && evt->count == 0) {
redraw_clients(); redraw_clients();
} }
@ -594,7 +597,7 @@ void tray_manager::handle(const evt::expose& evt) {
/** /**
* Event callback : XCB_CLIENT_MESSAGE * Event callback : XCB_CLIENT_MESSAGE
*/ */
void tray_manager::handle(const evt::client_message& evt) { void manager::handle(const evt::client_message& evt) {
if (!is_active()) { if (!is_active()) {
return; return;
} }
@ -625,7 +628,7 @@ void tray_manager::handle(const evt::client_message& evt) {
* wants to reconfigure its window. This is of course nothing we appreciate * wants to reconfigure its window. This is of course nothing we appreciate
* so we return an answer that'll put him in place. * so we return an answer that'll put him in place.
*/ */
void tray_manager::handle(const evt::configure_request& evt) { void manager::handle(const evt::configure_request& 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);
try { try {
@ -639,9 +642,9 @@ void tray_manager::handle(const evt::configure_request& evt) {
} }
/** /**
* @see tray_manager::handle(const evt::configure_request&); * @see manager::handle(const evt::configure_request&);
*/ */
void tray_manager::handle(const evt::resize_request& evt) { void manager::handle(const evt::resize_request& 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);
try { try {
@ -657,7 +660,7 @@ void tray_manager::handle(const evt::resize_request& evt) {
/** /**
* Event callback : XCB_SELECTION_CLEAR * Event callback : XCB_SELECTION_CLEAR
*/ */
void tray_manager::handle(const evt::selection_clear& evt) { void manager::handle(const evt::selection_clear& evt) {
if (is_inactive()) { if (is_inactive()) {
return; return;
} else if (evt->selection != m_atom) { } else if (evt->selection != m_atom) {
@ -673,7 +676,7 @@ void tray_manager::handle(const evt::selection_clear& evt) {
/** /**
* Event callback : XCB_PROPERTY_NOTIFY * Event callback : XCB_PROPERTY_NOTIFY
*/ */
void tray_manager::handle(const evt::property_notify& evt) { void manager::handle(const evt::property_notify& evt) {
if (!is_active()) { if (!is_active()) {
return; return;
} }
@ -708,7 +711,7 @@ void tray_manager::handle(const evt::property_notify& evt) {
/** /**
* Event callback : XCB_REPARENT_NOTIFY * Event callback : XCB_REPARENT_NOTIFY
*/ */
void tray_manager::handle(const evt::reparent_notify& evt) { void manager::handle(const evt::reparent_notify& evt) {
if (!is_active()) { if (!is_active()) {
return; return;
} }
@ -729,7 +732,7 @@ void tray_manager::handle(const evt::reparent_notify& evt) {
/** /**
* Event callback : XCB_DESTROY_NOTIFY * Event callback : XCB_DESTROY_NOTIFY
*/ */
void tray_manager::handle(const evt::destroy_notify& evt) { void manager::handle(const evt::destroy_notify& evt) {
if (is_waiting() && evt->window == m_othermanager) { if (is_waiting() && evt->window == m_othermanager) {
m_log.info("Systray selection unmanaged... re-activating"); m_log.info("Systray selection unmanaged... re-activating");
activate(); activate();
@ -743,7 +746,7 @@ void tray_manager::handle(const evt::destroy_notify& evt) {
/** /**
* Event callback : XCB_MAP_NOTIFY * Event callback : XCB_MAP_NOTIFY
*/ */
void tray_manager::handle(const evt::map_notify& evt) { void manager::handle(const evt::map_notify& evt) {
if (is_active() && evt->window == m_opts.selection_owner) { if (is_active() && evt->window == m_opts.selection_owner) {
m_log.trace("tray: Received map_notify for selection owner"); m_log.trace("tray: Received map_notify for selection owner");
redraw_clients(); redraw_clients();
@ -767,7 +770,7 @@ void tray_manager::handle(const evt::map_notify& evt) {
/** /**
* Event callback : XCB_UNMAP_NOTIFY * Event callback : XCB_UNMAP_NOTIFY
*/ */
void tray_manager::handle(const evt::unmap_notify& evt) { void 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);
@ -785,13 +788,13 @@ void tray_manager::handle(const evt::unmap_notify& evt) {
} }
} }
bool tray_manager::on(const signals::ui::update_background&) { bool manager::on(const signals::ui::update_background&) {
redraw_clients(); redraw_clients();
return false; return false;
} }
bool tray_manager::on(const signals::ui_tray::tray_pos_change& evt) { bool manager::on(const signals::ui_tray::tray_pos_change& evt) {
int new_x = std::max(0, std::min(evt.cast(), (int)(m_bar_opts.size.w - m_tray_width))); int new_x = std::max(0, std::min(evt.cast(), (int)(m_bar_opts.size.w - m_tray_width)));
if (new_x != m_pos.x) { if (new_x != m_pos.x) {
@ -802,8 +805,10 @@ bool tray_manager::on(const signals::ui_tray::tray_pos_change& evt) {
return true; return true;
} }
bool tray_manager::on(const signals::ui_tray::tray_visibility& evt) { bool manager::on(const signals::ui_tray::tray_visibility& evt) {
return change_visibility(evt.cast()); return change_visibility(evt.cast());
} }
} // namespace tray
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -11,7 +11,7 @@ POLYBAR_NS
namespace xembed { namespace xembed {
void info::set(uint32_t* data) { void info::set(const uint32_t* data) {
version = data[0]; version = data[0];
flags = data[1]; flags = data[1];
} }