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

libinput: Changes to 'upstream-unstable'



Rebased ref, commits from common ancestor:
commit 56bcb2999e92b0814768cdcf075dd87a5b09e446
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Nov 15 14:17:51 2017 +1000

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

diff --git a/meson.build b/meson.build
index 41e6ea4..20f3960 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,5 @@
 project('libinput', 'c', 'cpp',
-	version : '1.9.1',
+	version : '1.9.2',
 	license : 'MIT/Expat',
 	default_options : [ 'c_std=gnu99', 'warning_level=2' ],
 	meson_version : '>= 0.40.0')

commit 4ec04fa9601f8ade44cff97b72bac7cc01ab6acd
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Nov 15 13:32:30 2017 +1000

    man: add --enable-middlebutton to debug-events man page
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit 13c9ef07a238a94ca9e5d5d7918cf589d4bd334e)

diff --git a/tools/libinput-debug-events.man b/tools/libinput-debug-events.man
index abccfa6..4e720fc 100644
--- a/tools/libinput-debug-events.man
+++ b/tools/libinput-debug-events.man
@@ -62,6 +62,9 @@ Enable or disable natural scrolling
 .B \-\-enable\-left\-handed|\-\-disable\-left\-handed
 Enable or disable left handed button configuration
 .TP 8
+.B \-\-enable\-middlebutton|\-\-disable\-middlebutton
+Enable or disable middle button emulation
+.TP 8
 .B \-\-enable\-dwt|\-\-disable\-dwt
 Enable or disable disable-while-typing
 .TP 8

commit e35c202df78219aa83afea568ccbdae8040e7df7
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Nov 13 14:04:56 2017 +1000

    tools: handle missing evdev/pyudev modules with a better error message
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit 67bfb5cf2e917649a1be34aae899248467c2989f)

diff --git a/tools/libinput-measure-touch-size b/tools/libinput-measure-touch-size
index 66c7571..b7aa0e9 100755
--- a/tools/libinput-measure-touch-size
+++ b/tools/libinput-measure-touch-size
@@ -26,9 +26,15 @@
 
 import sys
 import argparse
-import evdev
-import evdev.ecodes
-import pyudev
+try:
+    import evdev
+    import evdev.ecodes
+    import pyudev
+except ModuleNotFoundError as e:
+    print('Error: {}'.format(str(e)), file=sys.stderr)
+    print('One or more python modules are missing. Please install those '
+          'modules and re-run this tool.')
+    sys.exit(1)
 
 
 class Range(object):
diff --git a/tools/libinput-measure-touchpad-pressure b/tools/libinput-measure-touchpad-pressure
index 64ea7b4..052d64d 100755
--- a/tools/libinput-measure-touchpad-pressure
+++ b/tools/libinput-measure-touchpad-pressure
@@ -26,9 +26,15 @@
 
 import sys
 import argparse
-import evdev
-import evdev.ecodes
-import pyudev
+try:
+    import evdev
+    import evdev.ecodes
+    import pyudev
+except ModuleNotFoundError as e:
+    print('Error: {}'.format(str(e)), file=sys.stderr)
+    print('One or more python modules are missing. Please install those '
+          'modules and re-run this tool.')
+    sys.exit(1)
 
 
 class Range(object):
diff --git a/tools/libinput-measure-trackpoint-range b/tools/libinput-measure-trackpoint-range
index 53dc67e..512978c 100755
--- a/tools/libinput-measure-trackpoint-range
+++ b/tools/libinput-measure-trackpoint-range
@@ -26,9 +26,15 @@
 
 import sys
 import argparse
-import evdev
-import evdev.ecodes
-import pyudev
+try:
+    import evdev
+    import evdev.ecodes
+    import pyudev
+except ModuleNotFoundError as e:
+    print('Error: {}'.format(str(e)), file=sys.stderr)
+    print('One or more python modules are missing. Please install those '
+          'modules and re-run this tool.')
+    sys.exit(1)
 
 MINIMUM_EVENT_COUNT = 1000
 

commit 1593d7da328ca9f08c4830d9cc7ead01bb28abe2
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Nov 9 15:17:37 2017 +1000

    tools: when the command isn't installed, print that
    
    Makes it more user-friendly to be able to split the tools into multiple
    packages
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit 92aa1d14183bd88a8080be96672682a2e5696477)

