From d1e70dc133cd283847dfc876b1db86f98deb24bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 20 Sep 2021 19:47:49 +0200 Subject: [PATCH] seat: support lo-res clients using hi-res backends When the selected backend supports high-resolution scroll but the client doesn't, we need to accumulate value120 deltas until we can notify a discrete event. In addition, add a expire time so accumulated deltas are reset after a period of inactivity. --- include/wlr/types/wlr_seat.h | 7 +++++++ types/seat/wlr_seat.c | 4 ++++ types/seat/wlr_seat_pointer.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h index a4c386e09..c734ebd06 100644 --- a/include/wlr/types/wlr_seat.h +++ b/include/wlr/types/wlr_seat.h @@ -53,6 +53,13 @@ struct wlr_seat_client { // for use by wlr_seat_client_{next_serial,validate_event_serial} struct wlr_serial_ringset serials; bool needs_touch_frame; + + // when the backend supports high-resolution scroll but the client doesn't, + // accumulate deltas until we can notify a discrete event. + int32_t acc_vertical_value120; + int32_t acc_horizontal_value120; + double acc_axis; + uint32_t last_value120_time; }; struct wlr_touch_point { diff --git a/types/seat/wlr_seat.c b/types/seat/wlr_seat.c index b5f1575a7..943e70c18 100644 --- a/types/seat/wlr_seat.c +++ b/types/seat/wlr_seat.c @@ -135,6 +135,10 @@ static void seat_handle_bind(struct wl_client *client, void *_wlr_seat, seat_client->client = client; seat_client->seat = wlr_seat; + seat_client->acc_vertical_value120 = 0; + seat_client->acc_horizontal_value120 = 0; + seat_client->acc_axis = 0; + seat_client->last_value120_time = 0; wl_list_init(&seat_client->resources); wl_list_init(&seat_client->pointers); wl_list_init(&seat_client->keyboards); diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index c79ab2e45..2d6f7e7ab 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -10,6 +10,8 @@ #include "util/signal.h" #include "util/array.h" +#define VALUE120_ACC_EXPIRE_TIME 1000 // milliseconds + static void default_pointer_enter(struct wlr_seat_pointer_grab *grab, struct wlr_surface *surface, double sx, double sy) { wlr_seat_pointer_enter(grab->seat, surface, sx, sy); @@ -341,6 +343,22 @@ void wlr_seat_pointer_send_axis_value120(struct wlr_seat *wlr_seat, send_source = true; } + bool send_axis = true; + wl_fixed_t axis_value = wl_fixed_from_double(delta); + + if (time - client->last_value120_time > VALUE120_ACC_EXPIRE_TIME) { + client->acc_vertical_value120 = 0; + client->acc_horizontal_value120 = 0; + client->acc_axis = 0; + } + + int32_t *acc_value = (orientation == WLR_AXIS_ORIENTATION_VERTICAL) ? + &client->acc_vertical_value120 : + &client->acc_horizontal_value120; + *acc_value += delta_value120; + client->acc_axis += delta; + client->last_value120_time = time; + struct wl_resource *resource; wl_resource_for_each(resource, &client->pointers) { if (wlr_seat_client_from_pointer_resource(resource) == NULL) { @@ -357,11 +375,24 @@ void wlr_seat_pointer_send_axis_value120(struct wlr_seat *wlr_seat, if (version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) { wl_pointer_send_axis_value120(resource, orientation, delta_value120); + } else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { + send_axis = (abs(*acc_value) >= 120); + if (send_axis) { + int32_t discrete = (*acc_value / 120); + *acc_value -= (discrete * 120); + + axis_value = wl_fixed_from_double(client->acc_axis); + client->acc_axis = 0; + + wl_pointer_send_axis_discrete(resource, orientation, + discrete); + } } } - wl_pointer_send_axis(resource, time, orientation, - wl_fixed_from_double(delta)); + if (send_axis) { + wl_pointer_send_axis(resource, time, orientation, axis_value); + } } else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) { wl_pointer_send_axis_stop(resource, time, orientation); }