master ohmu/wmutils / src / opt / wew.c
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}