2016-11-02 19:22:45 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <xcb/xcb.h>
|
2016-11-25 12:55:15 +00:00
|
|
|
#include <chrono>
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
#include "common.hpp"
|
|
|
|
#include "components/logger.hpp"
|
|
|
|
#include "components/types.hpp"
|
2016-11-20 22:04:31 +00:00
|
|
|
#include "utils/concurrency.hpp"
|
2016-11-25 03:10:26 +00:00
|
|
|
#include "x11/events.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
|
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
#define TRAY_WM_NAME "Polybar tray window"
|
|
|
|
#define TRAY_WM_CLASS "tray\0Polybar"
|
2016-11-02 19:22:45 +00:00
|
|
|
|
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;
|
|
|
|
|
2016-11-12 11:56:39 +00:00
|
|
|
// fwd declarations
|
|
|
|
class connection;
|
|
|
|
struct xembed_data;
|
|
|
|
|
2016-11-20 22:04:31 +00:00
|
|
|
namespace graphics_util {
|
|
|
|
struct root_pixmap;
|
|
|
|
}
|
|
|
|
|
2016-11-12 11:56:39 +00:00
|
|
|
using root_pixmap = graphics_util::root_pixmap;
|
|
|
|
|
|
|
|
// class definition : settings {{{
|
|
|
|
|
|
|
|
struct tray_settings {
|
|
|
|
tray_settings() = default;
|
|
|
|
tray_settings& operator=(const tray_settings& o) = default;
|
|
|
|
|
|
|
|
alignment align{alignment::NONE};
|
|
|
|
int16_t orig_x{0};
|
|
|
|
int16_t orig_y{0};
|
|
|
|
int16_t configured_x{0};
|
|
|
|
int16_t configured_y{0};
|
|
|
|
uint16_t configured_w{0};
|
|
|
|
uint16_t configured_h{0};
|
|
|
|
uint16_t configured_slots{0};
|
|
|
|
uint16_t width{0};
|
|
|
|
uint16_t width_max{0};
|
|
|
|
uint16_t height{0};
|
|
|
|
uint16_t height_fill{0};
|
|
|
|
uint16_t spacing{0};
|
|
|
|
uint32_t sibling{0};
|
|
|
|
uint32_t background{0};
|
|
|
|
bool transparent{false};
|
|
|
|
};
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
// class definition : tray_client {{{
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-11-12 11:56:39 +00:00
|
|
|
class tray_client {
|
2016-11-02 19:22:45 +00:00
|
|
|
public:
|
2016-11-12 11:56:39 +00:00
|
|
|
explicit tray_client(connection& conn, xcb_window_t win, uint16_t w, uint16_t h);
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-11-12 11:56:39 +00:00
|
|
|
~tray_client();
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
bool match(const xcb_window_t& win) const;
|
|
|
|
bool mapped() const;
|
|
|
|
void mapped(bool state);
|
|
|
|
|
|
|
|
xcb_window_t window() const;
|
|
|
|
xembed_data* xembed() const;
|
|
|
|
|
|
|
|
void ensure_state() const;
|
|
|
|
void reconfigure(int16_t x, int16_t y) const;
|
|
|
|
void configure_notify(int16_t x, int16_t y) const;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
connection& m_connection;
|
|
|
|
xcb_window_t m_window{0};
|
|
|
|
|
|
|
|
shared_ptr<xembed_data> m_xembed;
|
|
|
|
stateflag m_mapped{false};
|
|
|
|
|
|
|
|
uint16_t m_width;
|
|
|
|
uint16_t m_height;
|
|
|
|
};
|
|
|
|
|
|
|
|
// }}}
|
2016-11-12 11:56:39 +00:00
|
|
|
// class definition : tray_manager {{{
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-11-12 11:56:39 +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> {
|
2016-11-02 19:22:45 +00:00
|
|
|
public:
|
2016-11-12 11:56:39 +00:00
|
|
|
explicit tray_manager(connection& conn, const logger& logger);
|
|
|
|
|
|
|
|
~tray_manager();
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-11-12 11:56:39 +00:00
|
|
|
const tray_settings settings() const;
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
void bootstrap(tray_settings settings);
|
|
|
|
void activate();
|
2016-11-25 12:55:15 +00:00
|
|
|
void activate_delayed(chrono::duration<double, std::milli> delay = 1s);
|
2016-11-25 03:10:26 +00:00
|
|
|
void deactivate(bool clear_selection = true);
|
2016-11-02 19:22:45 +00:00
|
|
|
void reconfigure();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void reconfigure_window();
|
|
|
|
void reconfigure_clients();
|
2016-11-04 17:50:33 +00:00
|
|
|
void reconfigure_bg(bool realloc = false);
|
|
|
|
void refresh_window();
|
2016-12-03 19:26:29 +00:00
|
|
|
void redraw_window();
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
void query_atom();
|
|
|
|
void create_window();
|
2016-11-12 11:56:39 +00:00
|
|
|
void create_bg(bool realloc = false);
|
|
|
|
void restack_window();
|
2016-11-02 19:22:45 +00:00
|
|
|
void set_wmhints();
|
|
|
|
void set_traycolors();
|
|
|
|
|
|
|
|
void acquire_selection();
|
|
|
|
void notify_clients();
|
2016-11-25 12:55:15 +00:00
|
|
|
void notify_clients_delayed(chrono::duration<double, std::milli> delay = 1s);
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
void track_selection_owner(xcb_window_t owner);
|
|
|
|
void process_docking_request(xcb_window_t win);
|
|
|
|
|
|
|
|
void bar_visibility_change(bool state);
|
|
|
|
|
2016-11-04 17:50:33 +00:00
|
|
|
int16_t calculate_x(uint16_t width) const;
|
2016-11-02 19:22:45 +00:00
|
|
|
int16_t calculate_y() const;
|
|
|
|
uint16_t calculate_w() const;
|
|
|
|
uint16_t calculate_h() const;
|
|
|
|
|
|
|
|
int16_t calculate_client_x(const xcb_window_t& win);
|
|
|
|
int16_t calculate_client_y();
|
|
|
|
|
2016-11-12 11:56:39 +00:00
|
|
|
shared_ptr<tray_client> find_client(const xcb_window_t& win) const;
|
|
|
|
void remove_client(shared_ptr<tray_client>& client, bool reconfigure = true);
|
2016-11-02 19:22:45 +00:00
|
|
|
int mapped_clients() const;
|
|
|
|
|
|
|
|
void handle(const evt::expose& evt);
|
|
|
|
void handle(const evt::visibility_notify& evt);
|
|
|
|
void handle(const evt::client_message& evt);
|
|
|
|
void handle(const evt::configure_request& evt);
|
|
|
|
void handle(const evt::resize_request& evt);
|
|
|
|
void handle(const evt::selection_clear& evt);
|
|
|
|
void handle(const evt::property_notify& evt);
|
|
|
|
void handle(const evt::reparent_notify& evt);
|
|
|
|
void handle(const evt::destroy_notify& evt);
|
|
|
|
void handle(const evt::map_notify& evt);
|
|
|
|
void handle(const evt::unmap_notify& evt);
|
|
|
|
|
|
|
|
private:
|
|
|
|
connection& m_connection;
|
|
|
|
const logger& m_log;
|
2016-11-12 11:56:39 +00:00
|
|
|
vector<shared_ptr<tray_client>> m_clients;
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-11-12 11:56:39 +00:00
|
|
|
tray_settings m_opts;
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-11-04 17:50:33 +00:00
|
|
|
xcb_gcontext_t m_gc{0};
|
|
|
|
xcb_pixmap_t m_pixmap{0};
|
2016-11-12 11:56:39 +00:00
|
|
|
root_pixmap m_rootpixmap;
|
2016-11-04 17:50:33 +00:00
|
|
|
uint16_t m_prevwidth{0};
|
|
|
|
uint16_t m_prevheight{0};
|
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
xcb_atom_t m_atom{0};
|
|
|
|
xcb_window_t m_tray{0};
|
|
|
|
xcb_window_t m_othermanager{0};
|
|
|
|
|
|
|
|
stateflag m_activated{false};
|
|
|
|
stateflag m_mapped{false};
|
|
|
|
stateflag m_hidden{false};
|
2016-11-25 12:55:15 +00:00
|
|
|
stateflag m_acquired_selection{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-11-14 23:55:40 +00:00
|
|
|
bool m_restacked{false};
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
std::mutex m_mtx;
|
|
|
|
};
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
/**
|
|
|
|
* Configure injection module
|
|
|
|
*/
|
2016-11-12 11:56:39 +00:00
|
|
|
template <class T = unique_ptr<tray_manager>>
|
|
|
|
di::injector<T> configure_tray_manager() {
|
2016-11-02 19:22:45 +00:00
|
|
|
return di::make_injector(configure_logger(), configure_connection());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
POLYBAR_NS_END
|