libwm

A small library for X window manipulation
git clone git://git.zepp.club/libwm.git
Log | Files | Refs | README | LICENSE

commit 980cfc1e6fd9b72ec0ab20ab3858900f5866da22
Author: Anjeel <xein@zepp.club>
Date:   Sat,  6 Jul 2024 01:47:46 -0300

git: upload

Diffstat:
ALICENSE | 14++++++++++++++
AMakefile | 30++++++++++++++++++++++++++++++
AREADME.md | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig.mk | 7+++++++
Alibwm.c | 613+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awm.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__ */