commit 9fa2383

uint  ·  2026-08-03 20:41:30 +0000 UTC
parent 210774a
Wayland: initial event handling
2 files changed,  +373, -12
+29, -3
 1@@ -12,19 +12,45 @@ struct wl_registry;
 2 struct wl_compositor;
 3 struct wl_surface;
 4 struct wl_shm;
 5+struct wl_seat;
 6+struct wl_pointer;
 7+struct wl_keyboard;
 8 
 9 struct xdg_wm_base;
10 struct xdg_surface;
11 struct xdg_toplevel;
12 
13+typedef struct {
14+	int8_t  pending;
15+	int32_t type;
16+
17+	uint32_t width;
18+	uint32_t height;
19+
20+	uint32_t mouse_x;
21+	uint32_t mouse_y;
22+	uint32_t mouse_button;
23+	uint8_t  mouse_pressed;
24+
25+	uint32_t key_code;
26+	uint8_t  key_pressed;
27+} MausEventPending;
28+
29 typedef struct {
30 	struct wl_display*    display;
31 	struct wl_buffer*     buffer;
32 	struct wl_compositor* compositor;
33 	struct wl_surface*    surface;
34-	struct wl_shm*        shm;
35-	void*                 shm_data;
36-	size_t                shm_size;
37+
38+	struct wl_shm* shm;
39+	void*          shm_data;
40+	size_t         shm_size;
41+
42+	struct wl_seat*     seat;
43+	struct wl_pointer*  pointer;
44+	struct wl_keyboard* keyboard;
45+
46+	MausEventPending pending;
47 
48 	struct xdg_wm_base*  wm_base;
49 	struct xdg_surface*  xdg_surface;
+344, -9
  1@@ -1,4 +1,5 @@
  2 #include <fcntl.h>
  3+#include <poll.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <sys/mman.h>
  7@@ -12,26 +13,114 @@
  8 
  9 static void registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name);
 10 static void xdg_surface_configure(void* data, struct xdg_surface* xdg_surface, uint32_t serial);
 11+static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel,
 12+                                   int32_t width, int32_t height, struct wl_array* states);
 13+static void xdg_toplevel_close(void* data, struct xdg_toplevel* xdg_toplevel);
 14+static void xdg_toplevel_configure_bounds(void* data, struct xdg_toplevel* xdg_toplevel,
 15+                                          int32_t width, int32_t height);
 16+static void xdg_toplevel_wm_capabilities(void* data, struct xdg_toplevel* xdg_toplevel,
 17+                                         struct wl_array* capabilities);
 18 static void wm_base_ping(void* data, struct xdg_wm_base* wm_base, uint32_t serial);
 19+static void seat_capabilities(void* data, struct wl_seat* seat, uint32_t capabilities);
 20+static void seat_name(void* data, struct wl_seat* seat, const char* name);
 21+static void pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial,
 22+                          struct wl_surface* surface, wl_fixed_t sx, wl_fixed_t sy);
 23+static void pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial,
 24+                          struct wl_surface* surface);
 25+static void pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time,
 26+                           wl_fixed_t sx, wl_fixed_t sy);
 27+static void pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial,
 28+                           uint32_t time, uint32_t button, uint32_t state);
 29+static void pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time,
 30+                         uint32_t axis, wl_fixed_t value);
 31+static void pointer_frame(void* data, struct wl_pointer* pointer);
 32+static void pointer_axis_source(void* data, struct wl_pointer* pointer, uint32_t axis_source);
 33+static void pointer_axis_stop(void* data, struct wl_pointer* pointer, uint32_t time,
 34+                              uint32_t axis);
 35+static void pointer_axis_discrete(void* data, struct wl_pointer* pointer, uint32_t axis,
 36+                                  int32_t discrete);
 37+static void pointer_axis_value120(void* data, struct wl_pointer* pointer, uint32_t axis,
 38+                                  int32_t value120);
 39+static void pointer_axis_relative_direction(void* data, struct wl_pointer* pointer,
 40+                                            uint32_t axis, uint32_t direction);
 41+static void keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format,
 42+                            int32_t fd, uint32_t size);
 43+static void keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial,
 44+                           struct wl_surface* surface, struct wl_array* keys);
 45+static void keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial,
 46+                           struct wl_surface* surface);
 47+static void keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t serial,
 48+                         uint32_t time, uint32_t key, uint32_t state);
 49+static void keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial,
 50+                               uint32_t mods_depressed, uint32_t mods_latched,
 51+                               uint32_t mods_locked, uint32_t group);
 52+static void keyboard_repeat_info(void* data, struct wl_keyboard* keyboard,
 53+                                 int32_t rate, int32_t delay);
 54 static void registry_global(void* data, struct wl_registry* registry,
 55                             uint32_t name, const char* interface,
 56                             uint32_t version);
 57 static struct wl_registry_listener registry_listener = { registry_global, registry_global_remove };
 58 static struct xdg_surface_listener xdg_surface_listener = { xdg_surface_configure };
 59+static struct xdg_toplevel_listener xdg_toplevel_listener = {
 60+	xdg_toplevel_configure, xdg_toplevel_close,
 61+	xdg_toplevel_configure_bounds, xdg_toplevel_wm_capabilities
 62+};
 63 static struct xdg_wm_base_listener xdg_wm_base_listener = { wm_base_ping };
 64+static struct wl_seat_listener seat_listener = { seat_capabilities, seat_name };
 65+static struct wl_pointer_listener pointer_listener = {
 66+	pointer_enter, pointer_leave, pointer_motion, pointer_button,
 67+	pointer_axis, pointer_frame, pointer_axis_source, pointer_axis_stop,
 68+	pointer_axis_discrete, pointer_axis_value120, pointer_axis_relative_direction
 69+};
 70+static struct wl_keyboard_listener keyboard_listener = {
 71+	keyboard_keymap, keyboard_enter, keyboard_leave, keyboard_key,
 72+	keyboard_modifiers, keyboard_repeat_info
 73+};
 74+
 75+static void registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) { }
 76 
 77-static void registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name)
 78+static void xdg_surface_configure(void* data, struct xdg_surface* xdg_surface, uint32_t serial)
 79+{
 80+	Maus* mw = data;
 81+	xdg_surface_ack_configure(xdg_surface, serial);
 82+	mw->backend.configured = 1;
 83+	mw->backend.pending.pending = 1;
 84+	mw->backend.pending.type = MAUS_EV_REDRAW;
 85+}
 86+
 87+static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel,
 88+                                   int32_t width, int32_t height, struct wl_array* states)
 89 {
 90+	Maus* mw = data;
 91+
 92+	(void)xdg_toplevel;
 93+	(void)states;
 94+
 95+	if (width <= 0 || height <= 0)
 96+		return;
 97 
 98+	mw->backend.pending.pending = 1;
 99+	mw->backend.pending.type = MAUS_EV_RESIZE;
100+	mw->backend.pending.width = width;
101+	mw->backend.pending.height = height;
102 }
103 
104-static void xdg_surface_configure(void* data, struct xdg_surface* xdg_surface, uint32_t serial)
105+static void xdg_toplevel_close(void* data, struct xdg_toplevel* xdg_toplevel)
106 {
107 	Maus* mw = data;
108-	xdg_surface_ack_configure(xdg_surface, serial);
109-	mw->backend.configured = 1;
110+
111+	(void)xdg_toplevel;
112+
113+	mw->backend.pending.pending = 1;
114+	mw->backend.pending.type = MAUS_EV_CLOSE;
115 }
116 
117+static void xdg_toplevel_configure_bounds(void* data, struct xdg_toplevel* xdg_toplevel,
118+                                          int32_t width, int32_t height) { }
119+
120+static void xdg_toplevel_wm_capabilities(void* data, struct xdg_toplevel* xdg_toplevel,
121+                                         struct wl_array* capabilities) { }
122+
123 static void wm_base_ping(void* data, struct xdg_wm_base* wm_base, uint32_t serial)
124 {
125 	(void)data;
126@@ -51,19 +140,158 @@ static void registry_global(void* data, struct wl_registry* registry,
127 		be->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4);
128 	else if (strcmp(interface, wl_shm_interface.name) == 0)
129 		be->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
130-	else if (strcmp(interface, xdg_wm_base_interface.name) == 0)
131-		be->wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
132 	else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
133 		be->wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
134 		xdg_wm_base_add_listener(be->wm_base, &xdg_wm_base_listener, mw);
135 	}
136+	else if (strcmp(interface, wl_seat_interface.name) == 0) {
137+		be->seat = wl_registry_bind(registry, name, &wl_seat_interface, 5);
138+		wl_seat_add_listener(be->seat, &seat_listener, mw);
139+	}
140 }
141 
142+static void seat_capabilities(void* data, struct wl_seat* seat, uint32_t capabilities)
143+{
144+	Maus* mw = data;
145+	MausBackend* be = &mw->backend;
146 
147+	if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !be->pointer) {
148+		be->pointer = wl_seat_get_pointer(seat);
149+		wl_pointer_add_listener(be->pointer, &pointer_listener, mw);
150+	}
151+	else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && be->pointer) {
152+		wl_pointer_destroy(be->pointer);
153+		be->pointer = NULL;
154+	}
155+
156+	if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && !be->keyboard) {
157+		be->keyboard = wl_seat_get_keyboard(seat);
158+		wl_keyboard_add_listener(be->keyboard, &keyboard_listener, mw);
159+	}
160+	else if (!(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && be->keyboard) {
161+		wl_keyboard_destroy(be->keyboard);
162+		be->keyboard = NULL;
163+	}
164+}
165+
166+static void seat_name(void* data, struct wl_seat* seat, const char* name) { }
167+
168+static void pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial,
169+                          struct wl_surface* surface, wl_fixed_t sx, wl_fixed_t sy) { }
170+
171+static void pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial,
172+                          struct wl_surface* surface) { }
173+
174+static void pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time,
175+                           wl_fixed_t sx, wl_fixed_t sy)
176+{
177+	Maus* mw = data;
178+
179+	(void)pointer;
180+	(void)time;
181+
182+	mw->backend.pending.pending = 1;
183+	mw->backend.pending.type = MAUS_EV_MOUSE_MOTION;
184+	mw->backend.pending.mouse_x = wl_fixed_to_int(sx);
185+	mw->backend.pending.mouse_y = wl_fixed_to_int(sy);
186+}
187+
188+static void pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial,
189+                           uint32_t time, uint32_t button, uint32_t state)
190+{
191+	Maus* mw = data;
192+	MausMouseButton mb;
193+
194+	(void)pointer;
195+	(void)serial;
196+	(void)time;
197+
198+	mb = wl_button_to_maus(button);
199+	mw->backend.pending.pending = 1;
200+	mw->backend.pending.type = MAUS_EV_MOUSE_BUTTON;
201+	mw->backend.pending.mouse_button = mb;
202+	mw->backend.pending.mouse_pressed = state == WL_POINTER_BUTTON_STATE_PRESSED;
203+
204+	if (mb != MAUS_MOUSE_BUTTON_NONE)
205+		mw->mouse_buttons[mb] = mw->backend.pending.mouse_pressed;
206+}
207+
208+static void pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time,
209+                         uint32_t axis, wl_fixed_t value)
210+{
211+	Maus* mw = data;
212+
213+	(void)pointer;
214+	(void)time;
215+
216+	if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
217+		return;
218+
219+	mw->backend.pending.pending = 1;
220+	mw->backend.pending.type = MAUS_EV_MOUSE_BUTTON;
221+	mw->backend.pending.mouse_button = wl_fixed_to_int(value) > 0
222+		? MAUS_MOUSE_BUTTON_SCROLL_DOWN
223+		: MAUS_MOUSE_BUTTON_SCROLL_UP;
224+	mw->backend.pending.mouse_pressed = 1;
225+}
226+
227+static void pointer_frame(void* data, struct wl_pointer* pointer) { }
228+
229+static void pointer_axis_source(void* data, struct wl_pointer* pointer, uint32_t axis_source) { }
230+
231+static void pointer_axis_stop(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis) {
232+}
233+
234+static void pointer_axis_discrete(void* data, struct wl_pointer* pointer, uint32_t axis,
235+                                  int32_t discrete) { }
236+
237+static void pointer_axis_value120(void* data, struct wl_pointer* pointer, uint32_t axis,
238+                                  int32_t value120) { }
239+
240+static void pointer_axis_relative_direction(void* data, struct wl_pointer* pointer,
241+                                            uint32_t axis, uint32_t direction) { }
242+
243+static void keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format,
244+                            int32_t fd, uint32_t size) { }
245+
246+static void keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial,
247+                           struct wl_surface* surface, struct wl_array* keys) { }
248+
249+static void keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial,
250+                           struct wl_surface* surface) { }
251+
252+static void keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t serial,
253+                         uint32_t time, uint32_t key, uint32_t state)
254+{
255+	Maus* mw = data;
256+	uint32_t code;
257+
258+	(void)keyboard;
259+	(void)serial;
260+	(void)time;
261+
262+	code = key + 8;
263+	mw->backend.pending.pending = 1;
264+	mw->backend.pending.type = MAUS_EV_KEY;
265+	mw->backend.pending.key_code = code;
266+	mw->backend.pending.key_pressed = state == WL_KEYBOARD_KEY_STATE_PRESSED;
267+
268+	if (code < MAUS_KEYCODE_LAST)
269+		mw->key_codes[code] = mw->backend.pending.key_pressed;
270+}
271+
272+static void keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial,
273+                               uint32_t mods_depressed, uint32_t mods_latched,
274+                               uint32_t mods_locked, uint32_t group) { }
275+
276+static void keyboard_repeat_info(void* data, struct wl_keyboard* keyboard,
277+                                 int32_t rate, int32_t delay) { }
278 
279 
280 static int8_t fb_create(Maus* mw);
281 static int8_t fb_create_shm(size_t size);
282+static int8_t handle_event(Maus* mw, MausEvent* ev);
283+static MausMouseButton wl_button_to_maus(uint32_t button);
284 
285 static int8_t fb_create(Maus* mw)
286 {
287@@ -129,6 +357,57 @@ static int8_t fb_create_shm(size_t size)
288 	return -1;
289 }
290 
291+static int8_t handle_event(Maus* mw, MausEvent* ev)
292+{
293+	MausBackend* be = &mw->backend;
294+
295+	if (!be->pending.pending)
296+		return 0;
297+
298+	ev->type = be->pending.type;
299+	be->pending.pending = 0;
300+
301+	switch (ev->type) {
302+	case MAUS_EV_CLOSE:
303+		return 1;
304+
305+	case MAUS_EV_RESIZE:
306+		ev->resize.width = be->pending.width;
307+		ev->resize.height = be->pending.height;
308+		return 1;
309+
310+	case MAUS_EV_MOUSE_MOTION:
311+		ev->mouse.motion.x = be->pending.mouse_x;
312+		ev->mouse.motion.y = be->pending.mouse_y;
313+		return 1;
314+
315+	case MAUS_EV_MOUSE_BUTTON:
316+		ev->mouse.button.button = be->pending.mouse_button;
317+		ev->mouse.button.pressed = be->pending.mouse_pressed;
318+		return 1;
319+
320+	case MAUS_EV_KEY:
321+		ev->key.code = be->pending.key_code;
322+		ev->key.pressed = be->pending.key_pressed;
323+		ev->key.key = MAUS_KEY_NONE;
324+		ev->key.text = 0;
325+		return 1;
326+
327+	default:
328+		return 1;
329+	}
330+}
331+
332+static MausMouseButton wl_button_to_maus(uint32_t button)
333+{
334+	switch (button) {
335+		case 0x110: return MAUS_MOUSE_BUTTON_LEFT;
336+		case 0x111: return MAUS_MOUSE_BUTTON_RIGHT;
337+		case 0x112: return MAUS_MOUSE_BUTTON_MIDDLE;
338+		default:    return MAUS_MOUSE_BUTTON_NONE;
339+	}
340+}
341+
342 void maus_clear(Maus* mw, MausColor col)
343 {
344 	uint32_t up = MAUS_UNPACK_COL(col);
345@@ -174,6 +453,15 @@ void maus_close(Maus* mw)
346 	if (be->surface)
347 		wl_surface_destroy(be->surface);
348 
349+	if (be->keyboard)
350+		wl_keyboard_destroy(be->keyboard);
351+
352+	if (be->pointer)
353+		wl_pointer_destroy(be->pointer);
354+
355+	if (be->seat)
356+		wl_seat_destroy(be->seat);
357+
358 	if (be->wm_base)
359 		xdg_wm_base_destroy(be->wm_base);
360 
361@@ -240,6 +528,7 @@ int8_t maus_create_window(Maus* mw)
362 	if (!be->xdg_toplevel)
363 		return 0;
364 
365+	xdg_toplevel_add_listener(be->xdg_toplevel, &xdg_toplevel_listener, mw);
366 	xdg_toplevel_set_title(be->xdg_toplevel, mw->title);
367 
368 	if (!fb_create(mw))
369@@ -299,15 +588,61 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
370 
371 int8_t maus_event_poll(Maus* mw, MausEvent* ev)
372 {
373+	MausBackend* be = &mw->backend;
374+	struct pollfd pfd;
375+
376 	ev->type = MAUS_EV_NONE;
377-	wl_display_dispatch_pending(mw->backend.display);
378-	wl_display_flush(mw->backend.display);
379-	return 0;
380+
381+	if (handle_event(mw, ev))
382+		return 1;
383+
384+	wl_display_dispatch_pending(be->display);
385+	if (handle_event(mw, ev))
386+		return 1;
387+
388+	if (wl_display_prepare_read(be->display) != 0) {
389+		wl_display_dispatch_pending(be->display);
390+		return handle_event(mw, ev);
391+	}
392+
393+	wl_display_flush(be->display);
394+
395+	pfd.fd = wl_display_get_fd(be->display);
396+	pfd.events = POLLIN;
397+	pfd.revents = 0;
398+
399+	if (poll(&pfd, 1, 0) > 0 && (pfd.revents & POLLIN)) {
400+		if (wl_display_read_events(be->display) == -1) {
401+			ev->type = MAUS_EV_CLOSE;
402+			wl_display_cancel_read(be->display);
403+			return 1;
404+		}
405+	}
406+	else {
407+		wl_display_cancel_read(be->display);
408+		return 0;
409+	}
410+
411+	wl_display_dispatch_pending(be->display);
412+
413+	return handle_event(mw, ev);
414 }
415 
416 void maus_event_wait(Maus* mw, MausEvent* ev)
417 {
418+	MausBackend* be = &mw->backend;
419+
420+	ev->type = MAUS_EV_NONE;
421 
422+	for (;;) {
423+		if (handle_event(mw, ev))
424+			return;
425+
426+		if (wl_display_dispatch(be->display) == -1) {
427+			ev->type = MAUS_EV_CLOSE;
428+			return;
429+		}
430+	}
431 }
432 
433 void maus_present(Maus* mw)