mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-06 11:28:39 +02:00
wheel: fix Lenovo Scrollpoint quirk
The IBM/Lenovo Scrollpoint mouse features a trackpoint-like stick that
sends a great amount of scroll deltas.
In order to handle the device, a quirk is in place to normalize the
scroll events as they were relative motion.
However, when high-resolution scroll was implemented, we started
normalizing the hi-res events instead of the lo-res events by mistake.
Fix the quirk by normalizing the right deltas.
Fixes: 6bb02aaf30 ("High-resolution scroll wheel support")
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Tested-by: Peter Ganzhorn <peter.ganzhorn@gmail.com>
This commit is contained in:
parent
7688f35477
commit
4ae72b6eb2
5 changed files with 139 additions and 3 deletions
|
|
@ -758,6 +758,7 @@ if get_option('tests')
|
||||||
'test/litest-device-keyboard-razer-blackwidow.c',
|
'test/litest-device-keyboard-razer-blackwidow.c',
|
||||||
'test/litest-device-keyboard-razer-blade-stealth.c',
|
'test/litest-device-keyboard-razer-blade-stealth.c',
|
||||||
'test/litest-device-keyboard-razer-blade-stealth-videoswitch.c',
|
'test/litest-device-keyboard-razer-blade-stealth-videoswitch.c',
|
||||||
|
'test/litest-device-lenovo-scrollpoint.c',
|
||||||
'test/litest-device-lid-switch.c',
|
'test/litest-device-lid-switch.c',
|
||||||
'test/litest-device-lid-switch-surface3.c',
|
'test/litest-device-lid-switch-surface3.c',
|
||||||
'test/litest-device-logitech-media-keyboard-elite.c',
|
'test/litest-device-logitech-media-keyboard-elite.c',
|
||||||
|
|
|
||||||
|
|
@ -187,17 +187,22 @@ wheel_flush_scroll(struct fallback_dispatch *dispatch,
|
||||||
struct discrete_coords discrete = { 0.0, 0.0 };
|
struct discrete_coords discrete = { 0.0, 0.0 };
|
||||||
struct wheel_v120 v120 = { 0.0, 0.0 };
|
struct wheel_v120 v120 = { 0.0, 0.0 };
|
||||||
|
|
||||||
|
/* This mouse has a trackstick instead of a mouse wheel and sends
|
||||||
|
* trackstick data via REL_WHEEL. Normalize it like normal x/y coordinates.
|
||||||
|
*/
|
||||||
if (device->model_flags & EVDEV_MODEL_LENOVO_SCROLLPOINT) {
|
if (device->model_flags & EVDEV_MODEL_LENOVO_SCROLLPOINT) {
|
||||||
struct normalized_coords unaccel = { 0.0, 0.0 };
|
struct normalized_coords unaccel = { 0.0, 0.0 };
|
||||||
|
|
||||||
dispatch->wheel.hi_res.y *= -1;
|
dispatch->wheel.lo_res.y *= -1;
|
||||||
fallback_normalize_delta(device, &dispatch->wheel.hi_res, &unaccel);
|
fallback_normalize_delta(device, &dispatch->wheel.lo_res, &unaccel);
|
||||||
evdev_post_scroll(device,
|
evdev_post_scroll(device,
|
||||||
time,
|
time,
|
||||||
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
|
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
|
||||||
&unaccel);
|
&unaccel);
|
||||||
dispatch->wheel.hi_res.x = 0;
|
dispatch->wheel.hi_res.x = 0;
|
||||||
dispatch->wheel.hi_res.y = 0;
|
dispatch->wheel.hi_res.y = 0;
|
||||||
|
dispatch->wheel.lo_res.x = 0;
|
||||||
|
dispatch->wheel.lo_res.y = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
60
test/litest-device-lenovo-scrollpoint.c
Normal file
60
test/litest-device-lenovo-scrollpoint.c
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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.h"
|
||||||
|
#include "litest-int.h"
|
||||||
|
|
||||||
|
static struct input_id input_id = {
|
||||||
|
.bustype = 0x3,
|
||||||
|
.vendor = 0x04b3,
|
||||||
|
.product = 0x3109,
|
||||||
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
-1 , -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Note: device is not tagged with LITEST_WHEEL to avoid running the
|
||||||
|
* "standard" wheel tests. Device has a custom wheel
|
||||||
|
* behavior that is tested directly.
|
||||||
|
*/
|
||||||
|
TEST_DEVICE("lenovo-scrollpoint",
|
||||||
|
.type = LITEST_LENOVO_SCROLLPOINT,
|
||||||
|
.features = LITEST_RELATIVE | LITEST_BUTTON,
|
||||||
|
.interface = NULL,
|
||||||
|
|
||||||
|
.name = "HID 04b3:3109",
|
||||||
|
.id = &input_id,
|
||||||
|
.absinfo = NULL,
|
||||||
|
.events = events,
|
||||||
|
)
|
||||||
|
|
@ -322,6 +322,7 @@ enum litest_device_type {
|
||||||
LITEST_GENERIC_PRESSUREPAD,
|
LITEST_GENERIC_PRESSUREPAD,
|
||||||
LITEST_WACOM_ISDV4_524C_PEN,
|
LITEST_WACOM_ISDV4_524C_PEN,
|
||||||
LITEST_MOUSE_FORMAT_STRING,
|
LITEST_MOUSE_FORMAT_STRING,
|
||||||
|
LITEST_LENOVO_SCROLLPOINT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LITEST_DEVICELESS -2
|
#define LITEST_DEVICELESS -2
|
||||||
|
|
|
||||||
|
|
@ -900,6 +900,73 @@ START_TEST(pointer_scroll_wheel_inhibit_dir_change)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(pointer_scroll_wheel_lenovo_scrollpoint)
|
||||||
|
{
|
||||||
|
struct litest_device *dev = litest_current_device();
|
||||||
|
struct libinput *li = dev->libinput;
|
||||||
|
struct libinput_event *event;
|
||||||
|
struct libinput_event_pointer *ptrev;
|
||||||
|
double v;
|
||||||
|
|
||||||
|
litest_drain_events(dev->libinput);
|
||||||
|
|
||||||
|
/* Lenovo ScrollPoint has a trackstick instead of a wheel, data sent
|
||||||
|
* via REL_WHEEL is close to x/y coordinate space.
|
||||||
|
*/
|
||||||
|
litest_event(dev, EV_REL, REL_WHEEL, 30);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
litest_event(dev, EV_REL, REL_WHEEL, -60);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
|
||||||
|
/* Hi-res scroll event first */
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
litest_assert(litest_is_high_res_axis_event(event));
|
||||||
|
ptrev = litest_is_axis_event(event,
|
||||||
|
LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
|
||||||
|
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||||
|
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS);
|
||||||
|
|
||||||
|
v = libinput_event_pointer_get_scroll_value(ptrev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||||
|
litest_assert_double_eq(v, -30.0);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
|
/* legacy lo-res scroll event */
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
litest_assert(!litest_is_high_res_axis_event(event));
|
||||||
|
ptrev = litest_is_axis_event(event,
|
||||||
|
LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
|
||||||
|
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||||
|
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS);
|
||||||
|
v = libinput_event_pointer_get_axis_value(ptrev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||||
|
litest_assert_double_eq(v, -30.0);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
|
/* Hi-res scroll event first */
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
ptrev = litest_is_axis_event(event,
|
||||||
|
LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
|
||||||
|
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||||
|
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS);
|
||||||
|
|
||||||
|
v = libinput_event_pointer_get_scroll_value(ptrev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||||
|
litest_assert_double_eq(v, 60.0);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
|
/* legacy lo-res scroll event */
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
litest_assert(!litest_is_high_res_axis_event(event));
|
||||||
|
ptrev = litest_is_axis_event(event,
|
||||||
|
LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
|
||||||
|
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||||
|
LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS);
|
||||||
|
v = libinput_event_pointer_get_axis_value(ptrev, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
||||||
|
litest_assert_double_eq(v, 60.0);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(pointer_scroll_natural_defaults)
|
START_TEST(pointer_scroll_natural_defaults)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
|
|
@ -1964,7 +2031,8 @@ START_TEST(pointer_scroll_nowheel_defaults)
|
||||||
|
|
||||||
/* button scrolling is only enabled if there is a
|
/* button scrolling is only enabled if there is a
|
||||||
middle button present */
|
middle button present */
|
||||||
if (libinput_device_pointer_has_button(device, BTN_MIDDLE))
|
if (libinput_device_pointer_has_button(device, BTN_MIDDLE) &&
|
||||||
|
dev->which != LITEST_LENOVO_SCROLLPOINT)
|
||||||
expected = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
|
expected = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
|
||||||
else
|
else
|
||||||
expected = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
expected = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||||
|
|
@ -3528,6 +3596,7 @@ TEST_COLLECTION(pointer)
|
||||||
litest_add(pointer_scroll_wheel_hires_send_only_lores_horizontal, LITEST_WHEEL, LITEST_TABLET);
|
litest_add(pointer_scroll_wheel_hires_send_only_lores_horizontal, LITEST_WHEEL, LITEST_TABLET);
|
||||||
litest_add(pointer_scroll_wheel_inhibit_small_deltas, LITEST_WHEEL, LITEST_TABLET);
|
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(pointer_scroll_wheel_inhibit_dir_change, LITEST_WHEEL, LITEST_TABLET);
|
||||||
|
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, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
|
||||||
litest_add(pointer_scroll_button_noscroll, LITEST_ABSOLUTE|LITEST_BUTTON, LITEST_RELATIVE);
|
litest_add(pointer_scroll_button_noscroll, LITEST_ABSOLUTE|LITEST_BUTTON, LITEST_RELATIVE);
|
||||||
litest_add(pointer_scroll_button_noscroll, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON);
|
litest_add(pointer_scroll_button_noscroll, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue