High-resolution scroll wheel support
Description
Follow up on Peter's work to add high-resolution scroll wheel support !2 (closed)
Starting with Linux 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. A "detent" is the named used in the Kernel for a mouse wheel click:
https://www.kernel.org/doc/html/v5.11-rc7/input/event-codes.html#ev-rel
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 high-resolution 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()
.
Status (X11)
- libinput/libinput!652 (merged): Ready for merge, waiting on clients like this one ;)
- xf86-input-libinput: This MR
- xorg/xserver!118 (merged) (XWayland): Needs to be updated
For code reviewers
Updating Peter's code, I had to resolve a conflict in calculate_axis_value
. scroll_pixel_distance
should be working on this branch, but if you can, pay attention to this bit:
static inline bool
calculate_axis_value(struct xf86libinput *driver_data,
enum libinput_pointer_axis axis,
struct libinput_event_pointer *event,
double *value_out)
{
[...]
} else {
double dist = driver_data->options.scroll_pixel_distance;
assert(dist != 0.0);
value = libinput_event_pointer_get_axis_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
* 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 * 8;
}
*value_out = value;
return true;
}
Other than that, this MR is mostly API updates and a little bug fix.
cc @whot