diff options
| author | Joel Klinghed <the_jk@yahoo.com> | 2017-09-26 20:09:31 +0200 |
|---|---|---|
| committer | Joel Klinghed <the_jk@yahoo.com> | 2017-09-26 20:09:31 +0200 |
| commit | c85b624d28564a6f785b25000e2b7825592a919d (patch) | |
| tree | 647b756c824b470b35f1371eb869e9534ed6c1bb /src/x.hh | |
Initial commit
Diffstat (limited to 'src/x.hh')
| -rw-r--r-- | src/x.hh | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/src/x.hh b/src/x.hh new file mode 100644 index 0000000..ce4f812 --- /dev/null +++ b/src/x.hh @@ -0,0 +1,255 @@ +#ifndef X_HH +#define X_HH + +#include <memory> +#include <xcb/render.h> +#include <xcb/xcb.h> +#include <xcb/xcb_ewmh.h> +#include <xcb/xproto.h> +#include <xcb/render.h> + +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); + } +}; + +} // 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<xcb_connection_t> shared_; +}; + +template<typename T, typename D> +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<xcb_window_t, priv::XcbWindowDelete> unique_window; +typedef unique_resource<xcb_pixmap_t, priv::XcbPixmapDelete> unique_pixmap; +typedef unique_resource<xcb_gcontext_t, + priv::XcbGContextDelete> unique_gcontext; +typedef unique_resource<xcb_render_picture_t, + priv::XcbRenderPictureDelete> unique_picture; + +struct Format { + uint8_t depth; + xcb_visualtype_t* visual; + xcb_render_pictforminfo_t* render; + xcb_render_pictforminfo_t* render_alpha; + + bool good() const { + return depth > 0 && visual; + } + + Format(uint8_t depth, xcb_visualtype_t* visual, + xcb_render_pictforminfo_t* render, + xcb_render_pictforminfo_t* render_alpha) + : depth(depth), visual(visual), render(render), render_alpha(render_alpha) { + } + Format() + : depth(0), visual(nullptr), render(nullptr), render_alpha(nullptr) { + } +}; + +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 |