diff --git a/tools/shared.c b/tools/shared.c
index ae3287b..962159e 100644
--- a/tools/shared.c
+++ b/tools/shared.c
@@ -510,11 +510,20 @@ tools_exec_command(const char *prefix, int real_argc, char **real_argv)
 	setup_path();
 
 	rc = execvp(executable, argv);
-	if (rc)
-		fprintf(stderr,
-			"Failed to execute '%s' (%s)\n",
-			command,
-			strerror(errno));
+	if (rc) {
+		if (errno == ENOENT) {
+			fprintf(stderr,
+				"libinput: %s is not a libinput command or not installed. "
+				"See 'libinput --help'\n",
+				command);
+
+		} else {
+			fprintf(stderr,
+				"Failed to execute '%s' (%s)\n",
+				command,
+				strerror(errno));
+		}
+	}
 
 	return EXIT_FAILURE;
 }

commit 73c9ed2cd921e2aea8a33cde82e84ff97bae1559
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Nov 9 13:51:35 2017 +1000

    tools: fix missing words in man page
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit be344a3afbfb4a812b7c302e32c8373da9240c80)

diff --git a/tools/libinput-measure-touch-size.man b/tools/libinput-measure-touch-size.man
index f33f13c..5525ec5 100644
--- a/tools/libinput-measure-touch-size.man
+++ b/tools/libinput-measure-touch-size.man
@@ -9,7 +9,7 @@ libinput\-measure\-touch-size \- measure touch size and orientation of devices
 The
 .B "libinput measure touch\-size"
 tool measures the size and orientation of a touch as provided by the kernel.
-an interactive tool. When executed, the tool will prompt the user to
+This is an interactive tool. When executed, the tool will prompt the user to
 interact with the touch device. On termination, the tool prints a summary of the
 values seen. This data should be attached to any
 touch\-size\-related bug report.

commit ed17f8b6371498dba76590eb09c2c29fac28277f
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Nov 8 21:38:13 2017 +1000

    doc: add a FAQ regarding "please add a configuration option"
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit c67b74b45ec2e0e450dd25d39554018b539bfd33)

diff --git a/doc/faqs.dox b/doc/faqs.dox
index 3ef4c59..1d5ff3b 100644
--- a/doc/faqs.dox
+++ b/doc/faqs.dox
@@ -125,6 +125,20 @@ Changes performed by xinput do not persist across device hotplugs. xinput is
 considered a debugging and testing tool only and should not be used for
 permanent configurations.
 
+@section faq_configuration Can you add a configuration option for $FEATURE?
+
+No. At least that's going to be the initial answer. Read <a
+href="http://who-t.blogspot.com/2016/04/why-libinput-doesnt-have-lot-of-config.html";>Why
+libinput doesn't have a lot of configuration options</a> first.
+Configuration options for most features are a signal that we are incapable
+of handling it correctly. To get to that point, we want to be sure we're
+truly incapable of doing so. libinput has several features that
+are handled automatically (and correctly) that users wanted to have
+configuration options for initially.
+
+So the answer to this question will almost always be 'no'. A configuration
+option is, in most cases, a cop-out.
+
 @section faq_synclient Why don't synclient and syndaemon work with libinput?
 
 Synclient and syndaemon rely on X input device properties that are specific

commit 15e40a42e743356363722923737e9a1a0fffde19
Author: Stefan Brüns <stefan.bruens@rwth-aachen.de>
Date:   Fri Nov 3 23:01:23 2017 +0100

    tools: Handle LIBINPUT_SWITCH_TABLET_MODE
    
    Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit 48fd22def7ae1a8d67d1f6f2e0d6e6f98c7a9361)

diff --git a/tools/libinput-debug-events.c b/tools/libinput-debug-events.c
index 87b7b80..fb8d84d 100644
--- a/tools/libinput-debug-events.c
+++ b/tools/libinput-debug-events.c
@@ -747,6 +747,9 @@ print_switch_event(struct libinput_event *ev)
 	case LIBINPUT_SWITCH_LID:
 		which = "lid";
 		break;
+	case LIBINPUT_SWITCH_TABLET_MODE:
+		which = "tablet-mode";
+		break;
 	default:
 		abort();
 	}

commit 5c989940b6b3900d33e61bbddeac71f1fae9d7be
Author: Stefan Brüns <stefan.bruens@rwth-aachen.de>
Date:   Fri Nov 3 23:22:15 2017 +0100

    tools: Show gesture/switch capabilities in list-devices output
    
    Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de>
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit 5ea84fa7dad6e2f17f109f664d80a4d7956d5f9a)

