High-resolution scroll wheel support
Description
Follow up on Perter's work to add high-resolution scroll wheel support !139 (closed)
Starting with kernel v5.0 two new axes are available for high-resolution wheel scrolling: REL_WHEEL_HI_RES and REL_HWHEEL_HI_RES. Both axes send data in fractions of 120 where each multiple of 120 amounts to one logical scroll event. Fractions of 120 indicate a wheel movement less than one detent.
Three new events are now available on libinput: LIBINPUT_EVENT_POINTER_SCROLL_WHEEL
, LIBINPUT_EVENT_POINTER_SCROLL_FINGER
, and LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS
. These events replace the LIBINPUT_EVENT_POINTER_AXIS
event, so new clients should simply ignore that event.
This LIBINPUT_EVENT_POINTER_SCROLL_WHEEL
event adds a new API libinput_pointer_scroll_get_value_v120()
. The libinput_pointer_scroll_get_value_v120()
is a mirror from the kernel API (itself a copy of the Windows API). The new event is sent for all wheel events, even those that don't technically support hires scrolling and even on older kernels that don't have this feature. So callers can simply ignore any LIBINPUT_EVENT_POINTER_AXIS
event and use the new event types only.
For LIBINPUT_EVENT_POINTER_SCROLL_FINGER
and LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS
, as well as LIBINPUT_EVENT_POINTER_SCROLL_WHEEL
, a new API is available: libinput_pointer_scroll_get_value()
. This API is similar to libinput_pointer_axis_get_value()
.
Why new events? I couldn't make the existing pointer axis events work with existing clients and a new event is necessary. The v120 API is necessary anyway but the only way to merge this into the existing axis events was to have those send discrete events of zero. Turns out that's not something callers expect because it never happened before
- xf86-input-libinput had a divide-by-zero bug (fixed in 0.28.2)
- weston ends up sending scroll stop events for discrete 0
- mutter does a lot of busywork for nothing to actually happen, which I guess is lucky
- kwin/wlroots are fine though
Where discrete 0 events end up on the Wayland protocol (all but kwin, iirc), XWayland would scroll 200% (first based on the value, then one full movement for the discrete event). So less than ideal.
Fixes #130 (closed)
What's new?
Peter already did a lot of the hard work, if you were familiar with his MR, this is what's new:
- Rebase the code on main and fix conflicts
- Update the test suite
- API change: High-resolution enums and functions have been moved to the
pointer_scroll
namespace:- LIBINPUT_EVENT_POINTER_SCROLL_WHEEL
- LIBINPUT_EVENT_POINTER_SCROLL_FINGER
- LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS
- libinput_pointer_scroll_get_value
- libinput_pointer_scroll_get_value_v120
- Removed API overlap with the
pointer_axis
namespace
Reading list
A small list of links I found useful to understand high-resolution scroll wheel:
- RFC: Wayland high-resolution wheel scrolling
- Kernel
- High resolution wheel scrolling on Linux v4.21
- High resolution wheel scrolling in the desktop stack
Status
-
libinput (this MR) -
Wayland protocol wayland/wayland!72 (merged) -
XWayland xorg/xserver!118 (merged) -
xf86-input-libinput xorg/driver/xf86-input-libinput!24 (merged) -
wlroots wlroots/wlroots!3461 (merged) -
Weston wayland/weston!681 -
Mutter https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1962 -
GTK https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3839 -
Qt (by @carewolf) https://codereview.qt-project.org/c/qt/qtbase/+/360677