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}