ohmu
·
2026-07-25
1#include <stdio.h>
2#include <stdlib.h>
3#include <err.h>
4#include <getopt.h>
5#include <xcb/xcb.h>
6
7#include "util.h"
8#include "arg.h"
9
10void usage(char*);
11void list_events(void);
12void register_events(xcb_window_t, uint32_t);
13void print_event(xcb_generic_event_t*);
14
15static xcb_connection_t *conn;
16static xcb_screen_t *scr;
17static uint32_t mask = XCB_EVENT_MASK_NO_EVENT
18 | XCB_EVENT_MASK_STRUCTURE_NOTIFY
19 | XCB_EVENT_MASK_FOCUS_CHANGE
20 | XCB_EVENT_MASK_ENTER_WINDOW
21 /* | XCB_EVENT_MASK_LEAVE_WINDOW */
22 /* | XCB_EVENT_MASK_KEY_PRESS */
23 /* | XCB_EVENT_MASK_KEY_RELEASE */
24 | XCB_EVENT_MASK_BUTTON_PRESS
25 /* | XCB_EVENT_MASK_BUTTON_RELEASE */
26 /* | XCB_EVENT_MASK_POINTER_MOTION */
27 /* | XCB_EVENT_MASK_POINTER_MOTION_HINT */
28 /* | XCB_EVENT_MASK_BUTTON_1_MOTION */
29 /* | XCB_EVENT_MASK_BUTTON_2_MOTION */
30 /* | XCB_EVENT_MASK_BUTTON_3_MOTION */
31 /* | XCB_EVENT_MASK_BUTTON_4_MOTION */
32 /* | XCB_EVENT_MASK_BUTTON_5_MOTION */
33 /* | XCB_EVENT_MASK_BUTTON_MOTION */
34 /* | XCB_EVENT_MASK_KEYMAP_STATE */
35 /* | XCB_EVENT_MASK_EXPOSURE */
36 /* | XCB_EVENT_MASK_VISIBILITY_CHANGE */
37 /* | XCB_EVENT_MASK_RESIZE_REDIRECT */
38 /* | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY */
39 /* | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT */
40 /* | XCB_EVENT_MASK_PROPERTY_CHANGE */
41 /* | XCB_EVENT_MASK_COLOR_MAP_CHANGE */
42 /* | XCB_EVENT_MASK_OWNER_GRAB_BUTTON */
43 ;
44static uint32_t rootmask = XCB_EVENT_MASK_NO_EVENT
45 | XCB_EVENT_MASK_STRUCTURE_NOTIFY
46 | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY
47 | XCB_EVENT_MASK_BUTTON_PRESS
48 | XCB_EVENT_MASK_BUTTON_RELEASE
49 ;
50
51static const char *evname[] = {
52 [0] = "EVENT_ERROR",
53 [XCB_CREATE_NOTIFY] = "CREATE",
54 [XCB_DESTROY_NOTIFY] = "DESTROY",
55 [XCB_BUTTON_PRESS] = "BUTTON_PRESS",
56 [XCB_BUTTON_RELEASE] = "BUTTON_RELEASE",
57 [XCB_MOTION_NOTIFY] = "MOTION",
58 [XCB_ENTER_NOTIFY] = "ENTER",
59 [XCB_LEAVE_NOTIFY] = "LEAVE",
60 [XCB_CONFIGURE_NOTIFY] = "CONFIGURE",
61 [XCB_KEY_PRESS] = "KEY_PRESS",
62 [XCB_FOCUS_IN] = "FOCUS_IN",
63 [XCB_FOCUS_OUT] = "FOCUS_OUT",
64 [XCB_KEYMAP_NOTIFY] = "KEYMAP",
65 [XCB_EXPOSE] = "EXPOSE",
66 [XCB_GRAPHICS_EXPOSURE] = "GRAPHICS_EXPOSURE",
67 [XCB_NO_EXPOSURE] = "NO_EXPOSURE",
68 [XCB_VISIBILITY_NOTIFY] = "VISIBILITY",
69 [XCB_UNMAP_NOTIFY] = "UNMAP",
70 [XCB_MAP_NOTIFY] = "MAP",
71 [XCB_MAP_REQUEST] = "MAP_REQUEST",
72 [XCB_REPARENT_NOTIFY] = "REPARENT",
73 [XCB_CONFIGURE_REQUEST] = "CONFIGURE_REQUEST",
74 [XCB_GRAVITY_NOTIFY] = "GRAVITY",
75 [XCB_RESIZE_REQUEST] = "RESIZE_REQUEST",
76 [XCB_CIRCULATE_NOTIFY] = "CIRCULATE",
77 [XCB_PROPERTY_NOTIFY] = "PROPERTY",
78 [XCB_SELECTION_CLEAR] = "SELECTION_CLEAR",
79 [XCB_SELECTION_REQUEST] = "SELECTION_REQUEST",
80 [XCB_SELECTION_NOTIFY] = "SELECTION",
81 [XCB_COLORMAP_NOTIFY] = "COLORMAP",
82 [XCB_CLIENT_MESSAGE] = "CLIENT_MESSAGE",
83 [XCB_MAPPING_NOTIFY] = "MAPPING"
84};
85
86void
87usage(char *name)
88{
89 fprintf(stderr, "usage: %s [-l] [-rm <mask>]\n", name);
90 exit(1);
91}
92
93void
94list_events(void)
95{
96 printf(
97 "XCB_EVENT_MASK_NO_EVENT .............. 0\n"
98 "XCB_EVENT_MASK_KEY_PRESS ............. 1\n"
99 "XCB_EVENT_MASK_KEY_RELEASE ........... 2\n"
100 "XCB_EVENT_MASK_BUTTON_PRESS .......... 4\n"
101 "XCB_EVENT_MASK_BUTTON_RELEASE ........ 8\n"
102 "XCB_EVENT_MASK_ENTER_WINDOW .......... 16\n"
103 "XCB_EVENT_MASK_LEAVE_WINDOW .......... 32\n"
104 "XCB_EVENT_MASK_POINTER_MOTION ........ 64\n"
105 "XCB_EVENT_MASK_POINTER_MOTION_HINT ... 128\n"
106 "XCB_EVENT_MASK_BUTTON_1_MOTION ....... 256\n"
107 "XCB_EVENT_MASK_BUTTON_2_MOTION ....... 512\n"
108 "XCB_EVENT_MASK_BUTTON_3_MOTION ....... 1024\n"
109 "XCB_EVENT_MASK_BUTTON_4_MOTION ....... 2048\n"
110 "XCB_EVENT_MASK_BUTTON_5_MOTION ....... 4096\n"
111 "XCB_EVENT_MASK_BUTTON_MOTION ......... 8192\n"
112 "XCB_EVENT_MASK_KEYMAP_STATE .......... 16384\n"
113 "XCB_EVENT_MASK_EXPOSURE .............. 32768\n"
114 "XCB_EVENT_MASK_VISIBILITY_CHANGE ..... 65536\n"
115 "XCB_EVENT_MASK_STRUCTURE_NOTIFY ...... 131072\n"
116 "XCB_EVENT_MASK_RESIZE_REDIRECT ....... 262144\n"
117 "XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY ... 524288\n"
118 "XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT . 1048576\n"
119 "XCB_EVENT_MASK_FOCUS_CHANGE .......... 2097152\n"
120 "XCB_EVENT_MASK_PROPERTY_CHANGE ....... 4194304\n"
121 "XCB_EVENT_MASK_COLOR_MAP_CHANGE ...... 8388608\n"
122 "XCB_EVENT_MASK_OWNER_GRAB_BUTTON ..... 16777216\n"
123 );
124}
125
126void
127register_events(xcb_window_t w, uint32_t m)
128{
129 uint32_t val[] = { m };
130
131 xcb_change_window_attributes(conn, w, XCB_CW_EVENT_MASK, val);
132 xcb_flush(conn);
133}
134
135void
136print_event(xcb_generic_event_t *e)
137{
138 xcb_enter_notify_event_t *en;
139 xcb_focus_in_event_t *ef;
140
141 switch (e->response_type & ~0x80) {
142 case XCB_ENTER_NOTIFY:
143 case XCB_LEAVE_NOTIFY:
144 en = (xcb_enter_notify_event_t *)e;
145 if (en->mode != XCB_NOTIFY_MODE_NORMAL)
146 return;
147 printf("%s\t0x%08x\n", evname[e->response_type], en->event);
148 break;
149
150 case XCB_FOCUS_IN:
151 case XCB_FOCUS_OUT:
152 ef = (xcb_focus_in_event_t *)e;
153 if (ef->mode != XCB_NOTIFY_MODE_NORMAL)
154 return;
155 printf("%s\t0x%08x\n", evname[e->response_type], ef->event);
156 break;
157
158 case XCB_CREATE_NOTIFY:
159 case XCB_DESTROY_NOTIFY:
160 printf("%s\t0x%08x\n", evname[e->response_type],
161 ((xcb_create_notify_event_t*)e)->window);
162 break;
163
164 case XCB_UNMAP_NOTIFY:
165 case XCB_MAP_NOTIFY:
166 printf("%s\t0x%08x\n", evname[e->response_type],
167 ((xcb_map_notify_event_t*)e)->window);
168 break;
169
170 case XCB_BUTTON_PRESS:
171 case XCB_BUTTON_RELEASE:
172 printf("%s\t0x%08x %d\n", evname[e->response_type],
173 ((xcb_button_press_event_t*)e)->event,
174 ((xcb_button_press_event_t*)e)->detail);
175 break;
176
177 /*
178 * MOTION_NOTIFY. Be careful with this one...
179 * It triggers ALOT!
180 *
181 * |\.---./|_
182 * (o) (°) ''--._
183 * / .A--. '\
184 * |' `. \
185 * / \
186 * /_;`|__\------(__/-\
187 */
188 case XCB_MOTION_NOTIFY:
189 printf("%s\t0x%08x\n", evname[e->response_type],
190 ((xcb_motion_notify_event_t*)e)->event);
191 break;
192 /* please... handle me ... ;_;
193 case XCB_KEY_PRESS:
194 case XCB_KEY_RELEASE:
195 case XCB_KEYMAP_NOTIFY:
196 case XCB_EXPOSE:
197 case XCB_GRAPHICS_EXPOSURE:
198 case XCB_NO_EXPOSURE:
199 case XCB_VISIBILITY_NOTIFY:
200 case XCB_MAP_REQUEST:
201 case XCB_REPARENT_NOTIFY:
202 case XCB_CONFIGURE_NOTIFY:
203 case XCB_CONFIGURE_REQUEST:
204 case XCB_GRAVITY_NOTIFY:
205 case XCB_RESIZE_REQUEST:
206 case XCB_CIRCULATE_NOTIFY:
207 case XCB_CIRCULATE_REQUEST:
208 case XCB_PROPERTY_NOTIFY:
209 case XCB_SELECTION_CLEAR:
210 case XCB_SELECTION_REQUEST:
211 case XCB_SELECTION_NOTIFY:
212 case XCB_COLORMAP_NOTIFY:
213 case XCB_CLIENT_MESSAGE:
214 case XCB_MAPPING_NOTIFY:
215 */
216 }
217}
218
219int
220main (int argc, char **argv)
221{
222 int i, wn;
223 char *argv0;
224 xcb_window_t *wc;
225 xcb_generic_event_t *e;
226 xcb_create_notify_event_t *ec;
227
228 ARGBEGIN {
229 case 'l':
230 list_events();
231 exit(0);
232 case 'r':
233 rootmask = strtoul(EARGF(usage(argv0)), NULL, 10);
234 break;
235 case 'm':
236 mask = strtoul(EARGF(usage(argv0)), NULL, 10);
237 break;
238 default: usage(argv0);
239 } ARGEND;
240
241 init_xcb(&conn);
242 get_screen(conn, &scr);
243
244 /*
245 * We need to get notifed of window creations, no matter what, because
246 * we need to register the event mask on all newly created windows
247 */
248 register_events(scr->root, rootmask);
249
250 /* register the events on all mapped windows */
251 wn = get_windows(conn, scr->root, &wc);
252 for (i=0; i<wn; i++)
253 register_events(wc[i], mask);
254
255 while(xcb_flush(conn)) {
256 e = xcb_wait_for_event(conn);
257 switch (e->response_type & ~0x80)
258 {
259 /* register events for each new windows */
260 case XCB_CREATE_NOTIFY:
261 ec = (xcb_create_notify_event_t*)e;
262 register_events(ec->window, mask);
263 /* FALLTHROUGH */
264 }
265 print_event(e);
266 fflush(stdout);
267
268 free(e);
269 }
270
271 kill_xcb(&conn);
272
273 return 0;
274}