evdev: sync the initial x/y position for touchscreens
authorPeter Hutterer <peter.hutterer@who-t.net>
Fri, 8 May 2015 03:06:25 +0000 (13:06 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 21 May 2015 11:41:47 +0000 (21:41 +1000)
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 x/0 or 0/y event in libinput.

Sync the slot state on init, at least for Protocol B devices. For Protocol A
devices and mtdev, don't bother.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
src/evdev.c
test/touch.c

index 2436847..9a0d3d7 100644 (file)
@@ -1781,8 +1781,16 @@ evdev_configure_mt_device(struct evdev_device *device)
 
        for (slot = 0; slot < num_slots; ++slot) {
                slots[slot].seat_slot = -1;
-               slots[slot].point.x = 0;
-               slots[slot].point.y = 0;
+
+               if (evdev_need_mtdev(device))
+                       continue;
+
+               slots[slot].point.x = libevdev_get_slot_value(evdev,
+                                                             slot,
+                                                             ABS_MT_POSITION_X);
+               slots[slot].point.y = libevdev_get_slot_value(evdev,
+                                                             slot,
+                                                             ABS_MT_POSITION_Y);
        }
        device->mt.slots = slots;
        device->mt.slots_len = num_slots;
index d78deed..828c6ed 100644 (file)
@@ -582,9 +582,79 @@ START_TEST(touch_protocol_a_2fg_touch)
 }
 END_TEST
 
+START_TEST(touch_initial_state)
+{
+       struct litest_device *dev;
+       struct libinput *libinput1, *libinput2;
+       struct libinput_event *ev1, *ev2;
+       struct libinput_event_touch *t1, *t2;
+       struct libinput_device *device1, *device2;
+       int axis = _i; /* looped test */
+
+       dev = litest_current_device();
+       device1 = dev->libinput_device;
+       libinput_device_config_tap_set_enabled(device1,
+                                              LIBINPUT_CONFIG_TAP_DISABLED);
+
+       libinput1 = dev->libinput;
+       litest_touch_down(dev, 0, 40, 60);
+       litest_touch_up(dev, 0);
+
+       /* device is now on some x/y value */
+       litest_drain_events(libinput1);
+
+       libinput2 = litest_create_context();
+       device2 = libinput_path_add_device(libinput2,
+                                          libevdev_uinput_get_devnode(
+                                                              dev->uinput));
+       libinput_device_config_tap_set_enabled(device2,
+                                              LIBINPUT_CONFIG_TAP_DISABLED);
+       litest_drain_events(libinput2);
+
+       if (axis == ABS_X)
+               litest_touch_down(dev, 0, 40, 70);
+       else
+               litest_touch_down(dev, 0, 70, 60);
+       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);
+
+               t1 = litest_is_touch_event(ev1, 0);
+               t2 = litest_is_touch_event(ev2, 0);
+
+               ck_assert_int_eq(libinput_event_get_type(ev1),
+                                libinput_event_get_type(ev2));
+
+               if (libinput_event_get_type(ev1) == LIBINPUT_EVENT_TOUCH_UP ||
+                   libinput_event_get_type(ev1) == LIBINPUT_EVENT_TOUCH_FRAME)
+                       break;
+
+               ck_assert_int_eq(libinput_event_touch_get_x(t1),
+                                libinput_event_touch_get_x(t2));
+               ck_assert_int_eq(libinput_event_touch_get_y(t1),
+                                libinput_event_touch_get_y(t2));
+
+               libinput_event_destroy(ev1);
+               libinput_event_destroy(ev2);
+       }
+
+       libinput_event_destroy(ev1);
+       libinput_event_destroy(ev2);
+
+       libinput_unref(libinput2);
+}
+END_TEST
+
 int
 main(int argc, char **argv)
 {
+       struct range axes = { ABS_X, ABS_Y + 1};
+
        litest_add("touch:frame", touch_frame_events, LITEST_TOUCH, LITEST_ANY);
        litest_add_no_device("touch:abs-transform", touch_abs_transform);
        litest_add_no_device("touch:many-slots", touch_many_slots);
@@ -605,5 +675,7 @@ main(int argc, char **argv)
        litest_add("touch:protocol a", touch_protocol_a_touch, LITEST_PROTOCOL_A, LITEST_ANY);
        litest_add("touch:protocol a", touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY);
 
+       litest_add_ranged("touch:state", touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes);
+
        return litest_run(argc, argv);
 }