From 6f0327eb43a6532de8ed1a4d116d1e0f80f9c504 Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Wed, 19 Apr 2023 12:03:19 +0200 Subject: [PATCH] WIP: implement touch scrolling --- input.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- input.h | 1 + wayland.c | 17 ++++++++-- wayland.h | 10 ++++++ 4 files changed, 122 insertions(+), 3 deletions(-) diff --git a/input.c b/input.c index 7e5d204d..945d69de 100644 --- a/input.c +++ b/input.c @@ -411,7 +411,7 @@ execute_binding(struct seat *seat, struct terminal *term, term_damage_view(term); render_refresh(term); - break; + break; } return true; @@ -2634,3 +2634,98 @@ const struct wl_pointer_listener pointer_listener = { .axis_stop = wl_pointer_axis_stop, .axis_discrete = wl_pointer_axis_discrete, }; + +static void +wl_touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial, + uint32_t time, struct wl_surface *surface, int32_t id, + int32_t x, int32_t y) +{ + struct seat *seat = data; + if (seat->touch.id != 0) // Multi-touch is not supported + return; + seat->touch.id = id; + + struct terminal *term = ((const struct wl_window *)wl_surface_get_user_data(surface))->term; + xassert(term != NULL); + + seat->touch.serial = serial; + seat->touch.x = wl_fixed_to_int(x) * term->scale; + seat->touch.y = wl_fixed_to_int(y) * term->scale; + seat->touch.surface = surface; +} + +static void +wl_touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, + uint32_t time, int32_t id) +{ + struct seat *seat = data; + if (seat->touch.id != id) // Not our touch point. + return; + + seat->touch.id = 0; +} + +static void +wl_touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time, + int32_t id, wl_fixed_t x, wl_fixed_t y) +{ + struct seat *seat = data; + if (seat->touch.id != id) // Not our touch point. + return; + + struct terminal *term = ((const struct wl_window *)wl_surface_get_user_data(seat->touch.surface))->term; + xassert(term != NULL); + + int new_y = wl_fixed_to_int(y) * term->scale; + + int32_t distance = (new_y - seat->touch.y); + int32_t lines = distance / term->cell_height; + if (lines == 0) { + // Don't update the origin 'y'. + // This half-cell motion might compound with the next one. + return; + } + seat->touch.y = new_y; + + if (lines > 0) { + cmd_scrollback_up(term, lines); + } else if (lines < 0) { + cmd_scrollback_down(term, -lines); + } +} +static void +wl_touch_frame(void *data, struct wl_touch *wl_touch) +{ + // no-op +} + +static void +wl_touch_cancel(void *data, struct wl_touch *wl_touch) +{ + struct seat *seat = data; + seat->touch.id = 0; +} + +static void +wl_touch_shape(void *data, struct wl_touch *wl_touch, + int32_t id, int32_t major, int32_t minor) +{ + // no-op +} + +static void +wl_touch_orientation(void *data, struct wl_touch *wl_touch, + int32_t id, int32_t orientation) +{ + // no-op +} + +const struct wl_touch_listener touch_listener = { + .down = wl_touch_down, + .up = wl_touch_up, + .motion = wl_touch_motion, + .frame = wl_touch_frame, + .cancel = wl_touch_cancel, + .shape = wl_touch_shape, + .orientation = wl_touch_orientation, +}; diff --git a/input.h b/input.h index ea488a86..eeb95dbd 100644 --- a/input.h +++ b/input.h @@ -25,6 +25,7 @@ extern const struct wl_keyboard_listener keyboard_listener; extern const struct wl_pointer_listener pointer_listener; +extern const struct wl_touch_listener touch_listener; void input_repeat(struct seat *seat, uint32_t key); diff --git a/wayland.c b/wayland.c index 68a7a4f1..fbec00a7 100644 --- a/wayland.c +++ b/wayland.c @@ -270,9 +270,10 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, struct seat *seat = data; xassert(seat->wl_seat == wl_seat); - LOG_DBG("%s: keyboard=%s, pointer=%s", seat->name, + LOG_DBG("%s: keyboard=%s, pointer=%s, touch=%s", seat->name, (caps & WL_SEAT_CAPABILITY_KEYBOARD) ? "yes" : "no", - (caps & WL_SEAT_CAPABILITY_POINTER) ? "yes" : "no"); + (caps & WL_SEAT_CAPABILITY_POINTER) ? "yes" : "no", + (caps & WL_SEAT_CAPABILITY_TOUCH) ? "yes" : "no"); if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { if (seat->wl_keyboard == NULL) { @@ -313,6 +314,18 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, seat->pointer.cursor = NULL; } } + + if (caps & WL_SEAT_CAPABILITY_TOUCH) { + if (seat->wl_touch == NULL) { + seat->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_add_listener(seat->wl_touch, &touch_listener, seat); + } + } else { + if (seat->wl_touch != NULL) { + wl_touch_release(seat->wl_touch); + seat->wl_touch = NULL; + } + } } static void diff --git a/wayland.h b/wayland.h index 4b6939ab..cd10c6eb 100644 --- a/wayland.h +++ b/wayland.h @@ -157,6 +157,16 @@ struct seat { bool have_discrete; } mouse; + /* Pointer state */ + struct wl_touch *wl_touch; + struct { + uint32_t serial; // Unused for now; usable later for copying. + int32_t id; + struct wl_surface *surface; + int32_t x; + int32_t y; + } touch; + /* Clipboard */ struct wl_data_device *data_device; struct zwp_primary_selection_device_v1 *primary_selection_device;