From 545c452136786eb931a7a5bac48d7890c875ed65 Mon Sep 17 00:00:00 2001 From: werapi Date: Wed, 25 Mar 2026 22:29:52 +0100 Subject: [PATCH] fix: drop events for cancelled touch points --- src/mango.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/src/mango.c b/src/mango.c index 41fe45e5..576ee6eb 100644 --- a/src/mango.c +++ b/src/mango.c @@ -452,9 +452,15 @@ typedef struct { struct wl_listener destroy; } KeyboardGroup; +typedef struct { + struct wl_list link; + int32_t touch_id; +} TouchPoint; + typedef struct TouchGroup { struct wl_list link; struct wlr_touch *touch; + struct wl_list touch_points; Monitor *m; } TouchGroup; @@ -891,7 +897,7 @@ static struct wlr_output_layout *output_layout; static struct wlr_box sgeom; static struct wl_list mons; static Monitor *selmon; -static struct wl_list touches; +static struct wl_list touch_groups; static bool emulating_pointer_from_touch = false; static int32_t emulated_pointer_touch_id; @@ -3351,7 +3357,9 @@ void createtouch(struct wlr_touch *wlr_touch) { TouchGroup *touch = ecalloc(1, sizeof(TouchGroup)); touch->touch = wlr_touch; - wl_list_insert(&touches, &touch->link); + wl_list_init(&touch->touch_points); + wl_list_insert(&touch_groups, &touch->link); + wlr_touch->data = touch; wlr_cursor_attach_input_device(cursor, &wlr_touch->base); } @@ -3731,7 +3739,7 @@ void inputdevice(struct wl_listener *listener, void *data) { caps = WL_SEAT_CAPABILITY_POINTER; if (!wl_list_empty(&kb_group->wlr_group->devices)) caps |= WL_SEAT_CAPABILITY_KEYBOARD; - if (!wl_list_empty(&touches)) + if (!wl_list_empty(&touch_groups)) caps |= WL_SEAT_CAPABILITY_TOUCH; wlr_seat_set_capabilities(seat, caps); } @@ -5747,7 +5755,7 @@ void setup(void) { wl_signal_add(&cursor->events.axis, &cursor_axis); wl_signal_add(&cursor->events.frame, &cursor_frame); - wl_list_init(&touches); + wl_list_init(&touch_groups); wl_signal_add(&cursor->events.touch_down, &touch_down); wl_signal_add(&cursor->events.touch_frame, &touch_frame); @@ -5871,6 +5879,8 @@ void startdrag(struct wl_listener *listener, void *data) { void touchdown(struct wl_listener *listener, void *data) { struct wlr_touch_down_event *event = data; + TouchGroup *tg = event->touch->data; + TouchPoint *t = ecalloc(1, sizeof(TouchPoint)); double lx, ly; double sx, sy; double dx, dy; @@ -5878,6 +5888,9 @@ void touchdown(struct wl_listener *listener, void *data) { Client *c = NULL; Monitor *m; + t->touch_id = event->touch_id; + wl_list_insert(&tg->touch_points, &t->link); + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); if (!cursor_hidden) { @@ -5935,6 +5948,20 @@ void touchdown(struct wl_listener *listener, void *data) { void touchup(struct wl_listener *listener, void *data) { struct wlr_touch_up_event *event = data; + TouchGroup *tg = event->touch->data; + TouchPoint *t = NULL; + TouchPoint *t_iter; + + wl_list_for_each(t_iter, &tg->touch_points, link) { + if (t_iter->touch_id == event->touch_id) { + t = t_iter; + break; + } + } + if (!t) // invalid or cancelled + return; + wl_list_remove(&t->link); + free(t); if (emulating_pointer_from_touch) { if (emulated_pointer_touch_id == event->touch_id) { @@ -5969,6 +5996,9 @@ void touchframe(struct wl_listener *listener, void *data) { void touchmotion(struct wl_listener *listener, void *data) { struct wlr_touch_motion_event *event = data; + TouchGroup *tg = event->touch->data; + TouchPoint *t = NULL; + TouchPoint *t_iter; double lx, ly; double sx, sy; double dx, dy; @@ -5978,6 +6008,15 @@ void touchmotion(struct wl_listener *listener, void *data) { struct wlr_scene_tree *tree; struct wlr_touch_point *p = NULL; + wl_list_for_each(t_iter, &tg->touch_points, link) { + if (t_iter->touch_id == event->touch_id) { + t = t_iter; + break; + } + } + if (!t) // invalid or cancelled + return; + if (emulating_pointer_from_touch) { if (emulated_pointer_touch_id == event->touch_id) { wlr_cursor_absolute_to_layout_coords(cursor, &event->touch->base, @@ -6024,10 +6063,25 @@ void touchmotion(struct wl_listener *listener, void *data) { void touchcancel(struct wl_listener *listener, void *data) { struct wlr_touch_cancel_event *event = data; + TouchGroup *tg = event->touch->data; + TouchPoint *t = NULL; + TouchPoint *t_iter; struct wlr_touch_point *p = NULL; struct wl_client *client = NULL; struct wlr_seat_client *seat_client = NULL; + wl_list_for_each(t_iter, &tg->touch_points, link) { + if (t_iter->touch_id == event->touch_id) { + t = t_iter; + break; + } + } + if (!t) + return; + + wl_list_remove(&t->link); + free(t); + if (emulating_pointer_from_touch) { if (emulated_pointer_touch_id == event->touch_id) { struct wlr_pointer_button_event button_event = {