filter: support accelerating high-resolution scroll wheel events

Dispatch high-resolution scroll wheel events through filter_dispatch_scroll
so they can be accelerated using the custom acceleration profile.

Low-resolution scroll wheel events are not accelerated to avoid zero
delta-time in the filter.

Signed-off-by: Yinon Burgansky <yinonburgansky@gmail.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1316>
This commit is contained in:
Yinon Burgansky 2025-09-17 17:29:01 +03:00 committed by Marge Bot
parent 2d4482e03d
commit 94b7836456

View file

@ -206,10 +206,6 @@ fallback_flush_wheels(struct fallback_dispatch *dispatch,
struct evdev_device *device, struct evdev_device *device,
uint64_t time) 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 (!libinput_device_has_capability(&device->base, LIBINPUT_DEVICE_CAP_POINTER)) if (!libinput_device_has_capability(&device->base, LIBINPUT_DEVICE_CAP_POINTER))
return; return;
@ -238,59 +234,85 @@ fallback_flush_wheels(struct fallback_dispatch *dispatch,
return; return;
} }
if (dispatch->wheel.hi_res.y != 0) { /* High-resolution wheel events */
int value = dispatch->wheel.hi_res.y; if (dispatch->wheel.hi_res.x != 0 || dispatch->wheel.hi_res.y != 0) {
const struct device_float_coords v120_unaccelerated = {
v120.y = -1 * value; .x = dispatch->wheel.hi_res.x,
wheel_degrees.y = .y = -1 * dispatch->wheel.hi_res.y,
-1 * value / 120.0 * device->scroll.wheel_click_angle.y; };
evdev_notify_axis_wheel(device, const struct normalized_coords v120_accelerated =
time, device->pointer.filter
bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), ? filter_dispatch_scroll(device->pointer.filter,
&wheel_degrees, &v120_unaccelerated,
&v120); device,
time)
: (const struct normalized_coords){
.x = v120_unaccelerated.x,
.y = v120_unaccelerated.y
};
/* Truncate the fractional part when converting floating-point to
integer. This is acceptable because the v120 unit maps one logical
click to 120 units; values are effectively measured in 1/120 of a
click, so truncation does not lose meaningful resolution. */
const struct wheel_v120 v120 = {
.x = v120_accelerated.x,
.y = v120_accelerated.y,
};
const struct normalized_coords wheel_degrees = {
.x = v120.x / 120.0 * device->scroll.wheel_click_angle.x,
.y = v120.y / 120.0 * device->scroll.wheel_click_angle.y,
};
if (v120.x != 0) {
evdev_notify_axis_wheel(
device,
time,
bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL),
&wheel_degrees,
&v120);
}
if (v120.y != 0) {
evdev_notify_axis_wheel(
device,
time,
bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL),
&wheel_degrees,
&v120);
}
dispatch->wheel.hi_res.x = 0;
dispatch->wheel.hi_res.y = 0; dispatch->wheel.hi_res.y = 0;
} }
if (dispatch->wheel.lo_res.y != 0) { /* Low-resolution wheel events */
int value = dispatch->wheel.lo_res.y; if (dispatch->wheel.lo_res.x != 0 || dispatch->wheel.lo_res.y != 0) {
/* Do not accelerate low-resolution wheel events: they use different
wheel_degrees.y = -1 * value * device->scroll.wheel_click_angle.y; units than high-resolution events and should not be accelerated with
discrete.y = -1 * value; the same function. */
evdev_notify_axis_legacy_wheel( const struct discrete_coords discrete = {
device, .x = dispatch->wheel.lo_res.x,
time, .y = -1 * dispatch->wheel.lo_res.y,
bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), };
&wheel_degrees, const struct normalized_coords wheel_degrees = {
&discrete); .x = discrete.x * device->scroll.wheel_click_angle.x,
dispatch->wheel.lo_res.y = 0; .y = discrete.y * device->scroll.wheel_click_angle.y,
} };
if (discrete.x != 0) {
if (dispatch->wheel.hi_res.x != 0) { evdev_notify_axis_legacy_wheel(
int value = dispatch->wheel.hi_res.x; device,
time,
v120.x = value; bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL),
wheel_degrees.x = value / 120.0 * device->scroll.wheel_click_angle.x; &wheel_degrees,
evdev_notify_axis_wheel(device, &discrete);
time, }
bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), if (discrete.y != 0) {
&wheel_degrees, evdev_notify_axis_legacy_wheel(
&v120); device,
dispatch->wheel.hi_res.x = 0; time,
} bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL),
&wheel_degrees,
if (dispatch->wheel.lo_res.x != 0) { &discrete);
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; dispatch->wheel.lo_res.x = 0;
dispatch->wheel.lo_res.y = 0;
} }
} }