configure.ac | 4 +- debian/changelog | 6 +++ src/evdev-mt-touchpad.c | 12 +++--- src/evdev.c | 1 src/evdev.h | 1 test/touchpad.c | 68 +++++++++++++++++++++++++++++++++++++ udev/90-libinput-model-quirks.hwdb | 8 +++- udev/libinput-model-quirks.c | 6 +-- 8 files changed, 94 insertions(+), 12 deletions(-)
New commits: commit f03194da0298f7db2d46e26fa64dceebee8ce7a0 Author: Héctor Orón Martínez <zu...@debian.org> Date: Wed Feb 10 17:23:59 2016 +0100 Release Debian version libinput-1.1.7-1 Signed-off-by: Héctor Orón Martínez <zu...@debian.org> diff --git a/debian/changelog b/debian/changelog index 527550d..3c8b6f2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +libinput (1.1.7-1) unstable; urgency=medium + + * New upstream release + + -- Héctor Orón Martínez <zu...@debian.org> Wed, 10 Feb 2016 17:19:28 +0100 + libinput (1.1.6-1) unstable; urgency=medium * New upstream release. commit ee8f7d52015b86bb4910df4d855b39a67246df5e Author: Peter Hutterer <peter.hutte...@who-t.net> Date: Wed Feb 10 08:22:50 2016 +1000 configure.ac: libinput 1.1.7 Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> diff --git a/configure.ac b/configure.ac index 4a0ffff..31b54a6 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], [6]) +m4_define([libinput_micro_version], [7]) 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:6:6 +LIBINPUT_LT_VERSION=16:7:6 AC_SUBST(LIBINPUT_LT_VERSION) AM_SILENT_RULES([yes]) commit de3a6075e72d41b87770ea2297402e13207f1dab Author: Peter Hutterer <peter.hutte...@who-t.net> Date: Tue Feb 9 10:43:45 2016 +1000 touchpad: init a default hysteresis for ALPS rushmore touchpads https://bugs.freedesktop.org/show_bug.cgi?id=90590 Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> Reviewed-by: Hans de Goede <hdego...@redhat.com> (cherry picked from commit 07420eec05408e164de2db623bbbf778daad5616) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index d0bc52d..1f07017 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1983,7 +1983,8 @@ tp_init_hysteresis(struct tp_dispatch *tp) res_x = tp->device->abs.absinfo_x->resolution; res_y = tp->device->abs.absinfo_y->resolution; - if (tp->device->model_flags & EVDEV_MODEL_CYAPA) { + if (tp->device->model_flags & + (EVDEV_MODEL_CYAPA|EVDEV_MODEL_ALPS_RUSHMORE)) { tp->hysteresis_margin.x = res_x/2; tp->hysteresis_margin.y = res_y/2; } else { diff --git a/src/evdev.c b/src/evdev.c index 281a2a0..0ee86f5 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1665,6 +1665,7 @@ evdev_read_model_flags(struct evdev_device *device) { "LIBINPUT_MODEL_APPLE_INTERNAL_KEYBOARD", EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD }, { "LIBINPUT_MODEL_CYBORG_RAT", EVDEV_MODEL_CYBORG_RAT }, { "LIBINPUT_MODEL_CYAPA", EVDEV_MODEL_CYAPA }, + { "LIBINPUT_MODEL_ALPS_RUSHMORE", EVDEV_MODEL_ALPS_RUSHMORE }, { NULL, EVDEV_MODEL_DEFAULT }, }; const struct model_map *m = model_map; diff --git a/src/evdev.h b/src/evdev.h index 96bf621..64fbf10 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -111,6 +111,7 @@ enum evdev_device_model { EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD = (1 << 13), EVDEV_MODEL_CYBORG_RAT = (1 << 14), EVDEV_MODEL_CYAPA = (1 << 15), + EVDEV_MODEL_ALPS_RUSHMORE = (1 << 16), }; struct mt_slot { diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index 6225da1..eb2859e 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -26,6 +26,10 @@ libinput:name:*AlpsPS/2 ALPS DualPoint TouchPad:fwversion:800 libinput:name:*AlpsPS/2 ALPS GlidePoint:fwversion:800 LIBINPUT_ATTR_SIZE_HINT=100x55 +libinput:name:*AlpsPS/2 ALPS DualPoint TouchPad:fwversion:310 +libinput:name:*AlpsPS/2 ALPS GlidePoint:fwversion:310 + LIBINPUT_MODEL_ALPS_RUSHMORE=1 + ########################################## # Apple ########################################## diff --git a/udev/libinput-model-quirks.c b/udev/libinput-model-quirks.c index c8baae7..2dc917d 100644 --- a/udev/libinput-model-quirks.c +++ b/udev/libinput-model-quirks.c @@ -64,7 +64,7 @@ handle_touchpad_alps(struct udev_device *device) return; /* ALPS' firmware version is the version */ - if (pid) + if (version) printf("LIBINPUT_MODEL_FIRMWARE_VERSION=%x\n", version); } commit 6c44e5e5fb6cd8f6843d32b719df145a6a64d345 Author: Peter Hutterer <peter.hutte...@who-t.net> Date: Tue Feb 9 10:37:42 2016 +1000 udev: fix ALPS firmware detection The firmware version is in id.version, not id.model which is always PSMOUSE_ALPS for ALPS devices. The various fw versions are listed in <kernel>/drivers/input/mouse/alps.h and are all hex numbers. Version 8 is actually 0x800, change the match accordingly. Expected side-effect: earlier versions of ALPS touchpads now lose their (erroneous) size assignment. Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> (cherry picked from commit 1f304763b471f239817fab1350eaf6be0c99babd) diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index f23a7f9..6225da1 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -22,8 +22,8 @@ libinput:name:*AlpsPS/2 ALPS DualPoint TouchPad:dmi:* libinput:name:*AlpsPS/2 ALPS GlidePoint:dmi:* LIBINPUT_MODEL_ALPS_TOUCHPAD=1 -libinput:name:*AlpsPS/2 ALPS DualPoint TouchPad:fwversion:8 -libinput:name:*AlpsPS/2 ALPS GlidePoint:fwversion:8 +libinput:name:*AlpsPS/2 ALPS DualPoint TouchPad:fwversion:800 +libinput:name:*AlpsPS/2 ALPS GlidePoint:fwversion:800 LIBINPUT_ATTR_SIZE_HINT=100x55 ########################################## diff --git a/udev/libinput-model-quirks.c b/udev/libinput-model-quirks.c index 67115fa..c8baae7 100644 --- a/udev/libinput-model-quirks.c +++ b/udev/libinput-model-quirks.c @@ -63,9 +63,9 @@ handle_touchpad_alps(struct udev_device *device) if (sscanf(product, "%x/%x/%x/%x", &bus, &vid, &pid, &version) != 4) return; - /* ALPS' firmware version is the PID */ + /* ALPS' firmware version is the version */ if (pid) - printf("LIBINPUT_MODEL_FIRMWARE_VERSION=%d\n", pid); + printf("LIBINPUT_MODEL_FIRMWARE_VERSION=%x\n", version); } static void commit d1c76680894b24ce83ac82a0feedae4dc3bcfffe Author: Peter Hutterer <peter.hutte...@who-t.net> Date: Mon Feb 8 11:48:51 2016 +1000 touchpad: fix dwt disabling while a key is still down If dwt is disabled on the commandline, e.g. by setting an xinput property it may be disabled before the release event comes in. This caused the timer to refresh indefinitely since the key state mask was still on for that key. Always updating the key state mask (even when dwt is disabled) fixes that. If a key is held down while dwt is disabled, this can still cause a indefinite timer refresh, so in the timer func, check if dwt is enabled before refreshing the timer. https://bugs.freedesktop.org/show_bug.cgi?id=94015 Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> Reviewed-by: Hans de Goede <hdego...@redhat.com> (cherry picked from commit 0e87dc9af2be104fd6cfa50e5f013068e42666d4) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 91fb7a9..d0bc52d 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1185,7 +1185,8 @@ tp_keyboard_timeout(uint64_t now, void *data) { struct tp_dispatch *tp = data; - if (long_any_bit_set(tp->dwt.key_mask, + if (tp->dwt.dwt_enabled && + 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); @@ -1240,9 +1241,6 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data) unsigned int timeout; unsigned int key; - if (!tp->dwt.dwt_enabled) - return; - if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY) return; @@ -1256,6 +1254,9 @@ tp_keyboard_event(uint64_t time, struct libinput_event *event, void *data) return; } + if (!tp->dwt.dwt_enabled) + 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(key)) diff --git a/test/touchpad.c b/test/touchpad.c index 195937f..7ff3a96 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -3114,6 +3114,72 @@ START_TEST(touchpad_dwt_disable_before_touch) } END_TEST +START_TEST(touchpad_dwt_disable_during_key_release) +{ + 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 = dwt_init_paired_keyboard(li, touchpad); + litest_disable_tap(touchpad->libinput_device); + litest_drain_events(li); + + litest_keyboard_key(keyboard, KEY_A, true); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); + + disable_dwt(touchpad); + libinput_dispatch(li); + litest_keyboard_key(keyboard, KEY_A, false); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); + + /* touch down during timeout, wait, should generate events */ + litest_touch_down(touchpad, 0, 50, 50); + libinput_dispatch(li); + litest_timeout_dwt_long(); + litest_touch_move_to(touchpad, 0, 70, 50, 50, 50, 10, 1); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_delete_device(keyboard); +} +END_TEST + +START_TEST(touchpad_dwt_disable_during_key_hold) +{ + 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 = dwt_init_paired_keyboard(li, touchpad); + litest_disable_tap(touchpad->libinput_device); + litest_drain_events(li); + + litest_keyboard_key(keyboard, KEY_A, true); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); + + disable_dwt(touchpad); + libinput_dispatch(li); + + /* touch down during timeout, wait, should generate events */ + litest_touch_down(touchpad, 0, 50, 50); + libinput_dispatch(li); + litest_timeout_dwt_long(); + litest_touch_move_to(touchpad, 0, 70, 50, 50, 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_touch) { struct litest_device *touchpad = litest_current_device(); @@ -3925,6 +3991,8 @@ litest_setup_tests(void) 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_disable_during_key_release, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:dwt", touchpad_dwt_disable_during_key_hold, 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); commit b0c5296b245039d3c158bf2da5410432cef4701f Author: Peter Hutterer <peter.hutte...@who-t.net> Date: Fri Feb 5 09:59:32 2016 +1000 configure.ac: libinput 1.1.6 Signed-off-by: Peter Hutterer <peter.hutte...@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.hutte...@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.hutte...@who-t.net> Reviewed-by: Hans de Goede <hdego...@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.hutte...@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.hutte...@who-t.net> Reviewed-by: Hans de Goede <hdego...@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