#ifndef X_HH #define X_HH #include #include #include #include #include #include namespace x { namespace priv { struct XcbConnectionDelete { void operator()(xcb_connection_t* ptr) const { xcb_disconnect(ptr); } }; struct XcbWindowDelete { void operator()(xcb_connection_t* conn, xcb_window_t id) const { xcb_destroy_window(conn, id); } }; struct XcbPixmapDelete { void operator()(xcb_connection_t* conn, xcb_window_t id) const { xcb_free_pixmap(conn, id); } }; struct XcbGContextDelete { void operator()(xcb_connection_t* conn, xcb_gcontext_t id) const { xcb_free_gc(conn, id); } }; struct XcbRenderPictureDelete { void operator()(xcb_connection_t* conn, xcb_render_picture_t pic) const { xcb_render_free_picture(conn, pic); } }; struct XcbColormapDelete { void operator()(xcb_connection_t* conn, xcb_colormap_t id) const { xcb_free_colormap(conn, id); } }; } // priv class shared_connection { public: shared_connection() { } shared_connection(std::nullptr_t) { } explicit shared_connection(xcb_connection_t* conn) : shared_(conn, priv::XcbConnectionDelete()) { } shared_connection(shared_connection const& shared) : shared_(shared.shared_) { } shared_connection(shared_connection&& shared) : shared_(std::move(shared.shared_)) { } shared_connection& operator=(shared_connection const& shared) { shared_ = shared.shared_; return *this; } shared_connection& operator=(shared_connection&& shared) { shared_ = std::move(shared.shared_); return *this; } void swap(shared_connection& shared) { shared_.swap(shared.shared_); } void reset() { shared_.reset(); } void reset(xcb_connection_t* ptr) { shared_.reset(ptr, priv::XcbConnectionDelete()); } xcb_connection_t* get() const { return shared_.get(); } explicit operator bool() const { return shared_.get() != nullptr; } private: std::shared_ptr shared_; }; template class unique_resource { public: unique_resource() : id_(XCB_NONE) { } explicit unique_resource(shared_connection const& conn) : conn_(conn), id_(conn ? xcb_generate_id(conn.get()) : XCB_NONE) { } unique_resource(shared_connection const& conn, T id) : conn_(conn), id_(id) { if (id_ == XCB_NONE) conn_.reset(); } unique_resource(unique_resource&& res) : conn_(res.conn_), id_(res.release()) { } ~unique_resource() { destroy(); } unique_resource& operator=(shared_connection const& conn) { reset(conn); return *this; } unique_resource& operator=(unique_resource&& res) { swap(res); return *this; } xcb_connection_t* conn() const { return conn_.get(); } shared_connection const& shared_conn() const { return conn_; } T get() const { return id_; } explicit operator bool() const { return id_ != XCB_NONE; } void reset() { destroy(); conn_.reset(); id_ = XCB_NONE; } void reset(shared_connection const& conn) { if (conn) { reset(conn, xcb_generate_id(conn.get())); } else { reset(); } } void reset(shared_connection const& conn, T id) { destroy(); conn_ = conn; id_ = id; if (id_ == XCB_NONE) conn_.reset(); } void swap(unique_resource& res) { conn_.swap(res.conn_); auto tmp = id_; id_ = res.id_; res.id_ = tmp; } private: unique_resource(unique_resource const&) = delete; unique_resource& operator=(unique_resource const&) = delete; void destroy() { if (id_ == XCB_NONE) return; D()(conn_.get(), id_); } T release() { T ret = id_; id_ = XCB_NONE; conn_.reset(); return ret; } shared_connection conn_; T id_; }; typedef unique_resource unique_window; typedef unique_resource unique_pixmap; typedef unique_resource unique_gcontext; typedef unique_resource unique_picture; typedef unique_resource unique_colormap; struct Format { static uint8_t const FLAG_NEED_BORDER; static uint8_t const FLAG_NEED_COLORMAP; uint8_t depth; xcb_visualtype_t* visual; xcb_render_pictforminfo_t* render; xcb_render_pictforminfo_t* render_alpha; uint8_t flags; bool good() const { return depth > 0 && visual; } bool need_border() const { return flags & FLAG_NEED_BORDER; } bool need_colormap() const { return flags & FLAG_NEED_COLORMAP; } Format(uint8_t depth, xcb_visualtype_t* visual, xcb_render_pictforminfo_t* render, xcb_render_pictforminfo_t* render_alpha, uint8_t flags) : depth(depth), visual(visual), render(render), render_alpha(render_alpha), flags(flags) { } Format() : depth(0), visual(nullptr), render(nullptr), render_alpha(nullptr), flags(0) { } }; xcb_screen_t const* get_screen(xcb_connection_t* conn, int screen); void prefetch_extensions(xcb_connection_t* conn); Format get_best_format(xcb_connection_t* conn, xcb_screen_t const* screen, bool allow_render = true); class Atoms { public: virtual ~Atoms() {} static Atoms* create(shared_connection const& conn); virtual void preload(std::string const& name, bool create = true) = 0; virtual xcb_atom_t get(std::string const& name, bool create = true) = 0; protected: Atoms() {} Atoms(Atoms const&) = delete; Atoms& operator=(Atoms const&) = delete; }; class Ewmh { public: virtual ~Ewmh() {} static Ewmh* create(shared_connection const& conn, int screen); virtual xcb_ewmh_connection_t* conn() = 0; virtual bool supported(xcb_atom_t atom) = 0; protected: Ewmh() {} Ewmh(Ewmh const&) = delete; Ewmh& operator=(Ewmh const&) = delete; }; } // namespace x #endif // X_HH