aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Expósito <jose.exposito89@gmail.com>2022-03-27 19:07:25 +0200
committerJosé Expósito <jose.exposito89@gmail.com>2022-07-11 11:01:35 +0200
commitadd44b3e2e4ff7ef98b16813fb3c9e1d8b398008 (patch)
tree41a2c86b63c2983ec43a2357936dfbf56590c88e
parent40dc5121aa4cc76ed9a6ededd6ff56570c1a2e40 (diff)
seat: support low-resolution clients
When the client doesn't support high-resolution scroll, accumulate deltas until we can notify a discrete event. Some mice have a free spinning wheel, making possible to lock the wheel when the accumulator value is not 0. To avoid synchronization issues between the mouse wheel and the accumulators, store the last delta and when the scroll direction changes, reset the accumulator.
-rw-r--r--include/wlr/types/wlr_seat.h13
-rw-r--r--types/seat/wlr_seat_pointer.c48
2 files changed, 59 insertions, 2 deletions
diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h
index 8c1d4661..d1984449 100644
--- a/include/wlr/types/wlr_seat.h
+++ b/include/wlr/types/wlr_seat.h
@@ -54,6 +54,19 @@ 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 client doesn't support high-resolution scroll, accumulate deltas
+ // until we can notify a discrete event.
+ // Some mice have a free spinning wheel, making possible to lock the wheel
+ // when the accumulator value is not 0. To avoid synchronization issues
+ // between the mouse wheel and the accumulators, store the last delta and
+ // when the scroll direction changes, reset the accumulator.
+ // Indexed by wlr_axis_orientation.
+ struct {
+ int32_t acc_discrete[2];
+ int32_t last_discrete[2];
+ double acc_axis[2];
+ } value120;
};
struct wlr_touch_point {
diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c
index 1ddc1467..7d37fb12 100644
--- a/types/seat/wlr_seat_pointer.c
+++ b/types/seat/wlr_seat_pointer.c
@@ -269,6 +269,48 @@ uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time,
return serial;
}
+static bool should_reset_value120_accumulators(int32_t current, int32_t last) {
+ if (last == 0) {
+ return true;
+ }
+
+ return (current < 0 && last > 0) || (current > 0 && last < 0);
+}
+
+static void update_value120_accumulators(struct wlr_seat_client *client,
+ enum wlr_axis_orientation orientation,
+ double value, int32_t value_discrete) {
+ 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;
+ }
+ *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;
+ }
+
+ 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) {
@@ -294,6 +336,8 @@ 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);
+
struct wl_resource *resource;
wl_resource_for_each(resource, &client->pointers) {
if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
@@ -311,8 +355,8 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time,
send_axis_value120(resource, time, orientation, value,
value_discrete);
} else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) {
- wl_pointer_send_axis_discrete(resource, orientation,
- value_discrete / WLR_POINTER_AXIS_DISCRETE_STEP);
+ send_axis_discrete(client, resource, time, orientation,
+ value, value_discrete);
}
} else {
wl_pointer_send_axis(resource, time, orientation,