From 7298c42139f9f8c5538dd0ba837699d63609839e Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Mon, 18 Jul 2022 15:58:56 +0300 Subject: [PATCH] seat/pointer: rework sending axis events This commit fixes: - sending discrete scrolling events to multiple pointer resources - sending events to clients which don't support wl_pointer.axis_discrete --- types/seat/wlr_seat_pointer.c | 73 ++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index 7d37fb12..36ce42b3 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -279,10 +279,17 @@ static bool should_reset_value120_accumulators(int32_t current, int32_t last) { static void update_value120_accumulators(struct wlr_seat_client *client, enum wlr_axis_orientation orientation, - double value, int32_t value_discrete) { + double value, int32_t value_discrete, + double *low_res_value, int32_t *low_res_value_discrete) { + if (value_discrete == 0) { + // Continuous scrolling has no effect on accumulators + return; + } + int32_t *acc_discrete = &client->value120.acc_discrete[orientation]; int32_t *last_discrete = &client->value120.last_discrete[orientation]; double *acc_axis = &client->value120.acc_axis[orientation]; + if (should_reset_value120_accumulators(value_discrete, *last_discrete)) { *acc_discrete = 0; *acc_axis = 0; @@ -290,33 +297,17 @@ static void update_value120_accumulators(struct wlr_seat_client *client, *acc_discrete += value_discrete; *last_discrete = value_discrete; *acc_axis += value; -} -static void send_axis_discrete(struct wlr_seat_client *client, - struct wl_resource *resource, uint32_t time, - enum wlr_axis_orientation orientation, double value, - int32_t value_discrete) { - int32_t *acc_discrete = &client->value120.acc_discrete[orientation]; - double *acc_axis = &client->value120.acc_axis[orientation]; - - if (abs(*acc_discrete) < WLR_POINTER_AXIS_DISCRETE_STEP) { - return; + // Compute low resolution event values for older clients and reset + // the accumulators if needed + *low_res_value_discrete = *acc_discrete / WLR_POINTER_AXIS_DISCRETE_STEP; + if (*low_res_value_discrete == 0) { + *low_res_value = 0; + } else { + *acc_discrete -= *low_res_value_discrete * WLR_POINTER_AXIS_DISCRETE_STEP; + *low_res_value = *acc_axis; + *acc_axis = 0; } - - wl_pointer_send_axis_discrete(resource, orientation, - *acc_discrete / WLR_POINTER_AXIS_DISCRETE_STEP); - wl_pointer_send_axis(resource, time, orientation, - wl_fixed_from_double(*acc_axis)); - *acc_discrete %= WLR_POINTER_AXIS_DISCRETE_STEP; - *acc_axis = 0; -} - -static void send_axis_value120(struct wl_resource *resource, uint32_t time, - enum wlr_axis_orientation orientation, double value, - int32_t value_discrete) { - wl_pointer_send_axis_value120(resource, orientation, value_discrete); - wl_pointer_send_axis(resource, time, orientation, - wl_fixed_from_double(value)); } void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, @@ -336,7 +327,10 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, send_source = true; } - update_value120_accumulators(client, orientation, value, value_discrete); + double low_res_value; + int32_t low_res_value_discrete; + update_value120_accumulators(client, orientation, value, value_discrete, + &low_res_value, &low_res_value_discrete); struct wl_resource *resource; wl_resource_for_each(resource, &client->pointers) { @@ -346,19 +340,36 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, uint32_t version = wl_resource_get_version(resource); + if (version < WL_POINTER_AXIS_VALUE120_SINCE_VERSION && + value_discrete != 0 && low_res_value_discrete == 0) { + // The client doesn't support high resolution discrete scrolling + // and we haven't accumulated enough wheel clicks for a single + // low resolution event. Don't send anything. + continue; + } + if (send_source && version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) { wl_pointer_send_axis_source(resource, source); } if (value) { if (value_discrete) { if (version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) { - send_axis_value120(resource, time, orientation, value, + // High resolution discrete scrolling + wl_pointer_send_axis_value120(resource, orientation, value_discrete); - } else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { - send_axis_discrete(client, resource, time, orientation, - value, value_discrete); + wl_pointer_send_axis(resource, time, orientation, + wl_fixed_from_double(value)); + } else { + // Low resolution discrete scrolling + if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { + wl_pointer_send_axis_discrete(resource, orientation, + low_res_value_discrete); + } + wl_pointer_send_axis(resource, time, orientation, + wl_fixed_from_double(low_res_value)); } } else { + // Continuous scrolling wl_pointer_send_axis(resource, time, orientation, wl_fixed_from_double(value)); }