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 =
device->pointer.filter
? filter_dispatch_scroll(device->pointer.filter,
&v120_unaccelerated,
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, time,
bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL),
&wheel_degrees, &wheel_degrees,
&v120); &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. */
const struct discrete_coords discrete = {
.x = dispatch->wheel.lo_res.x,
.y = -1 * dispatch->wheel.lo_res.y,
};
const struct normalized_coords wheel_degrees = {
.x = discrete.x * device->scroll.wheel_click_angle.x,
.y = discrete.y * device->scroll.wheel_click_angle.y,
};
if (discrete.x != 0) {
evdev_notify_axis_legacy_wheel(
device,
time,
bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL),
&wheel_degrees,
&discrete);
}
if (discrete.y != 0) {
evdev_notify_axis_legacy_wheel( evdev_notify_axis_legacy_wheel(
device, device,
time, time,
bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL),
&wheel_degrees, &wheel_degrees,
&discrete); &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; dispatch->wheel.lo_res.x = 0;
dispatch->wheel.lo_res.y = 0;
} }
} }