wheel: add and use ignore_small_hi_res_movements

ignore_small_hi_res_movements is set to true if the underlying device is
not virtual.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1213>
This commit is contained in:
Ryan Hendrickson 2025-06-08 01:29:33 -04:00 committed by Marge Bot
parent efb4b6a3be
commit 8a95c0e3c8
7 changed files with 104 additions and 13 deletions

View file

@ -823,6 +823,7 @@ if get_option('tests')
'test/litest-device-mouse-wheel-tilt.c',
'test/litest-device-mouse-roccat.c',
'test/litest-device-mouse-low-dpi.c',
'test/litest-device-mouse-virtual.c',
'test/litest-device-mouse-wheel-click-angle.c',
'test/litest-device-mouse-wheel-click-count.c',
'test/litest-device-ms-nano-transceiver-mouse.c',

View file

@ -118,6 +118,7 @@ struct fallback_dispatch {
bool hi_res_event_received;
struct libinput_timer scroll_timer;
enum wheel_direction dir;
bool ignore_small_hi_res_movements;
} wheel;
struct {

View file

@ -92,7 +92,10 @@ wheel_handle_event_on_state_none(struct fallback_dispatch *dispatch,
{
switch (event) {
case WHEEL_EVENT_SCROLL:
dispatch->wheel.state = WHEEL_STATE_ACCUMULATING_SCROLL;
dispatch->wheel.state =
dispatch->wheel.ignore_small_hi_res_movements ?
WHEEL_STATE_ACCUMULATING_SCROLL :
WHEEL_STATE_SCROLLING;
break;
case WHEEL_EVENT_SCROLL_DIR_CHANGED:
break;
@ -132,14 +135,17 @@ wheel_handle_event_on_state_scrolling(struct fallback_dispatch *dispatch,
{
switch (event) {
case WHEEL_EVENT_SCROLL:
wheel_cancel_scroll_timer(dispatch);
wheel_set_scroll_timer(dispatch, time);
if (dispatch->wheel.ignore_small_hi_res_movements) {
wheel_cancel_scroll_timer(dispatch);
wheel_set_scroll_timer(dispatch, time);
}
break;
case WHEEL_EVENT_SCROLL_TIMEOUT:
dispatch->wheel.state = WHEEL_STATE_NONE;
break;
case WHEEL_EVENT_SCROLL_DIR_CHANGED:
wheel_cancel_scroll_timer(dispatch);
if (dispatch->wheel.ignore_small_hi_res_movements)
wheel_cancel_scroll_timer(dispatch);
dispatch->wheel.state = WHEEL_STATE_NONE;
break;
case WHEEL_EVENT_SCROLL_ACCUMULATED:
@ -447,13 +453,18 @@ fallback_init_wheel(struct fallback_dispatch *dispatch,
REL_HWHEEL_HI_RES)))
dispatch->wheel.emulate_hi_res_wheel = true;
snprintf(timer_name,
sizeof(timer_name),
"%s wheel scroll",
evdev_device_get_sysname(device));
libinput_timer_init(&dispatch->wheel.scroll_timer,
evdev_libinput_context(device),
timer_name,
wheel_init_scroll_timer,
device);
dispatch->wheel.ignore_small_hi_res_movements =
!evdev_device_is_virtual(dispatch->device);
if (dispatch->wheel.ignore_small_hi_res_movements) {
snprintf(timer_name,
sizeof(timer_name),
"%s wheel scroll",
evdev_device_get_sysname(device));
libinput_timer_init(&dispatch->wheel.scroll_timer,
evdev_libinput_context(device),
timer_name,
wheel_init_scroll_timer,
device);
}
}

View file

@ -77,6 +77,7 @@ enum evdev_device_tags {
EVDEV_TAG_EXTERNAL_KEYBOARD = bit(7),
EVDEV_TAG_TABLET_MODE_SWITCH = bit(8),
EVDEV_TAG_TABLET_TOUCHPAD = bit(9),
EVDEV_TAG_VIRTUAL = bit(10),
};
enum evdev_middlebutton_state {
@ -1046,4 +1047,10 @@ evdev_paired_keyboard_destroy(struct evdev_paired_keyboard *kbd)
free(kbd);
}
static inline bool
evdev_device_is_virtual(struct evdev_device *device)
{
return device->tags & EVDEV_TAG_VIRTUAL;
}
#endif /* EVDEV_H */

View file

@ -0,0 +1,54 @@
/*
* Copyright © 2025 Ryan Hendrickson
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "litest.h"
#include "litest-int.h"
static struct input_id input_id = {
.bustype = 0x11,
.vendor = 0x1,
.product = 0x2,
};
static int events[] = {
EV_REL, REL_WHEEL,
EV_REL, REL_WHEEL_HI_RES,
-1, -1,
};
static const char quirk_file[] =
"[litest Virtual Mouse is virtual]\n"
"MatchName=litest Virtual Mouse\n"
"AttrIsVirtual=1\n"
;
TEST_DEVICE(LITEST_MOUSE_VIRTUAL,
.features = LITEST_WHEEL | LITEST_IGNORED, /* Only needed for mouse wheel tests */
.interface = NULL,
.name = "Virtual Mouse",
.id = &input_id,
.events = events,
.absinfo = NULL,
.quirk_file = quirk_file,
)

View file

@ -461,6 +461,7 @@ enum litest_device_type {
LITEST_MOUSE_GLADIUS,
LITEST_MOUSE_LOW_DPI,
LITEST_MOUSE_ROCCAT,
LITEST_MOUSE_VIRTUAL,
LITEST_MOUSE_WHEEL_CLICK_ANGLE,
LITEST_MOUSE_WHEEL_CLICK_COUNT,
LITEST_MOUSE_WHEEL_TILT,

View file

@ -916,6 +916,21 @@ START_TEST(pointer_scroll_wheel_inhibit_dir_change)
}
END_TEST
START_TEST(pointer_scroll_wheel_no_inhibit_small_deltas_when_virtual)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
litest_drain_events(li);
/* Scroll deltas below the threshold (60) must *not* be ignored */
litest_event(dev, EV_REL, REL_WHEEL_HI_RES, 15);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
litest_dispatch(li);
test_high_and_low_wheel_events_value(dev, REL_WHEEL_HI_RES, -15);
}
END_TEST
START_TEST(pointer_scroll_wheel_lenovo_scrollpoint)
{
struct litest_device *dev = litest_current_device();
@ -3714,6 +3729,7 @@ TEST_COLLECTION(pointer)
}
litest_add(pointer_scroll_wheel_inhibit_small_deltas, LITEST_WHEEL, LITEST_TABLET);
litest_add(pointer_scroll_wheel_inhibit_dir_change, LITEST_WHEEL, LITEST_TABLET);
litest_add_for_device(pointer_scroll_wheel_no_inhibit_small_deltas_when_virtual, LITEST_MOUSE_VIRTUAL);
litest_add_for_device(pointer_scroll_wheel_lenovo_scrollpoint, LITEST_LENOVO_SCROLLPOINT);
litest_add(pointer_scroll_button, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
litest_add(pointer_scroll_button_noscroll, LITEST_ABSOLUTE|LITEST_BUTTON, LITEST_RELATIVE);