diff options
author | Rose Hudson <rose@krx.sh> | 2023-03-17 15:58:47 +0000 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2023-03-24 11:47:08 +0000 |
commit | 37f42e2df26ff694801e3b6593462f303c83b0fa (patch) | |
tree | 5867abecf59f913ce7a43dd2d0d86dedc19cacbd | |
parent | 1d64e12391a638201c679e71d4e22bb45e5faa8e (diff) |
backend/wayland: support touch cancel events
since wayland doesn't provide a touch id in cancel events, track what
points are active so we can cancel all of them
timestamp is also not provided - use 0 because no one's paying attention
to that anyway
Closes #3000
-rw-r--r-- | backend/wayland/seat.c | 33 | ||||
-rw-r--r-- | include/backend/wayland.h | 6 |
2 files changed, 38 insertions, 1 deletions
diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index a64795a8..46c6958b 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -141,6 +141,10 @@ static void touch_handle_down(void *data, struct wl_touch *wl_touch, struct wlr_wl_seat *seat = data; struct wlr_touch *touch = &seat->wlr_touch; + struct wlr_wl_touch_points *points = &seat->touch_points; + assert(points->len != sizeof(points->ids) / sizeof(points->ids[0])); + points->ids[points->len++] = id; + struct wlr_touch_down_event event = { .touch = touch, .time_msec = time, @@ -150,11 +154,26 @@ static void touch_handle_down(void *data, struct wl_touch *wl_touch, wl_signal_emit_mutable(&touch->events.down, &event); } +static bool remove_touch_point(struct wlr_wl_touch_points *points, int32_t id) { + size_t i = 0; + for (; i < points->len; i++) { + if (points->ids[i] == id) { + size_t remaining = points->len - i - 1; + memmove(&points->ids[i], &points->ids[i + 1], remaining * sizeof(id)); + points->len--; + return true; + } + } + return false; +} + static void touch_handle_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id) { struct wlr_wl_seat *seat = data; struct wlr_touch *touch = &seat->wlr_touch; + remove_touch_point(&seat->touch_points, id); + struct wlr_touch_up_event event = { .touch = touch, .time_msec = time, @@ -184,7 +203,19 @@ static void touch_handle_frame(void *data, struct wl_touch *wl_touch) { } static void touch_handle_cancel(void *data, struct wl_touch *wl_touch) { - // no-op + struct wlr_wl_seat *seat = data; + struct wlr_touch *touch = &seat->wlr_touch; + + // wayland's cancel event applies to all active touch points + for (size_t i = 0; i < seat->touch_points.len; i++) { + struct wlr_touch_cancel_event event = { + .touch = touch, + .time_msec = 0, + .touch_id = seat->touch_points.ids[i], + }; + wl_signal_emit_mutable(&touch->events.cancel, &event); + } + seat->touch_points.len = 0; } static void touch_handle_shape(void *data, struct wl_touch *wl_touch, diff --git a/include/backend/wayland.h b/include/backend/wayland.h index a1ed4414..75e85879 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -110,6 +110,11 @@ struct wlr_wl_pointer { struct wl_list link; }; +struct wlr_wl_touch_points { + int32_t ids[64]; + size_t len; +}; + struct wlr_wl_seat { char *name; struct wl_seat *wl_seat; @@ -131,6 +136,7 @@ struct wlr_wl_seat { struct wl_touch *wl_touch; struct wlr_touch wlr_touch; + struct wlr_wl_touch_points touch_points; struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2; struct zwp_tablet_v2 *zwp_tablet_v2; |