diff --git a/tools/libinput-list-devices.c b/tools/libinput-list-devices.c
index 376a3c9..aa225ca 100644
--- a/tools/libinput-list-devices.c
+++ b/tools/libinput-list-devices.c
@@ -314,6 +314,12 @@ print_device_notify(struct libinput_event *ev)
 	if (libinput_device_has_capability(dev,
 					   LIBINPUT_DEVICE_CAP_TABLET_PAD))
 		printf("tablet-pad");
+	if (libinput_device_has_capability(dev,
+					   LIBINPUT_DEVICE_CAP_GESTURE))
+		printf("gesture");
+	if (libinput_device_has_capability(dev,
+					   LIBINPUT_DEVICE_CAP_SWITCH))
+		printf("switch");
 	printf("\n");
 
 	printf("Tap-to-click:     %s\n", tap_default(dev));

commit edd83fe99e34c9bb6270687dcb5ef8b650b19085
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Nov 1 14:12:01 2017 +1000

    test: mkdir -p the udev rules and hwdb directories
    
    Especially /run/udev/rules.d may not exist, causing a test suite failure.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=103527
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit d332a64df8d6d91328012ebd4ae2dc664b087c23)

diff --git a/test/litest.c b/test/litest.c
index d34bd3c..ebb1867 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -27,6 +27,7 @@
 #include <check.h>
 #include <dirent.h>
 #include <errno.h>
+#include <libgen.h>
 #include <fcntl.h>
 #include <fnmatch.h>
 #include <getopt.h>
@@ -1071,20 +1072,35 @@ litest_install_model_quirks(struct list *created_files_list)
 	list_insert(created_files_list, &file->link);
 }
 
