From b6d27861d83fc1e548712d4739fde68c20188aa8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 3 Sep 2021 09:33:11 +1000 Subject: [PATCH] Add support for high-resolution wheel scrolling --- ...e-the-default-scroll-distance-to-120.patch | 56 +++++ ...t-scroll-source-in-the-event-handler.patch | 91 ++++++++ ...-v120-API-from-libinput-if-available.patch | 210 ++++++++++++++++++ xorg-x11-drv-libinput.spec | 10 +- 4 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 0001-Upgrade-the-default-scroll-distance-to-120.patch create mode 100644 0002-Get-scroll-source-in-the-event-handler.patch create mode 100644 0003-Use-the-new-v120-API-from-libinput-if-available.patch diff --git a/0001-Upgrade-the-default-scroll-distance-to-120.patch b/0001-Upgrade-the-default-scroll-distance-to-120.patch new file mode 100644 index 0000000..b3e3ae7 --- /dev/null +++ b/0001-Upgrade-the-default-scroll-distance-to-120.patch @@ -0,0 +1,56 @@ +From bf8dc2e2ed0780b947eccfc9ac3694c518dee605 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 23 Jan 2019 09:01:24 +1000 +Subject: [PATCH xf86-input-libinput 1/3] Upgrade the default scroll distance + to 120 + +This is just a number, to be used as divider and shouldn't have any effect in +correctly written clients. With the high-res scrolling coming up however, we +have a few devices where the dist cannot be expressed as an integer fraction +of 15, so let's up it to 120 because we know all hardware wheels have to be an +integer fraction of that that, thanks to Microsoft's API requirements. + +For non-wheel scrolls we need to now map into the new range. Previously we +just passed the scroll events on from the touchpad/button scrolling, meaning a +vdist of 15 meant 15 "libinput pixels" of scrolling resulted in a logical +wheel click. Now that we have 120 as vdist, we need to times the input data by +8 to keep the same proportions. + +See 39b0bb4585106a56a51236d8e9843b2da8d745a5 for the previous revert. + +Signed-off-by: Peter Hutterer +--- + src/xf86libinput.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/src/xf86libinput.c b/src/xf86libinput.c +index 33b02da..adbc724 100644 +--- a/src/xf86libinput.c ++++ b/src/xf86libinput.c +@@ -1652,8 +1652,11 @@ calculate_axis_value(struct xf86libinput *driver_data, + * device. The user may change the ScrollPixelDistance + * though, so where we have a dist of 10 but an increment of + * 15, we need to scale from 0..10 into 0..15. ++ * ++ * We now switched to vdist of 120, so make this ++ * proportionate - 120/15 is 8. + */ +- value = value/dist * SCROLL_INCREMENT; ++ value = value/dist * SCROLL_INCREMENT * 8; + } + + *value_out = value; +@@ -3585,8 +3588,8 @@ xf86libinput_pre_init(InputDriverPtr drv, + * affect touchpad scroll speed. For wheels it doesn't matter as + * we're using the discrete value only. + */ +- driver_data->scroll.v.dist = SCROLL_INCREMENT; +- driver_data->scroll.h.dist = SCROLL_INCREMENT; ++ driver_data->scroll.v.dist = 120; ++ driver_data->scroll.h.dist = 120; + + if (!is_subdevice) { + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) +-- +2.31.1 + diff --git a/0002-Get-scroll-source-in-the-event-handler.patch b/0002-Get-scroll-source-in-the-event-handler.patch new file mode 100644 index 0000000..da15742 --- /dev/null +++ b/0002-Get-scroll-source-in-the-event-handler.patch @@ -0,0 +1,91 @@ +From ca9042c7f08f8f0dc214b9cc19f3243728ec8c4a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= +Date: Wed, 4 Aug 2021 17:51:26 +0200 +Subject: [PATCH xf86-input-libinput 2/3] Get scroll source in the event + handler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Where libinput supports high-resolution scroll events, the scroll source +is encoded in the event type. + +Get the scroll source in xf86libinput_handle_event to facilitate the +migration. + +Refactor, no functional changes. + +Signed-off-by: José Expósito +--- + src/xf86libinput.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/src/xf86libinput.c b/src/xf86libinput.c +index adbc724..a8b7013 100644 +--- a/src/xf86libinput.c ++++ b/src/xf86libinput.c +@@ -1631,15 +1631,14 @@ static inline bool + calculate_axis_value(struct xf86libinput *driver_data, + enum libinput_pointer_axis axis, + struct libinput_event_pointer *event, ++ enum libinput_pointer_axis_source source, + double *value_out) + { +- enum libinput_pointer_axis_source source; + double value; + + if (!libinput_event_pointer_has_axis(event, axis)) + return false; + +- source = libinput_event_pointer_get_axis_source(event); + if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) { + value = get_wheel_scroll_value(driver_data, event, axis); + } else { +@@ -1665,7 +1664,9 @@ calculate_axis_value(struct xf86libinput *driver_data, + } + + static void +-xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *event) ++xf86libinput_handle_axis(InputInfoPtr pInfo, ++ struct libinput_event_pointer *event, ++ enum libinput_pointer_axis_source source) + { + DeviceIntPtr dev = pInfo->dev; + struct xf86libinput *driver_data = pInfo->private; +@@ -1678,7 +1679,6 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even + + valuator_mask_zero(mask); + +- source = libinput_event_pointer_get_axis_source(event); + switch(source) { + case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: + case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: +@@ -1691,6 +1691,7 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even + if (calculate_axis_value(driver_data, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + event, ++ source, + &value)) + valuator_mask_set_double(mask, 3, value); + +@@ -1700,6 +1701,7 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even + if (calculate_axis_value(driver_data, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + event, ++ source, + &value)) + valuator_mask_set_double(mask, 2, value); + +@@ -2381,7 +2383,8 @@ xf86libinput_handle_event(struct libinput_event *event) + break; + case LIBINPUT_EVENT_POINTER_AXIS: + xf86libinput_handle_axis(pInfo, +- libinput_event_get_pointer_event(event)); ++ libinput_event_get_pointer_event(event), ++ libinput_event_pointer_get_axis_source(event)); + break; + case LIBINPUT_EVENT_TOUCH_FRAME: + break; +-- +2.31.1 + diff --git a/0003-Use-the-new-v120-API-from-libinput-if-available.patch b/0003-Use-the-new-v120-API-from-libinput-if-available.patch new file mode 100644 index 0000000..44ba801 --- /dev/null +++ b/0003-Use-the-new-v120-API-from-libinput-if-available.patch @@ -0,0 +1,210 @@ +From beb94333e1450006942a7f0ee38bc2a2f5719238 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 23 Jan 2019 20:07:37 +1000 +Subject: [PATCH xf86-input-libinput 3/3] Use the new v120 API from libinput if + available + +Signed-off-by: Peter Hutterer +--- + configure.ac | 12 ++++++ + src/xf86libinput.c | 105 ++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 101 insertions(+), 16 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 176d22e..f747a3d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -62,6 +62,18 @@ AC_LINK_IFELSE( + [libinput_have_scroll_button_lock=yes]], + [AC_MSG_RESULT([no]) + [libinput_have_scroll_button_lock=no]]) ++ ++AC_MSG_CHECKING([if libinput_event_pointer_get_scroll_value_v120 is available]) ++AC_LINK_IFELSE( ++ [AC_LANG_PROGRAM([[#include ]], ++ [[libinput_event_pointer_get_scroll_value_v120(NULL, 0)]])], ++ [AC_MSG_RESULT([yes]) ++ AC_DEFINE(HAVE_LIBINPUT_AXIS_VALUE_V120, [1], ++ [libinput_event_pointer_get_scroll_value_v120() is available]) ++ [libinput_have_axis_value_v120=yes]], ++ [AC_MSG_RESULT([no]) ++ [libinput_have_axis_value_v120=no]]) ++ + LIBS=$OLD_LIBS + CFLAGS=$OLD_CFLAGS + +diff --git a/src/xf86libinput.c b/src/xf86libinput.c +index a8b7013..0cb0c3c 100644 +--- a/src/xf86libinput.c ++++ b/src/xf86libinput.c +@@ -1565,9 +1565,9 @@ xf86libinput_handle_key(InputInfoPtr pInfo, struct libinput_event_keyboard *even + * so the use-case above shouldn't matter anymore. + */ + static inline double +-get_wheel_scroll_value(struct xf86libinput *driver_data, +- struct libinput_event_pointer *event, +- enum libinput_pointer_axis axis) ++guess_wheel_scroll_value(struct xf86libinput *driver_data, ++ struct libinput_event_pointer *event, ++ enum libinput_pointer_axis axis) + { + struct scroll_axis *s; + double f; +@@ -1627,6 +1627,54 @@ out: + return s->dist/s->fraction * discrete; + } + ++#if HAVE_LIBINPUT_AXIS_VALUE_V120 ++static inline double ++get_wheel_120_value(struct xf86libinput *driver_data, ++ struct libinput_event_pointer *event, ++ enum libinput_pointer_axis axis) ++{ ++ struct scroll_axis *s; ++ double angle; ++ ++ switch (axis) { ++ case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: ++ s = &driver_data->scroll.h; ++ break; ++ case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: ++ s = &driver_data->scroll.v; ++ break; ++ default: ++ return 0.0; ++ } ++ ++ angle = libinput_event_pointer_get_scroll_value_v120(event, axis); ++ return s->dist * angle/120; ++} ++#endif ++ ++static inline double ++get_wheel_scroll_value(struct xf86libinput *driver_data, ++ struct libinput_event_pointer *event, ++ enum libinput_pointer_axis axis) ++{ ++#if HAVE_LIBINPUT_AXIS_VALUE_V120 ++ return get_wheel_120_value(driver_data, event, axis); ++#else ++ return guess_wheel_scroll_value(driver_data, event, axis); ++#endif ++} ++ ++static inline double ++get_finger_or_continuous_scroll_value(struct libinput_event_pointer *event, ++ enum libinput_pointer_axis axis) ++{ ++#if HAVE_LIBINPUT_AXIS_VALUE_V120 ++ return libinput_event_pointer_get_scroll_value(event, axis); ++#else ++ return libinput_event_pointer_get_axis_value(event, axis); ++#endif ++} ++ + static inline bool + calculate_axis_value(struct xf86libinput *driver_data, + enum libinput_pointer_axis axis, +@@ -1639,13 +1687,21 @@ calculate_axis_value(struct xf86libinput *driver_data, + if (!libinput_event_pointer_has_axis(event, axis)) + return false; + ++ /* Event may be LIBINPUT_POINTER_AXIS or ++ * LIBINPUT_EVENT_POINTER_SCROLL_{WHEEL|FINGER|CONTINUOUS}, depending ++ * on the libinput version. ++ * ++ * libinput guarantees the axis source is set for the second set of ++ * events too but we can switch to the event type once we ditch ++ * libinput < 1.19 support. ++ */ + if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) { + value = get_wheel_scroll_value(driver_data, event, axis); + } else { + double dist = driver_data->options.scroll_pixel_distance; + assert(dist != 0.0); + +- value = libinput_event_pointer_get_axis_value(event, axis); ++ value = get_finger_or_continuous_scroll_value(event, axis); + /* We need to scale this value into our scroll increment range + * because that one is constant for the lifetime of the + * device. The user may change the ScrollPixelDistance +@@ -1665,29 +1721,21 @@ calculate_axis_value(struct xf86libinput *driver_data, + + static void + xf86libinput_handle_axis(InputInfoPtr pInfo, +- struct libinput_event_pointer *event, ++ struct libinput_event *e, + enum libinput_pointer_axis_source source) + { ++ struct libinput_event_pointer *event; + DeviceIntPtr dev = pInfo->dev; + struct xf86libinput *driver_data = pInfo->private; + ValuatorMask *mask = driver_data->valuators; + double value; +- enum libinput_pointer_axis_source source; + + if ((driver_data->capabilities & CAP_POINTER) == 0) + return; + + valuator_mask_zero(mask); + +- switch(source) { +- case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: +- case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: +- case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: +- break; +- default: +- return; +- } +- ++ event = libinput_event_get_pointer_event(e); + if (calculate_axis_value(driver_data, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + event, +@@ -1705,6 +1753,11 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, + &value)) + valuator_mask_set_double(mask, 2, value); + ++ if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL && ++ !valuator_mask_isset(mask, 2) && ++ !valuator_mask_isset(mask, 3)) ++ return; ++ + out: + xf86PostMotionEventM(dev, Relative, mask); + } +@@ -2382,10 +2435,30 @@ xf86libinput_handle_event(struct libinput_event *event) + libinput_event_get_keyboard_event(event)); + break; + case LIBINPUT_EVENT_POINTER_AXIS: ++#if !HAVE_LIBINPUT_AXIS_VALUE_V120 ++ /* ignore POINTER_AXIS where we have libinput 1.19 and higher */ + xf86libinput_handle_axis(pInfo, +- libinput_event_get_pointer_event(event), ++ event, + libinput_event_pointer_get_axis_source(event)); ++#endif + break; ++#if HAVE_LIBINPUT_AXIS_VALUE_V120 ++ case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: ++ xf86libinput_handle_axis(pInfo, ++ event, ++ LIBINPUT_POINTER_AXIS_SOURCE_WHEEL); ++ break; ++ case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: ++ xf86libinput_handle_axis(pInfo, ++ event, ++ LIBINPUT_POINTER_AXIS_SOURCE_FINGER); ++ break; ++ case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: ++ xf86libinput_handle_axis(pInfo, ++ event, ++ LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS); ++ break; ++#endif + case LIBINPUT_EVENT_TOUCH_FRAME: + break; + case LIBINPUT_EVENT_TOUCH_UP: +-- +2.31.1 + diff --git a/xorg-x11-drv-libinput.spec b/xorg-x11-drv-libinput.spec index 70f9159..3ebf39a 100644 --- a/xorg-x11-drv-libinput.spec +++ b/xorg-x11-drv-libinput.spec @@ -8,7 +8,7 @@ Summary: Xorg X11 libinput input driver Name: xorg-x11-drv-libinput Version: 1.1.0 -Release: 1%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} +Release: 2%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} URL: http://www.x.org License: MIT @@ -23,6 +23,11 @@ Source1: 71-libinput-overrides-wacom.conf # https://bugzilla.redhat.com/show_bug.cgi?id=1413306 Patch01: 0001-Add-a-DPIScaleFactor-option-as-temporary-solution-to.patch +# High-resolution wheel scrolling (needs libinput 1.19) +Patch02: 0001-Upgrade-the-default-scroll-distance-to-120.patch +Patch03: 0002-Get-scroll-source-in-the-event-handler.patch +Patch04: 0003-Use-the-new-v120-API-from-libinput-if-available.patch + BuildRequires: make BuildRequires: autoconf automake libtool BuildRequires: xorg-x11-server-devel >= 1.14.0 @@ -78,6 +83,9 @@ Xorg X11 libinput input driver development files. %{_includedir}/xorg/libinput-properties.h %changelog +* Fri Sep 03 2021 Peter Hutterer - 1.1.0-2 +- Add support for high-resolution wheel scrolling + * Fri Sep 03 2021 Peter Hutterer - 1.1.0-1 - xf86-input-libinput 1.1.0