master ohmu/wmutils / src / core / slw.c
ohmu  ·  2026-07-25
 1/* See LICENSE file for copyright and license details. */
 2
 3#include <err.h>
 4#include <stdio.h>
 5#include <stdlib.h>
 6#include <xcb/xcb.h>
 7#include <xcb/xcb_aux.h>
 8#include <xcb/xcb_cursor.h>
 9
10#include "util.h"
11
12/* use "heart" to show us your love! */
13#define XHAIR "tcross"
14
15static xcb_connection_t *conn;
16static xcb_screen_t *scr;
17
18static xcb_window_t
19select_window(void)
20{
21	uint32_t val[] = { XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE  };
22	xcb_window_t w = 0;
23	xcb_cursor_t p;
24	xcb_cursor_context_t *ctx;
25	xcb_grab_pointer_cookie_t c;
26	xcb_grab_pointer_reply_t *r;
27	xcb_generic_event_t *e;
28
29	if (xcb_cursor_context_new(conn, scr, &ctx) < 0)
30		errx(1, "cannot instantiate cursor");
31
32	p = xcb_cursor_load_cursor(ctx, XHAIR);
33	xcb_flush(conn);
34
35	c = xcb_grab_pointer(conn, 0, scr->root,
36		XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE,
37		XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, p,
38		XCB_CURRENT_TIME);
39
40	r = xcb_grab_pointer_reply(conn, c, NULL);
41	if (!r || r->status != XCB_GRAB_STATUS_SUCCESS)
42		errx(1, "couldn't grab pointer");
43
44	xcb_change_window_attributes(conn, scr->root, XCB_CW_EVENT_MASK, val);
45	xcb_flush(conn);
46
47	for (;;) {
48		e = xcb_wait_for_event(conn);
49		switch ((e->response_type & ~0x80)) {
50		case XCB_BUTTON_PRESS:
51			w = ((xcb_button_press_event_t*)e)->child;
52			break;
53		case XCB_BUTTON_RELEASE:
54			xcb_cursor_context_free(ctx);
55			return w;
56			break; /* NOTREACHED */
57		}
58	}
59}
60
61int
62main(int argc, char **argv)
63{
64	init_xcb(&conn);
65	get_screen(conn, &scr);
66
67	printf("0x%08x\n", select_window());
68
69	kill_xcb(&conn);
70	return 0;
71}