From 31d0464c4af6045a43713a645dc30b020449edbb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 29 Mar 2016 11:59:41 +1000 Subject: [PATCH 1/4] test: apply the new t450 model flag to our X1 3rd test device Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/litest-device-synaptics-x1-carbon-3rd.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/litest-device-synaptics-x1-carbon-3rd.c b/test/litest-device-synaptics-x1-carbon-3rd.c index 718d1087..23d9c5b4 100644 --- a/test/litest-device-synaptics-x1-carbon-3rd.c +++ b/test/litest-device-synaptics-x1-carbon-3rd.c @@ -114,6 +114,16 @@ static struct input_absinfo absinfo[] = { { .value = -1 } }; +static const char udev_rule[] = +"ACTION==\"remove\", GOTO=\"touchpad_end\"\n" +"KERNEL!=\"event*\", GOTO=\"touchpad_end\"\n" +"ENV{ID_INPUT_TOUCHPAD}==\"\", GOTO=\"touchpad_end\"\n" +"\n" +"ATTRS{name}==\"litest SynPS/2 Synaptics TouchPad X1C3rd\"," +" ENV{LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD}=\"1\"\n" +"\n" +"LABEL=\"touchpad_end\""; + struct litest_test_device litest_synaptics_carbon3rd_device = { .type = LITEST_SYNAPTICS_TRACKPOINT_BUTTONS, .features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON, @@ -125,4 +135,5 @@ struct litest_test_device litest_synaptics_carbon3rd_device = { .id = &input_id, .events = events, .absinfo = absinfo, + .udev_rule = udev_rule, }; From bc17185f426dae7a1ea4df6ba3459083c2d51f9b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 29 Mar 2016 13:34:00 +1000 Subject: [PATCH 2/4] touchpad: only post motion events if we have motion Because our delta calculation factors in previous events on touchpads (to reduce jitter) we may get a nonzero delta if we have an event that doesn't actually change x or y. Drop the t->dirty workaround introduced in a608d9d, an event that virtually disappears can mess up our state machines. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-gestures.c | 3 ++- src/evdev-mt-touchpad.c | 5 +---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 3c8f5a7a..7bbd3b8c 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -500,7 +500,8 @@ tp_gesture_post_events(struct tp_dispatch *tp, uint64_t time) switch (tp->gesture.finger_count) { case 1: - tp_gesture_post_pointer_motion(tp, time); + if (tp->queued & TOUCHPAD_EVENT_MOTION) + tp_gesture_post_pointer_motion(tp, time); break; case 2: case 3: diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index f634ec86..e16aecbb 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -904,10 +904,7 @@ tp_need_motion_history_reset(struct tp_dispatch *tp) if (tp->device->model_flags & EVDEV_MODEL_LENOVO_T450_TOUCHPAD) { if (tp->queued & TOUCHPAD_EVENT_MOTION) { if (tp->quirks.nonmotion_event_count > 10) { - struct tp_touch *t; - - tp_for_each_touch(tp, t) - t->dirty = false; + tp->queued &= ~TOUCHPAD_EVENT_MOTION; rc = true; } tp->quirks.nonmotion_event_count = 0; From b5527fa4c73da687774971ddd7cf6ad2016f89e7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 30 Mar 2016 09:11:27 +1000 Subject: [PATCH 3/4] test: add a test for the T450 dropped motion events Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/touchpad.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/test/touchpad.c b/test/touchpad.c index be9c566f..4651b7a4 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -3924,6 +3924,72 @@ START_TEST(touchpad_tool_tripletap_touch_count) } END_TEST +START_TEST(touchpad_t450_motion_drops) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + int i; + double d; + + /* In some areas on the touchpad we only get pressure events. + * https://bugs.freedesktop.org/show_bug.cgi?id=94379 + */ + litest_drain_events(li); + + litest_touch_down(dev, 0, 50, 50); + + for (i = 0; i < 10; i++) { + litest_event(dev, EV_ABS, ABS_MT_SLOT, 0); + litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 3000 - i); + litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3000 - i); + litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 30); + litest_event(dev, EV_ABS, ABS_X, 3000 - i); + litest_event(dev, EV_ABS, ABS_Y, 3000 - i); + litest_event(dev, EV_ABS, ABS_PRESSURE, 30); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_drain_events(li); + } + + /* several pressure-only events */ + + for (i = 0; i< 20; i++) { + litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 30 + i % 2); + litest_event(dev, EV_ABS, ABS_PRESSURE, 30 + i % 2); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_assert_empty_queue(li); + } + + /* a 100 unit jump followed by fine-grained motion, we expect small + * motions without the jump */ + + for (i = 0; i < 10; i++) { + litest_event(dev, EV_ABS, ABS_MT_SLOT, 0); + litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 3100 + i); + litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3100 + i); + litest_event(dev, EV_ABS, ABS_X, 3100 + i); + litest_event(dev, EV_ABS, ABS_Y, 3100 + i); + litest_event(dev, EV_ABS, ABS_PRESSURE, 30); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + } + + event = libinput_get_event(li); + ck_assert_notnull(event); + while (event) { + ptrev = litest_is_motion_event(event); + d = libinput_event_pointer_get_dx(ptrev); + litest_assert_double_lt(d, 1.0); + d = libinput_event_pointer_get_dy(ptrev); + litest_assert_double_lt(d, 1.0); + libinput_event_destroy(event); + + event = libinput_get_event(li); + } +} +END_TEST + START_TEST(touchpad_time_usec) { struct litest_device *dev = litest_current_device(); @@ -4075,6 +4141,7 @@ litest_setup_tests(void) litest_add("touchpad:thumb", touchpad_thumb_tap_hold_2ndfg_tap, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count, LITEST_SYNAPTICS_TOPBUTTONPAD); + litest_add_for_device("touchpad:bugs", touchpad_t450_motion_drops, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); litest_add("touchpad:time", touchpad_time_usec, LITEST_TOUCHPAD, LITEST_ANY); } From aa901211252f0e492893a56d3ec368fbe327255b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 30 Mar 2016 11:36:59 +1000 Subject: [PATCH 4/4] touchpad: reset the motion history on significant negative pressure changes Resetting the motion history has the side-effect of swallowing movements, we don't calculate deltas until we have 4 motion events. During a finger release, we're likely to get a large pressure change between two events, resetting the motion history prevents the cursor from jumping on release. The value of 7 found by trial-and-error, tested on the T440 and T450 hardware. The absolute value is highly variable but recordings show that the pressure changes only by 1 or 2 units during normal interaction. Higher pressure changes are during finger position changes but since those should not cause a jump anyway, we tend to win there too. Currently only enabled for negative pressure changes, let's see how we go with that. https://bugs.freedesktop.org/show_bug.cgi?id=94379 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 4 ++++ src/evdev-mt-touchpad.h | 1 + test/litest.c | 34 +++++++++++++++++++++++++--------- test/litest.h | 7 +++++++ test/touchpad.c | 2 +- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index e16aecbb..0640974f 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -335,6 +335,7 @@ tp_process_absolute(struct tp_dispatch *tp, tp_end_sequence(tp, t, time); break; case ABS_MT_PRESSURE: + t->pressure_delta = e->value - t->pressure; t->pressure = e->value; t->dirty = true; tp->queued |= TOUCHPAD_EVENT_OTHERAXIS; @@ -946,6 +947,9 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time) if (!t->dirty) continue; + if (t->pressure_delta < -7) + tp_motion_history_reset(t); + tp_thumb_detect(tp, t, time); tp_palm_detect(tp, t, time); diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 1f05a03e..d1dae839 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -154,6 +154,7 @@ struct tp_touch { uint64_t millis; int distance; /* distance == 0 means touch */ int pressure; + int pressure_delta; struct { /* A quirk mostly used on Synaptics touchpads. In a diff --git a/test/litest.c b/test/litest.c index f679652f..1d729efc 100644 --- a/test/litest.c +++ b/test/litest.c @@ -1494,23 +1494,39 @@ litest_touch_move_extended(struct litest_device *d, } void -litest_touch_move_to(struct litest_device *d, - unsigned int slot, - double x_from, double y_from, - double x_to, double y_to, - int steps, int sleep_ms) +litest_touch_move_to_extended(struct litest_device *d, + unsigned int slot, + double x_from, double y_from, + double x_to, double y_to, + struct axis_replacement *axes, + int steps, int sleep_ms) { for (int i = 0; i < steps - 1; i++) { - litest_touch_move(d, slot, - x_from + (x_to - x_from)/steps * i, - y_from + (y_to - y_from)/steps * i); + litest_touch_move_extended(d, slot, + x_from + (x_to - x_from)/steps * i, + y_from + (y_to - y_from)/steps * i, + axes); if (sleep_ms) { libinput_dispatch(d->libinput); msleep(sleep_ms); libinput_dispatch(d->libinput); } } - litest_touch_move(d, slot, x_to, y_to); + litest_touch_move_extended(d, slot, x_to, y_to, axes); +} + +void +litest_touch_move_to(struct litest_device *d, + unsigned int slot, + double x_from, double y_from, + double x_to, double y_to, + int steps, int sleep_ms) +{ + litest_touch_move_to_extended(d, slot, + x_from, y_from, + x_to, y_to, + NULL, + steps, sleep_ms); } static int diff --git a/test/litest.h b/test/litest.h index e8542106..c218361e 100644 --- a/test/litest.h +++ b/test/litest.h @@ -403,6 +403,13 @@ litest_touch_move_to(struct litest_device *d, double x_from, double y_from, double x_to, double y_to, int steps, int sleep_ms); +void +litest_touch_move_to_extended(struct litest_device *d, + unsigned int slot, + double x_from, double y_from, + double x_to, double y_to, + struct axis_replacement *axes, + int steps, int sleep_ms); void litest_touch_move_two_touches(struct litest_device *d, diff --git a/test/touchpad.c b/test/touchpad.c index 4651b7a4..a58b3379 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -3594,7 +3594,7 @@ START_TEST(touchpad_thumb_edgescroll) libinput_dispatch(li); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); - litest_touch_move_to(dev, 0, 99, 55, 99, 70, 10, 0); + litest_touch_move_to_extended(dev, 0, 99, 55, 99, 70, axes, 10, 0); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); }