master ohmu/wmutils / src / core / chwb.c
ohmu  ·  2026-07-25
 1/* See LICENSE file for copyright and license details. */
 2
 3#include <xcb/xcb.h>
 4#include <xcb/xcb_aux.h>
 5#include <stdlib.h>
 6#include <stdio.h>
 7#include <err.h>
 8
 9#include "arg.h"
10#include "util.h"
11
12static xcb_connection_t *conn;
13
14static void usage(char *name);
15static void set_border(int, int, xcb_window_t);
16
17static void
18usage(char *name)
19{
20	fprintf(stderr, "usage: %s <-sc ...> <wid> [wid...]\n", name);
21	exit(1);
22}
23
24static void
25set_border(int width, int color, xcb_window_t win)
26{
27	uint32_t values[3];
28	uint16_t curr_width;
29	int mask;
30	xcb_get_geometry_reply_t *geom;
31
32	if (width != -1) {
33		geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL);
34		if (!geom)
35			return;
36
37		/* Windows track position based on the top left corner of the border.
38		 * To make the border move instead of the window, we move the window up and left
39		 * by the amount the border would have shifted it down and right.*/
40		curr_width = geom->border_width;
41		values[0] = geom->x + curr_width - width;
42		values[1] = geom->y + curr_width - width;
43		values[2] = width;
44
45		mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_BORDER_WIDTH ;
46		xcb_configure_window(conn, win, mask, values);
47
48		xcb_aux_sync(conn);
49
50		free(geom);
51	}
52
53	if (color != -1) {
54		values[0] = color;
55		mask = XCB_CW_BORDER_PIXEL;
56		xcb_change_window_attributes(conn, win, mask, values);
57
58		xcb_aux_sync(conn);
59	}
60}
61
62int
63main(int argc, char **argv)
64{
65	char *argv0;
66	int color,width;
67
68	color = width = -1;
69
70	if (argc < 2)
71		usage(argv[0]);
72
73	ARGBEGIN {
74		case 's':
75			width = strtoul(EARGF(usage(argv0)), NULL, 10);
76			break;
77		case 'c':
78			color = strtoul(EARGF(usage(argv0)), NULL, 16);
79			break;
80		default:
81			usage(argv0);
82			/* NOTREACHED */
83	} ARGEND
84
85	init_xcb(&conn);
86
87	/* assume remaining arguments are windows */
88	while (*argv)
89		set_border(width, color, strtoul(*argv++, NULL, 16));
90
91	xcb_aux_sync(conn);
92
93	kill_xcb(&conn);
94
95	return 0;
96}