From 4e52f0358056aaaee269a98c0f8bdb7e30c6342e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Sun, 26 Sep 2021 18:15:51 +0200 Subject: wheel: centralize wheel handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the logic to handle wheels to its own file. Refactor, no functional changes. Signed-off-by: José Expósito --- meson.build | 1 + src/evdev-fallback.c | 171 +++--------------------------------------- src/evdev-fallback.h | 25 +++++++ src/evdev-wheel.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 244 insertions(+), 160 deletions(-) create mode 100644 src/evdev-wheel.c diff --git a/meson.build b/meson.build index 4269e39d..a423a962 100644 --- a/meson.build +++ b/meson.build @@ -368,6 +368,7 @@ src_libinput = src_libfilter + [ 'src/evdev-tablet-pad.c', 'src/evdev-tablet-pad.h', 'src/evdev-tablet-pad-leds.c', + 'src/evdev-wheel.c', 'src/path-seat.c', 'src/udev-seat.c', 'src/udev-seat.h', diff --git a/src/evdev-fallback.c b/src/evdev-fallback.c index 785ac6e2..19ae4a0a 100644 --- a/src/evdev-fallback.c +++ b/src/evdev-fallback.c @@ -68,18 +68,8 @@ fallback_notify_physical_button(struct fallback_dispatch *dispatch, int button, enum libinput_button_state state) { - if (button == BTN_MIDDLE) - dispatch->wheel.is_inhibited = (state == LIBINPUT_BUTTON_STATE_PRESSED); - - /* Lenovo TrackPoint Keyboard II sends its own scroll events when its - * trackpoint is moved while the middle button is pressed. - * Do not inhibit the scroll events. - * https://gitlab.freedesktop.org/libinput/libinput/-/issues/651 - */ - if (evdev_device_has_model_quirk(device, - QUIRK_MODEL_LENOVO_TRACKPOINT_KEYBOARD_2)) - dispatch->wheel.is_inhibited = false; - + fallback_wheel_notify_physical_button(dispatch, device, time, + button, state); evdev_pointer_notify_physical_button(device, time, button, state); } @@ -102,10 +92,10 @@ fallback_interface_get_switch_state(struct evdev_dispatch *evdev_dispatch, LIBINPUT_SWITCH_STATE_OFF; } -static inline void -normalize_delta(struct evdev_device *device, - const struct device_coords *delta, - struct normalized_coords *normalized) +void +fallback_normalize_delta(struct evdev_device *device, + const struct device_coords *delta, + struct normalized_coords *normalized) { normalized->x = delta->x * DEFAULT_MOUSE_DPI / (double)device->dpi; normalized->y = delta->y * DEFAULT_MOUSE_DPI / (double)device->dpi; @@ -195,7 +185,7 @@ fallback_flush_relative_motion(struct fallback_dispatch *dispatch, fallback_rotate_relative(dispatch, device); - normalize_delta(device, &dispatch->rel, &unaccel); + fallback_normalize_delta(device, &dispatch->rel, &unaccel); raw.x = dispatch->rel.x; raw.y = dispatch->rel.y; dispatch->rel.x = 0; @@ -223,110 +213,6 @@ fallback_flush_relative_motion(struct fallback_dispatch *dispatch, pointer_notify_motion(base, time, &accel, &raw); } -static void -fallback_flush_wheels(struct fallback_dispatch *dispatch, - struct evdev_device *device, - uint64_t time) -{ - struct normalized_coords wheel_degrees = { 0.0, 0.0 }; - struct discrete_coords discrete = { 0.0, 0.0 }; - struct wheel_v120 v120 = { 0.0, 0.0 }; - - if (!(device->seat_caps & EVDEV_DEVICE_POINTER)) - return; - - if (!dispatch->wheel.emulate_hi_res_wheel && - !dispatch->wheel.hi_res_event_received && - (dispatch->wheel.lo_res.x != 0 || dispatch->wheel.lo_res.y != 0)) { - evdev_log_bug_kernel(device, - "device supports high-resolution scroll but only low-resolution events have been received.\n" - "See %s/incorrectly-enabled-hires.html for details\n", - HTTP_DOC_LINK); - dispatch->wheel.emulate_hi_res_wheel = true; - dispatch->wheel.hi_res.x = dispatch->wheel.lo_res.x * 120; - dispatch->wheel.hi_res.y = dispatch->wheel.lo_res.y * 120; - } - - if (dispatch->wheel.is_inhibited) { - dispatch->wheel.hi_res.x = 0; - dispatch->wheel.hi_res.y = 0; - dispatch->wheel.lo_res.x = 0; - dispatch->wheel.lo_res.y = 0; - return; - } - - if (device->model_flags & EVDEV_MODEL_LENOVO_SCROLLPOINT) { - struct normalized_coords unaccel = { 0.0, 0.0 }; - - dispatch->wheel.hi_res.y *= -1; - normalize_delta(device, &dispatch->wheel.hi_res, &unaccel); - evdev_post_scroll(device, - time, - LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, - &unaccel); - dispatch->wheel.hi_res.x = 0; - dispatch->wheel.hi_res.y = 0; - - return; - } - - if (dispatch->wheel.hi_res.y != 0) { - int value = dispatch->wheel.hi_res.y; - - v120.y = -1 * value; - wheel_degrees.y = -1 * value/120.0 * device->scroll.wheel_click_angle.y; - evdev_notify_axis_wheel( - device, - time, - bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), - &wheel_degrees, - &v120); - dispatch->wheel.hi_res.y = 0; - } - - if (dispatch->wheel.lo_res.y != 0) { - int value = dispatch->wheel.lo_res.y; - - wheel_degrees.y = -1 * value * device->scroll.wheel_click_angle.y; - discrete.y = -1 * value; - evdev_notify_axis_legacy_wheel( - device, - time, - bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), - &wheel_degrees, - &discrete); - dispatch->wheel.lo_res.y = 0; - } - - if (dispatch->wheel.hi_res.x != 0) { - int value = dispatch->wheel.hi_res.x; - - v120.x = value; - wheel_degrees.x = value/120.0 * device->scroll.wheel_click_angle.x; - evdev_notify_axis_wheel( - device, - time, - bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), - &wheel_degrees, - &v120); - dispatch->wheel.hi_res.x = 0; - } - - if (dispatch->wheel.lo_res.x != 0) { - int value = dispatch->wheel.lo_res.x; - - wheel_degrees.x = value * device->scroll.wheel_click_angle.x; - discrete.x = value; - evdev_notify_axis_legacy_wheel( - device, - time, - bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), - &wheel_degrees, - &discrete); - dispatch->wheel.lo_res.x = 0; - } -} - static void fallback_flush_absolute_motion(struct fallback_dispatch *dispatch, struct evdev_device *device, @@ -895,29 +781,9 @@ fallback_process_relative(struct fallback_dispatch *dispatch, dispatch->rel.y += e->value; dispatch->pending_event |= EVDEV_RELATIVE_MOTION; break; - case REL_WHEEL: - dispatch->wheel.lo_res.y += e->value; - if (dispatch->wheel.emulate_hi_res_wheel) - dispatch->wheel.hi_res.y += e->value * 120; - dispatch->pending_event |= EVDEV_WHEEL; - break; - case REL_HWHEEL: - dispatch->wheel.lo_res.x += e->value; - if (dispatch->wheel.emulate_hi_res_wheel) - dispatch->wheel.hi_res.x += e->value * 120; - dispatch->pending_event |= EVDEV_WHEEL; - break; - case REL_WHEEL_HI_RES: - dispatch->wheel.hi_res.y += e->value; - dispatch->wheel.hi_res_event_received = true; - dispatch->pending_event |= EVDEV_WHEEL; - break; - case REL_HWHEEL_HI_RES: - dispatch->wheel.hi_res.x += e->value; - dispatch->wheel.hi_res_event_received = true; - dispatch->pending_event |= EVDEV_WHEEL; - break; } + + fallback_wheel_process_relative(dispatch, device, e, time); } static inline void @@ -1079,7 +945,7 @@ fallback_handle_state(struct fallback_dispatch *dispatch, if (need_touch_frame) touch_notify_frame(&device->base, time); - fallback_flush_wheels(dispatch, device, time); + fallback_wheel_handle_state(dispatch, device, time); /* Buttons and keys */ if (dispatch->pending_event & EVDEV_KEY) { @@ -1827,22 +1693,7 @@ fallback_dispatch_create(struct libinput_device *libinput_device) want_config); } - /* On kernel < 5.0 we need to emulate high-resolution - wheel scroll events */ - if ((libevdev_has_event_code(device->evdev, - EV_REL, - REL_WHEEL) && - !libevdev_has_event_code(device->evdev, - EV_REL, - REL_WHEEL_HI_RES)) || - (libevdev_has_event_code(device->evdev, - EV_REL, - REL_HWHEEL) && - !libevdev_has_event_code(device->evdev, - EV_REL, - REL_HWHEEL_HI_RES))) - dispatch->wheel.emulate_hi_res_wheel = true; - + fallback_init_wheel(dispatch, device); fallback_init_debounce(dispatch); fallback_init_arbitration(dispatch, device); diff --git a/src/evdev-fallback.h b/src/evdev-fallback.h index e8c20631..3b3e3188 100644 --- a/src/evdev-fallback.h +++ b/src/evdev-fallback.h @@ -254,5 +254,30 @@ fallback_notify_physical_button(struct fallback_dispatch *dispatch, uint64_t time, int button, enum libinput_button_state state); +void +fallback_normalize_delta(struct evdev_device *device, + const struct device_coords *delta, + struct normalized_coords *normalized); + +void +fallback_init_wheel(struct fallback_dispatch *dispatch, + struct evdev_device *device); + +void +fallback_wheel_notify_physical_button(struct fallback_dispatch *dispatch, + struct evdev_device *device, + uint64_t time, + int button, + enum libinput_button_state state); + +void +fallback_wheel_process_relative(struct fallback_dispatch *dispatch, + struct evdev_device *device, + struct input_event *e, uint64_t time); + +void +fallback_wheel_handle_state(struct fallback_dispatch *dispatch, + struct evdev_device *device, + uint64_t time); #endif diff --git a/src/evdev-wheel.c b/src/evdev-wheel.c new file mode 100644 index 00000000..5cbaf3b9 --- /dev/null +++ b/src/evdev-wheel.c @@ -0,0 +1,207 @@ +/* + * Copyright © 2010 Intel Corporation + * Copyright © 2013 Jonas Ådahl + * Copyright © 2013-2017 Red Hat, Inc. + * Copyright © 2017 James Ye + * Copyright © 2021 José Expósito + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include "evdev-fallback.h" +#include "util-input-event.h" + +void +fallback_wheel_process_relative(struct fallback_dispatch *dispatch, + struct evdev_device *device, + struct input_event *e, uint64_t time) +{ + switch (e->code) { + case REL_WHEEL: + dispatch->wheel.lo_res.y += e->value; + if (dispatch->wheel.emulate_hi_res_wheel) + dispatch->wheel.hi_res.y += e->value * 120; + dispatch->pending_event |= EVDEV_WHEEL; + break; + case REL_HWHEEL: + dispatch->wheel.lo_res.x += e->value; + if (dispatch->wheel.emulate_hi_res_wheel) + dispatch->wheel.hi_res.x += e->value * 120; + dispatch->pending_event |= EVDEV_WHEEL; + break; + case REL_WHEEL_HI_RES: + dispatch->wheel.hi_res.y += e->value; + dispatch->wheel.hi_res_event_received = true; + dispatch->pending_event |= EVDEV_WHEEL; + break; + case REL_HWHEEL_HI_RES: + dispatch->wheel.hi_res.x += e->value; + dispatch->wheel.hi_res_event_received = true; + dispatch->pending_event |= EVDEV_WHEEL; + break; + } +} + +void +fallback_wheel_notify_physical_button(struct fallback_dispatch *dispatch, + struct evdev_device *device, + uint64_t time, + int button, + enum libinput_button_state state) +{ + if (button == BTN_MIDDLE) + dispatch->wheel.is_inhibited = (state == LIBINPUT_BUTTON_STATE_PRESSED); + + /* Lenovo TrackPoint Keyboard II sends its own scroll events when its + * trackpoint is moved while the middle button is pressed. + * Do not inhibit the scroll events. + * https://gitlab.freedesktop.org/libinput/libinput/-/issues/651 + */ + if (evdev_device_has_model_quirk(device, + QUIRK_MODEL_LENOVO_TRACKPOINT_KEYBOARD_2)) + dispatch->wheel.is_inhibited = false; +} + +void +fallback_wheel_handle_state(struct fallback_dispatch *dispatch, + struct evdev_device *device, + uint64_t time) +{ + struct normalized_coords wheel_degrees = { 0.0, 0.0 }; + struct discrete_coords discrete = { 0.0, 0.0 }; + struct wheel_v120 v120 = { 0.0, 0.0 }; + + if (!(device->seat_caps & EVDEV_DEVICE_POINTER)) + return; + + if (!dispatch->wheel.emulate_hi_res_wheel && + !dispatch->wheel.hi_res_event_received && + (dispatch->wheel.lo_res.x != 0 || dispatch->wheel.lo_res.y != 0)) { + evdev_log_bug_kernel(device, + "device supports high-resolution scroll but only low-resolution events have been received.\n" + "See %s/incorrectly-enabled-hires.html for details\n", + HTTP_DOC_LINK); + dispatch->wheel.emulate_hi_res_wheel = true; + dispatch->wheel.hi_res.x = dispatch->wheel.lo_res.x * 120; + dispatch->wheel.hi_res.y = dispatch->wheel.lo_res.y * 120; + } + + if (dispatch->wheel.is_inhibited) { + dispatch->wheel.hi_res.x = 0; + dispatch->wheel.hi_res.y = 0; + dispatch->wheel.lo_res.x = 0; + dispatch->wheel.lo_res.y = 0; + return; + } + + if (device->model_flags & EVDEV_MODEL_LENOVO_SCROLLPOINT) { + struct normalized_coords unaccel = { 0.0, 0.0 }; + + dispatch->wheel.hi_res.y *= -1; + fallback_normalize_delta(device, &dispatch->wheel.hi_res, &unaccel); + evdev_post_scroll(device, + time, + LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, + &unaccel); + dispatch->wheel.hi_res.x = 0; + dispatch->wheel.hi_res.y = 0; + + return; + } + + if (dispatch->wheel.hi_res.y != 0) { + int value = dispatch->wheel.hi_res.y; + + v120.y = -1 * value; + wheel_degrees.y = -1 * value/120.0 * device->scroll.wheel_click_angle.y; + evdev_notify_axis_wheel( + device, + time, + bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), + &wheel_degrees, + &v120); + dispatch->wheel.hi_res.y = 0; + } + + if (dispatch->wheel.lo_res.y != 0) { + int value = dispatch->wheel.lo_res.y; + + wheel_degrees.y = -1 * value * device->scroll.wheel_click_angle.y; + discrete.y = -1 * value; + evdev_notify_axis_legacy_wheel( + device, + time, + bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), + &wheel_degrees, + &discrete); + dispatch->wheel.lo_res.y = 0; + } + + if (dispatch->wheel.hi_res.x != 0) { + int value = dispatch->wheel.hi_res.x; + + v120.x = value; + wheel_degrees.x = value/120.0 * device->scroll.wheel_click_angle.x; + evdev_notify_axis_wheel( + device, + time, + bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), + &wheel_degrees, + &v120); + dispatch->wheel.hi_res.x = 0; + } + + if (dispatch->wheel.lo_res.x != 0) { + int value = dispatch->wheel.lo_res.x; + + wheel_degrees.x = value * device->scroll.wheel_click_angle.x; + discrete.x = value; + evdev_notify_axis_legacy_wheel( + device, + time, + bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), + &wheel_degrees, + &discrete); + dispatch->wheel.lo_res.x = 0; + } +} + +void +fallback_init_wheel(struct fallback_dispatch *dispatch, + struct evdev_device *device) +{ + /* On kernel < 5.0 we need to emulate high-resolution + wheel scroll events */ + if ((libevdev_has_event_code(device->evdev, + EV_REL, + REL_WHEEL) && + !libevdev_has_event_code(device->evdev, + EV_REL, + REL_WHEEL_HI_RES)) || + (libevdev_has_event_code(device->evdev, + EV_REL, + REL_HWHEEL) && + !libevdev_has_event_code(device->evdev, + EV_REL, + REL_HWHEEL_HI_RES))) + dispatch->wheel.emulate_hi_res_wheel = true; +} -- cgit v1.2.1