fix: drop events for cancelled touch points

This commit is contained in:
werapi 2026-03-25 22:29:52 +01:00
parent 8d719a4b00
commit 545c452136

View file

@ -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 = {