[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

libinput: Changes to 'upstream-unstable'



 configure.ac                                 |    4 
 doc/normalization-of-relative-motion.dox     |    4 
 src/evdev-mt-touchpad-gestures.c             |   59 +---
 src/evdev-mt-touchpad.c                      |  118 +++++++--
 src/evdev-mt-touchpad.h                      |    1 
 src/evdev.c                                  |   41 +++
 src/evdev.h                                  |    3 
 src/libinput-util.h                          |   15 +
 test/Makefile.am                             |    5 
 test/device.c                                |   64 +++++
 test/gestures.c                              |   34 +-
 test/litest-device-anker-mouse-kbd.c         |  225 ++++++++++++++++++
 test/litest-device-apple-internal-keyboard.c |  239 +++++++++++++++++++
 test/litest-device-cyborg-rat-5.c            |   71 +++++
 test/litest-device-synaptics-i2c.c           |  102 ++++++++
 test/litest-device-yubikey.c                 |  169 +++++++++++++
 test/litest-selftest.c                       |    4 
 test/litest.c                                |   15 +
 test/litest.h                                |   15 -
 test/touchpad-tap.c                          |    2 
 test/touchpad.c                              |  333 +++++++++++++++++++++++++--
 udev/90-libinput-model-quirks.hwdb           |   13 +
 udev/90-libinput-model-quirks.rules.in       |    4 
 23 files changed, 1423 insertions(+), 117 deletions(-)

New commits:
commit b0c5296b245039d3c158bf2da5410432cef4701f
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri Feb 5 09:59:32 2016 +1000

    configure.ac: libinput 1.1.6
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/configure.ac b/configure.ac
index f75652f..4a0ffff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ AC_PREREQ([2.64])
 
 m4_define([libinput_major_version], [1])
 m4_define([libinput_minor_version], [1])
-m4_define([libinput_micro_version], [5])
+m4_define([libinput_micro_version], [6])
 m4_define([libinput_version],
           [libinput_major_version.libinput_minor_version.libinput_micro_version])
 
@@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
 # b) If interfaces have been changed or added, but binary compatibility has
 #    been preserved, change to C+1:0:A+1
 # c) If the interface is the same as the previous version, change to C:R+1:A
-LIBINPUT_LT_VERSION=16:5:6
+LIBINPUT_LT_VERSION=16:6:6
 AC_SUBST(LIBINPUT_LT_VERSION)
 
 AM_SILENT_RULES([yes])

commit c7b064d7560208fcb263f05c448952523a048297
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Feb 4 11:20:38 2016 +1000

    touchpad: if we have a serio keyboard, override any previous dwt pairing
    
    If a USB keyboard like the YubiKey is found before the internal keyboard, it
    will be paired with the touchpad when it is seen. The internal keyboard is
    seen later bug ignored because we already have a keyboard paired with the
    touchpad.
    
    This is obviously wrong. For now, give priority to serio keyboards, and
    override existing dwt pairings with the new keyboard.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=93983
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: Hans de Goede <hdegoede@redhat.com>
    (cherry picked from commit 0b0150e08d4e3e88d7a81a7429306d8dca2fe4c8)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index ed86ef9..91fb7a9 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1325,6 +1325,38 @@ tp_want_dwt(struct evdev_device *touchpad,
 }
 
 static void
+tp_dwt_pair_keyboard(struct evdev_device *touchpad,
+		     struct evdev_device *keyboard)
+{
+	struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch;
+	unsigned int bus_kbd = libevdev_get_id_bustype(keyboard->evdev);
+
+	if (!tp_want_dwt(touchpad, keyboard))
+		return;
+
+	/* If we already have a keyboard paired, override it if the new one
+	 * is a serio device. Otherwise keep the current one */
+	if (tp->dwt.keyboard) {
+		if (bus_kbd != BUS_I8042)
+			return;
+
+		memset(tp->dwt.key_mask, 0, sizeof(tp->dwt.key_mask));
+		libinput_device_remove_event_listener(&tp->dwt.keyboard_listener);
+	}
+
+	libinput_device_add_event_listener(&keyboard->base,
+				&tp->dwt.keyboard_listener,
+				tp_keyboard_event, tp);
+	tp->dwt.keyboard = keyboard;
+	tp->dwt.keyboard_active = false;
+
+	log_debug(touchpad->base.seat->libinput,
+		  "palm: dwt activated with %s<->%s\n",
+		  touchpad->devname,
+		  keyboard->devname);
+}
+
+static void
 tp_interface_device_added(struct evdev_device *device,
 			  struct evdev_device *added_device)
 {
@@ -1348,20 +1380,8 @@ tp_interface_device_added(struct evdev_device *device,
 						tp_trackpoint_event, tp);
 	}
 
-	if (added_device->tags & EVDEV_TAG_KEYBOARD &&
-	    tp->dwt.keyboard == NULL &&
-	    tp_want_dwt(device, added_device)) {
-		log_debug(tp_libinput_context(tp),
-			  "palm: dwt activated with %s<->%s\n",
-			  device->devname,
-			  added_device->devname);
-
-		libinput_device_add_event_listener(&added_device->base,
-					&tp->dwt.keyboard_listener,
-					tp_keyboard_event, tp);
-		tp->dwt.keyboard = added_device;
-		tp->dwt.keyboard_active = false;
-	}
+	if (added_device->tags & EVDEV_TAG_KEYBOARD)
+	    tp_dwt_pair_keyboard(device, added_device);
 
 	if (tp->sendevents.current_mode !=
 	    LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
diff --git a/test/Makefile.am b/test/Makefile.am
index a298284..89b6fd6 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -37,6 +37,7 @@ liblitest_la_SOURCES = \
 	litest-device-qemu-usb-tablet.c \
 	litest-device-synaptics.c \
 	litest-device-synaptics-hover.c \
+	litest-device-synaptics-i2c.c \
 	litest-device-synaptics-st.c \
 	litest-device-synaptics-t440.c \
 	litest-device-synaptics-x1-carbon-3rd.c \
@@ -47,6 +48,7 @@ liblitest_la_SOURCES = \
 	litest-device-wheel-only.c \
 	litest-device-xen-virtual-pointer.c \
 	litest-device-vmware-virtual-usb-mouse.c \
+	litest-device-yubikey.c \
 	litest.c
 liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la
 liblitest_la_CFLAGS = $(AM_CFLAGS) \
diff --git a/test/litest-device-synaptics-i2c.c b/test/litest-device-synaptics-i2c.c
new file mode 100644
index 0000000..b6b632b
--- /dev/null
+++ b/test/litest-device-synaptics-i2c.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright © 2015 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+
+static void
+litest_synaptics_i2c_setup(void)
+{
+	struct litest_device *d = litest_create_device(LITEST_SYNAPTICS_I2C);
+	litest_set_current_device(d);
+}
+
+static struct input_event down[] = {
+	{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN  },
+	{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+	{ .type = -1, .code = -1 },
+};
+
+static struct input_event move[] = {
+	{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN  },
+	{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+	{ .type = -1, .code = -1 },
+};
+
+static struct litest_device_interface interface = {
+	.touch_down_events = down,
+	.touch_move_events = move,
+};
+
+static struct input_id input_id = {
+	.bustype = 0x18,
+	.vendor = 0x6cb,
+	.product = 0x76ad,
+};
+
+static int events[] = {
+	EV_KEY, BTN_LEFT,
+	EV_KEY, BTN_TOOL_FINGER,
+	EV_KEY, BTN_TOUCH,
+	EV_KEY, BTN_TOOL_DOUBLETAP,
+	EV_KEY, BTN_TOOL_TRIPLETAP,
+	INPUT_PROP_MAX, INPUT_PROP_POINTER,
+	INPUT_PROP_MAX, INPUT_PROP_BUTTONPAD,
+	-1, -1,
+};
+
+static struct input_absinfo absinfo[] = {
+	{ ABS_X, 0, 1216, 0, 0, 12 },
+	{ ABS_Y, 0, 680, 0, 0, 12 },
+	{ ABS_MT_SLOT, 0, 1, 0, 0, 0 },
+	{ ABS_MT_POSITION_X, 0, 1216, 0, 0, 12 },
+	{ ABS_MT_POSITION_Y, 0, 680, 0, 0, 12 },
+	{ ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 },
+	{ .value = -1 }
+};
+
+struct litest_test_device litest_synaptics_i2c_device = {
+	.type = LITEST_SYNAPTICS_I2C,
+	.features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON,
+	.shortname = "synaptics-i2c",
+	.setup = litest_synaptics_i2c_setup,
+	.interface = &interface,
+
+	.name = "DLL0704:01 06CB:76AD Touchpad",
+	.id = &input_id,
+	.events = events,
+	.absinfo = absinfo,
+};
diff --git a/test/litest-device-yubikey.c b/test/litest-device-yubikey.c
new file mode 100644
index 0000000..d2c1d4c
--- /dev/null
+++ b/test/litest-device-yubikey.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+
+static void litest_yubikey_setup(void)
+{
+	struct litest_device *d = litest_create_device(LITEST_YUBIKEY);
+	litest_set_current_device(d);
+}
+
+static struct input_id input_id = {
+	.bustype = 0x3,
+	.vendor = 0x1050,
+	.product = 0x10,
+};
+
+static int events[] = {
+	EV_KEY, KEY_ESC,
+	EV_KEY, KEY_1,
+	EV_KEY, KEY_2,
+	EV_KEY, KEY_3,
+	EV_KEY, KEY_4,
+	EV_KEY, KEY_5,
+	EV_KEY, KEY_6,
+	EV_KEY, KEY_7,
+	EV_KEY, KEY_8,
+	EV_KEY, KEY_9,
+	EV_KEY, KEY_0,
+	EV_KEY, KEY_MINUS,
+	EV_KEY, KEY_EQUAL,
+	EV_KEY, KEY_BACKSPACE,
+	EV_KEY, KEY_TAB,
+	EV_KEY, KEY_Q,
+	EV_KEY, KEY_W,
+	EV_KEY, KEY_E,
+	EV_KEY, KEY_R,
+	EV_KEY, KEY_T,
+	EV_KEY, KEY_Y,
+	EV_KEY, KEY_U,
+	EV_KEY, KEY_I,
+	EV_KEY, KEY_O,
+	EV_KEY, KEY_P,
+	EV_KEY, KEY_LEFTBRACE,
+	EV_KEY, KEY_RIGHTBRACE,
+	EV_KEY, KEY_ENTER,
+	EV_KEY, KEY_LEFTCTRL,
+	EV_KEY, KEY_A,
+	EV_KEY, KEY_S,
+	EV_KEY, KEY_D,
+	EV_KEY, KEY_F,
+	EV_KEY, KEY_G,
+	EV_KEY, KEY_H,
+	EV_KEY, KEY_J,
+	EV_KEY, KEY_K,
+	EV_KEY, KEY_L,
+	EV_KEY, KEY_SEMICOLON,
+	EV_KEY, KEY_APOSTROPHE,
+	EV_KEY, KEY_GRAVE,
+	EV_KEY, KEY_LEFTSHIFT,
+	EV_KEY, KEY_BACKSLASH,
+	EV_KEY, KEY_Z,
+	EV_KEY, KEY_X,
+	EV_KEY, KEY_C,
+	EV_KEY, KEY_V,
+	EV_KEY, KEY_B,
+	EV_KEY, KEY_N,
+	EV_KEY, KEY_M,
+	EV_KEY, KEY_COMMA,
+	EV_KEY, KEY_DOT,
+	EV_KEY, KEY_SLASH,
+	EV_KEY, KEY_RIGHTSHIFT,
+	EV_KEY, KEY_KPASTERISK,
+	EV_KEY, KEY_LEFTALT,
+	EV_KEY, KEY_SPACE,
+	EV_KEY, KEY_CAPSLOCK,
+	EV_KEY, KEY_F1,
+	EV_KEY, KEY_F2,
+	EV_KEY, KEY_F3,
+	EV_KEY, KEY_F4,
+	EV_KEY, KEY_F5,
+	EV_KEY, KEY_F6,
+	EV_KEY, KEY_F7,
+	EV_KEY, KEY_F8,
+	EV_KEY, KEY_F9,
+	EV_KEY, KEY_F10,
+	EV_KEY, KEY_NUMLOCK,
+	EV_KEY, KEY_SCROLLLOCK,
+	EV_KEY, KEY_KP7,
+	EV_KEY, KEY_KP8,
+	EV_KEY, KEY_KP9,
+	EV_KEY, KEY_KPMINUS,
+	EV_KEY, KEY_KP4,
+	EV_KEY, KEY_KP5,
+	EV_KEY, KEY_KP6,
+	EV_KEY, KEY_KPPLUS,
+	EV_KEY, KEY_KP1,
+	EV_KEY, KEY_KP2,
+	EV_KEY, KEY_KP3,
+	EV_KEY, KEY_KP0,
+	EV_KEY, KEY_KPDOT,
+	EV_KEY, KEY_102ND,
+	EV_KEY, KEY_F11,
+	EV_KEY, KEY_F12,
+	EV_KEY, KEY_KPENTER,
+	EV_KEY, KEY_RIGHTCTRL,
+	EV_KEY, KEY_KPSLASH,
+	EV_KEY, KEY_SYSRQ,
+	EV_KEY, KEY_RIGHTALT,
+	EV_KEY, KEY_HOME,
+	EV_KEY, KEY_UP,
+	EV_KEY, KEY_PAGEUP,
+	EV_KEY, KEY_LEFT,
+	EV_KEY, KEY_RIGHT,
+	EV_KEY, KEY_END,
+	EV_KEY, KEY_DOWN,
+	EV_KEY, KEY_PAGEDOWN,
+	EV_KEY, KEY_INSERT,
+	EV_KEY, KEY_DELETE,
+	EV_KEY, KEY_PAUSE,
+	EV_KEY, KEY_LEFTMETA,
+	EV_KEY, KEY_RIGHTMETA,
+	EV_KEY, KEY_COMPOSE,
+
+	EV_LED, LED_NUML,
+	EV_LED, LED_CAPSL,
+	EV_LED, LED_SCROLLL,
+	EV_LED, LED_COMPOSE,
+	EV_LED, LED_KANA,
+	-1, -1,
+};
+
+struct litest_test_device litest_yubikey_device = {
+	.type = LITEST_YUBIKEY,
+	.features = LITEST_KEYS,
+	.shortname = "yubikey",
+	.setup = litest_yubikey_setup,
+	.interface = NULL,
+
+	.name = "Yubico Yubico Yubikey II",
+	.id = &input_id,
+	.events = events,
+	.absinfo = NULL,
+};
diff --git a/test/litest.c b/test/litest.c
index d857449..7a80fdd 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -370,6 +370,8 @@ extern struct litest_test_device litest_mouse_wheel_click_angle_device;
 extern struct litest_test_device litest_apple_keyboard_device;
 extern struct litest_test_device litest_anker_mouse_kbd_device;
 extern struct litest_test_device litest_cyborg_rat_device;
+extern struct litest_test_device litest_yubikey_device;
+extern struct litest_test_device litest_synaptics_i2c_device;
 
 struct litest_test_device* devices[] = {
 	&litest_synaptics_clickpad_device,
@@ -406,6 +408,8 @@ struct litest_test_device* devices[] = {
 	&litest_apple_keyboard_device,
 	&litest_anker_mouse_kbd_device,
 	&litest_cyborg_rat_device,
+	&litest_yubikey_device,
+	&litest_synaptics_i2c_device,
 	NULL,
 };
 
diff --git a/test/litest.h b/test/litest.h
index 4235d2c..6cfa34e 100644
--- a/test/litest.h
+++ b/test/litest.h
@@ -147,6 +147,8 @@ enum litest_device_type {
 	LITEST_APPLE_KEYBOARD = -33,
 	LITEST_ANKER_MOUSE_KBD = -34,
 	LITEST_CYBORG_RAT = -41,
+	LITEST_YUBIKEY = -42,
+	LITEST_SYNAPTICS_I2C = -43,
 };
 
 enum litest_device_feature {
diff --git a/test/touchpad.c b/test/touchpad.c
index 32bf3c5..195937f 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -2336,6 +2336,106 @@ START_TEST(touchpad_dwt)
 }
 END_TEST
 
+START_TEST(touchpad_dwt_update_keyboard)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard, *yubikey;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	litest_disable_tap(touchpad->libinput_device);
+
+	/* Yubikey is initialized first */
+	yubikey = litest_add_device(li, LITEST_YUBIKEY);
+	litest_drain_events(li);
+
+	keyboard = dwt_init_paired_keyboard(li, touchpad);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	litest_keyboard_key(keyboard, KEY_A, false);
+	libinput_dispatch(li);
+	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_KEYBOARD_KEY);
+
+	/* within timeout - no events */
+	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_empty_queue(li);
+
+	litest_timeout_dwt_short();
+	libinput_dispatch(li);
+
+	/* after timeout  - motion events*/
+	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);
+	litest_delete_device(yubikey);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_update_keyboard_with_state)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard, *yubikey;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	litest_disable_tap(touchpad->libinput_device);
+
+	/* Yubikey is initialized first */
+	yubikey = litest_add_device(li, LITEST_YUBIKEY);
+	litest_drain_events(li);
+
+	litest_keyboard_key(yubikey, KEY_A, true);
+	litest_keyboard_key(yubikey, KEY_A, false);
+	litest_keyboard_key(yubikey, KEY_A, true);
+	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_empty_queue(li);
+
+	litest_keyboard_key(yubikey, KEY_A, false);
+	litest_keyboard_key(yubikey, KEY_A, true);
+	litest_drain_events(li);
+
+	/* yubikey still has A down */
+	keyboard = dwt_init_paired_keyboard(li, touchpad);
+	litest_drain_events(li);
+
+	/* expected repairing, dwt should be disabled */
+	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);
+
+	/* release remaining key */
+	litest_keyboard_key(yubikey, 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);
+	litest_delete_device(yubikey);
+}
+END_TEST
 START_TEST(touchpad_dwt_enable_touch)
 {
 	struct litest_device *touchpad = litest_current_device();
@@ -3805,6 +3905,8 @@ litest_setup_tests(void)
 	litest_add_ranged("touchpad:state", touchpad_initial_state, LITEST_TOUCHPAD, LITEST_ANY, &axis_range);
 
 	litest_add("touchpad:dwt", touchpad_dwt, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add_for_device("touchpad:dwt", touchpad_dwt_update_keyboard, LITEST_SYNAPTICS_I2C);
+	litest_add_for_device("touchpad:dwt", touchpad_dwt_update_keyboard_with_state, LITEST_SYNAPTICS_I2C);
 	litest_add("touchpad:dwt", touchpad_dwt_enable_touch, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:dwt", touchpad_dwt_touch_hold, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:dwt", touchpad_dwt_key_hold, LITEST_TOUCHPAD, LITEST_ANY);

commit 990726b289629a55bfbc683647cb6185135d8d99
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Feb 4 08:31:25 2016 +1000

    touchpad: while a key is held down, don't disable dwt
    
    If a key enables dwt and is held down when the timeout expires, re-issue the
    timeout.
    
    There is a corner case where dwt may not work as expected:
    1. key down and held down
    2. dwt timer expires, dwt is re-issued
    3. touch starts
    4. key is released
    5. dwt timer expires
    6. touch now starts moving the pointer
    
    This is an effect of the smart touch detection. A touch starting after the
    last key press is released for pointer motion once dwt turns off again. This
    is what happens in the above case, the dwt timer expiring is the last virtual
    key press. This is a corner case and likely hard to trigger by a real user.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=93984
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: Hans de Goede <hdegoede@redhat.com>
    (cherry picked from commit b27f04689e60a9148523124aa610b23dbe173377)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 23b7419..ed86ef9 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1185,6 +1185,15 @@ tp_keyboard_timeout(uint64_t now, void *data)
 {
 	struct tp_dispatch *tp = data;
 
+	if (long_any_bit_set(tp->dwt.key_mask,
+			     ARRAY_LENGTH(tp->dwt.key_mask))) {
+		libinput_timer_set(&tp->dwt.keyboard_timer,
+				   now + DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2);
+		tp->dwt.keyboard_last_press_time = now;
+		log_debug(tp_libinput_context(tp), "palm: keyboard timeout refresh\n");
+		return;
+	}
+
 	tp_tap_resume(tp, now);
 
 	tp->dwt.keyboard_active = false;
@@ -1229,6 +1238,7 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
 	struct tp_dispatch *tp = data;
 	struct libinput_event_keyboard *kbdev;
 	unsigned int timeout;
+	unsigned int key;
 
 	if (!tp->dwt.dwt_enabled)
 		return;
@@ -1237,15 +1247,18 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
 		return;
 
 	kbdev = libinput_event_get_keyboard_event(event);
+	key = libinput_event_keyboard_get_key(kbdev);
 
 	/* Only trigger the timer on key down. */
 	if (libinput_event_keyboard_get_key_state(kbdev) !=
-	    LIBINPUT_KEY_STATE_PRESSED)
+	    LIBINPUT_KEY_STATE_PRESSED) {
+		long_clear_bit(tp->dwt.key_mask, key);
 		return;
+	}
 
 	/* modifier keys don't trigger disable-while-typing so things like
 	 * ctrl+zoom or ctrl+click are possible */
-	if (tp_key_ignore_for_dwt(libinput_event_keyboard_get_key(kbdev)))
+	if (tp_key_ignore_for_dwt(key))
 		return;
 
 	if (!tp->dwt.keyboard_active) {
@@ -1259,6 +1272,7 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data)
 	}
 
 	tp->dwt.keyboard_last_press_time = time;
+	long_set_bit(tp->dwt.key_mask, key);
 	libinput_timer_set(&tp->dwt.keyboard_timer,
 			   time + timeout);
 }
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index f42fb02..a1a2291 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -342,6 +342,7 @@ struct tp_dispatch {
 		struct libinput_event_listener keyboard_listener;
 		struct libinput_timer keyboard_timer;
 		struct evdev_device *keyboard;
+		unsigned long key_mask[NLONGS(KEY_CNT)];
 
 		uint64_t keyboard_last_press_time;
 	} dwt;
