diff --git a/src/backends/native/meta-input-device-native.h b/src/backends/native/meta-input-device-native.h index 88af07c43..0fd17b86c 100644 --- a/src/backends/native/meta-input-device-native.h +++ b/src/backends/native/meta-input-device-native.h @@ -88,6 +88,19 @@ struct _MetaInputDeviceNative float pointer_x; float pointer_y; + /* 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. */ + struct { + int32_t acc_dx; + int32_t acc_dy; + int32_t last_dx; + int32_t last_dy; + } value120; + /* Keyboard a11y */ MetaKeyboardA11yFlags a11y_flags; GList *slow_keys_list; diff --git a/src/backends/native/meta-seat-impl.c b/src/backends/native/meta-seat-impl.c index 6f3380691..def778eb5 100644 --- a/src/backends/native/meta-seat-impl.c +++ b/src/backends/native/meta-seat-impl.c @@ -895,23 +895,78 @@ discrete_to_direction (double discrete_dx, return 0; } +static gboolean +should_reset_discrete_acc (double current_delta, + double last_delta) +{ + if (last_delta == 0) + return TRUE; + + return (current_delta < 0 && last_delta > 0) || + (current_delta > 0 && last_delta < 0); +} + void meta_seat_impl_notify_discrete_scroll_in_impl (MetaSeatImpl *seat_impl, ClutterInputDevice *input_device, uint64_t time_us, - double discrete_dx, - double discrete_dy, + double dx_value120, + double dy_value120, ClutterScrollSource scroll_source) { - notify_scroll (input_device, time_us, - discrete_dx * DISCRETE_SCROLL_STEP, - discrete_dy * DISCRETE_SCROLL_STEP, - scroll_source, CLUTTER_SCROLL_FINISHED_NONE, - TRUE); - notify_discrete_scroll (input_device, time_us, - discrete_to_direction (discrete_dx, discrete_dy), - scroll_source, FALSE); + MetaInputDeviceNative *evdev_device; + double dx = 0, dy = 0; + int discrete_dx = 0, discrete_dy = 0; + /* Convert into DISCRETE_SCROLL_STEP range. 120/DISCRETE_SCROLL_STEP = 12.0 */ + dx = dx_value120 / 12.0; + dy = dy_value120 / 12.0; + + notify_scroll (input_device, time_us, + dx, + dy, + scroll_source, CLUTTER_SCROLL_FINISHED_NONE, + FALSE); + + /* Notify discrete scroll only when the accumulated value reach 120 */ + evdev_device = META_INPUT_DEVICE_NATIVE (input_device); + + if (dx_value120 != 0) + { + if (should_reset_discrete_acc (dx_value120, evdev_device->value120.last_dx)) + evdev_device->value120.acc_dx = 0; + + evdev_device->value120.last_dx = dx_value120; + } + + if (dy_value120 != 0) + { + if (should_reset_discrete_acc (dy_value120, evdev_device->value120.last_dy)) + evdev_device->value120.acc_dy = 0; + + evdev_device->value120.last_dy = dy_value120; + } + + evdev_device->value120.acc_dx += dx_value120; + evdev_device->value120.acc_dy += dy_value120; + discrete_dx = (evdev_device->value120.acc_dx / 120); + discrete_dy = (evdev_device->value120.acc_dy / 120); + + if (discrete_dx != 0) + { + evdev_device->value120.acc_dx -= (discrete_dx * 120); + notify_discrete_scroll (input_device, time_us, + discrete_to_direction (discrete_dx, 0), + scroll_source, FALSE); + } + + if (discrete_dy != 0) + { + evdev_device->value120.acc_dy -= (discrete_dy * 120); + notify_discrete_scroll (input_device, time_us, + discrete_to_direction (0, discrete_dy), + scroll_source, FALSE); + } } void @@ -1923,24 +1978,24 @@ notify_discrete_axis (MetaSeatImpl *seat_impl, ClutterScrollSource scroll_source, struct libinput_event_pointer *axis_event) { - double discrete_dx = 0.0, discrete_dy = 0.0; + double dx_value120 = 0.0, dy_value120 = 0.0; if (libinput_event_pointer_has_axis (axis_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { - discrete_dx = libinput_event_pointer_get_axis_value_discrete ( + dx_value120 = libinput_event_pointer_get_scroll_value_v120 ( axis_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); } if (libinput_event_pointer_has_axis (axis_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { - discrete_dy = libinput_event_pointer_get_axis_value_discrete ( + dy_value120 = libinput_event_pointer_get_scroll_value_v120 ( axis_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); } meta_seat_impl_notify_discrete_scroll_in_impl (seat_impl, device, time_us, - discrete_dx, discrete_dy, + dx_value120, dy_value120, scroll_source); } diff --git a/src/backends/native/meta-seat-impl.h b/src/backends/native/meta-seat-impl.h index d3e2ab860..995582bcd 100644 --- a/src/backends/native/meta-seat-impl.h +++ b/src/backends/native/meta-seat-impl.h @@ -176,8 +176,8 @@ void meta_seat_impl_notify_scroll_continuous_in_impl (MetaSeatImpl * void meta_seat_impl_notify_discrete_scroll_in_impl (MetaSeatImpl *seat_impl, ClutterInputDevice *input_device, uint64_t time_us, - double discrete_dx, - double discrete_dy, + double dx_value120, + double dy_value120, ClutterScrollSource source); void meta_seat_impl_notify_touch_event_in_impl (MetaSeatImpl *seat_impl, diff --git a/src/backends/native/meta-virtual-input-device-native.c b/src/backends/native/meta-virtual-input-device-native.c index d2d13748a..9fe77dfdc 100644 --- a/src/backends/native/meta-virtual-input-device-native.c +++ b/src/backends/native/meta-virtual-input-device-native.c @@ -699,7 +699,8 @@ notify_discrete_scroll_in_impl (GTask *task) meta_seat_impl_notify_discrete_scroll_in_impl (seat, virtual_evdev->impl_state->device, event->time_us, - discrete_dx, discrete_dy, + discrete_dx * 120.0, + discrete_dy * 120.0, event->scroll_source); g_task_return_boolean (task, TRUE);