[PATCH libinput 7/7] touchpad: sync the initial touch state

Peter Hutterer peter.hutterer at who-t.net
Tue May 19 15:52:38 PDT 2015


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 <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad.c | 28 ++++++++++++++++++++++
 test/touchpad.c         | 62 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 026f9ee..409d81e 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 f7f9dd5..3bdcc2b 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -4530,9 +4530,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);
@@ -4675,5 +4735,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);
 }
-- 
2.3.5



More information about the wayland-devel mailing list