mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-03-26 06:30:43 +01:00
touchpad: improve pointer jump detection
Previously, we had a hard threshold of 20mm per event frame. That is just about achievable by really fast movements (in which case you don't care too much about the jumps anyway because you've already hit the edge of the screen). Sometimes pointer jumps have lower deltas that are achievable even on slower, more likely motions. Analysis of finger motion has shown that while a delta >7mm per event is possible, jumping _by_ 7mm between two events is unlikely and indicates a pointer jump. So let's diff the most recent delta and the current delta, if it increases by 7mm between two event frames let's say it's a pointer jump and discard it. Helps with but does not fully resolve: https://gitlab.freedesktop.org/libinput/libinput/issues/80 https://gitlab.freedesktop.org/libinput/libinput/issues/36 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
02c9c240a2
commit
eca2f8c9c6
3 changed files with 63 additions and 3 deletions
|
|
@ -1440,8 +1440,9 @@ tp_detect_jumps(const struct tp_dispatch *tp, struct tp_touch *t)
|
|||
{
|
||||
struct device_coords delta;
|
||||
struct phys_coords mm;
|
||||
const int JUMP_THRESHOLD_MM = 20;
|
||||
struct tp_history_point *last;
|
||||
double distance;
|
||||
bool is_jump = false;
|
||||
|
||||
/* We haven't seen pointer jumps on Wacom tablets yet, so exclude
|
||||
* those.
|
||||
|
|
@ -1449,8 +1450,10 @@ tp_detect_jumps(const struct tp_dispatch *tp, struct tp_touch *t)
|
|||
if (tp->device->model_flags & EVDEV_MODEL_WACOM_TOUCHPAD)
|
||||
return false;
|
||||
|
||||
if (t->history.count == 0)
|
||||
if (t->history.count == 0) {
|
||||
t->jumps.last_delta_mm = 0.0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* called before tp_motion_history_push, so offset 0 is the most
|
||||
* recent coordinate */
|
||||
|
|
@ -1459,7 +1462,17 @@ tp_detect_jumps(const struct tp_dispatch *tp, struct tp_touch *t)
|
|||
delta.y = abs(t->point.y - last->point.y);
|
||||
mm = evdev_device_unit_delta_to_mm(tp->device, &delta);
|
||||
|
||||
return hypot(mm.x, mm.y) > JUMP_THRESHOLD_MM;
|
||||
distance = hypot(mm.x, mm.y);
|
||||
|
||||
/* Cursor jump if:
|
||||
* - current single-event delta is >20mm, or
|
||||
* - we increased the delta by over 7mm within a frame.
|
||||
*/
|
||||
is_jump = distance > 20.0 ||
|
||||
(distance - t->jumps.last_delta_mm) > 7;
|
||||
t->jumps.last_delta_mm = distance;
|
||||
|
||||
return is_jump;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -176,6 +176,10 @@ struct tp_touch {
|
|||
unsigned int count;
|
||||
} history;
|
||||
|
||||
struct {
|
||||
double last_delta_mm;
|
||||
} jumps;
|
||||
|
||||
struct {
|
||||
struct device_coords center;
|
||||
uint8_t x_motion_history;
|
||||
|
|
|
|||
|
|
@ -5540,6 +5540,8 @@ START_TEST(touchpad_jump_finger_motion)
|
|||
litest_touch_move_to(dev, 0, 20, 30, 90, 30, 10, 0);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* this test uses a specific test device to trigger a >20mm jump to
|
||||
* test jumps. These numbers may not work on any other device */
|
||||
litest_disable_log_handler(li);
|
||||
litest_touch_move_to(dev, 0, 90, 30, 20, 80, 1, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
|
|
@ -5566,6 +5568,46 @@ START_TEST(touchpad_jump_finger_motion)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_jump_delta)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libinput_event *event;
|
||||
struct libinput_event_pointer *ptrev;
|
||||
|
||||
litest_touch_down(dev, 0, 20, 30);
|
||||
litest_touch_move_to(dev, 0, 20, 30, 90, 30, 10, 0);
|
||||
litest_drain_events(li);
|
||||
|
||||
/* this test uses a specific test device to trigger a >7mm but <20mm
|
||||
* jump to test the delta jumps. These numbers may not work on any
|
||||
* other device */
|
||||
litest_disable_log_handler(li);
|
||||
litest_touch_move_to(dev, 0, 90, 30, 90, 80, 1, 0);
|
||||
litest_assert_empty_queue(li);
|
||||
litest_restore_log_handler(li);
|
||||
|
||||
litest_touch_move_to(dev, 0, 90, 80, 91, 81, 10, 0);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
/* expect lots of little events, no big jump */
|
||||
libinput_dispatch(li);
|
||||
event = libinput_get_event(li);
|
||||
do {
|
||||
double dx, dy;
|
||||
|
||||
ptrev = litest_is_motion_event(event);
|
||||
dx = libinput_event_pointer_get_dx(ptrev);
|
||||
dy = libinput_event_pointer_get_dy(ptrev);
|
||||
ck_assert_int_lt(abs((int)dx), 20);
|
||||
ck_assert_int_lt(abs((int)dy), 20);
|
||||
|
||||
libinput_event_destroy(event);
|
||||
event = libinput_get_event(li);
|
||||
} while (event != NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_disabled_on_mouse)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -6749,6 +6791,7 @@ TEST_COLLECTION(touchpad)
|
|||
litest_add("touchpad:time", touchpad_time_usec, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
|
||||
litest_add_for_device("touchpad:jumps", touchpad_jump_finger_motion, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
litest_add_for_device("touchpad:jumps", touchpad_jump_delta, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
|
||||
litest_add_for_device("touchpad:sendevents", touchpad_disabled_on_mouse, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
litest_add_for_device("touchpad:sendevents", touchpad_disabled_on_mouse_suspend_mouse, LITEST_SYNAPTICS_CLICKPAD_X220);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue