core

WMUtils core.
git clone git://git.zepp.club/core.git
Log | Files | Refs | README | LICENSE

commit 24a9d7d38f9523044bffa1594dd468b395ebb4a7
Author: Anjeel <xein@zepp.club>
Date:   Sat,  6 Jul 2024 01:49:54 -0300

git: upload

Diffstat:
ALICENSE | 16++++++++++++++++
AMakefile | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AREADME.md | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aarg.h | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aatomx.c | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Achwb.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Achwso.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig.mk | 9+++++++++
Aignw.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Akillw.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alsw.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aman/Makefile | 31+++++++++++++++++++++++++++++++
Aman/atomx.1 | 43+++++++++++++++++++++++++++++++++++++++++++
Aman/chwb.1 | 40++++++++++++++++++++++++++++++++++++++++
Aman/chwso.1 | 33+++++++++++++++++++++++++++++++++
Aman/ignw.1 | 37+++++++++++++++++++++++++++++++++++++
Aman/killw.1 | 25+++++++++++++++++++++++++
Aman/lsw.1 | 43+++++++++++++++++++++++++++++++++++++++++++
Aman/mapw.1 | 32++++++++++++++++++++++++++++++++
Aman/pdw.1 | 24++++++++++++++++++++++++
Aman/pfw.1 | 16++++++++++++++++
Aman/slw.1 | 17+++++++++++++++++
Aman/wattr.1 | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aman/wmp.1 | 37+++++++++++++++++++++++++++++++++++++
Aman/wmutils.1 | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aman/wmv.1 | 41+++++++++++++++++++++++++++++++++++++++++
Aman/wrs.1 | 31+++++++++++++++++++++++++++++++
Aman/wtf.1 | 19+++++++++++++++++++
Aman/wtp.1 | 27+++++++++++++++++++++++++++
Amapw.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apdw.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apfw.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Aslw.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autil.c | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autil.h | 14++++++++++++++
Awattr.c | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awmp.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awmv.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awrs.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awtf.c | 44++++++++++++++++++++++++++++++++++++++++++++
Awtp.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; +}