2016-11-02 19:22:45 +00:00
|
|
|
#pragma once
|
|
|
|
|
2021-09-21 18:59:48 +00:00
|
|
|
#include <atomic>
|
2016-11-25 12:55:15 +00:00
|
|
|
#include <chrono>
|
2019-01-05 00:08:18 +00:00
|
|
|
#include <memory>
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2017-05-23 19:32:34 +00:00
|
|
|
#include "cairo/context.hpp"
|
|
|
|
#include "cairo/surface.hpp"
|
2016-11-02 19:22:45 +00:00
|
|
|
#include "common.hpp"
|
|
|
|
#include "components/logger.hpp"
|
|
|
|
#include "components/types.hpp"
|
2016-12-05 19:41:00 +00:00
|
|
|
#include "events/signal_fwd.hpp"
|
2017-01-24 07:49:27 +00:00
|
|
|
#include "events/signal_receiver.hpp"
|
2016-11-20 22:04:31 +00:00
|
|
|
#include "utils/concurrency.hpp"
|
2016-12-05 19:41:00 +00:00
|
|
|
#include "x11/atoms.hpp"
|
|
|
|
#include "x11/connection.hpp"
|
|
|
|
#include "x11/tray_client.hpp"
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
|
|
|
|
#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1
|
|
|
|
|
|
|
|
#define SYSTEM_TRAY_REQUEST_DOCK 0
|
|
|
|
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
|
|
|
|
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
|
|
|
|
|
2017-01-01 20:28:28 +00:00
|
|
|
#define TRAY_PLACEHOLDER "<placeholder-systray>"
|
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
POLYBAR_NS
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-11-25 12:55:15 +00:00
|
|
|
namespace chrono = std::chrono;
|
|
|
|
using namespace std::chrono_literals;
|
2021-09-21 18:59:48 +00:00
|
|
|
using std::atomic;
|
2016-11-25 12:55:15 +00:00
|
|
|
|
2016-11-12 11:56:39 +00:00
|
|
|
// fwd declarations
|
|
|
|
class connection;
|
2019-01-05 00:08:18 +00:00
|
|
|
class bg_slice;
|
2016-11-12 11:56:39 +00:00
|
|
|
|
|
|
|
struct tray_settings {
|
2022-02-27 20:36:16 +00:00
|
|
|
/**
|
|
|
|
* Dimensions for client windows.
|
|
|
|
*/
|
|
|
|
size client_size{0, 0};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Number of pixels added between tray icons
|
|
|
|
*/
|
2022-07-26 19:26:13 +00:00
|
|
|
unsigned spacing{0U};
|
2019-10-27 21:27:58 +00:00
|
|
|
rgba background{};
|
2021-11-17 10:41:40 +00:00
|
|
|
rgba foreground{};
|
2022-02-27 19:42:10 +00:00
|
|
|
|
2022-08-27 21:02:34 +00:00
|
|
|
/**
|
|
|
|
* Window ID of tray selection owner.
|
|
|
|
*
|
|
|
|
* Matches the bar window
|
|
|
|
*/
|
|
|
|
xcb_window_t selection_owner{XCB_NONE};
|
2016-11-12 11:56:39 +00:00
|
|
|
};
|
|
|
|
|
2022-09-03 19:33:22 +00:00
|
|
|
using on_update = std::function<void(void)>;
|
|
|
|
|
2022-08-28 13:29:36 +00:00
|
|
|
class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify, evt::client_message,
|
|
|
|
evt::configure_request, evt::resize_request, evt::selection_clear, evt::property_notify,
|
|
|
|
evt::reparent_notify, evt::destroy_notify, evt::map_notify, evt::unmap_notify>,
|
|
|
|
public signal_receiver<SIGN_PRIORITY_TRAY, signals::ui::update_background,
|
|
|
|
signals::ui_tray::tray_pos_change, signals::ui_tray::tray_visibility> {
|
2016-11-02 19:22:45 +00:00
|
|
|
public:
|
2022-09-03 20:34:00 +00:00
|
|
|
explicit tray_manager(connection& conn, signal_emitter& emitter, const logger& logger, const bar_settings& bar_opts,
|
|
|
|
on_update on_update);
|
2016-11-12 11:56:39 +00:00
|
|
|
|
|
|
|
~tray_manager();
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2022-08-28 13:29:36 +00:00
|
|
|
int get_width() const;
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2022-09-03 18:56:32 +00:00
|
|
|
void setup(const config& conf, const string& module_section_name);
|
2016-11-02 19:22:45 +00:00
|
|
|
void activate();
|
2022-09-11 19:47:50 +00:00
|
|
|
void wait_for_selection(xcb_window_t other);
|
|
|
|
void deactivate();
|
2016-11-02 19:22:45 +00:00
|
|
|
void reconfigure();
|
|
|
|
|
2022-09-11 19:47:50 +00:00
|
|
|
bool is_active() const;
|
|
|
|
bool is_inactive() const;
|
|
|
|
bool is_waiting() const;
|
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
protected:
|
|
|
|
void reconfigure_window();
|
|
|
|
void reconfigure_clients();
|
2016-11-04 17:50:33 +00:00
|
|
|
void refresh_window();
|
2022-03-06 22:43:06 +00:00
|
|
|
void redraw_window();
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
void query_atom();
|
2016-12-05 19:41:00 +00:00
|
|
|
void set_tray_colors();
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2022-09-11 19:47:50 +00:00
|
|
|
bool acquire_selection(xcb_window_t& other_owner);
|
2016-11-02 19:22:45 +00:00
|
|
|
void notify_clients();
|
2016-12-14 10:34:09 +00:00
|
|
|
void notify_clients_delayed();
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
void track_selection_owner(xcb_window_t owner);
|
|
|
|
void process_docking_request(xcb_window_t win);
|
|
|
|
|
2022-07-26 19:26:13 +00:00
|
|
|
/**
|
|
|
|
* Final x-position of the tray window relative to the very top-left bar window.
|
|
|
|
*/
|
2022-08-27 21:02:34 +00:00
|
|
|
int calculate_x() const;
|
2022-07-26 19:26:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Final y-position of the tray window relative to the very top-left bar window.
|
|
|
|
*/
|
2022-02-27 19:30:23 +00:00
|
|
|
int calculate_y() const;
|
2022-04-15 21:50:04 +00:00
|
|
|
|
2022-07-26 19:26:13 +00:00
|
|
|
unsigned calculate_w() const;
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2017-01-19 10:11:28 +00:00
|
|
|
int calculate_client_y();
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2022-09-03 19:33:22 +00:00
|
|
|
void update_width();
|
2022-08-28 13:29:36 +00:00
|
|
|
|
2022-09-03 20:34:00 +00:00
|
|
|
bool is_embedded(const xcb_window_t& win);
|
2022-03-07 11:20:05 +00:00
|
|
|
tray_client* find_client(const xcb_window_t& win);
|
|
|
|
void remove_client(const tray_client& client, bool reconfigure = true);
|
2016-12-15 02:30:41 +00:00
|
|
|
void remove_client(xcb_window_t win, bool reconfigure = true);
|
2022-06-16 10:53:49 +00:00
|
|
|
bool change_visibility(bool visible);
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2021-01-04 09:38:43 +00:00
|
|
|
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::configure_request& evt) override;
|
|
|
|
void handle(const evt::resize_request& evt) override;
|
|
|
|
void handle(const evt::selection_clear& evt) override;
|
|
|
|
void handle(const evt::property_notify& evt) override;
|
|
|
|
void handle(const evt::reparent_notify& evt) override;
|
|
|
|
void handle(const evt::destroy_notify& evt) override;
|
|
|
|
void handle(const evt::map_notify& evt) override;
|
|
|
|
void handle(const evt::unmap_notify& evt) override;
|
|
|
|
|
|
|
|
bool on(const signals::ui::update_background& evt) override;
|
2022-04-15 21:50:04 +00:00
|
|
|
bool on(const signals::ui_tray::tray_pos_change& evt) override;
|
2022-06-16 10:53:49 +00:00
|
|
|
bool on(const signals::ui_tray::tray_visibility& evt) override;
|
2016-12-05 19:41:00 +00:00
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
private:
|
|
|
|
connection& m_connection;
|
2016-12-05 19:41:00 +00:00
|
|
|
signal_emitter& m_sig;
|
2016-11-02 19:22:45 +00:00
|
|
|
const logger& m_log;
|
2022-03-07 11:20:05 +00:00
|
|
|
vector<tray_client> m_clients;
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-12-15 08:29:14 +00:00
|
|
|
tray_settings m_opts{};
|
2022-02-27 19:30:23 +00:00
|
|
|
const bar_settings& m_bar_opts;
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2022-09-03 19:33:22 +00:00
|
|
|
const on_update m_on_update;
|
|
|
|
|
2022-09-11 19:47:50 +00:00
|
|
|
enum class state {
|
|
|
|
/**
|
|
|
|
* The tray manager is completely deactivated and doesn't own any resources.
|
|
|
|
*/
|
|
|
|
INACTIVE = 0,
|
|
|
|
/**
|
|
|
|
* There is currently another application owning the systray selection and the tray manager waits until the
|
|
|
|
* selection becomes available again.
|
|
|
|
*
|
|
|
|
* The signal receiver is detached in m_othermanager is set
|
|
|
|
*/
|
|
|
|
WAITING,
|
|
|
|
/**
|
|
|
|
* The tray manager owns the systray selection.
|
|
|
|
*
|
|
|
|
* The signal receiver is attached
|
|
|
|
*/
|
|
|
|
ACTIVE,
|
|
|
|
};
|
|
|
|
atomic<state> m_state{state::INACTIVE};
|
|
|
|
|
2022-08-28 12:49:09 +00:00
|
|
|
/**
|
|
|
|
* Systray selection atom _NET_SYSTEM_TRAY_Sn
|
|
|
|
*/
|
|
|
|
xcb_atom_t m_atom{XCB_NONE};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Owner of systray selection (if we don't own it)
|
|
|
|
*/
|
|
|
|
xcb_window_t m_othermanager{XCB_NONE};
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2022-08-28 12:49:09 +00:00
|
|
|
/**
|
|
|
|
* Specifies the top-left corner of the tray area relative to inner area of the bar.
|
|
|
|
*/
|
|
|
|
position m_pos{0, 0};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Current width of the tray.
|
2022-08-28 12:56:56 +00:00
|
|
|
*
|
|
|
|
* Caches the value calculated from all mapped tray clients.
|
2022-08-28 12:49:09 +00:00
|
|
|
*/
|
|
|
|
unsigned m_tray_width{0};
|
|
|
|
|
|
|
|
/**
|
2022-09-11 19:47:50 +00:00
|
|
|
* Whether the tray is visible
|
2022-08-28 12:49:09 +00:00
|
|
|
*/
|
2022-09-14 19:53:02 +00:00
|
|
|
bool m_hidden{false};
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-11-25 12:55:15 +00:00
|
|
|
thread m_delaythread;
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-12-14 10:34:09 +00:00
|
|
|
bool m_firstactivation{true};
|
2016-11-02 19:22:45 +00:00
|
|
|
};
|
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
POLYBAR_NS_END
|