aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRose Hudson <rose@krx.sh>2023-03-17 15:58:47 +0000
committerSimon Ser <contact@emersion.fr>2023-03-24 11:47:08 +0000
commit37f42e2df26ff694801e3b6593462f303c83b0fa (patch)
tree5867abecf59f913ce7a43dd2d0d86dedc19cacbd
parent1d64e12391a638201c679e71d4e22bb45e5faa8e (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.c33
-rw-r--r--include/backend/wayland.h6
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;