commit 980cfc1e6fd9b72ec0ab20ab3858900f5866da22
Author: Anjeel <xein@zepp.club>
Date: Sat, 6 Jul 2024 01:47:46 -0300
git: upload
Diffstat:
| A | LICENSE | | | 14 | ++++++++++++++ |
| A | Makefile | | | 30 | ++++++++++++++++++++++++++++++ |
| A | README.md | | | 64 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | config.mk | | | 7 | +++++++ |
| A | libwm.c | | | 613 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | wm.h | | | 257 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
6 files changed, 985 insertions(+), 0 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,14 @@
+Copyright (c) 2015, <blank_for_now>
+<dcat at iotek dot org>, <willy at mailoo dot org>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile b/Makefile
@@ -0,0 +1,30 @@
+include config.mk
+
+LIB = libwm.a
+HDR = wm.h
+
+.POSIX:
+.SUFFIXES: .a .o
+
+all: $(LIB)
+
+.o.a:
+ @echo "AR $@"
+ @$(AR) rcs $@ $<
+
+.c.o:
+ @echo "CC $<"
+ @$(CC) -c $< $(CFLAGS)
+
+install: $(LIB) $(HDR)
+ mkdir -p $(DESTDIR)$(PREFIX)/lib
+ mkdir -p $(DESTDIR)$(PREFIX)/include
+ cp -f $(LIB) $(DESTDIR)$(PREFIX)/lib/
+ cp -f $(HDR) $(DESTDIR)$(PREFIX)/include/
+
+uninstall:
+ rm -f $(DESTDIR)$(PREFIX)/lib/$(LIB)
+ rm -f $(DESTDIR)$(PREFIX)/include/$(HDR)
+
+clean :
+ rm -f $(LIB)
diff --git a/README.md b/README.md
@@ -0,0 +1,64 @@
+libwm
+=====
+A small library for X window manipulation
+
+Features
+-----
+* Depends on [libxcb][0] only
+* Wrappers for all window management operations
+* Built-in checks for off-screen operations
+
+Usage
+-----
+In order to use the library, you must first include its header file in
+your source file:
+
+ #include <wm.h>
+
+To link your program against it, compile it as follows:
+
+ cc pgm.c -lwm -lxcb -o pgm
+
+Here is the list of all functions provided by `libwm`:
+
+ wm_init_xcb();
+ wm_kill_xcb();
+ wm_is_alive(wid);
+ wm_is_ignored(wid);
+ wm_is_listable(wid, mask);
+ wm_is_mapped(wid);
+ wm_add_atom(name, len);
+ wm_set_atom(wid, atom, type, len, data);
+ wm_get_atom(wid, atom, type, &len);
+ wm_get_atom_name(wid, atom, &len);
+ wm_get_screen();
+ wm_get_windows(wid, &list);
+ wm_get_focus();
+ wm_get_attribute(wid, attr);
+ wm_get_cursor(mode, wid, &x, &y);
+ wm_set_border(width, color, wid);
+ wm_set_focus(wid);
+ wm_set_cursor(x, y, mode);
+ wm_set_override(wid, mode);
+ wm_teleport(wid, w, h, x, y);
+ wm_move(wid, mode, x, y);
+ wm_remap(wid, mode);
+ wm_resize(wid, mode, w, h);
+ wm_restack(wid, mode);
+ wm_reg_event(wid, mask);
+ wm_get_monitors(wid, list);
+ wm_get_monitor(index);
+
+Their usage is specified in the `wm.h` header file, as it is quite small for
+now.
+
+Installation
+-----
+Edit config.mk as needed, then build/install with the following commands:
+
+ make
+ make install
+
+Require [libxcb][0].
+
+[0]: https://xcb.freedesktop.org
diff --git a/config.mk b/config.mk
@@ -0,0 +1,7 @@
+PREFIX = /usr/local
+
+CC = cc
+LD = $(CC)
+
+CFLAGS = -I/usr/X11R6/include -L/usr/X11R6/lib -std=c99 -pedantic -Wall -fPIC -Os
+LDFLAGS = -lxcb -lxcb-randr
diff --git a/libwm.c b/libwm.c
@@ -0,0 +1,613 @@
+#include <xcb/xcb.h>
+#include <xcb/xcb_cursor.h>
+#include <xcb/randr.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "wm.h"
+
+int
+wm_init_xcb()
+{
+ conn = xcb_connect(NULL, NULL);
+ if (xcb_connection_has_error(conn))
+ return -1;
+ return 0;
+}
+
+int
+wm_kill_xcb()
+{
+ if (!conn)
+ return -1;
+ xcb_disconnect(conn);
+ return 0;
+}
+
+int
+wm_is_alive(xcb_window_t wid)
+{
+ xcb_get_window_attributes_cookie_t c;
+ xcb_get_window_attributes_reply_t *r;
+
+ c = xcb_get_window_attributes(conn, wid);
+ r = xcb_get_window_attributes_reply(conn, c, NULL);
+
+ if (r == NULL)
+ return 0;
+
+ free(r);
+ return 1;
+}
+
+int
+wm_is_mapped(xcb_window_t wid)
+{
+ int ms;
+ xcb_get_window_attributes_cookie_t c;
+ xcb_get_window_attributes_reply_t *r;
+
+ c = xcb_get_window_attributes(conn, wid);
+ r = xcb_get_window_attributes_reply(conn, c, NULL);
+
+ if (r == NULL)
+ return 0;
+
+ ms = r->map_state;
+
+ free(r);
+ return ms == XCB_MAP_STATE_VIEWABLE;
+}
+
+int
+wm_is_ignored(xcb_window_t wid)
+{
+ int or;
+ xcb_get_window_attributes_cookie_t c;
+ xcb_get_window_attributes_reply_t *r;
+
+ c = xcb_get_window_attributes(conn, wid);
+ r = xcb_get_window_attributes_reply(conn, c, NULL);
+
+ if (r == NULL)
+ return 0;
+
+ or = r->override_redirect;
+
+ free(r);
+ return or;
+}
+
+int
+wm_is_listable(xcb_window_t wid, int mask)
+{
+ if (!mask && wm_is_mapped (wid) && !wm_is_ignored(wid))
+ return 1;
+ if ((mask & LIST_ALL))
+ return 1;
+ if (!wm_is_mapped (wid) && mask & LIST_HIDDEN)
+ return 1;
+ if (wm_is_ignored(wid) && mask & LIST_IGNORE)
+ return 1;
+
+ return 0;
+}
+
+int
+wm_get_screen()
+{
+ scrn = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
+ if (scrn == NULL)
+ return -1;
+ return 0;
+}
+
+int
+wm_get_windows(xcb_window_t wid, xcb_window_t **l)
+{
+ uint32_t childnum = 0;
+ xcb_query_tree_cookie_t c;
+ xcb_query_tree_reply_t *r;
+
+ c = xcb_query_tree(conn, wid);
+ r = xcb_query_tree_reply(conn, c, NULL);
+ if (r == NULL)
+ return -1;
+
+ *l = malloc(sizeof(xcb_window_t) * r->children_len);
+ memcpy(*l, xcb_query_tree_children(r),
+ sizeof(xcb_window_t) * r->children_len);
+
+ childnum = r->children_len;
+
+ free(r);
+ return childnum;
+}
+
+xcb_window_t
+wm_get_focus(void)
+{
+ xcb_window_t wid = 0;
+ xcb_get_input_focus_cookie_t c;
+ xcb_get_input_focus_reply_t *r;
+
+ c = xcb_get_input_focus(conn);
+ r = xcb_get_input_focus_reply(conn, c, NULL);
+ if (r == NULL)
+ return scrn->root;
+
+ wid = r->focus;
+ free(r);
+ return wid;
+}
+
+
+int
+wm_get_attribute(xcb_window_t wid, int attr)
+{
+ xcb_get_geometry_cookie_t c;
+ xcb_get_geometry_reply_t *r;
+
+ c = xcb_get_geometry(conn, wid);
+ r = xcb_get_geometry_reply(conn, c, NULL);
+
+ if (r == NULL)
+ return -1;
+
+ switch (attr) {
+ case ATTR_X:
+ attr = r->x;
+ break;
+ case ATTR_Y:
+ attr = r->y;
+ break;
+ case ATTR_W:
+ attr = r->width;
+ break;
+ case ATTR_H:
+ attr = r->height;
+ break;
+ case ATTR_B:
+ attr = r->border_width;
+ break;
+ case ATTR_D:
+ attr = r->depth;
+ break;
+ }
+
+ free(r);
+ return attr;
+}
+
+xcb_atom_t
+wm_add_atom(char *name, size_t len)
+{
+ xcb_atom_t atom;
+ xcb_intern_atom_cookie_t c;
+ xcb_intern_atom_reply_t *r;
+
+ c = xcb_intern_atom(conn, 0, len, name);
+ r = xcb_intern_atom_reply(conn, c, NULL);
+ if (!r)
+ return 0;
+
+ atom = r->atom;
+ free(r);
+
+ return atom;
+}
+
+int
+wm_set_atom(xcb_window_t wid, xcb_atom_t atom, xcb_atom_t type, size_t len, void *data)
+{
+ int errcode;
+ xcb_void_cookie_t c;
+ xcb_generic_error_t *e;
+
+ c = xcb_change_property_checked(conn, XCB_PROP_MODE_REPLACE,
+ wid, atom, type, 32, len, data);
+ e = xcb_request_check(conn, c);
+ if (!e)
+ return 0;
+
+ errcode = e->error_code;
+ free(e);
+
+ return errcode;
+}
+
+void *
+wm_get_atom(xcb_window_t wid, xcb_atom_t atom, xcb_atom_t type, size_t *len)
+{
+ void *d;
+ size_t n;
+ xcb_get_property_cookie_t c;
+ xcb_get_property_reply_t *r;
+
+ c = xcb_get_property(conn, 0, wid, atom, type, 0, 32);
+ r = xcb_get_property_reply(conn, c, NULL);
+ if (!r)
+ return NULL;
+
+ if (!(n = xcb_get_property_value_length(r))) {
+ free(r);
+ return NULL;
+ }
+
+ if (len)
+ *len = n;
+
+ d = xcb_get_property_value(r);
+
+ return d;
+}
+
+char *
+wm_get_atom_name(xcb_atom_t atom, size_t *len)
+{
+ size_t n;
+ char *name;
+ xcb_get_atom_name_cookie_t c;
+ xcb_get_atom_name_reply_t *r;
+
+ c = xcb_get_atom_name(conn, atom);
+ r = xcb_get_atom_name_reply(conn, c, NULL);
+ if (!r)
+ return NULL;
+
+ n = xcb_get_atom_name_name_length(r) + 1;
+ name = malloc(xcb_get_atom_name_name_length(r) + 1);
+ if (!name) {
+ free(r);
+ return NULL;
+ }
+
+ if (len)
+ *len = n;
+
+ memset(name, 0, xcb_get_atom_name_name_length(r) + 1);
+ strncpy(name, xcb_get_atom_name_name(r), xcb_get_atom_name_name_length(r));
+ free(r);
+
+ return name;
+}
+
+
+int
+wm_get_cursor(int mode, uint32_t wid, int *x, int *y)
+{
+ xcb_query_pointer_reply_t *r;
+ xcb_query_pointer_cookie_t c;
+
+ c = xcb_query_pointer(conn, wid);
+ r = xcb_query_pointer_reply(conn, c, NULL);
+
+ if (r == NULL)
+ return -1;
+
+ if (r->child != XCB_NONE) {
+ *x = r->win_x;
+ *y = r->win_y;
+ } else {
+ *x = r->root_x;
+ *y = r->root_y;
+ }
+
+ return 0;
+}
+
+int
+wm_set_border(int width, int color, xcb_window_t wid)
+{
+ uint32_t values[1];
+ int mask;
+
+ /* change width if >= 0 */
+ if (width > -1) {
+ values[0] = width;
+ mask = XCB_CONFIG_WINDOW_BORDER_WIDTH;
+ xcb_configure_window(conn, wid, mask, values);
+ }
+
+ /*
+ * color is an ARGB representation (eg. 0x80ff0000) for
+ * translucent red.
+ * Absolutely all values are valid color representations, so we
+ * will set it no matter what.
+ */
+ values[0] = color;
+ mask = XCB_CW_BORDER_PIXEL;
+ xcb_change_window_attributes(conn, wid, mask, values);
+
+ return 0;
+}
+
+int
+wm_set_cursor(int x, int y, int mode)
+{
+ xcb_warp_pointer(conn, XCB_NONE, mode ? XCB_NONE : scrn->root,
+ 0, 0, 0, 0, x, y);
+ return 0;
+}
+
+int
+wm_teleport(xcb_window_t wid, int x, int y, int w, int h)
+{
+ uint32_t values[4];
+ uint32_t mask = XCB_CONFIG_WINDOW_X
+ | XCB_CONFIG_WINDOW_Y
+ | XCB_CONFIG_WINDOW_WIDTH
+ | XCB_CONFIG_WINDOW_HEIGHT;
+ values[0] = x;
+ values[1] = y;
+ values[2] = w;
+ values[3] = h;
+ xcb_configure_window(conn, wid, mask, values);
+
+ return 0;
+}
+
+int
+wm_move(xcb_window_t wid, int mode, int x, int y)
+{
+ int curx, cury, curw, curh, curb;
+
+ if (!wm_is_mapped(wid) || wid == scrn->root)
+ return -1;
+
+ curb = wm_get_attribute(wid, ATTR_B);
+ curx = wm_get_attribute(wid, ATTR_X);
+ cury = wm_get_attribute(wid, ATTR_Y);
+ curw = wm_get_attribute(wid, ATTR_W);
+ curh = wm_get_attribute(wid, ATTR_H);
+
+ if (mode == RELATIVE) {
+ x += curx;
+ y += cury;
+ }
+
+ /* the following prevent windows from moving off the screen */
+ if (x < 0)
+ x = 0;
+ else if (x > scrn->width_in_pixels - curw - 2*curb)
+ x = scrn->width_in_pixels - curw - 2*curb;
+
+ if (y < 0)
+ y = 0;
+ else if (y > scrn->height_in_pixels - curh - 2*curb)
+ y = scrn->height_in_pixels - curh - 2*curb;
+
+ wm_teleport(wid, x, y, curw, curh);
+ return 0;
+}
+
+int
+wm_set_override(xcb_window_t wid, int or)
+{
+ uint32_t mask = XCB_CW_OVERRIDE_REDIRECT;
+ uint32_t val[] = { or };
+
+ xcb_change_window_attributes(conn, wid, mask, val);
+
+ return 0;
+}
+
+
+int
+wm_remap(xcb_window_t wid, int mode)
+{
+ switch (mode) {
+ case MAP:
+ xcb_map_window(conn, wid);
+ break;
+ case UNMAP:
+ xcb_unmap_window(conn, wid);
+ break;
+ case TOGGLE:
+ if (wm_is_mapped(wid))
+ xcb_unmap_window(conn, wid);
+ else
+ xcb_map_window(conn, wid);
+ break;
+ }
+
+ return 0;
+}
+
+int
+wm_resize(xcb_window_t wid, int mode, int w, int h)
+{
+ int curx, cury, curw, curh, curb;
+
+ if (!wm_is_mapped(wid) || wid == scrn->root)
+ return -1;
+
+ curb = wm_get_attribute(wid, ATTR_B);
+ curx = wm_get_attribute(wid, ATTR_X);
+ cury = wm_get_attribute(wid, ATTR_Y);
+ curw = wm_get_attribute(wid, ATTR_W);
+ curh = wm_get_attribute(wid, ATTR_H);
+
+ if (mode == RELATIVE) {
+ w += curw;
+ h += curh;
+ } else {
+ w -= curx;
+ h -= cury;
+ }
+
+ /*
+ * The following prevent windows from growing out of the screen, or
+ * having a negative size
+ */
+ if (w < 0)
+ w = curw;
+ if (curx + w > scrn->width_in_pixels)
+ w = scrn->width_in_pixels - curx - 2*curb;
+
+ if (h < 0)
+ h = curh;
+ if (cury + h > scrn->height_in_pixels)
+ h = scrn->height_in_pixels - cury - 2*curb;
+
+ wm_teleport(wid, curx, cury, w, h);
+ return 0;
+}
+
+int
+wm_restack(xcb_window_t wid, uint32_t mode)
+{
+ uint32_t values[1] = { mode };
+ xcb_configure_window(conn, wid, XCB_CONFIG_WINDOW_STACK_MODE, values);
+ return 0;
+}
+
+int
+wm_set_focus(xcb_window_t wid)
+{
+ xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, wid,
+ XCB_CURRENT_TIME);
+ return 0;
+}
+
+int
+wm_reg_window_event(xcb_window_t wid, uint32_t mask)
+{
+ uint32_t val[] = { mask };
+ xcb_void_cookie_t c;
+ xcb_generic_error_t *e;
+
+ c = xcb_change_window_attributes_checked(conn, wid, XCB_CW_EVENT_MASK, val);
+ e = xcb_request_check(conn, c);
+ if (!e)
+ return -1;
+
+ free(e);
+ return 0;
+}
+
+
+int
+wm_reg_cursor_event(xcb_window_t wid, uint32_t mask, char *cursor)
+{
+ xcb_cursor_t p;
+ xcb_cursor_context_t *cx;
+ xcb_grab_pointer_cookie_t c;
+ xcb_grab_pointer_reply_t *r;
+
+ p = XCB_NONE;
+ if (cursor) {
+ if (xcb_cursor_context_new(conn, scrn, &cx) < 0)
+ return -1;
+
+ p = xcb_cursor_load_cursor(cx, cursor);
+ }
+
+ c = xcb_grab_pointer(conn, 1, scrn->root, mask,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
+ XCB_NONE, p, XCB_CURRENT_TIME);
+
+ r = xcb_grab_pointer_reply(conn, c, NULL);
+ if (!r || r->status != XCB_GRAB_STATUS_SUCCESS)
+ return -1;
+
+ xcb_cursor_context_free(cx);
+ return 0;
+}
+
+int
+wm_get_monitors(xcb_window_t wid, int *l)
+{
+ int n;
+ xcb_randr_get_monitors_cookie_t c;
+ xcb_randr_get_monitors_reply_t *r;
+ xcb_randr_monitor_info_iterator_t i;
+
+ /* get_active: ignore inactive monitors */
+ c = xcb_randr_get_monitors(conn, wid, 0);
+ r = xcb_randr_get_monitors_reply(conn, c, NULL);
+ if (!r)
+ return -1;
+
+ i = xcb_randr_get_monitors_monitors_iterator(r);
+ if (!i.data)
+ return 0;
+
+ for (n = 0; l && i.rem > 0; xcb_randr_monitor_info_next(&i))
+ l[n++] = i.index;
+
+ n = r->nMonitors;
+ free(r);
+
+ return n;
+}
+
+xcb_randr_monitor_info_t *
+wm_get_monitor(int index)
+{
+ xcb_randr_monitor_info_t *monitor;
+ xcb_randr_get_monitors_cookie_t c;
+ xcb_randr_get_monitors_reply_t *r;
+ xcb_randr_monitor_info_iterator_t i;
+
+ /* get_active: ignore inactive monitors */
+ c = xcb_randr_get_monitors(conn, scrn->root, 0);
+ r = xcb_randr_get_monitors_reply(conn, c, NULL);
+ if (!r)
+ return NULL;
+
+ i = xcb_randr_get_monitors_monitors_iterator(r);
+ if (!i.data)
+ return NULL;
+
+ for (; i.rem > 0; xcb_randr_monitor_info_next(&i)) {
+ if (i.index != index)
+ continue;
+
+ monitor = calloc(1, sizeof(*monitor));
+ if (!monitor)
+ return NULL;
+
+ memcpy(monitor, i.data, sizeof(*monitor));
+ free(r);
+ return monitor;
+ }
+
+ free(r);
+ return NULL;
+}
+
+int
+wm_find_monitor(int x, int y)
+{
+ /* patch me if you use more than 64 monitors, and get a reward! */
+ int n, monitors[64];
+ xcb_randr_monitor_info_t *p;
+
+ n = wm_get_monitors(scrn->root, monitors);
+
+ /*
+ * When you have multiple monitors, like so:
+ * - 1920x1080+0+0
+ * - 1920x1080+1920+0
+ * the pixel located at 1920,500 would match both the first AND
+ * second monitor. By crawling monitors backward it ensures that
+ * the "farthest" monitor will match first.
+ * Also I love that backward loop notation.
+ */
+ while (n --> 0) {
+ p = wm_get_monitor(monitors[n]);
+ if (!p)
+ continue;
+
+ if (x >= p->x && x <= p->x + p->width
+ && y >= p->y && y <= p->y + p->height) {
+ free(p);
+ return monitors[n];
+ }
+ free(p);
+ }
+
+ return -1;
+}
diff --git a/wm.h b/wm.h
@@ -0,0 +1,257 @@
+#ifndef __LIBWM_H__
+#define __LIBWM_H__
+
+/*
+ * Variables used to hold the connection to the X server, and the first screen
+ * of this connection. Both have to be defined as `extern`.
+ */
+extern xcb_connection_t *conn;
+extern xcb_screen_t *scrn;
+
+/*
+ * Mask attributes used to select which windows have to be listed by the
+ * function `wm_is_listable(wid, mask)`.
+ */
+enum {
+ LIST_HIDDEN = 1 << 0, /* windows that are not on-screen */
+ LIST_IGNORE = 1 << 1, /* windows with override_redirect set to 1 */
+ LIST_ALL = 1 << 2 /* All existing windows */
+};
+
+/*
+ * Actions used by the `wm_remap(wid, mode)` function to select what needs to be
+ * done.
+ */
+enum {
+ MAP = 1 << 0,
+ UNMAP = 1 << 1,
+ TOGGLE = 1 << 2
+};
+
+/*
+ * Attributes used internally by different functions to refer to windows
+ * attributes, and select them.
+ */
+enum {
+ ATTR_W = 1 << 0,
+ ATTR_H = 1 << 1,
+ ATTR_X = 1 << 2,
+ ATTR_Y = 1 << 3,
+ ATTR_B = 1 << 4,
+ ATTR_M = 1 << 5,
+ ATTR_I = 1 << 6,
+ ATTR_D = 1 << 7,
+ ATTR_MAX
+};
+
+/*
+ * Selector used by both `wm_move(wid, mode, x, y)` and `wm_resize(wid, mode, w, h)`
+ * to choose between relative or absolute coordinates
+ */
+enum {
+ ABSOLUTE = 0,
+ RELATIVE = 1
+};
+
+/*
+ * Initialize the connection to the X server. The connection could then be
+ * accessed by other functions through the "conn" variable.
+ */
+int wm_init_xcb();
+
+/*
+ * Close connection to the X server.
+ */
+int wm_kill_xcb();
+
+/*
+ * Check existence of a window.
+ * + 1 - window exists
+ * + 0 - window doesn't exist
+ */
+int wm_is_alive(xcb_window_t wid);
+
+/*
+ * Returns the value of the "override_redirect" attribute of a window.
+ * When this attribute is set to 1, it means the window manager should NOT
+ * handle this window.
+ */
+int wm_is_ignored(xcb_window_t wid);
+
+/*
+ * Returns 1 if a window match the mask, 0 otherwise.
+ * Possible value for the masks are:
+ * LIST_HIDDEN
+ * LIST_IGNORE
+ * LIST_ALL
+ */
+int wm_is_listable(xcb_window_t wid, int mask);
+
+/*
+ * Returns 1 if the window is mapped on screen, 0 otherwise
+ */
+int wm_is_mapped(xcb_window_t wid);
+
+/*
+ * Request the X server to add a new atom, and return this new atom ID
+ */
+xcb_atom_t wm_add_atom(char *name, size_t len);
+
+/*
+ * Change the value of the specified atom
+ */
+int wm_set_atom(xcb_window_t wid, xcb_atom_t atom, xcb_atom_t type, size_t len, void *data);
+
+/*
+ * Retrieve the value of the given atom. The value length is set in the
+ * `len` pointer if specified
+ */
+void *wm_get_atom(xcb_window_t wid, xcb_atom_t atom, xcb_atom_t type, size_t *len);
+
+/*
+ * Retrieve the name of the given atom. The name length is set in the
+ * `len` pointer if specified
+ */
+char *wm_get_atom_name(xcb_atom_t atom, size_t *len);
+
+/*
+ * Get the first screen, and set the `scrn` global variable accordingly.
+ */
+int wm_get_screen();
+
+/*
+ * Ask the list of all existing windows to the X server, and fills the `*list`
+ * argument with them.
+ * The windows are listed in stacking order, from lower to upper window.
+ * Returns the number of windows in the *list array
+ */
+int wm_get_windows(xcb_window_t wid, xcb_window_t **list);
+
+/*
+ * Returns the window that has keyboard focus
+ * Will return the root window ID if no window has focus
+ */
+xcb_window_t wm_get_focus(void);
+
+/*
+ * Retrieve the value of an attribute for a specific windows.
+ * The possible values for the attributes are:
+ * ATTR_W - width
+ * ATTR_H - height
+ * ATTR_X - X offset
+ * ATTR_Y - Y offset
+ * ATTR_B - border width
+ * ATTR_M - map state
+ * ATTR_I - ignore state (override_redirect)
+ */
+int wm_get_attribute(xcb_window_t wid, int attr);
+
+/*
+ * Get the cursor position, and store its coordinates in the `x` and `y`
+ * pointers.
+ * The `mode` attribute isn't used yet, but is reserved to ask for either
+ * absolute or relative coordinates
+ */
+int wm_get_cursor(int mode, uint32_t wid, int *x, int *y);
+
+/*
+ * Set a window's border.
+ * The color should be an hexadecimal number, eg: 0xdeadca7
+ */
+int wm_set_border(int width, int color, xcb_window_t wid);
+
+/*
+ * Give the input focus to the specified window
+ */
+int wm_set_focus(xcb_window_t wid);
+
+/*
+ * Change the cursor position, either relatively or absolutely, eg:
+ * wm_set_cursor(10, 10, ABSOLUTE);
+ * wm_set_cursor(-10, 20, RELATIVE);
+ */
+int wm_set_cursor(int x, int y, int mode);
+
+/*
+ * Set override_redirect value for given window
+ */
+int wm_set_override(xcb_window_t wid, int override);
+
+/*
+ * Teleport a window to the given position.
+ */
+int wm_teleport(xcb_window_t wid, int w, int h, int x, int y);
+
+/*
+ * Move a window to the given position, either relatively or absolutely.
+ * If the wm_move is supposed to wm_move the window outside the screen, then the
+ * windows will only be wm_moved to the edge of the screen.
+ *
+ * You cannot wm_move windows outside the screen with this method. Use
+ * `wm_teleport()` instead.
+ */
+int wm_move(xcb_window_t wid, int mode, int x, int y);
+
+/*
+ * Resize a window to the given size, either relatively or absolutely.
+ * If the wm_resize is supposed to put an area of the window outside the screen,
+ * then the windows will only be wm_resized to the edge of the screen.
+ *
+ * You cannot wm_resize windows farther than the screen edge with this method. Use
+ * `wm_teleport()` instead.
+ */
+int wm_resize(xcb_window_t wid, int mode, int w, int h);
+
+/*
+ * Change the mapping state of a window. The `mode` attribute can be as follow:
+ * MAP
+ * UNMAP
+ * TOGGLE
+ */
+int wm_remap(xcb_window_t wid, int mode);
+
+/*
+ * Change the position of the given window in the stack order.
+ * You can either put it at the top, or at the bottom.
+ * The possible values for the mode are:
+ * XCB_STACK_MODE_ABOVE
+ * XCB_STACK_MODE_BELOW
+ * XCB_STACK_MODE_OPPOSITE
+ */
+int wm_restack(xcb_window_t wid, uint32_t mode);
+
+/*
+ * Register the given event(s) on the window.
+ * Multiple events can be registered by ORing them together
+ */
+int wm_reg_window_event(xcb_window_t wid, uint32_t mask);
+
+/*
+ * Register the given cursor event(s) on the window.
+ * Multiple events can be registered by ORing them together.
+ * The cursor will be changed to the `cursor` while the pointer is
+ * grabbed, if not NULL.
+ */
+int wm_reg_cursor_event(xcb_window_t wid, uint32_t mask, char *cursor);
+
+/*
+ * Return the number of active monitors connected to the display where
+ * window `wid` is sitting.
+ * The `list` argument, if not NULL, will be filled with the monitor's
+ * index numbers. Note that `list` must be big enough to hold all indexes,
+ * as it is not reallocated.
+ */
+int wm_get_monitors(xcb_window_t wid, int *list);
+
+/*
+ * Return the info scructure defining monitor with index number `index`.
+ */
+xcb_randr_monitor_info_t *wm_get_monitor(int index);
+
+/*
+ * Return the index of the (first) monitor associated with the
+ * coordinates.
+ */
+int wm_find_monitor(int x, int y);
+
+#endif /* __LIBWM_H__ */