-static void
-litest_init_udev_rules(struct list *created_files)
+static inline void
+mkdir_p(const char *dir)
 {
+	char *path, *parent;
 	int rc;
 
-	rc = mkdir(UDEV_RULES_D, 0755);
-	if (rc == -1 && errno != EEXIST)
-		litest_abort_msg("Failed to create udev rules directory (%s)\n",
-				 strerror(errno));
+	if (streq(dir, "/"))
+		return;
+
+	path = strdup(dir);
+	parent = dirname(path);
+
+	mkdir_p(parent);
+	rc = mkdir(dir, 0755);
 
-	rc = mkdir(UDEV_HWDB_D, 0755);
-	if (rc == -1 && errno != EEXIST)
-		litest_abort_msg("Failed to create udev hwdb directory (%s)\n",
+	if (rc == -1 && errno != EEXIST) {
+		litest_abort_msg("Failed to create directory %s (%s)\n",
+				 dir,
 				 strerror(errno));
+	}
+
+	free(path);
+}
+
+static void
+litest_init_udev_rules(struct list *created_files)
+{
+	mkdir_p(UDEV_RULES_D);
+	mkdir_p(UDEV_HWDB_D);
 
 	litest_install_model_quirks(created_files);
 	litest_init_all_device_udev_rules(created_files);

commit e7be909838a4d04863b6d0fb3e9104e2240a145f
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Nov 2 10:23:50 2017 +1000

    doc: update test suite page for ninja and other recent changes
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit b15b66616e474f7587700a7fb7d7a757f0d31864)

diff --git a/doc/test-suite.dox b/doc/test-suite.dox
index e6fbe62..d939689 100644
--- a/doc/test-suite.dox
+++ b/doc/test-suite.dox
@@ -1,18 +1,21 @@
 /**
 @page test-suite libinput test suite
 
-The libinput test suite is based on
-[Check](http://check.sourceforge.net/doc/check_html/) and runs automatically
-during `make check`. Check itself is wrapped into a libinput-specific test
-suite called *litest*. Tests are found in `$srcdir/test/`, the main test
-suite is `libinput-test-suite-runner`.
-
-The test suite has a make-like job control enabled by the `-j` or `--jobs`
-flag and will fork off as many parallel processes as given by this flag. The
-default if unspecified is 8. When debugging a specific test case failure it
-is recommended to employ test filtures (see @ref test-filtering) and disable
-parallel tests. The test suite automatically disables parallel make when run
-in gdb.
+libinput ships with a number of tests all run automatically on `ninja test`.
+The primary test suite is the `libinput-test-suite-runner`. When testing,
+the `libinput-test-suite-runner` should always be invoked to check for
+behavior changes.
+
+The test suite runner uses
+[Check](http://check.sourceforge.net/doc/check_html/) underneath the hood
+but most of the functionality is abstracted into *litest* wrappers.
+
+The test suite runner has a make-like job control enabled by the `-j` or
+`--jobs` flag and will fork off as many parallel processes as given by this
+flag. The default if unspecified is 8. When debugging a specific test case
+failure it is recommended to employ test filtures (see @ref test-filtering)
+and disable parallel tests. The test suite automatically disables parallel
+make when run in gdb.
 
 @section test-config X.Org config to avoid interference
 
@@ -28,35 +31,67 @@ with your desktop.
 
 Most tests require the creation of uinput devices and access to the
 resulting `/dev/input/eventX` nodes. Some tests require temporary udev rules.
-<b>This usually requires the tests to be run as root</b>.
+<b>This usually requires the tests to be run as root</b>. If not run as
+root, the test suite runner will exit with status 77, interpreted as
+"skipped" by ninja.
 
 @section test-filtering Selective running of tests
 
-litest's tests are grouped by test groups and devices. A test group is e.g.
-"touchpad:tap" and incorporates all tapping-related tests for touchpads.
-Each test function is (usually) run with one or more specific devices.
-The `--list` commandline argument shows the list of suites and tests.
+litest's tests are grouped into test groups, test names and devices. A test
+group is e.g.  "touchpad:tap" and incorporates all tapping-related tests for
+touchpads. Each test function is (usually) run with one or more specific
+devices. The `--list` commandline argument shows the list of suites and
+tests. This is useful when trying to figure out if a specific test is
+run for a device.
+
 @code
 $ ./test/libinput-test-suite-runner --list
-device:wheel:
-	wheel only
-	blackwidow
-device:invalid devices:
-	no device
-device:group:
-	no device
-	logitech trackball
-	MS surface cover
-	mouse_roccat
-	wheel only
-	blackwidow
+...
+pointer:left-handed:
+	pointer_left_handed_during_click_multiple_buttons:
+		trackpoint
+		ms-surface-cover
+		mouse-wheelclickcount
+		mouse-wheelclickangle
+		low-dpi-mouse
+		mouse-roccat
+		mouse-wheel-tilt
+		mouse
+		logitech-trackball
+		cyborg-rat
+		magicmouse
+	pointer_left_handed_during_click:
+		trackpoint
+		ms-surface-cover
+		mouse-wheelclickcount
+		mouse-wheelclickangle
+		low-dpi-mouse
+		mouse-roccat
+		mouse-wheel-tilt
+		mouse
+		logitech-trackball
+		cyborg-rat
+		litest-magicmouse-device
+	pointer_left_handed:
+		trackpoint
+		ms-surface-cover
+		mouse-wheelclickcount
+		mouse-wheelclickangle
+		low-dpi-mouse
+		mouse-roccat
+		mouse-wheel-tilt
+		mouse
 ...
 @endcode
 
-In the above example, the "device:wheel" suite is run for the "wheel only" and
-the "blackwidow" device. Both devices are automatically instantiated through
-uinput by litest. The "no device" entry signals that litest does not
-instantiate a uinput device for a specific test (though the test itself may
+In the above example, the "pointer:left-handed" suite contains multiple
+tests, e.g. "pointer_left_handed_during_click" (this is also the function
+name of the test, making it easy to grep for). This particular test is run
+for various devices including the trackpoint device and the magic mouse
+device.
+
+The "no device" entry signals that litest does not instantiate a uinput
+device for a specific test (though the test itself may
 instantiate one).
 
 The `--filter-test` argument enables selective running of tests through
@@ -93,7 +128,7 @@ environment variable, if set, also enables verbose mode.
 
 @code
 $ ./test/libinput-test-suite-runner --verbose
-$ LITEST_VERBOSE=1 make check
+$ LITEST_VERBOSE=1 ninja test
 @endcode
 
 */

commit 03cd377e00f9eacf3716c9b901ccf1295ba721de
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Nov 2 10:21:46 2017 +1000

    test: fix the device name for the magic mouse test device
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit 04c6439449a81310c436be6ef85ad5edef1c4d59)

diff --git a/test/litest-device-apple-magicmouse.c b/test/litest-device-apple-magicmouse.c
index f657415..10852e9 100644
--- a/test/litest-device-apple-magicmouse.c
+++ b/test/litest-device-apple-magicmouse.c
@@ -100,7 +100,7 @@ static const char udev_rule[] =
 "\n"
 "LABEL=\"mouse_end\"";
 
