[PATCH libinput 4/6] evdev: release current touches when the device is suspended

Peter Hutterer peter.hutterer at who-t.net
Mon Aug 22 06:14:56 UTC 2016


Previously suspending a touch device with at least one touch down would never
release the touch point.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev.c   | 39 +++++++++++++++++++++++-----
 test/device.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+), 6 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 4bd4aab..0e506bc 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1082,16 +1082,37 @@ fallback_process(struct evdev_dispatch *evdev_dispatch,
 }
 
 static void
+release_touches(struct fallback_dispatch *dispatch,
+		struct evdev_device *device,
+		uint64_t time)
+{
+	unsigned int idx;
+	bool need_frame = false;
+
+	need_frame = fallback_flush_st_up(dispatch, device, time);
+
+	for (idx = 0; idx < dispatch->mt.slots_len; idx++) {
+		struct mt_slot *slot = &dispatch->mt.slots[idx];
+
+		if (slot->seat_slot == -1)
+			continue;
+
+		if (fallback_flush_mt_up(dispatch, device, idx, time))
+			need_frame = true;
+	}
+
+	if (need_frame)
+		touch_notify_frame(&device->base, time);
+}
+
+static void
 release_pressed_keys(struct fallback_dispatch *dispatch,
-		     struct evdev_device *device)
+		     struct evdev_device *device,
+		     uint64_t time)
 {
 	struct libinput *libinput = evdev_libinput_context(device);
-	uint64_t time;
 	int code;
 
-	if ((time = libinput_now(libinput)) == 0)
-		return;
-
 	for (code = 0; code < KEY_CNT; code++) {
 		int count = get_key_down_count(device, code);
 
@@ -1140,8 +1161,14 @@ fallback_suspend(struct evdev_dispatch *evdev_dispatch,
 		 struct evdev_device *device)
 {
 	struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch;
+	struct libinput *libinput = evdev_libinput_context(device);
+	uint64_t time;
 
-	release_pressed_keys(dispatch, device);
+	if ((time = libinput_now(libinput)) == 0)
+		return;
+
+	release_touches(dispatch, device, time);
+	release_pressed_keys(dispatch, device, time);
 	memset(dispatch->hw_key_mask, 0, sizeof(dispatch->hw_key_mask));
 }
 
diff --git a/test/device.c b/test/device.c
index 82ef03b..68f9b8b 100644
--- a/test/device.c
+++ b/test/device.c
@@ -211,6 +211,85 @@ START_TEST(device_disable_touchpad)
 }
 END_TEST
 
+START_TEST(device_disable_touch)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_device *device;
+	enum libinput_config_status status;
+
+	device = dev->libinput_device;
+
+	litest_drain_events(li);
+
+	status = libinput_device_config_send_events_set_mode(device,
+			LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+	/* no event from disabling */
+	litest_assert_empty_queue(li);
+
+	litest_touch_down(dev, 0, 50, 50);
+	litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10, 0);
+	litest_touch_up(dev, 0);
+
+	litest_assert_empty_queue(li);
+
+	/* no event from resuming */
+	status = libinput_device_config_send_events_set_mode(device,
+			LIBINPUT_CONFIG_SEND_EVENTS_ENABLED);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+	litest_assert_empty_queue(li);
+}
+END_TEST
+
+START_TEST(device_disable_touch_during_touch)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_device *device;
+	enum libinput_config_status status;
+	struct libinput_event *event;
+
+	device = dev->libinput_device;
+
+	litest_touch_down(dev, 0, 50, 50);
+	litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10, 0);
+	litest_drain_events(li);
+
+	status = libinput_device_config_send_events_set_mode(device,
+			LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+	/* after disabling sendevents we require a touch up */
+	libinput_dispatch(li);
+	event = libinput_get_event(li);
+	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_UP);
+	libinput_event_destroy(event);
+
+	event = libinput_get_event(li);
+	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
+	libinput_event_destroy(event);
+
+	litest_assert_empty_queue(li);
+
+	litest_touch_move_to(dev, 0, 90, 90, 50, 50, 10, 0);
+	litest_touch_up(dev, 0);
+
+	litest_touch_down(dev, 0, 50, 50);
+	litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10, 0);
+	litest_touch_up(dev, 0);
+
+	litest_assert_empty_queue(li);
+
+	/* no event from resuming */
+	status = libinput_device_config_send_events_set_mode(device,
+			LIBINPUT_CONFIG_SEND_EVENTS_ENABLED);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+	litest_assert_empty_queue(li);
+}
+END_TEST
+
 START_TEST(device_disable_events_pending)
 {
 	struct litest_device *dev = litest_current_device();
@@ -1353,6 +1432,10 @@ litest_setup_tests_device(void)
 	litest_add("device:sendevents", device_sendevents_config_default, LITEST_ANY, LITEST_TABLET);
 	litest_add("device:sendevents", device_disable, LITEST_RELATIVE, LITEST_TABLET);
 	litest_add("device:sendevents", device_disable_touchpad, LITEST_TOUCHPAD, LITEST_TABLET);
+	litest_add("device:sendevents", device_disable_touch, LITEST_TOUCH, LITEST_ANY);
+	litest_add("device:sendevents", device_disable_touch_during_touch, LITEST_TOUCH, LITEST_ANY);
+	litest_add("device:sendevents", device_disable_touch, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD);
+	litest_add("device:sendevents", device_disable_touch_during_touch, LITEST_SINGLE_TOUCH, LITEST_TOUCHPAD);
 	litest_add("device:sendevents", device_disable_events_pending, LITEST_RELATIVE, LITEST_TOUCHPAD|LITEST_TABLET);
 	litest_add("device:sendevents", device_double_disable, LITEST_ANY, LITEST_TABLET);
 	litest_add("device:sendevents", device_double_enable, LITEST_ANY, LITEST_TABLET);
-- 
2.7.4



More information about the wayland-devel mailing list