summaryrefslogtreecommitdiff
path: root/src/x.hh
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@yahoo.com>2017-09-26 20:09:31 +0200
committerJoel Klinghed <the_jk@yahoo.com>2017-09-26 20:09:31 +0200
commitc85b624d28564a6f785b25000e2b7825592a919d (patch)
tree647b756c824b470b35f1371eb869e9534ed6c1bb /src/x.hh
Initial commit
Diffstat (limited to 'src/x.hh')
-rw-r--r--src/x.hh255
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