-TEST_DEVICE("litest-magicmouse-device",
+TEST_DEVICE("magicmouse",
 	.type = LITEST_MAGICMOUSE,
 	.features = LITEST_RELATIVE | LITEST_BUTTON | LITEST_WHEEL,
 	.interface = &interface,

commit 89660005a8b58051c1422e553426f6e4f891fed4
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Nov 1 14:54:59 2017 +1000

    doc: quote all paths in the doxygen file
    
    https://bugs.freedesktop.org/show_bug.cgi?id=103532
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit fb467dce8fd3271697b5cc1aec6fdf6a12b865cc)

diff --git a/doc/libinput.doxygen.in b/doc/libinput.doxygen.in
index e3c3d34..7d6ce9c 100644
--- a/doc/libinput.doxygen.in
+++ b/doc/libinput.doxygen.in
@@ -9,8 +9,8 @@ EXTRACT_STATIC         = YES
 MAX_INITIALIZER_LINES  = 0
 QUIET                  = YES
 INPUT                  = @INPUT@
-IMAGE_PATH             = @top_srcdir@/doc/svg \
-			 @top_srcdir@/doc/dot
+IMAGE_PATH             = "@top_srcdir@/doc/svg" \
+			 "@top_srcdir@/doc/dot"
 GENERATE_HTML          = YES
 SEARCHENGINE           = NO
 USE_MATHJAX            = YES
@@ -20,11 +20,11 @@ MACRO_EXPANSION        = YES
 EXPAND_ONLY_PREDEF     = YES
 PREDEFINED             = LIBINPUT_ATTRIBUTE_PRINTF(f, a)= \
                          LIBINPUT_ATTRIBUTE_DEPRECATED
-DOTFILE_DIRS           = @top_srcdir@/doc/dot
+DOTFILE_DIRS           = "@top_srcdir@/doc/dot"
 
-HTML_HEADER = @top_srcdir@/doc/style/header.html
-HTML_FOOTER = @top_srcdir@/doc/style/footer.html
-HTML_EXTRA_STYLESHEET = @top_srcdir@/doc/style/bootstrap.css \
-			@top_srcdir@/doc/style/customdoxygen.css \
-			@top_srcdir@/doc/style/libinputdoxygen.css
-USE_MDFILE_AS_MAINPAGE = @top_srcdir@/README.md
+HTML_HEADER = "@top_srcdir@/doc/style/header.html"
+HTML_FOOTER = "@top_srcdir@/doc/style/footer.html"
+HTML_EXTRA_STYLESHEET = "@top_srcdir@/doc/style/bootstrap.css" \
+			"@top_srcdir@/doc/style/customdoxygen.css" \
+			"@top_srcdir@/doc/style/libinputdoxygen.css"
+USE_MDFILE_AS_MAINPAGE = "@top_srcdir@/README.md"

commit 5b862de70d0017f5c513af06a1ef014aff56de5e
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Nov 1 11:19:08 2017 +1000

    circle.yml: add ninja dist to tests
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit e182489ce7fe9b543db05cab49c298173013c580)

diff --git a/circle.yml b/circle.yml
index 7ecbaf6..a55578e 100644
--- a/circle.yml
+++ b/circle.yml
@@ -41,6 +41,12 @@ libinput_jobs:
       name: Build - No docs
       environment:
         MESON_PARAMS: -Ddocumentation=false
+  build_dist: &build_dist
+    run:
+      <<: *build_and_test_default
+      name: Build - ninja dist
+      environment:
+        NINJA_ARGS: dist
   ninja_scan_build: &ninja_scan_build
     run:
       <<: *build_and_test_default
@@ -88,6 +94,7 @@ fedora_build_all: &fedora_build_all
     - *build_no_debug_gui
     - *build_no_tests
     - *build_no_docs
+    - *build_dist
 
 ubuntu_install: &ubuntu_install
   run:
@@ -112,6 +119,7 @@ ubuntu_build_all: &ubuntu_build_all
     - *build_no_debug_gui
     - *build_no_tests
     - *build_no_docs
+    - *build_dist
 
 scan_build_run: &scan_build_run
   <<: *default_settings

