master ohmu/wmutils / src / opt / xmrs.c
ohmu  ·  2026-07-25
  1/* See LICENSE file for copyright and license details. */
  2#include <xcb/xcb.h>
  3#include <stdlib.h>
  4#include <stdio.h>
  5#include <err.h>
  6
  7#include "util.h"
  8
  9#define CLEANMASK(m)	((m & ~0x80))
 10#define MAX(a, b) (a > b ? a : b)
 11
 12static xcb_connection_t	*conn;
 13static xcb_screen_t	*scr;
 14
 15static void usage(char *);
 16static xcb_window_t get_focuswin(void);
 17static void cleanup(void);
 18
 19static void
 20cleanup(void)
 21{
 22	kill_xcb(&conn);
 23}
 24
 25static void
 26usage(char *name)
 27{
 28	fprintf(stderr, "usage: %s <wid>\n", name);
 29	exit(1);
 30}
 31
 32static xcb_window_t
 33get_focuswin(void) {
 34	xcb_window_t w = 0;
 35
 36	xcb_get_input_focus_cookie_t  c;
 37	xcb_get_input_focus_reply_t  *r;
 38
 39	c = xcb_get_input_focus(conn);
 40	r = xcb_get_input_focus_reply(conn, c, NULL);
 41
 42	if (r == NULL)
 43		errx(1, "failed to get focused window");
 44
 45	w = r->focus;
 46	free(r);
 47	return w;
 48}
 49
 50static void
 51mresize(xcb_window_t win) {
 52	uint32_t values[3];
 53	xcb_get_geometry_reply_t *geom;
 54	xcb_query_pointer_reply_t *ptr;
 55	xcb_generic_event_t *ev = NULL;
 56	int orig_width, orig_height;
 57
 58	geom = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL);
 59	xcb_warp_pointer(conn, XCB_NONE, win, 0, 0, 0, 0,
 60			geom->width, geom->height);
 61
 62	if (!geom)
 63		errx(1, "could not get window size");
 64
 65	orig_width = geom->width;
 66	orig_height = geom->height;
 67
 68	if (!scr->root)
 69		return;
 70
 71	xcb_grab_pointer(conn, 0, scr->root,
 72			XCB_EVENT_MASK_BUTTON_RELEASE
 73			| XCB_EVENT_MASK_BUTTON_PRESS,
 74			XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
 75			scr->root, XCB_NONE, XCB_CURRENT_TIME);
 76
 77	xcb_flush(conn);
 78
 79
 80	for (;;) {
 81		ev = xcb_poll_for_event(conn);
 82
 83		if (geom->width != orig_width || geom->height != orig_height)
 84			if (ev != NULL) {
 85				if (ev->response_type == XCB_MOTION_NOTIFY)
 86					break;
 87				exit(0);
 88			}
 89
 90		geom = xcb_get_geometry_reply(conn,
 91				xcb_get_geometry(conn, win), NULL);
 92		if (!geom)
 93			errx(1, "could not get window size");
 94
 95
 96		ptr = xcb_query_pointer_reply(conn,
 97				xcb_query_pointer(conn, scr->root), 0);
 98
 99		if (!ptr)
100			errx(1, "could not get pointer location");
101
102		values[0] = MAX(1, ptr->root_x - geom->x - 2 * geom->border_width);
103		values[1] = MAX(1, ptr->root_y - geom->y - 2 * geom->border_width);
104
105
106		if (values[0] >= 0 && values[1] >= 0)
107			xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_WIDTH
108					| XCB_CONFIG_WINDOW_HEIGHT, values);
109		xcb_flush(conn);
110	}
111
112	xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
113}
114
115int
116main(int argc, char **argv)
117{
118	xcb_window_t win;
119
120	if (argc > 2)
121		usage(argv[0]);
122
123	init_xcb(&conn);
124	get_screen(conn, &scr);
125	atexit(cleanup);
126
127	if (argc == 2)
128		win = strtoul(argv[1], NULL, 16);
129	else
130		win = get_focuswin();
131
132	mresize(win);
133
134	return 0;
135}