From: Peter Hutterer Date: Fri, 8 May 2015 03:30:13 +0000 (+1000) Subject: touchpad: sync the initial touch state X-Git-Tag: upstream/0.15.0+92+gec468e8~35 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=af4ff07f6b0543a87bb20914d6bf4775d6360bdb;p=platform%2Fupstream%2Flibinput.git touchpad: sync the initial touch state Unlikely, but there's the odd chance of the first touch coming in with the same X or Y coordinate the kernel already has internally. This would generate a bogus delta on the second event when the touch coordinate jumps from 0/y or x/0 to the real coordinates. For touchpads with distance support this is a real issue since the default value for a touch distance is > 0. Signed-off-by: Peter Hutterer Tested-by: Benjamin Tissoires Reviewed-by: Hans de Goede --- diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 026f9ee2..409d81e9 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1087,6 +1087,28 @@ tp_init_touch(struct tp_dispatch *tp, t->has_ended = true; } +static void +tp_sync_touch(struct tp_dispatch *tp, + struct evdev_device *device, + struct tp_touch *t, + int slot) +{ + struct libevdev *evdev = device->evdev; + + if (!libevdev_fetch_slot_value(evdev, + slot, + ABS_MT_POSITION_X, + &t->point.x)) + t->point.x = libevdev_get_event_value(evdev, EV_ABS, ABS_X); + if (!libevdev_fetch_slot_value(evdev, + slot, + ABS_MT_POSITION_Y, + &t->point.y)) + t->point.y = libevdev_get_event_value(evdev, EV_ABS, ABS_Y); + + libevdev_fetch_slot_value(evdev, slot, ABS_MT_DISTANCE, &t->distance); +} + static int tp_init_slots(struct tp_dispatch *tp, struct evdev_device *device) @@ -1134,6 +1156,12 @@ tp_init_slots(struct tp_dispatch *tp, for (i = 0; i < tp->ntouches; i++) tp_init_touch(tp, &tp->touches[i]); + /* Always sync the first touch so we get ABS_X/Y synced on + * single-touch touchpads */ + tp_sync_touch(tp, device, &tp->touches[0], 0); + for (i = 1; i < tp->num_slots; i++) + tp_sync_touch(tp, device, &tp->touches[i], i); + return 0; } diff --git a/test/touchpad.c b/test/touchpad.c index 6f8c036d..381349d4 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -4531,9 +4531,69 @@ START_TEST(touchpad_trackpoint_no_trackpoint) } END_TEST +START_TEST(touchpad_initial_state) +{ + struct litest_device *dev; + struct libinput *libinput1, *libinput2; + struct libinput_event *ev1, *ev2; + struct libinput_event_pointer *p1, *p2; + int axis = _i; /* looped test */ + int x = 40, y = 60; + + dev = litest_current_device(); + libinput1 = dev->libinput; + + libinput_device_config_tap_set_enabled(dev->libinput_device, + LIBINPUT_CONFIG_TAP_DISABLED); + + litest_touch_down(dev, 0, x, y); + litest_touch_up(dev, 0); + + /* device is now on some x/y value */ + litest_drain_events(libinput1); + + libinput2 = litest_create_context(); + libinput_path_add_device(libinput2, + libevdev_uinput_get_devnode(dev->uinput)); + litest_drain_events(libinput2); + + if (axis == ABS_X) + x = 30; + else + y = 30; + litest_touch_down(dev, 0, x, y); + litest_touch_move_to(dev, 0, x, y, 80, 80, 10, 1); + litest_touch_up(dev, 0); + + litest_wait_for_event(libinput1); + litest_wait_for_event(libinput2); + + while (libinput_next_event_type(libinput1)) { + ev1 = libinput_get_event(libinput1); + ev2 = libinput_get_event(libinput2); + + p1 = litest_is_motion_event(ev1); + p2 = litest_is_motion_event(ev2); + + ck_assert_int_eq(libinput_event_get_type(ev1), + libinput_event_get_type(ev2)); + + ck_assert_int_eq(libinput_event_pointer_get_dx(p1), + libinput_event_pointer_get_dx(p2)); + ck_assert_int_eq(libinput_event_pointer_get_dy(p1), + libinput_event_pointer_get_dy(p2)); + libinput_event_destroy(ev1); + libinput_event_destroy(ev2); + } + + libinput_unref(libinput2); +} +END_TEST + int main(int argc, char **argv) { struct range multitap_range = {3, 8}; + struct range axis_range = {ABS_X, ABS_Y + 1}; litest_add("touchpad:motion", touchpad_1fg_motion, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:motion", touchpad_2fg_no_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); @@ -4676,5 +4736,7 @@ int main(int argc, char **argv) litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_buttons_2fg_scroll, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_no_trackpoint, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS); + litest_add_ranged("touchpad:state", touchpad_initial_state, LITEST_TOUCHPAD, LITEST_ANY, &axis_range); + return litest_run(argc, argv); }