diff --git a/src/libinput-util.h b/src/libinput-util.h
index 25de8e5..5c52343 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -25,6 +25,7 @@
 #ifndef LIBINPUT_UTIL_H
 #define LIBINPUT_UTIL_H
 
+#include <assert.h>
 #include <unistd.h>
 #include <math.h>
 #include <stdarg.h>
@@ -146,6 +147,19 @@ long_set_bit_state(unsigned long *array, int bit, int state)
 		long_clear_bit(array, bit);
 }
 
+static inline int
+long_any_bit_set(unsigned long *array, size_t size)
+{
+	unsigned long i;
+
+	assert(size > 0);
+
+	for (i = 0; i < size; i++)
+		if (array[i] != 0)
+			return 1;
+	return 0;
+}
+
 struct matrix {
 	float val[3][3]; /* [row][col] */
 };
diff --git a/test/touchpad.c b/test/touchpad.c
index 626611c..32bf3c5 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -2438,6 +2438,145 @@ START_TEST(touchpad_dwt_key_hold)
 }
 END_TEST
 
+START_TEST(touchpad_dwt_key_hold_timeout)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	keyboard = dwt_init_paired_keyboard(li, touchpad);
+	litest_disable_tap(touchpad->libinput_device);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	libinput_dispatch(li);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+	litest_timeout_dwt_long();
+	libinput_dispatch(li);
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5, 1);
+	litest_touch_up(touchpad, 0);
+
+	litest_assert_empty_queue(li);
+
+	litest_keyboard_key(keyboard, KEY_A, false);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+	/* key is up, but still within timeout */
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5, 1);
+	litest_touch_up(touchpad, 0);
+	litest_assert_empty_queue(li);
+
+	/* expire timeout */
+	litest_timeout_dwt_long();
+	libinput_dispatch(li);
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5, 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_key_hold_timeout_existing_touch_cornercase)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	/* Note: this tests for the current behavior of a cornercase, and
+	 * the behaviour is essentially a bug. If this test fails it may be
+	 * because the buggy behavior was fixed.
+	 */
+
+	keyboard = dwt_init_paired_keyboard(li, touchpad);
+	litest_disable_tap(touchpad->libinput_device);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	libinput_dispatch(li);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+	litest_timeout_dwt_long();
+	libinput_dispatch(li);
+
+	/* Touch starting after re-issuing the dwt timeout */
+	litest_touch_down(touchpad, 0, 50, 50);
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5, 1);
+
+	litest_assert_empty_queue(li);
+
+	litest_keyboard_key(keyboard, KEY_A, false);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+	/* key is up, but still within timeout */
+	litest_touch_move_to(touchpad, 0, 70, 50, 50, 50, 5, 1);
+	litest_assert_empty_queue(li);
+
+	/* Expire dwt timeout. Because the touch started after re-issuing
+	 * the last timeout, it looks like the touch started after the last
+	 * key press. Such touches are enabled for pointer motion by
+	 * libinput when dwt expires.
+	 * This is buggy behavior and not what a user would typically
+	 * expect. But it's hard to trigger in real life too.
+	 */
+	litest_timeout_dwt_long();
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5, 1);
+	litest_touch_up(touchpad, 0);
+	/* If the below check for motion event fails because no events are
+	 * in the pipe, the buggy behavior was fixed and this test case
+	 * can be removed */
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+	litest_delete_device(keyboard);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_key_hold_timeout_existing_touch)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboard;
+	struct libinput *li = touchpad->libinput;
+
+	if (!has_disable_while_typing(touchpad))
+		return;
+
+	keyboard = dwt_init_paired_keyboard(li, touchpad);
+	litest_disable_tap(touchpad->libinput_device);
+	litest_drain_events(li);
+
+	litest_keyboard_key(keyboard, KEY_A, true);
+	libinput_dispatch(li);
+	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, 5, 1);
+	libinput_dispatch(li);
+	litest_timeout_dwt_long();
+	libinput_dispatch(li);
+
+	litest_assert_empty_queue(li);
+
+	litest_keyboard_key(keyboard, KEY_A, false);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
+	/* key is up, but still within timeout */
+	litest_touch_move_to(touchpad, 0, 70, 50, 50, 50, 5, 1);
+	litest_assert_empty_queue(li);
+
+	/* expire timeout, but touch started before release */
+	litest_timeout_dwt_long();
+	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5, 1);
+	litest_touch_up(touchpad, 0);
+	litest_assert_empty_queue(li);
+
+	litest_delete_device(keyboard);
+}
+END_TEST
+
 START_TEST(touchpad_dwt_type)
 {
 	struct litest_device *touchpad = litest_current_device();
@@ -3669,6 +3808,9 @@ litest_setup_tests(void)
 	litest_add("touchpad:dwt", touchpad_dwt_enable_touch, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:dwt", touchpad_dwt_touch_hold, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:dwt", touchpad_dwt_key_hold, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:dwt", touchpad_dwt_key_hold_timeout, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:dwt", touchpad_dwt_key_hold_timeout_existing_touch, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:dwt", touchpad_dwt_key_hold_timeout_existing_touch_cornercase, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:dwt", touchpad_dwt_type, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:dwt", touchpad_dwt_type_short_timeout, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:dwt", touchpad_dwt_tap, LITEST_TOUCHPAD, LITEST_ANY);

commit 3f29b61cb6218164a2d2cc72f656607a102ba10a
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri Jan 29 16:25:31 2016 +1000

    touchpad: drop motion hysteresis by default
    
    Some older touchpad devices jitter a fair bit when a finger is resting on the
    touchpad. That's why the hysteresis was introduced in the synaptics driver
    back in 2011. However, the default value of the hysteresis in the synaptics
    driver ended up being 0, even though the code looks like it's using a fraction
    of the touchpad diagonal. When the hysteresis code was ported to libinput it
    was eventually set to 0.5mm.
    
    Turns out this is still too high and tiny finger motions are either
    nonreactive or quite jumpy, making it hard to select small targets. Drop the
    default hysteresis by reducing its margin to 0, but leave it in place for
    those devices where we need them (e.g. the cyapa touchpads).
    
    https://bugs.freedesktop.org/show_bug.cgi?id=93503
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: Hans de Goede <hdegoede@redhat.com>
    (cherry picked from commit 6e0553ab5553d63fa737c1739cfa86fbeee9f641)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index db8aa1d..23b7419 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1940,13 +1940,29 @@ tp_init_default_resolution(struct tp_dispatch *tp,
 	return 0;
 }
 
+static inline void
+tp_init_hysteresis(struct tp_dispatch *tp)
+{
+	int res_x, res_y;
+
+	res_x = tp->device->abs.absinfo_x->resolution;
+	res_y = tp->device->abs.absinfo_y->resolution;
+
+	if (tp->device->model_flags & EVDEV_MODEL_CYAPA) {
+		tp->hysteresis_margin.x = res_x/2;
+		tp->hysteresis_margin.y = res_y/2;
+	} else {
+		tp->hysteresis_margin.x = 0;
+		tp->hysteresis_margin.y = 0;
+	}
+}
+
 static int
 tp_init(struct tp_dispatch *tp,
 	struct evdev_device *device)
 {
 	int width, height;
 	double diagonal;
-	int res_x, res_y;
 
 	tp->base.interface = &tp_interface;
 	tp->device = device;
@@ -1960,8 +1976,6 @@ tp_init(struct tp_dispatch *tp,
 	if (tp_init_slots(tp, device) != 0)
 		return -1;
 
-	res_x = tp->device->abs.absinfo_x->resolution;
-	res_y = tp->device->abs.absinfo_y->resolution;
 	width = device->abs.dimensions.x;
 	height = device->abs.dimensions.y;
 	diagonal = sqrt(width*width + height*height);
@@ -1970,8 +1984,7 @@ tp_init(struct tp_dispatch *tp,
 						       EV_ABS,
 						       ABS_MT_DISTANCE);
 
-	tp->hysteresis_margin.x = res_x/2;
-	tp->hysteresis_margin.y = res_y/2;
+	tp_init_hysteresis(tp);
 
 	if (tp_init_accel(tp, diagonal) != 0)
 		return -1;
diff --git a/src/evdev.c b/src/evdev.c
index 7448103..281a2a0 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1664,6 +1664,7 @@ evdev_read_model_flags(struct evdev_device *device)
 		{ "LIBINPUT_MODEL_ELANTECH_TOUCHPAD", EVDEV_MODEL_ELANTECH_TOUCHPAD },
 		{ "LIBINPUT_MODEL_APPLE_INTERNAL_KEYBOARD", EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD },
 		{ "LIBINPUT_MODEL_CYBORG_RAT", EVDEV_MODEL_CYBORG_RAT },
+		{ "LIBINPUT_MODEL_CYAPA", EVDEV_MODEL_CYAPA },
 		{ NULL, EVDEV_MODEL_DEFAULT },
 	};
 	const struct model_map *m = model_map;
diff --git a/src/evdev.h b/src/evdev.h
index 560559a..96bf621 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -110,6 +110,7 @@ enum evdev_device_model {
 	EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81 = (1 << 12),
 	EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD = (1 << 13),
 	EVDEV_MODEL_CYBORG_RAT = (1 << 14),
+	EVDEV_MODEL_CYAPA = (1 << 15),
 };
 
 struct mt_slot {
diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb
index fa668d6..f23a7f9 100644
--- a/udev/90-libinput-model-quirks.hwdb
+++ b/udev/90-libinput-model-quirks.hwdb
@@ -73,6 +73,9 @@ libinput:name:Cypress APA Trackpad (cyapa):dmi:*svn*SAMSUNG*:pn*Lumpy*
 libinput:name:Atmel maXTouch Touchpad:dmi:*svn*GOOGLE*:pn*Samus*


Reply to: