[PATCH libinput 2/2] touchpad: hook up disable-while-typing configuration

Peter Hutterer peter.hutterer at who-t.net
Sun Jul 12 19:46:27 PDT 2015


This is not a frequent toggle, so we don't need to jump through too many hoops
here. We simply enable/disable on command and once any current timeouts have
expired the new setting takes effect.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad.c | 107 ++++++++++++++++--
 src/evdev-mt-touchpad.h |   3 +
 test/touchpad.c         | 287 +++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 381 insertions(+), 16 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 3f5daba..55cde5a 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -495,7 +495,8 @@ tp_palm_tap_is_palm(struct tp_dispatch *tp, struct tp_touch *t)
 static int
 tp_palm_detect_dwt(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
 {
-	if (tp->dwt.keyboard_active &&
+	if (tp->dwt.dwt_enabled &&
+	    tp->dwt.keyboard_active &&
 	    t->state == TOUCH_BEGIN) {
 		t->palm.state = PALM_TYPING;
 		t->palm.first = t->point;
@@ -1069,6 +1070,9 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
 	struct libinput_event_keyboard *kbdev;
 	unsigned int timeout;
 
+	if (!tp->dwt.dwt_enabled)
+		return;
+
 	if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY)
 		return;
 
@@ -1100,17 +1104,30 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
 }
 
 static bool
+tp_dwt_device_is_blacklisted(struct evdev_device *device)
+{
+	unsigned int bus = libevdev_get_id_bustype(device->evdev);
+
+	/* evemu will set the right bus type */
+	if (bus == BUS_BLUETOOTH || bus == BUS_VIRTUAL)
+		return true;
+
+	/* Wacom makes touchpads, but not internal ones */
+	if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_WACOM)
+		return true;
+
+	return false;
+}
+
+static bool
 tp_want_dwt(struct evdev_device *touchpad,
 	    struct evdev_device *keyboard)
 {
 	unsigned int bus_tp = libevdev_get_id_bustype(touchpad->evdev),
 		     bus_kbd = libevdev_get_id_bustype(keyboard->evdev);
 
-	if (bus_tp == BUS_BLUETOOTH || bus_kbd == BUS_BLUETOOTH)
-		return false;
-
-	/* evemu will set the right bus type */
-	if (bus_tp == BUS_VIRTUAL || bus_kbd == BUS_VIRTUAL)
+	if (tp_dwt_device_is_blacklisted(touchpad) ||
+	    tp_dwt_device_is_blacklisted(keyboard))
 		return false;
 
 	/* If the touchpad is on serio, the keyboard is too, so ignore any
@@ -1118,10 +1135,6 @@ tp_want_dwt(struct evdev_device *touchpad,
 	if (bus_tp == BUS_I8042 && bus_kbd != bus_tp)
 		return false;
 
-	/* Wacom makes touchpads, but not internal ones */
-	if (libevdev_get_id_vendor(touchpad->evdev) == VENDOR_ID_WACOM)
-		return false;
-
 	/* everything else we don't really know, so we have to assume
 	   they go together */
 
@@ -1459,6 +1472,77 @@ tp_init_scroll(struct tp_dispatch *tp, struct evdev_device *device)
 }
 
 static int
+tp_dwt_config_is_available(struct libinput_device *device)
+{
+	return 1;
+}
+
+static enum libinput_config_status
+tp_dwt_config_set(struct libinput_device *device,
+	   enum libinput_config_dwt_state enable)
+{
+	struct evdev_device *evdev = (struct evdev_device*)device;
+	struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
+
+	switch(enable) {
+	case LIBINPUT_CONFIG_DWT_ENABLED:
+	case LIBINPUT_CONFIG_DWT_DISABLED:
+		break;
+	default:
+		return LIBINPUT_CONFIG_STATUS_INVALID;
+	}
+
+	tp->dwt.dwt_enabled = (enable == LIBINPUT_CONFIG_DWT_ENABLED);
+
+	return LIBINPUT_CONFIG_STATUS_SUCCESS;
+}
+
+static enum libinput_config_dwt_state
+tp_dwt_config_get(struct libinput_device *device)
+{
+	struct evdev_device *evdev = (struct evdev_device*)device;
+	struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
+
+	return tp->dwt.dwt_enabled ?
+		LIBINPUT_CONFIG_DWT_ENABLED :
+		LIBINPUT_CONFIG_DWT_DISABLED;
+}
+
+static bool
+tp_dwt_default_enabled(struct tp_dispatch *tp)
+{
+	return true;
+}
+
+static enum libinput_config_dwt_state
+tp_dwt_config_get_default(struct libinput_device *device)
+{
+	struct evdev_device *evdev = (struct evdev_device*)device;
+	struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch;
+
+	return tp_dwt_default_enabled(tp) ?
+		LIBINPUT_CONFIG_DWT_ENABLED :
+		LIBINPUT_CONFIG_DWT_DISABLED;
+}
+
+static int
+tp_init_dwt(struct tp_dispatch *tp,
+	    struct evdev_device *device)
+{
+	if (tp_dwt_device_is_blacklisted(device))
+		return 0;
+
+	tp->dwt.config.is_available = tp_dwt_config_is_available;
+	tp->dwt.config.set_enabled = tp_dwt_config_set;
+	tp->dwt.config.get_enabled = tp_dwt_config_get;
+	tp->dwt.config.get_default_enabled = tp_dwt_config_get_default;
+	tp->dwt.dwt_enabled = tp_dwt_default_enabled(tp);
+	device->base.config.dwt = &tp->dwt.config;
+
+	return 0;
+}
+
+static int
 tp_init_palmdetect(struct tp_dispatch *tp,
 		   struct evdev_device *device)
 {
@@ -1604,6 +1688,9 @@ tp_init(struct tp_dispatch *tp,
 	if (tp_init_buttons(tp, device) != 0)
 		return -1;
 
+	if (tp_init_dwt(tp, device) != 0)
+		return -1;
+
 	if (tp_init_palmdetect(tp, device) != 0)
 		return -1;
 
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index eda17a9..35df46f 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -314,6 +314,9 @@ struct tp_dispatch {
 	} sendevents;
 
 	struct {
+		struct libinput_device_config_dwt config;
+		bool dwt_enabled;
+
 		bool keyboard_active;
 		struct libinput_event_listener keyboard_listener;
 		struct libinput_timer keyboard_timer;
diff --git a/test/touchpad.c b/test/touchpad.c
index 78c084e..d7e859c 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -3329,12 +3329,7 @@ END_TEST
 static inline bool
 has_disable_while_typing(struct litest_device *device)
 {
-	if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_WACOM)
-		return false;
-	if (libevdev_get_id_bustype(device->evdev) == BUS_BLUETOOTH)
-		return false;
-
-	return true;
+	return libinput_device_config_dwt_is_available(device->libinput_device);
 }
 
 START_TEST(touchpad_dwt)
@@ -3747,6 +3742,278 @@ START_TEST(touchpad_dwt_edge_scroll_interrupt)
 }
 END_TEST
 
+START_TEST(touchpad_dwt_config_default_on)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput_device *device = dev->libinput_device;
+	enum libinput_config_status status;
+	enum libinput_config_dwt_state state;
+
+	if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM ||
+	    libevdev_get_id_bustype(dev->evdev) == BUS_BLUETOOTH) {
+		ck_assert(!libinput_device_config_dwt_is_available(device));
+		return;
+	}
+
+	ck_assert(libinput_device_config_dwt_is_available(device));
+	state = libinput_device_config_dwt_get_enabled(device);
+	ck_assert_int_eq(state, LIBINPUT_CONFIG_DWT_ENABLED);
+	state = libinput_device_config_dwt_get_default_enabled(device);
+	ck_assert_int_eq(state, LIBINPUT_CONFIG_DWT_ENABLED);
+
+	status = libinput_device_config_dwt_set_enabled(device,
+					LIBINPUT_CONFIG_DWT_ENABLED);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+	status = libinput_device_config_dwt_set_enabled(device,
+					LIBINPUT_CONFIG_DWT_DISABLED);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+	status = libinput_device_config_dwt_set_enabled(device, 3);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_config_default_off)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput_device *device = dev->libinput_device;
+	enum libinput_config_status status;
+	enum libinput_config_dwt_state state;
+
+	ck_assert(!libinput_device_config_dwt_is_available(device));
+	state = libinput_device_config_dwt_get_enabled(device);
+	ck_assert_int_eq(state, LIBINPUT_CONFIG_DWT_DISABLED);
+	state = libinput_device_config_dwt_get_default_enabled(device);
+	ck_assert_int_eq(state, LIBINPUT_CONFIG_DWT_DISABLED);
+
+	status = libinput_device_config_dwt_set_enabled(device,
+					LIBINPUT_CONFIG_DWT_ENABLED);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
+	status = libinput_device_config_dwt_set_enabled(device,
+					LIBINPUT_CONFIG_DWT_DISABLED);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+	status = libinput_device_config_dwt_set_enabled(device, 3);
+	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
+}
+END_TEST
+
+static inline void
+disable_dwt(struct litest_device *dev)
+{
+	enum libinput_config_status status,
+				    expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+	status = libinput_device_config_dwt_set_enabled(dev->libinput_device,
+						LIBINPUT_CONFIG_DWT_DISABLED);
+	litest_assert_int_eq(status, expected);
+}
+
+static inline void
+enable_dwt(struct litest_device *dev)
+{
+	enum libinput_config_status status,
+				    expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
+	status = libinput_device_config_dwt_set_enabled(dev->libinput_device,
+						LIBINPUT_CONFIG_DWT_ENABLED);
+	litest_assert_int_eq(status, expected);
+}
+
+START_TEST(touchpad_dwt_disabled)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	disable_dwt(touchpad);
+
+	keyboard = litest_add_device(li, LITEST_KEYBOARD);
+	litest_disable_tap(touchpad->libinput_device);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	litest_keyboard_key(keyboard, KEY_A, false);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
+	litest_touch_up(touchpad, 0);
+
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+	litest_delete_device(keyboard);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_disable_during_touch)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	enable_dwt(touchpad);
+
+	keyboard = litest_add_device(li, LITEST_KEYBOARD);
+	litest_disable_tap(touchpad->libinput_device);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	litest_keyboard_key(keyboard, KEY_A, false);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
+	litest_assert_empty_queue(li);
+
+	disable_dwt(touchpad);
+
+	/* touch already down -> keeps being ignored */
+	litest_touch_move_to(touchpad, 0, 70, 50, 50, 70, 10, 1);
+	litest_touch_up(touchpad, 0);
+
+	litest_assert_empty_queue(li);
+
+	litest_delete_device(keyboard);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_disable_before_touch)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	enable_dwt(touchpad);
+
+	keyboard = litest_add_device(li, LITEST_KEYBOARD);
+	litest_disable_tap(touchpad->libinput_device);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	litest_keyboard_key(keyboard, KEY_A, false);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+
+	disable_dwt(touchpad);
+	libinput_dispatch(li);
+
+	/* touch down during timeout -> still discarded */
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
+	litest_assert_empty_queue(li);
+
+	litest_delete_device(keyboard);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_enable_during_touch)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	disable_dwt(touchpad);
+
+	keyboard = litest_add_device(li, LITEST_KEYBOARD);
+	litest_disable_tap(touchpad->libinput_device);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	litest_keyboard_key(keyboard, KEY_A, false);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+	enable_dwt(touchpad);
+
+	/* touch already down -> still sends events */
+	litest_touch_move_to(touchpad, 0, 70, 50, 50, 70, 10, 1);
+	litest_touch_up(touchpad, 0);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+	litest_delete_device(keyboard);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_enable_before_touch)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	disable_dwt(touchpad);
+
+	keyboard = litest_add_device(li, LITEST_KEYBOARD);
+	litest_disable_tap(touchpad->libinput_device);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	litest_keyboard_key(keyboard, KEY_A, false);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+
+	enable_dwt(touchpad);
+	libinput_dispatch(li);
+
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+	litest_delete_device(keyboard);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_enable_during_tap)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	litest_enable_tap(touchpad->libinput_device);
+	disable_dwt(touchpad);
+
+	keyboard = litest_add_device(li, LITEST_KEYBOARD);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	litest_keyboard_key(keyboard, KEY_A, false);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+
+	litest_touch_down(touchpad, 0, 50, 50);
+	libinput_dispatch(li);
+	enable_dwt(touchpad);
+	libinput_dispatch(li);
+	litest_touch_up(touchpad, 0);
+	libinput_dispatch(li);
+
+	litest_timeout_tap();
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
+
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1);
+	litest_touch_up(touchpad, 0);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+	litest_delete_device(keyboard);
+}
+END_TEST
 static int
 has_thumb_detect(struct litest_device *dev)
 {
@@ -4243,6 +4510,14 @@ litest_setup_tests(void)
 	litest_add("touchpad:dwt", touchpad_dwt_click, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:dwt", touchpad_dwt_edge_scroll, LITEST_TOUCHPAD, LITEST_CLICKPAD);
 	litest_add("touchpad:dwt", touchpad_dwt_edge_scroll_interrupt, LITEST_TOUCHPAD, LITEST_CLICKPAD);
+	litest_add("touchpad:dwt", touchpad_dwt_config_default_on, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:dwt", touchpad_dwt_config_default_off, LITEST_ANY, LITEST_TOUCHPAD);
+	litest_add("touchpad:dwt", touchpad_dwt_disabled, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:dwt", touchpad_dwt_disable_during_touch, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:dwt", touchpad_dwt_disable_before_touch, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:dwt", touchpad_dwt_enable_during_touch, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:dwt", touchpad_dwt_enable_before_touch, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:dwt", touchpad_dwt_enable_during_tap, LITEST_TOUCHPAD, LITEST_ANY);
 
 	litest_add("touchpad:thumb", touchpad_thumb_begin_no_motion, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:thumb", touchpad_thumb_update_no_motion, LITEST_TOUCHPAD, LITEST_ANY);
-- 
2.4.3



More information about the wayland-devel mailing list