commit a83085e4f98d783c2f96593989ca36788ef3d332
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Oct 23 14:34:47 2017 +1000

    touchpad: allow for multiple paired keyboards
    
    needed for the razer blade keybard which provides multiple event nodes for
    one physical device but it's hard/impossible to identify which one is the real
    event node we care about.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=103156
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit 4d7592066a120b00386283ebcbb7503296720626)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 1ad66fb..749f941 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1588,6 +1588,8 @@ tp_interface_process(struct evdev_dispatch *dispatch,
 static void
 tp_remove_sendevents(struct tp_dispatch *tp)
 {
+	struct paired_keyboard *kbd;
+
 	libinput_timer_cancel(&tp->palm.trackpoint_timer);
 	libinput_timer_cancel(&tp->dwt.keyboard_timer);
 
@@ -1596,9 +1598,10 @@ tp_remove_sendevents(struct tp_dispatch *tp)
 		libinput_device_remove_event_listener(
 					&tp->palm.trackpoint_listener);
 
-	if (tp->dwt.keyboard)
-		libinput_device_remove_event_listener(
-					&tp->dwt.keyboard_listener);
+	ARRAY_FOR_EACH(tp->dwt.paired_keyboard, kbd) {
+		if (kbd->device)
+			libinput_device_remove_event_listener(&kbd->listener);
+	}
 
 	if (tp->lid_switch.lid_switch)
 		libinput_device_remove_event_listener(
@@ -1964,9 +1967,8 @@ tp_dwt_pair_keyboard(struct evdev_device *touchpad,
 		     struct evdev_device *keyboard)
 {
 	struct tp_dispatch *tp = (struct tp_dispatch*)touchpad->dispatch;
-
-	if (tp->dwt.keyboard)
-		return;
+	struct paired_keyboard *kbd;
+	bool found = false;
 
 	if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0)
 		return;
@@ -1974,16 +1976,25 @@ tp_dwt_pair_keyboard(struct evdev_device *touchpad,
 	if (!tp_want_dwt(touchpad, keyboard))
 		return;
 
-	libinput_device_add_event_listener(&keyboard->base,
-					   &tp->dwt.keyboard_listener,
-					   tp_keyboard_event, tp);
-	tp->dwt.keyboard = keyboard;
-	tp->dwt.keyboard_active = false;
+	ARRAY_FOR_EACH(tp->dwt.paired_keyboard, kbd) {
+		if (kbd->device)
+			continue;
 
-	evdev_log_debug(touchpad,
-			"palm: dwt activated with %s<->%s\n",
-			touchpad->devname,
-			keyboard->devname);
+		found = true;
+		libinput_device_add_event_listener(&keyboard->base,
+						   &kbd->listener,
+						   tp_keyboard_event, tp);
+		kbd->device = keyboard;
+		evdev_log_debug(touchpad,
+				"palm: dwt activated with %s<->%s\n",
+				touchpad->devname,
+				keyboard->devname);
+		break;
+	}
+
+	if (!found)
+		evdev_log_bug_libinput(touchpad,
+				       "too many internal keyboards for dwt\n");
 }
 
 static void
@@ -2121,6 +2132,7 @@ tp_interface_device_removed(struct evdev_device *device,
 			    struct evdev_device *removed_device)
 {
 	struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
+	struct paired_keyboard *kbd;
 
 	if (removed_device == tp->buttons.trackpoint) {
 		/* Clear any pending releases for the trackpoint */
@@ -2134,11 +2146,12 @@ tp_interface_device_removed(struct evdev_device *device,
 		tp->buttons.trackpoint = NULL;
 	}
 
-	if (removed_device == tp->dwt.keyboard) {
-		libinput_device_remove_event_listener(
-					&tp->dwt.keyboard_listener);
-		tp->dwt.keyboard = NULL;
-		tp->dwt.keyboard_active = false;
+	ARRAY_FOR_EACH(tp->dwt.paired_keyboard, kbd) {
+		if (kbd->device == removed_device) {
+			libinput_device_remove_event_listener(&kbd->listener);
+			kbd->device = NULL;
+			tp->dwt.keyboard_active = false;
+		}
 	}
 
 	if (removed_device == tp->lid_switch.lid_switch) {
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 9d9f082..9459e76 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -383,13 +383,20 @@ struct tp_dispatch {
 		struct libinput_device_config_dwt config;
 		bool dwt_enabled;
 
-		bool keyboard_active;
-		struct libinput_event_listener keyboard_listener;
-		struct libinput_timer keyboard_timer;
-		struct evdev_device *keyboard;
+		/* We have to allow for more than one device node to be the
+		 * internal dwt keyboard (Razer Blade). But they're the same
+		 * physical device, so we don't care about per-keyboard
+		 * key/modifier masks.
+		 */
+		struct paired_keyboard {
+			struct evdev_device *device;
+			struct libinput_event_listener listener;
+		} paired_keyboard[3];
+
 		unsigned long key_mask[NLONGS(KEY_CNT)];
 		unsigned long mod_mask[NLONGS(KEY_CNT)];
-
+		bool keyboard_active;
+		struct libinput_timer keyboard_timer;
 		uint64_t keyboard_last_press_time;
 	} dwt;
 
diff --git a/test/test-touchpad.c b/test/test-touchpad.c
index 6d2aee5..895de1f 100644
--- a/test/test-touchpad.c
+++ b/test/test-touchpad.c
@@ -4232,6 +4232,152 @@ START_TEST(touchpad_dwt_acer_hawaii)
 }
 END_TEST
 
+START_TEST(touchpad_dwt_multiple_keyboards)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *k1, *k2;
+	struct libinput *li = touchpad->libinput;
+
+	ck_assert(has_disable_while_typing(touchpad));
+
+	enable_dwt(touchpad);
+
+	k1 = litest_add_device(li, LITEST_KEYBOARD);
+	k2 = litest_add_device(li, LITEST_KEYBOARD);
+
+	litest_keyboard_key(k1, KEY_A, true);
+	litest_keyboard_key(k1, KEY_A, false);
+	litest_drain_events(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_empty_queue(li);
+
+	litest_timeout_dwt_short();
+
+	litest_keyboard_key(k2, KEY_A, true);
+	litest_keyboard_key(k2, KEY_A, false);
+	litest_drain_events(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_empty_queue(li);
+
+	litest_timeout_dwt_short();
+
+	litest_delete_device(k1);
+	litest_delete_device(k2);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_multiple_keyboards_bothkeys)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *k1, *k2;
+	struct libinput *li = touchpad->libinput;
+
+	ck_assert(has_disable_while_typing(touchpad));
+
+	enable_dwt(touchpad);
+
+	k1 = litest_add_device(li, LITEST_KEYBOARD);
+	k2 = litest_add_device(li, LITEST_KEYBOARD);
+
+	litest_keyboard_key(k1, KEY_A, true);
+	litest_keyboard_key(k1, KEY_A, false);
+	litest_keyboard_key(k2, KEY_B, true);
+	litest_keyboard_key(k2, KEY_B, false);
+	litest_drain_events(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_empty_queue(li);
+
+	litest_delete_device(k1);
+	litest_delete_device(k2);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_multiple_keyboards_bothkeys_modifier)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *k1, *k2;
+	struct libinput *li = touchpad->libinput;
+
+	ck_assert(has_disable_while_typing(touchpad));
+
+	enable_dwt(touchpad);
+
+	k1 = litest_add_device(li, LITEST_KEYBOARD);
+	k2 = litest_add_device(li, LITEST_KEYBOARD);
+
+	litest_keyboard_key(k1, KEY_RIGHTCTRL, true);
+	litest_keyboard_key(k1, KEY_RIGHTCTRL, false);
+	litest_keyboard_key(k2, KEY_B, true);
+	litest_keyboard_key(k2, KEY_B, false);
+	litest_drain_events(li);
+
+	/* If the keyboard is a single physical device, the above should
+	 * trigger the modifier behavior for dwt. But libinput views it as
+	 * two separate devices and this is such a niche case that it
+	 * doesn't matter. So we test for the easy behavior:
+	 * ctrl+B across two devices is *not* a dwt modifier combo
+	 */
+	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_delete_device(k1);
+	litest_delete_device(k2);
+}
+END_TEST
+
+START_TEST(touchpad_dwt_multiple_keyboards_remove)
+{
+	struct litest_device *touchpad = litest_current_device();
+	struct litest_device *keyboards[2];
+	struct libinput *li = touchpad->libinput;
+	int which = _i; /* ranged test */
+	struct litest_device *removed, *remained;
+
+	ck_assert_int_le(which, 1);
+
+	ck_assert(has_disable_while_typing(touchpad));
+
+	enable_dwt(touchpad);
+
+	keyboards[0] = litest_add_device(li, LITEST_KEYBOARD);
+	keyboards[1] = litest_add_device(li, LITEST_KEYBOARD);
+
+	litest_keyboard_key(keyboards[0], KEY_A, true);
+	litest_keyboard_key(keyboards[0], KEY_A, false);
+	litest_keyboard_key(keyboards[1], KEY_B, true);
+	litest_keyboard_key(keyboards[1], KEY_B, false);
+	litest_drain_events(li);
+
+	litest_timeout_dwt_short();
+
+	removed = keyboards[which % 2];
+	remained = keyboards[(which + 1) % 2];
+
+	litest_delete_device(removed);
+	litest_keyboard_key(remained, KEY_C, true);
+	litest_keyboard_key(remained, KEY_C, false);
+	litest_drain_events(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_empty_queue(li);
+
+	litest_delete_device(remained);
+}
+END_TEST
+
 static int
 has_thumb_detect(struct litest_device *dev)
 {
@@ -5493,6 +5639,7 @@ void
 litest_setup_tests_touchpad(void)
 {
 	struct range axis_range = {ABS_X, ABS_Y + 1};
+	struct range twice = {0, 2 };
 
 	litest_add("touchpad:motion", touchpad_1fg_motion, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:motion", touchpad_2fg_no_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
@@ -5620,6 +5767,10 @@ litest_setup_tests_touchpad(void)
 	litest_add("touchpad:dwt", touchpad_dwt_remove_kbd_while_active, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add_for_device("touchpad:dwt", touchpad_dwt_apple, LITEST_BCM5974);
 	litest_add_for_device("touchpad:dwt", touchpad_dwt_acer_hawaii, LITEST_ACER_HAWAII_TOUCHPAD);
+	litest_add_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards, LITEST_SYNAPTICS_I2C);
+	litest_add_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards_bothkeys, LITEST_SYNAPTICS_I2C);
+	litest_add_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards_bothkeys_modifier, LITEST_SYNAPTICS_I2C);
+	litest_add_ranged_for_device("touchpad:dwt", touchpad_dwt_multiple_keyboards_remove, LITEST_SYNAPTICS_I2C, &twice);
 
 	litest_add("touchpad:thumb", touchpad_thumb_begin_no_motion, LITEST_CLICKPAD, LITEST_ANY);
 	litest_add("touchpad:thumb", touchpad_thumb_update_no_motion, LITEST_CLICKPAD, LITEST_ANY);

commit 021865232d375da3aa94893026309ce0e2c0b320
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Oct 30 14:58:05 2017 +1000

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

diff --git a/meson.build b/meson.build
index ac3902a..41e6ea4 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,5 @@
 project('libinput', 'c', 'cpp',
-	version : '1.9.0',
+	version : '1.9.1',
 	license : 'MIT/Expat',
 	default_options : [ 'c_std=gnu99', 'warning_level=2' ],
 	meson_version : '>= 0.40.0')

commit 41a70bbe924c4867283bfdec67cd76012744afcb
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri Oct 27 15:03:52 2017 +1000

    fallback: fix lid switch event listener being initialized twice
    
    Once the lid is closed, the keyboard event listener is set up to open the lid
    for us on keyboard events. With the right sequence, we can trigger the
    listener to be added to the list multiple times, triggering an assert in the
    list test code (or an infinite loop in the 1.8 branch).
    
    Conditions:
    * SW_LID value 1 - sets up the keyboard listener
    * keyboard event - sets lid_is_closed to false
    * SW_LID value 0 - is ignored because we're already open
    * SW_LID value 1 - sets up the keyboard listener again
    
    https://bugs.freedesktop.org/show_bug.cgi?id=103298
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/src/evdev-fallback.c b/src/evdev-fallback.c
index 13e130a..4da07e7 100644
--- a/src/evdev-fallback.c
+++ b/src/evdev-fallback.c
@@ -949,6 +949,8 @@ fallback_lid_toggle_keyboard_listener(struct fallback_dispatch *dispatch,
 {
 	assert(kbd->device);
 
+	libinput_device_remove_event_listener(&kbd->listener);
+
 	if (is_closed) {
 		libinput_device_add_event_listener(
 					&kbd->device->base,
@@ -956,10 +958,7 @@ fallback_lid_toggle_keyboard_listener(struct fallback_dispatch *dispatch,
 					fallback_lid_keyboard_event,
 					dispatch);
 	} else {
-		libinput_device_remove_event_listener(
-					&kbd->listener);
-		libinput_device_init_event_listener(
-					&kbd->listener);
+		libinput_device_init_event_listener(&kbd->listener);
 	}
 }
 
@@ -992,11 +991,11 @@ fallback_process_switch(struct fallback_dispatch *dispatch,
 	case SW_LID:
 		is_closed = !!e->value;
 
+		fallback_lid_toggle_keyboard_listeners(dispatch, is_closed);


Reply to: