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;