1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
#pragma once
#include <xcb/xcb.h>
#include <cstdlib>
#include <xpp/core.hpp>
#include <xpp/generic/factory.hpp>
#include <xpp/proto/x.hpp>
#include "common.hpp"
#include "components/screen.hpp"
#include "x11/extensions/all.hpp"
#include "x11/registry.hpp"
#include "x11/types.hpp"
POLYBAR_NS
namespace detail {
template <typename Connection, typename... Extensions>
class interfaces : public xpp::x::extension::interface<interfaces<Connection, Extensions...>, Connection>,
public Extensions::template interface<interfaces<Connection, Extensions...>, Connection>... {
public:
const Connection& connection() const {
return static_cast<const Connection&>(*this);
}
};
template <typename Derived, typename... Extensions>
class connection_base : public xpp::core,
public xpp::generic::error_dispatcher,
public detail::interfaces<connection_base<Derived, Extensions...>, Extensions...>,
private xpp::x::extension,
private xpp::x::extension::error_dispatcher,
private Extensions...,
private Extensions::error_dispatcher... {
public:
explicit connection_base(xcb_connection_t* c, int s)
: xpp::core(c)
, interfaces<connection_base<Derived, Extensions...>, Extensions...>(*this)
, Extensions(m_c.get())...
, Extensions::error_dispatcher(static_cast<Extensions&>(*this).get())... {
core::m_screen = s;
m_root_window = screen_of_display(s)->root;
}
void operator()(const shared_ptr<xcb_generic_error_t>& error) const override {
check<xpp::x::extension, Extensions...>(error);
}
template <typename Extension>
const Extension& extension() const {
return static_cast<const Extension&>(*this);
}
xcb_window_t root() const {
return m_root_window;
}
shared_ptr<xcb_generic_event_t> wait_for_event() const override {
try {
return core::wait_for_event();
} catch (const shared_ptr<xcb_generic_error_t>& error) {
check<xpp::x::extension, Extensions...>(error);
}
throw; // re-throw exception
}
shared_ptr<xcb_generic_event_t> wait_for_special_event(xcb_special_event_t* se) const override {
try {
return core::wait_for_special_event(se);
} catch (const shared_ptr<xcb_generic_error_t>& error) {
check<xpp::x::extension, Extensions...>(error);
}
throw; // re-throw exception
}
private:
xcb_window_t m_root_window;
template <typename Extension, typename Next, typename... Rest>
void check(const shared_ptr<xcb_generic_error_t>& error) const {
check<Extension>(error);
check<Next, Rest...>(error);
}
template <typename Extension>
void check(const shared_ptr<xcb_generic_error_t>& error) const {
using error_dispatcher = typename Extension::error_dispatcher;
auto& dispatcher = static_cast<const error_dispatcher&>(*this);
dispatcher(error);
}
};
} // namespace detail
class connection : public detail::connection_base<connection&, XPP_EXTENSION_LIST> {
public:
using base_type = detail::connection_base<connection&, XPP_EXTENSION_LIST>;
using make_type = connection&;
static make_type make(xcb_connection_t* conn = nullptr, int default_screen = 0);
explicit connection(xcb_connection_t* c, int default_screen);
~connection();
const connection& operator=(const connection& o) {
return o;
}
static void pack_values(uint32_t mask, const void* src, std::array<uint32_t, 32>& dest);
void reset_screen();
xcb_screen_t* screen();
string id(xcb_window_t w) const;
void ensure_event_mask(xcb_window_t win, unsigned int event);
void clear_event_mask(xcb_window_t win);
xcb_client_message_event_t make_client_message(xcb_atom_t type, xcb_window_t target) const;
void send_client_message(const xcb_client_message_event_t& message, xcb_window_t target,
unsigned int event_mask = 0xFFFFFF, bool propagate = false) const;
xcb_visualtype_t* visual_type(xcb_visual_class_t class_, int match_depth);
xcb_visualtype_t* visual_type_for_id(xcb_visualid_t visual_id);
bool root_pixmap(xcb_pixmap_t* pixmap, int* depth, xcb_rectangle_t* rect);
static string error_str(int error_code);
void dispatch_event(const shared_ptr<xcb_generic_event_t>& evt) const;
template <typename Sink>
void attach_sink(Sink&& sink, registry::priority prio = 0) {
m_registry.attach(prio, forward<Sink>(sink));
}
template <typename Sink>
void detach_sink(Sink&& sink, registry::priority prio = 0) {
m_registry.detach(prio, forward<Sink>(sink));
}
protected:
registry m_registry{*this};
xcb_screen_t* m_screen{nullptr};
};
POLYBAR_NS_END
|