commit 24a9d7d38f9523044bffa1594dd468b395ebb4a7
Author: Anjeel <xein@zepp.club>
Date: Sat, 6 Jul 2024 01:49:54 -0300
git: upload
Diffstat:
| A | LICENSE | | | 16 | ++++++++++++++++ |
| A | Makefile | | | 56 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | README.md | | | 103 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | arg.h | | | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | atomx.c | | | 145 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | chwb.c | | | 96 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | chwso.c | | | 67 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | config.mk | | | 9 | +++++++++ |
| A | ignw.c | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | killw.c | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | lsw.c | | | 96 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | man/Makefile | | | 31 | +++++++++++++++++++++++++++++++ |
| A | man/atomx.1 | | | 43 | +++++++++++++++++++++++++++++++++++++++++++ |
| A | man/chwb.1 | | | 40 | ++++++++++++++++++++++++++++++++++++++++ |
| A | man/chwso.1 | | | 33 | +++++++++++++++++++++++++++++++++ |
| A | man/ignw.1 | | | 37 | +++++++++++++++++++++++++++++++++++++ |
| A | man/killw.1 | | | 25 | +++++++++++++++++++++++++ |
| A | man/lsw.1 | | | 43 | +++++++++++++++++++++++++++++++++++++++++++ |
| A | man/mapw.1 | | | 32 | ++++++++++++++++++++++++++++++++ |
| A | man/pdw.1 | | | 24 | ++++++++++++++++++++++++ |
| A | man/pfw.1 | | | 16 | ++++++++++++++++ |
| A | man/slw.1 | | | 17 | +++++++++++++++++ |
| A | man/wattr.1 | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | man/wmp.1 | | | 37 | +++++++++++++++++++++++++++++++++++++ |
| A | man/wmutils.1 | | | 64 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | man/wmv.1 | | | 41 | +++++++++++++++++++++++++++++++++++++++++ |
| A | man/wrs.1 | | | 31 | +++++++++++++++++++++++++++++++ |
| A | man/wtf.1 | | | 19 | +++++++++++++++++++ |
| A | man/wtp.1 | | | 27 | +++++++++++++++++++++++++++ |
| A | mapw.c | | | 71 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | pdw.c | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | pfw.c | | | 45 | +++++++++++++++++++++++++++++++++++++++++++++ |
| A | slw.c | | | 71 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | util.c | | | 106 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | util.h | | | 14 | ++++++++++++++ |
| A | wattr.c | | | 118 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | wmp.c | | | 92 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | wmv.c | | | 100 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | wrs.c | | | 93 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | wtf.c | | | 44 | ++++++++++++++++++++++++++++++++++++++++++++ |
| A | wtp.c | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
41 files changed, 2297 insertions(+), 0 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,16 @@
+ISC License
+
+Copyright (c) 2014-2016 brosephs <dcat at iotek dot org>,
+ <willy at mailoo dot org>
+
+Permission to use, copy, modify, and 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,56 @@
+include config.mk
+
+HDR = arg.h util.h
+SRC = \
+ pfw.c \
+ pdw.c \
+ lsw.c \
+ mapw.c \
+ killw.c \
+ wattr.c \
+ wtp.c \
+ wmv.c \
+ chwso.c \
+ wtf.c \
+ wrs.c \
+ chwb.c \
+ ignw.c \
+ wmp.c \
+ slw.c \
+ atomx.c
+
+OBJ = $(SRC:.c=.o)
+BIN = $(SRC:.c=)
+MAN = $(SRC:.c=.1)
+
+.POSIX:
+.SUFFIXES: .1 .1.gz
+
+all: binutils
+
+binutils: $(BIN)
+
+$(OBJ): $(HDR) util.o
+
+.o:
+ @echo "LD $@"
+ @$(LD) $< util.o -o $@ $(LDFLAGS)
+
+.c.o:
+ @echo "CC $<"
+ @$(CC) -c $< -o $@ $(CFLAGS)
+
+install: $(BIN)
+ mkdir -p $(DESTDIR)$(PREFIX)/bin/
+ cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin/
+ cd man; $(MAKE) install
+
+uninstall:
+ @echo "uninstalling binaries"
+ @for util in $(BIN); do \
+ rm -f $(DESTDIR)$(PREFIX)/bin/$$util; \
+ done
+ cd man; $(MAKE) uninstall
+
+clean :
+ rm -f $(OBJ) $(BIN) util.o
diff --git a/README.md b/README.md
@@ -0,0 +1,103 @@
+wmutils' core
+=============
+
+wmutils' core is a set of tools for X windows manipulation. Each tool only has
+one purpose, to make it as flexible and reliable as possible.
+
+Here's a quick example. This snippet will put the currently focused window in
+the middle of the screen:
+
+ #!/bin/sh
+
+ # get current window id, width and height
+ WID=$(pfw)
+ WW=$(wattr w $WID)
+ WH=$(wattr h $WID)
+
+ # get screen width and height
+ ROOT=$(lsw -r)
+ SW=$(wattr w $ROOT)
+ SH=$(wattr h $ROOT)
+
+ # move the current window to the center of the screen
+ wtp $(((SW - WW)/2)) $(((SH - WH)/2)) $WW $WH $WID
+
+You also might want to check [sxhkd](https://github.com/baskerville/sxhkd), a
+daemon which allow binding applications to hot keys.
+
+utilities
+---------
+
+* chwb - change window's border
+* chwso - change window's stacking order
+* ignw - ignore/unignore window
+* killw - kill windows
+* lsw - list windows
+* mapw - map/unmap windows
+* pfw - print focused window
+* pdw - print decoration window
+* slw - select window interactively
+* wattr - show window's attributes
+* wmp - move the mouse pointer
+* wmv - move a window
+* wrs - resize a window
+* wtf - focus a window
+* wtp - teleport a window
+* atomx - modify atoms on a window
+
+All these tools come with a manpage ! read them for further informations.
+
+dependencies
+------------
+
+wmutils only relies on the XCB library.
+
+license
+-------
+
+All the code of this project is released under the
+[ISC](http://www.openbsd.org/policy.html) license. See LICENSE file.
+
+build & install
+---------------
+
+System-wide installation (default PREFIX is `/usr`):
+
+ $ make
+ # make install
+
+Here are the variables you can override, along with their default values:
+
+ CC = cc
+ LD = $(CC)
+ CFLAGS = -std=c99 -pedantic -Wall -Os
+ LDFLAGS = -lxcb
+ PREFIX = /usr
+ MANPREFIX = $(PREFIX)/man
+ DESTDIR =
+
+You can override them by passing them on the command line:
+
+ make DESTDIR=/newroot install
+
+Or by setting them via the environment:
+
+ CC=c99; export CC
+ make -e
+
+contribute
+----------
+
+You can contribute to the project in many ways; be it by testing the software,
+reporting bugs, submitting patches, or simply talking about it to other
+people!
+The official IRC channel for wmutils' talks is #wmutils @irc.freenode.net.
+
+If you find a bug in the software, please report an issue. Same goes for
+feature requests, if they match the project's philosophy.
+
+When submitting pull requests, please reference the issue number. If there is
+no issue to reference, then create one and wait for a validation of the bug
+before submitting the pull request.
+
+IF YOUR PULL REQUEST DOESN'T REFER TO A VALID ISSUE, IT WILL BE DISCARDED.
diff --git a/arg.h b/arg.h
@@ -0,0 +1,63 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef ARG_H__
+#define ARG_H__
+
+extern char *argv0;
+
+/* use main(int argc, char *argv[]) */
+#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
+ argv[0] && argv[0][1]\
+ && argv[0][0] == '-';\
+ argc--, argv++) {\
+ char argc_;\
+ char **argv_;\
+ int brk_;\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
+ break;\
+ }\
+ for (brk_ = 0, argv[0]++, argv_ = argv;\
+ argv[0][0] && !brk_;\
+ argv[0]++) {\
+ if (argv_ != argv)\
+ break;\
+ argc_ = argv[0][0];\
+ switch (argc_)
+
+/* Handles obsolete -NUM syntax */
+#define ARGNUM case '0':\
+ case '1':\
+ case '2':\
+ case '3':\
+ case '4':\
+ case '5':\
+ case '6':\
+ case '7':\
+ case '8':\
+ case '9'
+
+#define ARGEND }\
+ }
+
+#define ARGC() argc_
+
+#define ARGNUMF(base) (brk_ = 1, estrtol(argv[0], (base)))
+
+#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ ((x), abort(), (char *)0) :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ (char *)0 :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#endif
diff --git a/atomx.c b/atomx.c
@@ -0,0 +1,145 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+#include "util.h"
+#include "arg.h"
+
+#define MAXLEN 512
+
+static xcb_connection_t *conn;
+
+void
+usage(char *name)
+{
+ fprintf(stderr, "%s [-d] atom[=value] wid\n", name);
+}
+
+xcb_atom_t
+add_atom(xcb_atom_t type, 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
+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, 8, len, data);
+ e = xcb_request_check(conn, c);
+ if (!e)
+ return 0;
+
+ errcode = e->error_code;
+ free(e);
+
+ return errcode;
+}
+
+int
+get_atom(xcb_window_t wid, xcb_atom_t atom, char *data, xcb_atom_t *type)
+{
+ size_t n;
+ xcb_get_property_cookie_t c;
+ xcb_get_property_reply_t *r;
+
+ c = xcb_get_property(conn, 0, wid, atom, XCB_ATOM_ANY, 0, MAXLEN);
+ r = xcb_get_property_reply(conn, c, NULL);
+ if (!r)
+ return -1;
+
+ if (!(n = xcb_get_property_value_length(r))) {
+ free(r);
+ return -1;
+ }
+
+ strncpy(data, xcb_get_property_value(r), n);
+ data[n] = 0;
+
+ *type = r->type;
+
+ free(r);
+
+ return 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ int i, dflag = 0;
+ char *key, *val, *argv0;
+ char data[MAXLEN];
+ xcb_window_t wid;
+ xcb_atom_t atom;
+
+ ARGBEGIN {
+ case 'd':
+ dflag = 1;
+ break;
+ default:
+ usage(argv0);
+ return -1;
+ } ARGEND;
+
+ if (argc < 1)
+ return -1;
+
+ key = strtok(argv[0], "=");
+ val = strtok(NULL, "=");
+
+ init_xcb(&conn);
+
+ for (i = 0; i < argc - 1; i++) {
+ wid = strtoul(argv[i+1], NULL, 16);
+
+ /* retrieve atom ID from server */
+ atom = add_atom(XCB_ATOM_STRING, key, strlen(key));
+ if (!atom)
+ return -1;
+
+ /* set property on window (must be a string) */
+ if (val)
+ set_atom(wid, atom, XCB_ATOM_STRING, strlen(val), val);
+
+ /* remove property from window */
+ if (dflag)
+ xcb_delete_property(conn, wid, atom);
+
+ /* retrieve and print atom value to stdout */
+ xcb_atom_t type;
+ if (!get_atom(wid, atom, data, &type))
+ switch (type) {
+ case XCB_ATOM_INTEGER:
+ printf("%d\n", *data);
+ break;
+ default:
+ printf("%s\n", data);
+ }
+ }
+
+ kill_xcb(&conn);
+
+ return 0;
+}
diff --git a/chwb.c b/chwb.c
@@ -0,0 +1,96 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+
+#include "arg.h"
+#include "util.h"
+
+static xcb_connection_t *conn;
+
+static void usage(char *name);
+static void set_border(int, int, xcb_window_t);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s <-sc ...> <wid> [wid...]\n", name);
+ exit(1);
+}
+
+static void
+set_border(int width, int color, xcb_window_t win)
+{
+ uint32_t values[3];
+ uint16_t curr_width;
+ int mask;
+ xcb_get_geometry_reply_t *geom;
+
+ if (width != -1) {
+ geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL);
+ if (!geom)
+ return;
+
+ /* Windows track position based on the top left corner of the border.
+ * To make the border move instead of the window, we move the window up and left
+ * by the amount the border would have shifted it down and right.*/
+ curr_width = geom->border_width;
+ values[0] = geom->x + curr_width - width;
+ values[1] = geom->y + curr_width - width;
+ values[2] = width;
+
+ mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_BORDER_WIDTH ;
+ xcb_configure_window(conn, win, mask, values);
+
+ xcb_aux_sync(conn);
+
+ free(geom);
+ }
+
+ if (color != -1) {
+ values[0] = color;
+ mask = XCB_CW_BORDER_PIXEL;
+ xcb_change_window_attributes(conn, win, mask, values);
+
+ xcb_aux_sync(conn);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ char *argv0;
+ int color,width;
+
+ color = width = -1;
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ ARGBEGIN {
+ case 's':
+ width = strtoul(EARGF(usage(argv0)), NULL, 10);
+ break;
+ case 'c':
+ color = strtoul(EARGF(usage(argv0)), NULL, 16);
+ break;
+ default:
+ usage(argv0);
+ /* NOTREACHED */
+ } ARGEND
+
+ init_xcb(&conn);
+
+ /* assume remaining arguments are windows */
+ while (*argv)
+ set_border(width, color, strtoul(*argv++, NULL, 16));
+
+ xcb_aux_sync(conn);
+
+ kill_xcb(&conn);
+
+ return 0;
+}
diff --git a/chwso.c b/chwso.c
@@ -0,0 +1,67 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+
+#include "arg.h"
+#include "util.h"
+
+static xcb_connection_t *conn;
+
+static void usage(char *);
+static void stack(xcb_window_t, uint32_t[1]);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s -rli <wid>\n", name);
+ exit(1);
+}
+
+static void
+stack(xcb_window_t win, uint32_t values[1])
+{
+ xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
+}
+
+int
+main(int argc, char **argv)
+{
+ xcb_window_t win;
+ uint32_t values[1];
+ char *argv0 = NULL;
+
+ if (argc != 3)
+ usage(argv[0]);
+
+ init_xcb(&conn);
+
+ win = strtoul(argv[2], NULL, 16);
+ if (!win)
+ return 1;
+
+ ARGBEGIN {
+ case 'r':
+ values[0] = XCB_STACK_MODE_ABOVE;
+ break;
+ case 'l':
+ values[0] = XCB_STACK_MODE_BELOW;
+ break;
+ case 'i':
+ values[0] = XCB_STACK_MODE_OPPOSITE;
+ break;
+ default:
+ usage(argv0);
+ break;
+ } ARGEND
+
+ stack(win, values);
+ xcb_aux_sync(conn);
+
+ kill_xcb(&conn);
+
+ return 0;
+}
diff --git a/config.mk b/config.mk
@@ -0,0 +1,9 @@
+PREFIX = /usr/local
+MANPREFIX = $(PREFIX)/man
+
+CC = cc
+LD = $(CC)
+
+CFLAGS = -std=c99 -pedantic -Wall -Os -I/usr/X11R6/include
+LDFLAGS = -lxcb -lxcb-util -lxcb-cursor -L/usr/X11R6/lib
+
diff --git a/ignw.c b/ignw.c
@@ -0,0 +1,55 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+#include "arg.h"
+#include "util.h"
+
+static xcb_connection_t *conn;
+
+static void usage(char *);
+static void set_override(xcb_window_t, int);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-sr] <wid> [wid..]\n", name);
+ exit(1);
+}
+
+static void
+set_override(xcb_window_t w, int or)
+{
+ uint32_t mask = XCB_CW_OVERRIDE_REDIRECT;
+ uint32_t val[] = { or };
+
+ xcb_change_window_attributes(conn, w, mask, val);
+}
+
+int
+main(int argc, char **argv)
+{
+ int setflag = 0;
+ char *argv0;
+
+ ARGBEGIN {
+ case 's': setflag = 1; break;
+ case 'r': setflag = 0; break;
+ default: usage(argv0);
+ } ARGEND;
+
+ init_xcb(&conn);
+
+ while (*argv)
+ set_override(strtoul(*argv++, NULL, 16), setflag);
+
+ xcb_aux_sync(conn);
+
+ kill_xcb(&conn);
+
+ return 0;
+}
diff --git a/killw.c b/killw.c
@@ -0,0 +1,54 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+#include "arg.h"
+#include "util.h"
+
+static xcb_connection_t *conn;
+
+static void usage(char *);
+
+static void
+usage (char *name)
+{
+ fprintf(stderr, "usage: %s [-p] <wid> [wid...]\n", name);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int parent = 0;
+ char *argv0;
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ ARGBEGIN{
+ case 'p': parent=1; break;
+ default: usage(argv0);
+ }ARGEND;
+
+ init_xcb(&conn);
+
+ /* assume remaining arguments are windows */
+ while (*argv) {
+ if (parent) {
+ /* kills the client whose WID belongs to */
+ xcb_kill_client(conn, strtoul(*argv++, NULL, 16));
+ } else {
+ /* destroy the given window and all its children */
+ xcb_destroy_window(conn, strtoul(*argv++, NULL, 16));
+ }
+ }
+
+ xcb_aux_sync(conn);
+ kill_xcb(&conn);
+
+ return 0;
+}
diff --git a/lsw.c b/lsw.c
@@ -0,0 +1,96 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+#include "arg.h"
+#include "util.h"
+
+static xcb_connection_t *conn;
+static xcb_screen_t *scrn;
+
+static void usage(char *);
+static int should_list(xcb_window_t, int);
+static void list_windows(xcb_window_t, int);
+
+enum {
+ LIST_HIDDEN = 1 << 0,
+ LIST_IGNORE = 1 << 1,
+ LIST_ALL = 1 << 2
+};
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-houra] [wid...]\n", name);
+ exit(1);
+}
+
+static int
+should_list(xcb_window_t w, int mask)
+{
+ if ((mask & LIST_ALL)
+ || (!mapped(conn, w) && mask & LIST_HIDDEN)
+ || (ignore(conn, w) && mask & LIST_IGNORE)
+ || (mapped(conn, w)
+ && !ignore(conn, w)
+ && mask == 0))
+ return 1;
+
+ return 0;
+}
+
+static void
+list_windows(xcb_window_t w, int listmask)
+{
+ int i, wn;
+ xcb_window_t *wc;
+
+ wn = get_windows(conn, w, &wc);
+
+ if (wc == NULL)
+ errx(1, "0x%08x: unable to retrieve children", w);
+
+ for (i=0; i<wn; i++) {
+ if (should_list(wc[i], listmask))
+ printf("0x%08x\n", wc[i]);
+ }
+
+ free(wc);
+}
+
+int
+main(int argc, char **argv)
+{
+ int listmask = 0, rootflag = 0;
+ char *argv0;
+
+ ARGBEGIN {
+ case 'a': listmask |= LIST_ALL; break;
+ case 'u': listmask |= LIST_HIDDEN; break;
+ case 'o': listmask |= LIST_IGNORE; break;
+ case 'r': rootflag = 1; break;
+ default : usage(argv0);
+ } ARGEND;
+
+ init_xcb(&conn);
+ get_screen(conn, &scrn);
+
+ if (rootflag == 1) {
+ printf("0x%08x\n", scrn->root);
+ return 0;
+ }
+
+ if (argc == 0)
+ list_windows(scrn->root, listmask);
+
+ while (*argv)
+ list_windows(strtoul(*argv++, NULL, 16), listmask);
+
+ kill_xcb(&conn);
+
+ return 0;
+}
diff --git a/man/Makefile b/man/Makefile
@@ -0,0 +1,31 @@
+include ../config.mk
+
+MAN = \
+ pfw.1 \
+ lsw.1 \
+ mapw.1 \
+ killw.1 \
+ wattr.1 \
+ wtp.1 \
+ wmv.1 \
+ chwso.1 \
+ wtf.1 \
+ wrs.1 \
+ chwb.1 \
+ ignw.1 \
+ wmp.1 \
+ slw.1 \
+ atomx.1 \
+ wmutils.1
+
+.POSIX:
+
+install: $(MAN)
+ mkdir -p $(DESTDIR)$(MANPREFIX)/man1/
+ cp -f $(MAN) $(DESTDIR)$(MANPREFIX)/man1/
+
+uninstall:
+ @echo "uninstalling manpages"
+ @for page in $(MAN); do \
+ rm -f $(DESTDIR)$(MANPREFIX)/man1/$$page; \
+ done
diff --git a/man/atomx.1 b/man/atomx.1
@@ -0,0 +1,43 @@
+.Dd November 21, 2019
+.Dt ATOMX 1
+.Os wmutils
+.Sh NAME
+.Nm atomx
+.Nd manage X atoms on a window
+.Sh SYNOPSIS
+.Nm atomx
+.Op Fl d
+.Ar atom
+.Op Ar =value
+.Ar wid
+.Sh DESCRIPTION
+.Nm
+will print, add, change and remove X atoms on the window with ID
+.Ar wid .
+By default
+.Nm
+will print the value of the atom
+.Ar atom
+if it exists.
+.Pp
+To set an atom on a window, you must specify it as
+.Ar atom=value .
+.Bl -tag -width Ds
+.It Fl d
+Delete atom
+.Ar atom
+from the window.
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
+.Sh EXAMPLES
+Print value of property "WM_CLASS"
+.Dl $ atomx WM_CLASS 0x00e00005
+.Pp
+Change window name to "atomx"
+.Dl $ atomx WM_NAME=atomx 0x00e00005
+.Pp
+Delete property "IS_FULLSCREEN" on a window
+.Dl $ atomx -d IS_FULLSCREEN 0x00e00005
diff --git a/man/chwb.1 b/man/chwb.1
@@ -0,0 +1,40 @@
+.Dd December 13, 2014
+.Dt CHWB 1
+.Os wmutils
+.Sh NAME
+.Nm chwb
+.Nd change window borders
+.Sh SYNOPSIS
+.Nm chwb
+.Op Fl c Ar color
+.Op Fl s Ar size
+.Ar wid Op Ar ...
+.Sh DESCRIPTION
+.Nm
+changes the border size or color of the window
+.Ar wid .
+.Bl -tag -width Ds
+.It Fl c Ar color
+Set border color of
+.Ar wid
+to
+.Ar color .
+Colors should be passed as numerical values (see
+.Xr strtoul 3 )
+in RGB format.
+.It Fl s Ar size
+Set border width of
+.Ar wid
+to
+.Ar size .
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
+.Sh EXAMPLES
+Set the border color to 128 red, 100 green, 204 blue:
+.Dl $ chwb -c 0x8064cc
+.Sh SEE ALSO
+.Xr strtoul 3
diff --git a/man/chwso.1 b/man/chwso.1
@@ -0,0 +1,33 @@
+.Dd December 13, 2014
+.Dt CHWSO 1
+.Os wmutils
+.Sh NAME
+.Nm chwso
+.Nd change window stacking order
+.Sh SYNOPSIS
+.Nm chwso
+.Op Fl ilr
+.Ar wid
+.Sh DESCRIPTION
+.Nm
+will change the place of a window in the server\(cqs window stack,
+putting it in either the foreground or the background.
+.Bl -tag -width Ds
+.It Fl i
+Invert
+.Ar wid Ns \(cqs
+position in the window stack.
+.It Fl l
+Put
+.Ar wid
+at the bottom of the window stack.
+.It Fl r
+Put
+.Ar wid
+on top of the window stack.
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
diff --git a/man/ignw.1 b/man/ignw.1
@@ -0,0 +1,37 @@
+.Dd December 13, 2014
+.Dt IGNW 1
+.Os wmutils
+.Sh NAME
+.Nm ignw
+.Nd ignore window
+.Sh SYNOPSIS
+.Nm ignw
+.Fl rs
+.Ar wid Op ...
+.Sh DESCRIPTION
+.Nm
+changes the value of the
+.Em override_redirect
+attribute of a window to either 0 or 1.
+This affects whether the window manager ignores the window.
+.Bl -tag -width Ds
+.It Fl r
+Reset
+.Ar wid Ns \(cqs
+.Em override_redirect
+value to 0, unignoring the window.
+.It Fl s
+Set
+.Ar wid Ns \(cqs
+.Em override_redirect
+value to 1, ignoring the window.
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
+.Sh SEE ALSO
+.Xr lsw 1 ,
+.Xr wattr 1 ,
+.Xr xcb_get_window_attributes 3
diff --git a/man/killw.1 b/man/killw.1
@@ -0,0 +1,25 @@
+.Dd December 13, 2014
+.Dt KILLW 1
+.Os wmutils
+.Sh NAME
+.Nm killw
+.Nd kill windows
+.Sh SYNOPSIS
+.Nm killw
+.Op Fl p
+.Ar wid Op ...
+.Sh DESCRIPTION
+.Nm
+will destroy the window passed as an argument, and all its children.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl p
+Kill the parent application of the window instead of the window itself.
+This is useful to terminate frozen applications (This will close all the windows
+belonging to the applications).
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
diff --git a/man/lsw.1 b/man/lsw.1
@@ -0,0 +1,43 @@
+.Dd December 13, 2014
+.Dt LSW 1
+.Os wmutils
+.Sh NAME
+.Nm lsw
+.Nd list child windows
+.Sh SYNOPSIS
+.Nm lsw
+.Op Fl arou
+.Op Ar wid ...
+.Sh DESCRIPTION
+.Nm
+lists child windows of the given window.
+If no windows are given,
+.Nm
+lists the children of the root window.
+.Pp
+By default,
+.Nm
+lists only windows that are mapped (visible) and with the
+.Em override_redirect
+value set to 0 (i.e., unignored).
+.Bl -tag -width Ds
+.It Fl a
+List all windows.
+.It Fl r
+Print the ID of the root window.
+.It Fl o
+List windows whose
+.Em override_redirect
+attribute is set to 1.
+.It Fl u
+List unmapped (invisible) windows.
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
+.Sh SEE ALSO
+.Xr ignw 1 ,
+.Xr mapw 1 ,
+.Xr xargs 1
diff --git a/man/mapw.1 b/man/mapw.1
@@ -0,0 +1,32 @@
+.Dd December 13, 2014
+.Dt MAPW 1
+.Os wmutils
+.Sh NAME
+.Nm mapw
+.Nd map or unmap window
+.Sh SYNOPSIS
+.Nm mapw
+.Op Fl mtu
+.Ar wid Op ...
+.Sh DESCRIPTION
+.Nm
+will either map or unmap a window from the screen,
+thus modifying the visibility state of the window.
+.Bl -tag -width Ds
+.It Fl m
+Map (show)
+.Ar wid .
+.It Fl t
+Toggle
+.Ar wid Ns \(cqs visibility.
+.It Fl u
+Unmap (hide)
+.Ar wid .
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
+.Sh SEE ALSO
+.Xr lsw 1
diff --git a/man/pdw.1 b/man/pdw.1
@@ -0,0 +1,24 @@
+.Dd July 01, 2022
+.Dt PDW 1
+.Os wmutils
+.Sh NAME
+.Nm pdw
+.Nd print decoration window
+.Sh SYNOPSIS
+.Nm pdw
+.Op Ar wid
+.Sh DESCRIPTION
+Print the ID of the highest parent related to
+.Ar wid
+(or currently focused window when
+.Ar wid
+is omitted).
+.Pp
+In reparenting environments, this is usually the decoration window.
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
+.Sh SEE ALSO
+.Xr pfw 1
diff --git a/man/pfw.1 b/man/pfw.1
@@ -0,0 +1,16 @@
+.Dd December 13, 2014
+.Dt PFW 1
+.Os wmutils
+.Sh NAME
+.Nm pfw
+.Nd print focused window
+.Sh SYNOPSIS
+.Nm pfw
+.Sh DESCRIPTION
+Print the ID of the currently focused window to
+.Dv stdout .
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
diff --git a/man/slw.1 b/man/slw.1
@@ -0,0 +1,17 @@
+.Dd October 14, 2019
+.Dt SLW 1
+.Os wmutils
+.Sh NAME
+.Nm slw
+.Nd select window interactively
+.Sh SYNOPSIS
+.Nm slw
+.Sh DESCRIPTION
+Wait for a button press event and print the window ID that got the
+event to
+.Dv stdout .
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
diff --git a/man/wattr.1 b/man/wattr.1
@@ -0,0 +1,81 @@
+'\" e
+.Dd December 13, 2014
+.Dt WATTR 1
+.Os wmutils
+.Sh NAME
+.Nm wattr
+.Nd get window attributes
+.Sh SYNOPSIS
+.Nm wattr
+.Op Cm bmiowhxy
+.Ar wid
+.Sh DESCRIPTION
+.Nm
+prints information about the window
+.Ar wid
+to
+.Dv stdout .
+.Pp
+What information is presented depends on the commands given to
+.Nm .
+The queried arguments are printed in the order they are requested,
+separated by a space.
+If no commands are given,
+.Nm
+will return 0 if
+.Ar wid
+exists, and 1 otherwise.
+.Bl -tag -width Ds
+.It Cm i
+Print
+.Ar wid
+.It Cm b
+Print
+.Ar wid Ns \(cqs border width.
+.It Cm x
+Print
+.Ar wid Ns \(cqs
+.EQ
+x
+.EN
+offset.
+.It Cm y
+Print
+.Ar wid Ns \(cqs
+.EQ
+y
+.EN
+offset.
+.It Cm w
+Print
+.Ar wid Ns \(cqs width.
+.It Cm h
+Print
+.Ar wid Ns \(cqs
+height.
+.It Cm o
+.Nm
+returns 0 if the override_redirect attribute is set on the window.
+.It Cm m
+.Nm
+returns 0 if
+.Ar wid
+is mapped on screen, and 1 otherwise.
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
+.Sh EXAMPLES
+.Dl $ wattr m 0x01000006 && echo ismapped
+.Dl ismapped
+.Pp
+.Dl $ wattr whxy 0x01000006
+.Dl 484 244 756 166
+.Pp
+.Dl $ wattr xyhw 0x01000006
+.Dl 756 166 244 484
+.Pp
+.Dl $ wattr 0x00000000 ; echo $?
+.Dl 1
diff --git a/man/wmp.1 b/man/wmp.1
@@ -0,0 +1,37 @@
+.Dd December 17, 2014
+.Dt WMP 1
+.Os wmutils
+.Sh NAME
+.Nm wmp
+.Nd warp mouse cursor
+.Sh SYNOPSIS
+.Nm wmp
+.Fl [ ar
+.Ar <x> <y> ]
+.Ar [ wid ]
+.Sh DESCRIPTION
+.Nm
+warps cursor to an absolute or relative position, passed by
+.Ar x
+and
+.Ar y .
+Returns the position relative to the root window, or
+.Ar wid .
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
+.Sh EXAMPLES
+.Pp
+.Dl $ wmp -a $(wattr xy $(pfw))
+.Pp
+.Dl $ wmp -r 100 0
+.Pp
+.Dl $ wmp -r -- -100 0
+.Pp
+.Dl $ wmp 0x01600006
+.Dl 311 49
+.Pp
+.Dl $ wmp
+.Dl 915 548
diff --git a/man/wmutils.1 b/man/wmutils.1
@@ -0,0 +1,64 @@
+.Dd June 9, 2015
+.Dt WMUTILS 1
+.Os wmutils
+.Sh NAME
+.Nm wmutils
+.Nd window manipulation utilities
+.Sh DESCRIPTION
+.Nm
+is a compilation of utilities for manipulating windows in X
+.Sh COMMANDS
+.Bl -tag -width Ds -offset 60
+.It chwb
+change window's border
+.It chwso
+change window's stacking order
+.It ignw
+ignore/unignore window
+.It killw
+kill windows
+.It lsw
+list windows
+.It mapw
+map/unmap windows
+.It pfw
+print focused window
+.It pdw
+print decoration window
+.It wattr
+show window's attributes
+.It wmp
+move the mouse pointer
+.It wmv
+move a window
+.It wrs
+resize a window
+.It wtf
+focus a window
+.It wtp
+teleport a window
+.It atomx
+modify atoms on a window
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
+.Sh SEE ALSO
+.Xr chwb 1 ,
+.Xr chwso 1 ,
+.Xr ignw 1 ,
+.Xr killw 1 ,
+.Xr lsw 1 ,
+.Xr mapw 1 ,
+.Xr pfw 1 ,
+.Xr pdw 1 ,
+.Xr wattr 1 ,
+.Xr wmp 1 ,
+.Xr wmv 1 ,
+.Xr wname 1 ,
+.Xr wrs 1 ,
+.Xr wtf 1 ,
+.Xr wtp 1 ,
+.Xr atomx 1
diff --git a/man/wmv.1 b/man/wmv.1
@@ -0,0 +1,41 @@
+'\" e
+.Dd December 13, 2014
+.Dt WMV 1
+.Os wmutils
+.Sh NAME
+.Nm wmv
+.Nd move windows
+.Sh SYNOPSIS
+.Nm wmv
+.Op Fl a
+.Ar x y wid
+.Sh DESCRIPTION
+.Nm wmv
+repositions
+.Ar wid
+relatively,
+.Ar x
+pixels in the
+.EQ
+x
+.EN
+direction and
+.Ar y
+pixels in the
+.EQ
+y
+.EN
+direction.
+.Bl -tag -width Ds
+.It Fl a
+Absolute mode. The window will be centered to the
+.Ar x
+and
+.Ar y
+coordinates.
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
diff --git a/man/wrs.1 b/man/wrs.1
@@ -0,0 +1,31 @@
+.Dd December 13, 2014
+.Dt WRS 1
+.Os wmutils
+.Sh NAME
+.Nm wrs
+.Nd resize windows
+.Sh SYNOPSIS
+.Nm wrs
+.Op Fl a
+.Ar x y wid Op ...
+.Sh DESCRIPTION
+.Nm
+resizes the window
+.Ar wid
+based on the relative pixel values
+.Ar x
+and
+.Ar y .
+.Bl -tag -width Ds
+.It Fl a
+Absolute mode. The window will be resized up to the
+.Ar x
+and
+.Ar y
+coordinates.
+.El
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
diff --git a/man/wtf.1 b/man/wtf.1
@@ -0,0 +1,19 @@
+.Dd December 13, 2014
+.Dt WTF 1
+.Os wmutils
+.Sh NAME
+.Nm wtf
+.Nd transfer window focus
+.Sh SYNOPSIS
+.Nm wtf
+.Ar wid
+.Sh DESCRIPTION
+.Nm
+sets the keyboard input focus to the window
+.Ar wid
+if it exists and is viewable.
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
diff --git a/man/wtp.1 b/man/wtp.1
@@ -0,0 +1,27 @@
+.Dd December 13, 2014
+.Dt WTP 1
+.Os wmutils
+.Sh NAME
+.Nm wtp
+.Nd teleport window (absolutely)
+.Sh SYNOPSIS
+.Nm wtp
+.Ar x y w h wid
+.Sh DESCRIPTION
+.Nm
+moves (or teleports) the window
+.Ar wid
+to the position given by
+.Ar x
+and
+.Ar y ,
+and resize it to width
+.Ar w
+and height
+.Ar h .
+Value are absolute value from the the upper-left-hand corner.
+.Sh ENVIRONMENT
+.Nm
+acts on the X display specified by the
+.Ev DISPLAY
+variable.
diff --git a/mapw.c b/mapw.c
@@ -0,0 +1,71 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+#include "arg.h"
+#include "util.h"
+
+enum {
+ MAP = 1 << 0,
+ UNMAP = 1 << 1,
+ TOGGLE = 1 << 2
+};
+
+static xcb_connection_t *conn;
+
+static void usage(char *);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-h] [-mut <wid> [wid..]]\n", name);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int mapflag = 0;
+ xcb_window_t w = 0;
+ char *argv0;
+
+ ARGBEGIN {
+ case 'm': mapflag = MAP; break;
+ case 'u': mapflag = UNMAP; break;
+ case 't': mapflag = TOGGLE; break;
+ default : usage(argv0);
+ } ARGEND;
+
+ if (argc < 1 || mapflag == 0)
+ usage(argv0);
+
+ init_xcb(&conn);
+
+ while (*argv) {
+ w = strtoul(*argv++, NULL, 16);
+
+ switch (mapflag) {
+ case MAP:
+ xcb_map_window(conn, w);
+ break;
+ case UNMAP:
+ xcb_unmap_window(conn, w);
+ break;
+ case TOGGLE:
+ if (mapped(conn, w))
+ xcb_unmap_window(conn, w);
+ else
+ xcb_map_window(conn, w);
+ break;
+ }
+ }
+ xcb_aux_sync(conn);
+
+ kill_xcb(&conn);
+
+ return 0;
+}
diff --git a/pdw.c b/pdw.c
@@ -0,0 +1,81 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+#include "util.h"
+
+static xcb_connection_t *conn;
+static xcb_screen_t *scrn;
+
+static void usage(char *);
+static xcb_window_t focus_window(void);
+static xcb_window_t parent(xcb_window_t);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s [wid]\n", name);
+ exit(1);
+}
+
+static xcb_window_t
+focus_window(void)
+{
+ xcb_window_t w = 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)
+ errx(1, "xcb_get_input_focus");
+
+ w = r->focus;
+ free(r);
+
+ if (w == XCB_NONE || w == XCB_INPUT_FOCUS_POINTER_ROOT)
+ errx(1, "focus not set");
+
+ return w;
+}
+
+static xcb_window_t
+parent(xcb_window_t w)
+{
+ xcb_query_tree_cookie_t c;
+ xcb_query_tree_reply_t *r;
+
+ c = xcb_query_tree(conn, w);
+ r = xcb_query_tree_reply(conn, c, NULL);
+ if (r == NULL)
+ errx(1, "failed to get parent");
+
+ w = (!r->parent || r->parent == scrn->root) ? w : parent(r->parent);
+ free(r);
+
+ return w;
+}
+
+int
+main(int argc, char **argv)
+{
+ xcb_window_t w;
+
+ if (argc > 2 || (argc > 1 && (!strncmp(argv[1], "-h", 2))))
+ usage(argv[0]);
+
+ init_xcb(&conn);
+ get_screen(conn, &scrn);
+
+ w = (argc > 1) ? strtoul(argv[1], NULL, 16) : focus_window();
+
+ printf("0x%08x\n", parent(w));
+
+ kill_xcb(&conn);
+ return 0;
+}
diff --git a/pfw.c b/pfw.c
@@ -0,0 +1,45 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+#include "util.h"
+
+static xcb_connection_t *conn;
+
+static xcb_window_t focus_window(void);
+
+static xcb_window_t
+focus_window(void)
+{
+ xcb_window_t w = 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)
+ errx(1, "xcb_get_input_focus");
+
+ w = r->focus;
+ free(r);
+
+ if (w == XCB_NONE || w == XCB_INPUT_FOCUS_POINTER_ROOT)
+ errx(1, "focus not set");
+
+ return w;
+}
+
+int
+main(int argc, char **argv)
+{
+ init_xcb(&conn);
+
+ printf("0x%08x\n", focus_window());
+
+ kill_xcb(&conn);
+ return 0;
+}
diff --git a/slw.c b/slw.c
@@ -0,0 +1,71 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#include <xcb/xcb_cursor.h>
+
+#include "util.h"
+
+/* use "heart" to show us your love! */
+#define XHAIR "tcross"
+
+static xcb_connection_t *conn;
+static xcb_screen_t *scr;
+
+static xcb_window_t
+select_window(void)
+{
+ uint32_t val[] = { XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE };
+ xcb_window_t w = 0;
+ xcb_cursor_t p;
+ xcb_cursor_context_t *ctx;
+ xcb_grab_pointer_cookie_t c;
+ xcb_grab_pointer_reply_t *r;
+ xcb_generic_event_t *e;
+
+ if (xcb_cursor_context_new(conn, scr, &ctx) < 0)
+ errx(1, "cannot instantiate cursor");
+
+ p = xcb_cursor_load_cursor(ctx, XHAIR);
+ xcb_flush(conn);
+
+ c = xcb_grab_pointer(conn, 0, scr->root,
+ XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE,
+ 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)
+ errx(1, "couldn't grab pointer");
+
+ xcb_change_window_attributes(conn, scr->root, XCB_CW_EVENT_MASK, val);
+ xcb_flush(conn);
+
+ for (;;) {
+ e = xcb_wait_for_event(conn);
+ switch ((e->response_type & ~0x80)) {
+ case XCB_BUTTON_PRESS:
+ w = ((xcb_button_press_event_t*)e)->child;
+ break;
+ case XCB_BUTTON_RELEASE:
+ xcb_cursor_context_free(ctx);
+ return w;
+ break; /* NOTREACHED */
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ init_xcb(&conn);
+ get_screen(conn, &scr);
+
+ printf("0x%08x\n", select_window());
+
+ kill_xcb(&conn);
+ return 0;
+}
diff --git a/util.c b/util.c
@@ -0,0 +1,106 @@
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+#include "util.h"
+
+void
+init_xcb(xcb_connection_t **con)
+{
+ *con = xcb_connect(NULL, NULL);
+ if (xcb_connection_has_error(*con))
+ errx(1, "unable connect to the X server");
+}
+
+void
+kill_xcb(xcb_connection_t **con)
+{
+ if (*con)
+ xcb_disconnect(*con);
+}
+
+void
+get_screen(xcb_connection_t *con, xcb_screen_t **scr)
+{
+ *scr = xcb_setup_roots_iterator(xcb_get_setup(con)).data;
+ if (*scr == NULL)
+ errx(1, "unable to retrieve screen informations");
+}
+
+int
+exists(xcb_connection_t *con, xcb_window_t w)
+{
+ xcb_get_window_attributes_cookie_t c;
+ xcb_get_window_attributes_reply_t *r;
+
+ c = xcb_get_window_attributes(con, w);
+ r = xcb_get_window_attributes_reply(con, c, NULL);
+
+ if (r == NULL)
+ return 0;
+
+ free(r);
+ return 1;
+}
+
+int
+mapped(xcb_connection_t *con, xcb_window_t w)
+{
+ int ms;
+ xcb_get_window_attributes_cookie_t c;
+ xcb_get_window_attributes_reply_t *r;
+
+ c = xcb_get_window_attributes(con, w);
+ r = xcb_get_window_attributes_reply(con, c, NULL);
+
+ if (r == NULL)
+ return 0;
+
+ ms = r->map_state;
+
+ free(r);
+ return ms == XCB_MAP_STATE_VIEWABLE;
+}
+
+int
+ignore(xcb_connection_t *con, xcb_window_t w)
+{
+ int or;
+ xcb_get_window_attributes_cookie_t c;
+ xcb_get_window_attributes_reply_t *r;
+
+ c = xcb_get_window_attributes(con, w);
+ r = xcb_get_window_attributes_reply(con, c, NULL);
+
+ if (r == NULL)
+ return 0;
+
+ or = r->override_redirect;
+
+ free(r);
+ return or;
+}
+
+int
+get_windows(xcb_connection_t *con, xcb_window_t w, xcb_window_t **l)
+{
+ uint32_t childnum = 0;
+ xcb_query_tree_cookie_t c;
+ xcb_query_tree_reply_t *r;
+
+ c = xcb_query_tree(con, w);
+ r = xcb_query_tree_reply(con, c, NULL);
+ if (r == NULL)
+ errx(1, "0x%08x: no such window", w);
+
+ *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;
+}
diff --git a/util.h b/util.h
@@ -0,0 +1,14 @@
+#ifndef UTIL_H__
+#define UTIL_H__
+
+void init_xcb(xcb_connection_t **);
+void kill_xcb(xcb_connection_t **);
+
+void get_screen(xcb_connection_t *, xcb_screen_t **);
+int get_windows(xcb_connection_t *, xcb_window_t, xcb_window_t **);
+
+int exists(xcb_connection_t *, xcb_window_t);
+int mapped(xcb_connection_t *, xcb_window_t);
+int ignore(xcb_connection_t *, xcb_window_t);
+
+#endif
diff --git a/wattr.c b/wattr.c
@@ -0,0 +1,118 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+
+#include "util.h"
+
+static xcb_connection_t *conn;
+
+static void usage(char *);
+static int get_attribute(xcb_window_t, int);
+
+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_MAX
+};
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-h] [bmiowhxy] <wid>\n", name);
+ exit(1);
+}
+
+static int
+get_attribute(xcb_window_t w, int attr)
+{
+ xcb_get_geometry_cookie_t c;
+ xcb_get_geometry_reply_t *r;
+
+ c = xcb_get_geometry(conn, w);
+ r = xcb_get_geometry_reply(conn, c, NULL);
+
+ if (r == NULL)
+ errx(1, "0x%08x: no such window", w);
+
+ 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;
+ }
+
+ free(r);
+ return attr;
+}
+
+int
+main(int argc, char **argv)
+{
+ int c, ret = 0;
+ size_t i;
+ xcb_window_t w = 0;
+
+ if (argc < 2 || (strncmp(argv[1], "-h", 2) == 0)) {
+ usage(argv[0]);
+ }
+
+ init_xcb(&conn);
+
+ if (argc == 2) {
+ w = strtoul(argv[1], NULL, 16);
+ ret = exists(conn, w) ? 0 : 1;
+ goto end;
+ }
+
+ for (c=2; argv[c]; c++) {
+ w = strtoul(argv[c], NULL, 16);
+
+ for (i=0; i<strlen(argv[1]); i++) {
+ switch (argv[1][i]) {
+ case 'i':
+ printf("0x%08x", w);
+ break;
+ case 'b':
+ printf("%d", get_attribute(w, ATTR_B));
+ break;
+ case 'h':
+ printf("%d", get_attribute(w, ATTR_H));
+ break;
+ case 'x':
+ printf("%d", get_attribute(w, ATTR_X));
+ break;
+ case 'y':
+ printf("%d", get_attribute(w, ATTR_Y));
+ break;
+ case 'w':
+ printf("%d", get_attribute(w, ATTR_W));
+ break;
+ case 'o':
+ ret = ignore(conn, w) ? 0 : 1;
+ goto end;
+ case 'm':
+ ret = mapped(conn, w) ? 0 : 1;
+ goto end;
+ default: kill_xcb(&conn); usage(argv[0]);
+ }
+ /* add a space if more attribute come after */
+ putc(i+1 < strlen(argv[1]) ? ' ' : '\n',stdout);
+ }
+ }
+
+end:
+ kill_xcb(&conn);
+
+ return ret;
+}
diff --git a/wmp.c b/wmp.c
@@ -0,0 +1,92 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+
+#include "arg.h"
+#include "util.h"
+
+enum {
+ ABSOLUTE = 0,
+ RELATIVE = 1
+};
+
+static xcb_screen_t *scr;
+static xcb_connection_t *conn;
+
+static void usage(char *);
+static void spot_cursor(int, uint32_t);
+static void warp_cursor(int, int, int);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-ar <x> <y>] [wid]\n", name);
+ exit(1);
+}
+
+static void
+spot_cursor(int mode, uint32_t win)
+{
+ xcb_query_pointer_reply_t *r;
+ xcb_query_pointer_cookie_t c;
+
+ c = xcb_query_pointer(conn, win);
+ r = xcb_query_pointer_reply(conn, c, NULL);
+
+ if (r == NULL)
+ errx(1, "cannot retrieve pointer position");
+
+ if (r->child != XCB_NONE) {
+ printf("%d %d\n", r->win_x, r->win_y);
+ } else {
+ printf("%d %d\n", r->root_x, r->root_y);
+ }
+}
+
+static void
+warp_cursor(int x, int y, int mode)
+{
+ xcb_warp_pointer(conn, XCB_NONE, mode ? XCB_NONE : scr->root,
+ 0, 0, 0, 0, x, y);
+}
+
+int
+main(int argc, char **argv)
+{
+ char *argv0;
+ int mode = ABSOLUTE;
+ uint32_t win;
+
+ ARGBEGIN {
+ case 'a': mode = ABSOLUTE;
+ break;
+ case 'r': mode = RELATIVE;
+ break;
+ default : usage(argv0);
+ } ARGEND;
+
+ init_xcb(&conn);
+ get_screen(conn, &scr);
+
+ switch (argc) {
+ case 0:
+ case 1:
+ win = argc > 0 ? strtoul(*argv, NULL, 16) : scr->root;
+ spot_cursor(mode, win);
+ break;
+ case 2:
+ warp_cursor(atoi(argv[0]), atoi(argv[1]), mode);
+ break;
+ default:
+ usage(argv0);
+ }
+
+ xcb_aux_sync(conn);
+
+ kill_xcb(&conn);
+ return 0;
+}
diff --git a/wmv.c b/wmv.c
@@ -0,0 +1,100 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+
+#include "util.h"
+
+enum {
+ ABSOLUTE = 0,
+ RELATIVE = 1
+};
+
+static xcb_connection_t *conn;
+static xcb_screen_t *scr;
+
+static void usage(char *);
+static void move(xcb_window_t, int, int, int);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-a] <x> <y> <win>\n", name);
+ exit(1);
+}
+
+static void
+move(xcb_window_t win, int mode, int x, int y)
+{
+ uint32_t values[2];
+ int real;
+ xcb_get_geometry_reply_t *geom;
+
+ if (!win || win == scr->root)
+ return;
+
+ geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL);
+ if (!geom)
+ return;
+
+ if (mode == ABSOLUTE) {
+ x -= geom->x + geom->width /2;
+ y -= geom->y + geom->height/2;
+ }
+ values[0] = x ? geom->x + x : geom->x;
+ values[1] = y ? geom->y + y : geom->y;
+
+ if (x)
+ {
+ real = geom->width + (geom->border_width * 2);
+ if (geom->x + x < 1)
+ values[0] = 0;
+ if (geom->x + x > scr->width_in_pixels - real)
+ values[0] = scr->width_in_pixels - real;
+ }
+
+ if (y)
+ {
+ real = geom->height + (geom->border_width * 2);
+ if (geom->y + y < 1)
+ values[1] = 0;
+ if (geom->y + y > scr->height_in_pixels - real)
+ values[1] = scr->height_in_pixels - real;
+ }
+
+ xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_X
+ | XCB_CONFIG_WINDOW_Y, values);
+
+ free(geom);
+}
+
+int
+main(int argc, char **argv)
+{
+ int x, y, mode = RELATIVE;
+ if (argc < 4)
+ usage(argv[0]);
+
+ init_xcb(&conn);
+ get_screen(conn, &scr);
+
+ if (argv[1][0] == '-' && argv[1][1] == 'a') {
+ mode = ABSOLUTE;
+ argv++;
+ }
+
+ x = atoi(*(++argv));
+ y = atoi(*(++argv));
+
+ while (*argv)
+ move(strtoul(*argv++, NULL, 16), mode, x, y);
+
+ xcb_aux_sync(conn);
+
+ kill_xcb(&conn);
+
+ return 0;
+}
diff --git a/wrs.c b/wrs.c
@@ -0,0 +1,93 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+
+#include "util.h"
+
+enum {
+ ABSOLUTE = 0,
+ RELATIVE = 1
+};
+
+static xcb_connection_t *conn;
+static xcb_screen_t *scr;
+
+static void usage(char *);
+static void resize(xcb_window_t, int, int, int);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-a] <x> <y> <wid> [wid..]\n", name);
+ exit(1);
+}
+
+static void
+resize(xcb_window_t w, int mode, int x, int y)
+{
+ uint32_t val[3];
+ uint32_t mask = XCB_CONFIG_WINDOW_WIDTH
+ | XCB_CONFIG_WINDOW_HEIGHT
+ | XCB_CONFIG_WINDOW_STACK_MODE;
+ xcb_get_geometry_cookie_t c;
+ xcb_get_geometry_reply_t *r;
+
+ c = xcb_get_geometry(conn, w);
+ r = xcb_get_geometry_reply(conn, c, NULL);
+
+ if (r == NULL)
+ return;
+
+ if (mode == ABSOLUTE) {
+ x -= r->x + r->width;
+ y -= r->y + r->height;
+ }
+
+ if ((r->x + r->width + 2*r->border_width + x) > scr->width_in_pixels)
+ x = scr->width_in_pixels - (
+ r->x + r->width + (2*r->border_width));
+
+ if ((r->y + r->height + 2*r->border_width + y) > scr->height_in_pixels)
+ y = scr->height_in_pixels - (
+ r->y + r->height + (2*r->border_width));
+
+ val[0] = r->width + x;
+ val[1] = r->height + y;
+ val[2] = XCB_STACK_MODE_ABOVE;
+
+ xcb_configure_window(conn, w, mask, val);
+
+ free(r);
+}
+
+int
+main(int argc, char **argv)
+{
+ int x, y, mode = RELATIVE;
+ if (argc < 4)
+ usage(argv[0]);
+
+ init_xcb(&conn);
+ get_screen(conn, &scr);
+
+ if (argv[1][0] == '-' && argv[1][1] == 'a') {
+ mode = ABSOLUTE;
+ argv++;
+ }
+
+ x = atoi(*(++argv));
+ y = atoi(*(++argv));
+
+ while (*argv)
+ resize(strtoul(*argv++, NULL, 16), mode, x, y);
+
+ xcb_aux_sync(conn);
+
+ kill_xcb(&conn);
+
+ return 0;
+}
diff --git a/wtf.c b/wtf.c
@@ -0,0 +1,44 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+
+#include "util.h"
+
+static xcb_connection_t *conn;
+
+static void usage (char *);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s <wid>\n", name);
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ xcb_window_t win;
+
+ if (argc != 2 || strncmp(argv[0], "-h", 2) == 0)
+ usage(argv[0]);
+
+ init_xcb(&conn);
+
+ win = strtoul(argv[1], NULL, 16);
+
+ if (win) {
+ xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, win,
+ XCB_CURRENT_TIME);
+
+ xcb_aux_sync(conn);
+ }
+
+ kill_xcb(&conn);
+ return 0;
+}
diff --git a/wtp.c b/wtp.c
@@ -0,0 +1,61 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_aux.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+
+#include "util.h"
+
+static xcb_connection_t *conn;
+
+static void usage(char *name);
+static void teleport(xcb_window_t, int, int, int, int);
+
+static void
+usage(char *name)
+{
+ fprintf(stderr, "usage: %s <x> <y> <w> <h> <wid>\n", name);
+ exit(1);
+}
+
+static void
+teleport(xcb_window_t win, 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, win, mask, values);
+}
+
+int
+main(int argc, char **argv)
+{
+ xcb_window_t win;
+
+ if (argc != 6)
+ usage(argv[0]);
+
+ init_xcb(&conn);
+
+ win = strtoul(argv[5], NULL, 16);
+ if (!win)
+ errx(1, "cannot get window");
+
+ teleport(win, atoi(argv[1]), atoi(argv[2]),
+ atoi(argv[3]), atoi(argv[4]));
+ xcb_aux_sync(conn);
+
+ kill_xcb(&conn);
+
+ return 0;
+}