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)