diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index a2273b65..1393c308 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -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 diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 2c46d28c..00332ad3 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -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; diff --git a/test/test-touchpad.c b/test/test-touchpad.c index 525bf475..68dc7229 100644 --- a/test/test-touchpad.c +++ b/test/test-touchpad.c @@ -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);