mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-20 02:10:07 +01:00
plugin: ignore high-resolution wheel events from disabled wheels
Make sure we drop any potential high-resolution wheel events from a device that isn't supposed to have them. Where the device's axes were disabled due to a quirk, re-enabling the axes means the device's events won't be filtered anymore. Our wheel emulation plugin thus emulates high-resolution wheel events in addition to the hardware events. Fix this by simply filtering out any high-resolution wheel events on any device that uses this plugin. Closes #1160 Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1279>
This commit is contained in:
parent
6aefc2f166
commit
36b2afae82
5 changed files with 157 additions and 2 deletions
|
|
@ -842,6 +842,7 @@ if get_option('tests')
|
|||
'test/litest-device-magic-trackpad.c',
|
||||
'test/litest-device-mouse.c',
|
||||
'test/litest-device-mouse-wheel-tilt.c',
|
||||
'test/litest-device-mouse-wheel-hires-disabled.c',
|
||||
'test/litest-device-mouse-ps2.c',
|
||||
'test/litest-device-mouse-roccat.c',
|
||||
'test/litest-device-mouse-low-dpi.c',
|
||||
|
|
|
|||
|
|
@ -64,24 +64,43 @@ wheel_plugin_evdev_frame(struct libinput_plugin *libinput_plugin,
|
|||
size_t nevents;
|
||||
struct evdev_event *events = evdev_frame_get_events(frame, &nevents);
|
||||
|
||||
_unref_(evdev_frame) *filtered_frame = evdev_frame_new(nevents + 2);
|
||||
for (size_t i = 0; i < nevents; i++) {
|
||||
struct evdev_event *e = &events[i];
|
||||
|
||||
switch (evdev_usage_enum(e->usage)) {
|
||||
case EVDEV_REL_WHEEL_HI_RES:
|
||||
case EVDEV_REL_HWHEEL_HI_RES:
|
||||
/* In the uncommon case that our device sends high-res events
|
||||
* filter those out. This can happen on devices that have the
|
||||
* highres scroll axes disabled via quirks. The device still
|
||||
* sends events so when we re-enable the axis in
|
||||
* wheel_plugin_device_new we get the device events again,
|
||||
* effectively duplicating the high resolution scroll events.
|
||||
*/
|
||||
break;
|
||||
case EVDEV_REL_WHEEL:
|
||||
evdev_frame_append_one(frame,
|
||||
evdev_frame_append(filtered_frame, e, 1);
|
||||
evdev_frame_append_one(filtered_frame,
|
||||
evdev_usage_from(EVDEV_REL_WHEEL_HI_RES),
|
||||
e->value * 120);
|
||||
break;
|
||||
case EVDEV_REL_HWHEEL:
|
||||
evdev_frame_append(filtered_frame, e, 1);
|
||||
evdev_frame_append_one(
|
||||
frame,
|
||||
filtered_frame,
|
||||
evdev_usage_from(EVDEV_REL_HWHEEL_HI_RES),
|
||||
e->value * 120);
|
||||
break;
|
||||
default:
|
||||
evdev_frame_append(filtered_frame, e, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
evdev_frame_set(frame,
|
||||
evdev_frame_get_events(filtered_frame, NULL),
|
||||
evdev_frame_get_count(filtered_frame));
|
||||
}
|
||||
|
||||
static const struct libinput_plugin_interface interface = {
|
||||
|
|
|
|||
63
test/litest-device-mouse-wheel-hires-disabled.c
Normal file
63
test/litest-device-mouse-wheel-hires-disabled.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright © 2013 Red Hat, Inc.
|
||||
*
|
||||
* 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 "config.h"
|
||||
|
||||
#include "litest-int.h"
|
||||
#include "litest.h"
|
||||
|
||||
static struct input_id input_id = {
|
||||
.bustype = 0x3,
|
||||
.vendor = 0x1234,
|
||||
.product = 0xabcd,
|
||||
};
|
||||
|
||||
/* clang-format off */
|
||||
static int events[] = {
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_KEY, BTN_MIDDLE,
|
||||
EV_REL, REL_X,
|
||||
EV_REL, REL_Y,
|
||||
EV_REL, REL_WHEEL,
|
||||
EV_REL, REL_WHEEL_HI_RES,
|
||||
EV_REL, REL_HWHEEL,
|
||||
EV_REL, REL_HWHEEL_HI_RES,
|
||||
-1 , -1,
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
static const char quirk_file[] =
|
||||
"[litest hires wheel disabled mouse]\n"
|
||||
"MatchName=litest Mouse with disabled high-res wheels\n"
|
||||
"AttrEventCode=-REL_WHEEL_HI_RES;-REL_HWHEEL_HI_RES\n";
|
||||
|
||||
TEST_DEVICE(LITEST_MOUSE_WHEEL_HIRES_DISABLED,
|
||||
.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL,
|
||||
.interface = NULL,
|
||||
|
||||
.name = "Mouse with disabled high-res wheels",
|
||||
.id = &input_id,
|
||||
.absinfo = NULL,
|
||||
.events = events,
|
||||
.quirk_file = quirk_file, )
|
||||
|
|
@ -477,6 +477,7 @@ enum litest_device_type {
|
|||
LITEST_MOUSE_WHEEL_CLICK_ANGLE,
|
||||
LITEST_MOUSE_WHEEL_CLICK_COUNT,
|
||||
LITEST_MOUSE_WHEEL_TILT,
|
||||
LITEST_MOUSE_WHEEL_HIRES_DISABLED,
|
||||
LITEST_MS_NANO_TRANSCEIVER_MOUSE,
|
||||
LITEST_SONY_VAIO_KEYS,
|
||||
LITEST_SYNAPTICS_TRACKPOINT_BUTTONS,
|
||||
|
|
|
|||
|
|
@ -794,6 +794,9 @@ START_TEST(pointer_scroll_wheel_hires)
|
|||
test_hi_res_wheel_event(dev, axis, -5 * 120);
|
||||
test_hi_res_wheel_event(dev, axis, 6 * 120);
|
||||
|
||||
if (dev->which == LITEST_MOUSE_WHEEL_HIRES_DISABLED)
|
||||
return LITEST_NOT_APPLICABLE;
|
||||
|
||||
test_hi_res_wheel_event(dev, axis, 30);
|
||||
test_hi_res_wheel_event(dev, axis, -60);
|
||||
test_hi_res_wheel_event(dev, axis, -40);
|
||||
|
|
@ -855,6 +858,64 @@ START_TEST(pointer_scroll_wheel_hires_send_only_lores)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_wheel_hires_disabled)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
int direction;
|
||||
unsigned int lores_code, hires_code;
|
||||
enum libinput_pointer_axis axis =
|
||||
litest_test_param_get_i32(test_env->params, "axis");
|
||||
|
||||
switch (axis) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
lores_code = REL_WHEEL;
|
||||
hires_code = REL_WHEEL_HI_RES;
|
||||
direction = -1;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
lores_code = REL_HWHEEL;
|
||||
hires_code = REL_HWHEEL_HI_RES;
|
||||
direction = 1;
|
||||
break;
|
||||
default:
|
||||
litest_abort_msg("Invalid test axis '%d'", axis);
|
||||
}
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_log_group("High-res events on this device should be ignored") {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
litest_event(dev, EV_REL, hires_code, 60);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
|
||||
litest_log_group("Only low-res events should be handled") {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
litest_event(dev, EV_REL, hires_code, 60);
|
||||
litest_event(dev, EV_REL, lores_code, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
litest_dispatch(li);
|
||||
|
||||
litest_drain_events_of_type(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
_destroy_(libinput_event) *ev = libinput_get_event(li);
|
||||
struct libinput_event_pointer *pev = litest_is_axis_event(
|
||||
ev,
|
||||
LIBINPUT_EVENT_POINTER_SCROLL_WHEEL,
|
||||
axis,
|
||||
0);
|
||||
int v120 =
|
||||
libinput_event_pointer_get_scroll_value_v120(pev, axis);
|
||||
litest_assert_int_eq(v120, direction * 120);
|
||||
}
|
||||
litest_drain_events_of_type(li, LIBINPUT_EVENT_POINTER_AXIS);
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_scroll_wheel_inhibit_small_deltas)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -865,6 +926,9 @@ START_TEST(pointer_scroll_wheel_inhibit_small_deltas)
|
|||
!libevdev_has_event_code(dev->evdev, EV_REL, REL_HWHEEL_HI_RES))
|
||||
return LITEST_NOT_APPLICABLE;
|
||||
|
||||
if (dev->which == LITEST_MOUSE_WHEEL_HIRES_DISABLED)
|
||||
return LITEST_NOT_APPLICABLE;
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
/* A single delta (below the hardcoded threshold 60) is ignored */
|
||||
|
|
@ -910,6 +974,9 @@ START_TEST(pointer_scroll_wheel_inhibit_small_deltas_reduce_delta)
|
|||
!libevdev_has_event_code(dev->evdev, EV_REL, REL_HWHEEL_HI_RES))
|
||||
return LITEST_NOT_APPLICABLE;
|
||||
|
||||
if (dev->which == LITEST_MOUSE_WHEEL_HIRES_DISABLED)
|
||||
return LITEST_NOT_APPLICABLE;
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
/* A single delta (below the hardcoded threshold 30) is ignored */
|
||||
|
|
@ -959,6 +1026,9 @@ START_TEST(pointer_scroll_wheel_inhibit_dir_change)
|
|||
if (!libevdev_has_event_code(dev->evdev, EV_REL, REL_WHEEL_HI_RES))
|
||||
return LITEST_NOT_APPLICABLE;
|
||||
|
||||
if (dev->which == LITEST_MOUSE_WHEEL_HIRES_DISABLED)
|
||||
return LITEST_NOT_APPLICABLE;
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
/* Scroll one detent and a bit */
|
||||
|
|
@ -3707,6 +3777,7 @@ TEST_COLLECTION(pointer)
|
|||
litest_with_parameters(params, "axis", 'I', 2, litest_named_i32(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, "vertical"),
|
||||
litest_named_i32(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, "horizontal")) {
|
||||
litest_add_parametrized(pointer_scroll_wheel_hires_send_only_lores, LITEST_WHEEL, LITEST_TABLET, params);
|
||||
litest_add_parametrized_for_device(pointer_scroll_wheel_hires_disabled, LITEST_MOUSE_WHEEL_HIRES_DISABLED, params);
|
||||
}
|
||||
litest_with_parameters(params, "hires-delta", 'u', 3, 5, 15, 20) {
|
||||
litest_add_parametrized(pointer_scroll_wheel_inhibit_small_deltas, LITEST_WHEEL, LITEST_TABLET, params);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue