commit f634045
uint
·
2026-08-04 12:43:35 +0000 UTC
parent 0a53089
Wayland: implement queued events, handle key repeats
2 files changed,
+219,
-54
+13,
-0
1@@ -4,6 +4,8 @@
2 #include <stddef.h>
3 #include <stdint.h>
4
5+#define MAUS_EVQ_MAX 64
6+
7 /* must forward declare so that other
8 ANSI abiding files arent affected */
9 struct wl_display;
10@@ -90,6 +92,17 @@ typedef struct {
11
12
13 MausEventPending pending;
14+ MausEventPending evq[MAUS_EVQ_MAX];
15+ uint32_t evq_head;
16+ uint32_t evq_tail;
17+ uint32_t evq_count;
18+
19+ int32_t repeat_rate;
20+ int32_t repeat_delay;
21+ uint32_t repeat_key_code;
22+ uint32_t repeat_key_sym;
23+ char repeat_key_text;
24+ uint64_t repeat_next_ns;
25
26 struct xdg_wm_base* wm_base;
27 struct xdg_surface* xdg_surface;
+206,
-54
1@@ -54,6 +54,12 @@ static void cursor_show(Maus* mw);
2 static void cursor_hide(Maus* mw);
3 static void cursor_relative(Maus* mw);
4 static void cursor_absolute(Maus* mw);
5+static void event_push_pending(Maus* mw);
6+static int8_t event_pop(Maus* mw, MausEventPending* ev);
7+static void event_push_key(Maus* mw, uint32_t code, uint32_t sym, char text, uint8_t pressed);
8+static int8_t repeat_push_due(Maus* mw);
9+static int32_t repeat_timeout_ms(Maus* mw);
10+static int8_t display_read(Maus* mw, int timeout_ms);
11 static MausKey keysym_to_mauskey(xkb_keysym_t sym);
12 static MausMouseButton wl_button_to_maus(uint32_t button);
13 static void wl_buffer_release(void* data, struct wl_buffer* buffer);
14@@ -89,6 +95,50 @@ static void wl_buffer_release(void* data, struct wl_buffer* buffer)
15 wb->busy = 0;
16 }
17
18+static void event_push_pending(Maus* mw)
19+{
20+ MausBackend* be = &mw->backend;
21+
22+ if (!be->pending.pending)
23+ return;
24+
25+ if (be->evq_count == MAUS_EVQ_MAX) {
26+ be->evq_head = (be->evq_head + 1) % MAUS_EVQ_MAX;
27+ be->evq_count--;
28+ }
29+
30+ be->evq[be->evq_tail] = be->pending;
31+ be->evq_tail = (be->evq_tail + 1) % MAUS_EVQ_MAX;
32+ be->evq_count++;
33+ be->pending.pending = 0;
34+}
35+
36+static int8_t event_pop(Maus* mw, MausEventPending* ev)
37+{
38+ MausBackend* be = &mw->backend;
39+
40+ if (be->evq_count == 0)
41+ return 0;
42+
43+ *ev = be->evq[be->evq_head];
44+ be->evq_head = (be->evq_head + 1) % MAUS_EVQ_MAX;
45+ be->evq_count--;
46+ return 1;
47+}
48+
49+static void event_push_key(Maus* mw, uint32_t code, uint32_t sym, char text, uint8_t pressed)
50+{
51+ MausBackend* be = &mw->backend;
52+
53+ be->pending.pending = 1;
54+ be->pending.type = MAUS_EV_KEY;
55+ be->pending.key_code = code;
56+ be->pending.key_sym = sym;
57+ be->pending.key_text = text;
58+ be->pending.key_pressed = pressed;
59+ event_push_pending(mw);
60+}
61+
62 static void registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name)
63 {
64 (void)data;
65@@ -105,6 +155,7 @@ static void xdg_surface_configure(void* data, struct xdg_surface* xdg_surface, u
66 mw->backend.pending.pending = 1;
67 mw->backend.pending.type = MAUS_EV_REDRAW;
68 }
69+ event_push_pending(mw);
70 }
71
72 static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel,
73@@ -122,6 +173,7 @@ static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel
74 mw->backend.pending.type = MAUS_EV_RESIZE;
75 mw->backend.pending.width = width;
76 mw->backend.pending.height = height;
77+ event_push_pending(mw);
78 }
79
80 static void xdg_toplevel_close(void* data, struct xdg_toplevel* xdg_toplevel)
81@@ -132,6 +184,7 @@ static void xdg_toplevel_close(void* data, struct xdg_toplevel* xdg_toplevel)
82
83 mw->backend.pending.pending = 1;
84 mw->backend.pending.type = MAUS_EV_CLOSE;
85+ event_push_pending(mw);
86 }
87
88 static void xdg_toplevel_configure_bounds(void* data, struct xdg_toplevel* xdg_toplevel,
89@@ -268,6 +321,7 @@ static void pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time
90 be->mouse_x = x;
91 be->mouse_y = y;
92 be->mouse_pos_set = 1;
93+ event_push_pending(mw);
94 }
95
96 static void pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial,
97@@ -288,6 +342,7 @@ static void pointer_button(void* data, struct wl_pointer* pointer, uint32_t seri
98
99 if (mb != MAUS_MOUSE_BUTTON_NONE)
100 mw->mouse_buttons[mb] = mw->backend.pending.mouse_pressed;
101+ event_push_pending(mw);
102 }
103
104 static void pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time,
105@@ -307,6 +362,7 @@ static void pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time,
106 ? MAUS_MOUSE_BUTTON_SCROLL_DOWN
107 : MAUS_MOUSE_BUTTON_SCROLL_UP;
108 mw->backend.pending.mouse_pressed = 1;
109+ event_push_pending(mw);
110 }
111
112 static void pointer_frame(void* data, struct wl_pointer* pointer)
113@@ -375,6 +431,7 @@ static void relative_pointer_motion(void* data, struct zwp_relative_pointer_v1*
114 mw->backend.pending.mouse_y = wl_fixed_to_int(dy);
115 mw->backend.pending.mouse_dx = wl_fixed_to_int(dx);
116 mw->backend.pending.mouse_dy = wl_fixed_to_int(dy);
117+ event_push_pending(mw);
118 }
119
120 static void keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format,
121@@ -430,10 +487,13 @@ static void keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t se
122 static void keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial,
123 struct wl_surface* surface)
124 {
125- (void)data;
126+ Maus* mw = data;
127+
128 (void)keyboard;
129 (void)serial;
130 (void)surface;
131+
132+ mw->backend.repeat_key_code = 0;
133 }
134
135 static void keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t serial,
136@@ -443,8 +503,10 @@ static void keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t seri
137 MausBackend* be = &mw->backend;
138 uint32_t code;
139 xkb_keysym_t sym;
140+ MausKey maus_key;
141 char text[8];
142 int len;
143+ uint8_t pressed;
144
145 (void)keyboard;
146 (void)serial;
147@@ -463,19 +525,32 @@ static void keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t seri
148 }
149 }
150
151- be->pending.pending = 1;
152- be->pending.type = MAUS_EV_KEY;
153- be->pending.key_code = code;
154- be->pending.key_sym = keysym_to_mauskey(sym);
155- be->pending.key_text = text[0];
156- if (be->pending.key_sym == MAUS_KEY_ENTER)
157- be->pending.key_text = '\n';
158- be->pending.key_pressed = state == WL_KEYBOARD_KEY_STATE_PRESSED;
159+ maus_key = keysym_to_mauskey(sym);
160+ if (maus_key == MAUS_KEY_ENTER)
161+ text[0] = '\n';
162+ pressed = state == WL_KEYBOARD_KEY_STATE_PRESSED;
163+ event_push_key(mw, code, maus_key, text[0], pressed);
164
165 if (code < MAUS_KEYCODE_LAST)
166- mw->key_codes[code] = be->pending.key_pressed;
167- if (be->pending.key_sym != MAUS_KEY_NONE)
168- mw->key_syms[be->pending.key_sym] = be->pending.key_pressed;
169+ mw->key_codes[code] = pressed;
170+ if (maus_key != MAUS_KEY_NONE)
171+ mw->key_syms[maus_key] = pressed;
172+
173+ if (!pressed) {
174+ if (be->repeat_key_code == code)
175+ be->repeat_key_code = 0;
176+ return;
177+ }
178+
179+ if (be->repeat_rate > 0 && be->xkb_keymap &&
180+ xkb_keymap_key_repeats(be->xkb_keymap, code)) {
181+ be->repeat_key_code = code;
182+ be->repeat_key_sym = maus_key;
183+ be->repeat_key_text = text[0];
184+ be->repeat_next_ns = maus_get_time_ns() + be->repeat_delay * 1000000;
185+ }
186+ else
187+ be->repeat_key_code = 0;
188 }
189
190 static void keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial,
191@@ -500,10 +575,85 @@ static void keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_
192 static void keyboard_repeat_info(void* data, struct wl_keyboard* keyboard,
193 int32_t rate, int32_t delay)
194 {
195- (void)data;
196+ Maus* mw = data;
197+
198 (void)keyboard;
199- (void)rate;
200- (void)delay;
201+
202+ mw->backend.repeat_rate = rate;
203+ mw->backend.repeat_delay = delay;
204+ if (rate <= 0)
205+ mw->backend.repeat_key_code = 0;
206+}
207+
208+static int8_t repeat_push_due(Maus* mw)
209+{
210+ MausBackend* be = &mw->backend;
211+ uint64_t now;
212+ uint64_t interval;
213+
214+ if (be->repeat_key_code == 0 || be->repeat_rate <= 0)
215+ return 0;
216+
217+ now = maus_get_time_ns();
218+ if (now < be->repeat_next_ns)
219+ return 0;
220+
221+ event_push_key(mw, be->repeat_key_code, be->repeat_key_sym, be->repeat_key_text, 1);
222+ interval = 1000000000 / be->repeat_rate;
223+ do {
224+ be->repeat_next_ns += interval;
225+ } while (be->repeat_next_ns <= now);
226+
227+ return 1;
228+}
229+
230+static int32_t repeat_timeout_ms(Maus* mw)
231+{
232+ MausBackend* be = &mw->backend;
233+ uint64_t now;
234+ uint64_t diff;
235+
236+ if (be->repeat_key_code == 0 || be->repeat_rate <= 0)
237+ return -1;
238+
239+ now = maus_get_time_ns();
240+ if (now >= be->repeat_next_ns)
241+ return 0;
242+
243+ diff = be->repeat_next_ns - now;
244+ /* round xto nearest ms */
245+ return (int32_t)((diff + 999999) / 1000000);
246+}
247+
248+static int8_t display_read(Maus* mw, int timeout_ms)
249+{
250+ MausBackend* be = &mw->backend;
251+ struct pollfd pfd;
252+ int ret;
253+
254+ if (wl_display_prepare_read(be->display) != 0) {
255+ wl_display_dispatch_pending(be->display);
256+ return 1;
257+ }
258+
259+ wl_display_flush(be->display);
260+
261+ pfd.fd = wl_display_get_fd(be->display);
262+ pfd.events = POLLIN;
263+ pfd.revents = 0;
264+
265+ ret = poll(&pfd, 1, timeout_ms);
266+ if (ret > 0 && (pfd.revents & POLLIN)) {
267+ if (wl_display_read_events(be->display) == -1) {
268+ wl_display_cancel_read(be->display);
269+ return -1;
270+ }
271+ wl_display_dispatch_pending(be->display);
272+ return 1;
273+ }
274+
275+ wl_display_cancel_read(be->display);
276+ return 0;
277 }
278
279
280@@ -748,40 +898,39 @@ static void fb_destroy(Maus* mw)
281
282 static int8_t handle_event(Maus* mw, MausEvent* ev)
283 {
284- MausBackend* be = &mw->backend;
285+ MausEventPending pending;
286
287- if (!be->pending.pending)
288+ if (!event_pop(mw, &pending))
289 return 0;
290
291- ev->type = be->pending.type;
292- be->pending.pending = 0;
293+ ev->type = pending.type;
294
295 switch (ev->type) {
296 case MAUS_EV_CLOSE:
297 return 1;
298
299 case MAUS_EV_RESIZE:
300- ev->resize.width = be->pending.width;
301- ev->resize.height = be->pending.height;
302+ ev->resize.width = pending.width;
303+ ev->resize.height = pending.height;
304 return 1;
305
306 case MAUS_EV_MOUSE_MOTION:
307- ev->mouse.motion.x = be->pending.mouse_x;
308- ev->mouse.motion.y = be->pending.mouse_y;
309- ev->mouse.motion.dx = be->pending.mouse_dx;
310- ev->mouse.motion.dy = be->pending.mouse_dy;
311+ ev->mouse.motion.x = pending.mouse_x;
312+ ev->mouse.motion.y = pending.mouse_y;
313+ ev->mouse.motion.dx = pending.mouse_dx;
314+ ev->mouse.motion.dy = pending.mouse_dy;
315 return 1;
316
317 case MAUS_EV_MOUSE_BUTTON:
318- ev->mouse.button.button = be->pending.mouse_button;
319- ev->mouse.button.pressed = be->pending.mouse_pressed;
320+ ev->mouse.button.button = pending.mouse_button;
321+ ev->mouse.button.pressed = pending.mouse_pressed;
322 return 1;
323
324 case MAUS_EV_KEY:
325- ev->key.code = be->pending.key_code;
326- ev->key.pressed = be->pending.key_pressed;
327- ev->key.key = be->pending.key_sym;
328- ev->key.text = be->pending.key_text;
329+ ev->key.code = pending.key_code;
330+ ev->key.pressed = pending.key_pressed;
331+ ev->key.key = pending.key_sym;
332+ ev->key.text = pending.key_text;
333 return 1;
334
335 default:
336@@ -1052,10 +1201,13 @@ close:
337 int8_t maus_event_poll(Maus* mw, MausEvent* ev)
338 {
339 MausBackend* be = &mw->backend;
340- struct pollfd pfd;
341+ int8_t read;
342
343 ev->type = MAUS_EV_NONE;
344
345+ if (repeat_push_due(mw) && handle_event(mw, ev))
346+ return 1;
347+
348 if (handle_event(mw, ev))
349 return 1;
350
351@@ -1063,30 +1215,15 @@ int8_t maus_event_poll(Maus* mw, MausEvent* ev)
352 if (handle_event(mw, ev))
353 return 1;
354
355- if (wl_display_prepare_read(be->display) != 0) {
356- wl_display_dispatch_pending(be->display);
357- return handle_event(mw, ev);
358- }
359-
360- wl_display_flush(be->display);
361-
362- pfd.fd = wl_display_get_fd(be->display);
363- pfd.events = POLLIN;
364- pfd.revents = 0;
365-
366- if (poll(&pfd, 1, 0) > 0 && (pfd.revents & POLLIN)) {
367- if (wl_display_read_events(be->display) == -1) {
368- ev->type = MAUS_EV_CLOSE;
369- wl_display_cancel_read(be->display);
370- return 1;
371- }
372+ read = display_read(mw, 0);
373+ if (read == -1) {
374+ ev->type = MAUS_EV_CLOSE;
375+ return 1;
376 }
377- else {
378- wl_display_cancel_read(be->display);
379+ if (read == 0)
380 return 0;
381- }
382-
383- wl_display_dispatch_pending(be->display);
384+ if (repeat_push_due(mw) && handle_event(mw, ev))
385+ return 1;
386
387 return handle_event(mw, ev);
388 }
389@@ -1094,13 +1231,28 @@ int8_t maus_event_poll(Maus* mw, MausEvent* ev)
390 void maus_event_wait(Maus* mw, MausEvent* ev)
391 {
392 MausBackend* be = &mw->backend;
393+ int32_t timeout;
394+ int8_t read;
395
396 ev->type = MAUS_EV_NONE;
397
398 for (;;) {
399+ if (repeat_push_due(mw) && handle_event(mw, ev))
400+ return;
401+
402 if (handle_event(mw, ev))
403 return;
404
405+ timeout = repeat_timeout_ms(mw);
406+ if (timeout >= 0) {
407+ read = display_read(mw, timeout);
408+ if (read == -1) {
409+ ev->type = MAUS_EV_CLOSE;
410+ return;
411+ }
412+ continue;
413+ }
414+
415 if (wl_display_dispatch(be->display) == -1) {
416 ev->type = MAUS_EV_CLOSE;
417 return;