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

libinput: Changes to 'upstream-unstable'



 README.txt                                     |   14 
 configure.ac                                   |   29 
 doc/Makefile.am                                |    2 
 doc/building.dox                               |  100 ++
 doc/faqs.dox                                   |    2 
 doc/libinput.doxygen.in                        |    1 
 doc/middle-button-emulation.dox                |   34 
 doc/page-hierarchy.dox                         |    2 
 doc/tablet-support.dox                         |   13 
 doc/test-suite.dox                             |   21 
 src/evdev-mt-touchpad-buttons.c                |  113 +-
 src/evdev-mt-touchpad-edge-scroll.c            |   24 
 src/evdev-mt-touchpad-gestures.c               |    5 
 src/evdev-mt-touchpad-tap.c                    |   82 +
 src/evdev-mt-touchpad.c                        |  260 +++--
 src/evdev-mt-touchpad.h                        |   28 
 src/evdev-tablet-pad.c                         |    1 
 src/evdev-tablet.c                             |  119 ++
 src/evdev-tablet.h                             |    5 
 src/evdev.c                                    | 1208 +++++++++++++++----------
 src/evdev.h                                    |  157 ++-
 src/libinput-private.h                         |   18 
 src/libinput-uninstalled.pc.in                 |   10 
 src/libinput-util.c                            |    2 
 src/libinput-util.h                            |   16 
 src/libinput.c                                 |   36 
 src/libinput.h                                 |  105 +-
 src/libinput.sym                               |    6 
 test/Makefile.am                               |  111 --
 test/device.c                                  |   95 +
 test/gestures.c                                |    4 
 test/keyboard.c                                |    2 
 test/litest-device-mouse-wheel-click-angle.c   |    1 
 test/litest-device-synaptics.c                 |    4 
 test/litest-device-wacom-cintiq-13hdt-finger.c |   10 
 test/litest-device-wacom-cintiq-13hdt-pad.c    |    3 
 test/litest-device-wacom-cintiq-13hdt-pen.c    |   10 
 test/litest-device-wacom-hid4800-pen.c         |  119 ++
 test/litest-device-wacom-intuos-finger.c       |   10 
 test/litest-device-wacom-intuos-tablet.c       |   10 
 test/litest-device-wacom-intuos5-pad.c         |    1 
 test/litest.c                                  |  592 +++++++-----
 test/litest.h                                  |   46 
 test/log.c                                     |    4 
 test/misc.c                                    |    6 
 test/pad.c                                     |    2 
 test/path.c                                    |   14 
 test/pointer.c                                 |   13 
 test/tablet.c                                  |  455 +++++++++
 test/touch.c                                   |    2 
 test/touchpad-buttons.c                        |    2 
 test/touchpad-tap.c                            |  302 ++++--
 test/touchpad.c                                |  494 ++++++++++
 test/trackball.c                               |    2 
 test/trackpoint.c                              |  100 ++
 test/udev.c                                    |   14 
 tools/event-debug.c                            |   12 
 tools/shared.c                                 |   21 
 tools/shared.h                                 |    1 
 udev/90-libinput-model-quirks.hwdb             |   15 
 udev/Makefile.am                               |    9 
 udev/libinput-device-group.c                   |   64 +
 62 files changed, 3748 insertions(+), 1215 deletions(-)

New commits:
commit 47b59ca85084d87db6a3d312ddf500e5dbaa937e
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Sep 14 14:49:55 2016 +1000

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

diff --git a/configure.ac b/configure.ac
index 38b465d..47e1594 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,8 +1,8 @@
 AC_PREREQ([2.64])
 
 m4_define([libinput_major_version], [1])
-m4_define([libinput_minor_version], [4])
-m4_define([libinput_micro_version], [901])
+m4_define([libinput_minor_version], [5])
+m4_define([libinput_micro_version], [0])
 m4_define([libinput_version],
           [libinput_major_version.libinput_minor_version.libinput_micro_version])
 
@@ -35,7 +35,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=20:0:10
+LIBINPUT_LT_VERSION=20:1:10
 AC_SUBST(LIBINPUT_LT_VERSION)
 
 AM_SILENT_RULES([yes])

commit f43a072d2c7ea87a2430c373765190f785e57fa0
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Sep 14 11:21:55 2016 +1000

    udev: fix hwdb match for the HP Stream 11
    
    prefix must be libinput, not evdev
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb
index ec71c26..fed28e2 100644
--- a/udev/90-libinput-model-quirks.hwdb
+++ b/udev/90-libinput-model-quirks.hwdb
@@ -96,7 +96,7 @@ libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnHewlett-Packard:*pnHPCompaq8510
  LIBINPUT_MODEL_HP8510_TOUCHPAD=1
 
 # HP Stream 11
-evdev:name:SYN1EDE:00 06CB:7442:dmi:*svnHewlett-Packard:pnHPStreamNotebookPC11*
+libinput:name:SYN1EDE:00 06CB:7442:dmi:*svnHewlett-Packard:pnHPStreamNotebookPC11*
  LIBINPUT_MODEL_HP_STREAM11_TOUCHPAD=1
 
 ##########################################

commit 416fa44d80b0f2c53b652ddfa35dd4a156a65c65
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Sep 7 08:18:33 2016 +1000

    touchpad: require at least 3 events before enabling trackpoint palm detection
    
    Some trackpoints, notably the one on the Lenovo T460s have a tendency to send
    the odd event even when they're not actually used. Trackpoint events trigger
    palm detection (see 0210f1fee193) and thus effectively disable the touchpad,
    causing the touchpad to appear nonresponsive.
    
    Fix this by requiring at least 3 events from a trackpoint before palm
    detection is enabled. For normal use it's hard enough to trigger a single
    event anyway so this should not affect the normal use-case.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1364850
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: Hans de Goede <hdegoede@redhat.com>

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 2354061..38b638b 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1305,6 +1305,7 @@ tp_trackpoint_timeout(uint64_t now, void *data)
 
 	tp_tap_resume(tp, now);
 	tp->palm.trackpoint_active = false;
+	tp->palm.trackpoint_event_count = 0;
 }
 
 static void
@@ -1317,6 +1318,13 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
 	if (event->type == LIBINPUT_EVENT_POINTER_BUTTON)
 		return;
 
+	tp->palm.trackpoint_last_event_time = time;
+	tp->palm.trackpoint_event_count++;
+
+	/* Require at least three events before enabling palm detection */
+	if (tp->palm.trackpoint_event_count < 3)
+		return;
+
 	if (!tp->palm.trackpoint_active) {
 		tp_edge_scroll_stop_events(tp, time);
 		tp_gesture_cancel(tp, time);
@@ -1324,7 +1332,6 @@ tp_trackpoint_event(uint64_t time, struct libinput_event *event, void *data)
 		tp->palm.trackpoint_active = true;
 	}
 
-	tp->palm.trackpoint_last_event_time = time;
 	libinput_timer_set(&tp->palm.trackpoint_timer,
 			   time + DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT);
 }
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index de9bdb5..f4ad090 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -341,6 +341,7 @@ struct tp_dispatch {
 		struct libinput_event_listener trackpoint_listener;
 		struct libinput_timer trackpoint_timer;
 		uint64_t trackpoint_last_event_time;
+		uint32_t trackpoint_event_count;
 		bool monitor_trackpoint;
 	} palm;
 
diff --git a/test/trackpoint.c b/test/trackpoint.c
index b92b994..e9ba027 100644
--- a/test/trackpoint.c
+++ b/test/trackpoint.c
@@ -349,6 +349,31 @@ START_TEST(trackpoint_palmdetect_resume_touch)
 }
 END_TEST
 
+START_TEST(trackpoint_palmdetect_require_min_events)
+{
+	struct litest_device *trackpoint = litest_current_device();
+	struct litest_device *touchpad;
+	struct libinput *li = trackpoint->libinput;
+
+	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
+	litest_drain_events(li);
+
+	/* A single event does not trigger palm detection */
+	litest_event(trackpoint, EV_REL, REL_X, 1);
+	litest_event(trackpoint, EV_REL, REL_Y, 1);
+	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
+	libinput_dispatch(li);
+	litest_drain_events(li);
+
+	litest_touch_down(touchpad, 0, 30, 30);
+	litest_touch_move_to(touchpad, 0, 30, 30, 80, 80, 10, 1);
+	litest_touch_up(touchpad, 0);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
+
+	litest_delete_device(touchpad);
+}
+END_TEST
+
 void
 litest_setup_tests_trackpoint(void)
 {
@@ -362,4 +387,5 @@ litest_setup_tests_trackpoint(void)
 
 	litest_add("trackpoint:palmdetect", trackpoint_palmdetect, LITEST_POINTINGSTICK, LITEST_ANY);
 	litest_add("trackpoint:palmdetect", trackpoint_palmdetect_resume_touch, LITEST_POINTINGSTICK, LITEST_ANY);
+	litest_add("trackpoint:palmdetect", trackpoint_palmdetect_require_min_events, LITEST_POINTINGSTICK, LITEST_ANY);
 }

commit 38a562e48574166ab7ae754d853b9723e00dc7ff
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri Sep 9 12:54:01 2016 +1000

    test: rename SYNAPTICS_CLICKPAD to SYNAPTICS_CLICKPAD_X220
    
    That's where this device comes from. The x220 is special because it's too
    small to trigger some of the features, eg. palm detection. Make this more
    obvious by changing to a less generic name.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/test/device.c b/test/device.c
index 68f9b8b..4ed12d9 100644
--- a/test/device.c
+++ b/test/device.c
@@ -1448,7 +1448,7 @@ litest_setup_tests_device(void)
 	litest_add("device:sendevents", device_disable_release_softbutton, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
 	litest_add("device:sendevents", device_disable_topsoftbutton, LITEST_TOPBUTTONPAD, LITEST_ANY);
 	litest_add("device:id", device_ids, LITEST_ANY, LITEST_ANY);
-	litest_add_for_device("device:context", device_context, LITEST_SYNAPTICS_CLICKPAD);
+	litest_add_for_device("device:context", device_context, LITEST_SYNAPTICS_CLICKPAD_X220);
 
 	litest_add("device:udev", device_get_udev_handle, LITEST_ANY, LITEST_ANY);
 
diff --git a/test/litest-device-synaptics.c b/test/litest-device-synaptics.c
index 4dcdebf..3186a3a 100644
--- a/test/litest-device-synaptics.c
+++ b/test/litest-device-synaptics.c
@@ -31,7 +31,7 @@
 static void
 litest_synaptics_clickpad_setup(void)
 {
-	struct litest_device *d = litest_create_device(LITEST_SYNAPTICS_CLICKPAD);
+	struct litest_device *d = litest_create_device(LITEST_SYNAPTICS_CLICKPAD_X220);
 	litest_set_current_device(d);
 }
 
@@ -112,7 +112,7 @@ static struct input_absinfo absinfo[] = {
 };
 
 struct litest_test_device litest_synaptics_clickpad_device = {
-	.type = LITEST_SYNAPTICS_CLICKPAD,
+	.type = LITEST_SYNAPTICS_CLICKPAD_X220,
 	.features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON,
 	.shortname = "synaptics",
 	.setup = litest_synaptics_clickpad_setup,
diff --git a/test/litest.h b/test/litest.h
index d7a7327..4602355 100644
--- a/test/litest.h
+++ b/test/litest.h
@@ -170,7 +170,7 @@ litest_fail_comparison_ptr(const char *file,
 
 enum litest_device_type {
 	LITEST_NO_DEVICE = -1,
-	LITEST_SYNAPTICS_CLICKPAD = -1000,
+	LITEST_SYNAPTICS_CLICKPAD_X220 = -1000,
 	LITEST_SYNAPTICS_TOUCHPAD,
 	LITEST_SYNAPTICS_TOPBUTTONPAD,
 	LITEST_BCM5974,
diff --git a/test/path.c b/test/path.c
index 221c175..0890d3e 100644
--- a/test/path.c
+++ b/test/path.c
@@ -952,13 +952,13 @@ litest_setup_tests_path(void)
 	litest_add_no_device("path:suspend", path_add_device_suspend_resume);
 	litest_add_no_device("path:suspend", path_add_device_suspend_resume_fail);
 	litest_add_no_device("path:suspend", path_add_device_suspend_resume_remove_device);
-	litest_add_for_device("path:seat", path_added_seat, LITEST_SYNAPTICS_CLICKPAD);
-	litest_add_for_device("path:seat", path_seat_change, LITEST_SYNAPTICS_CLICKPAD);
+	litest_add_for_device("path:seat", path_added_seat, LITEST_SYNAPTICS_CLICKPAD_X220);
+	litest_add_for_device("path:seat", path_seat_change, LITEST_SYNAPTICS_CLICKPAD_X220);
 	litest_add("path:device events", path_added_device, LITEST_ANY, LITEST_ANY);
 	litest_add("path:device events", path_device_sysname, LITEST_ANY, LITEST_ANY);
-	litest_add_for_device("path:device events", path_add_device, LITEST_SYNAPTICS_CLICKPAD);
+	litest_add_for_device("path:device events", path_add_device, LITEST_SYNAPTICS_CLICKPAD_X220);
 	litest_add_no_device("path:device events", path_add_invalid_path);
-	litest_add_for_device("path:device events", path_remove_device, LITEST_SYNAPTICS_CLICKPAD);
-	litest_add_for_device("path:device events", path_double_remove_device, LITEST_SYNAPTICS_CLICKPAD);
+	litest_add_for_device("path:device events", path_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220);
+	litest_add_for_device("path:device events", path_double_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220);
 	litest_add_no_device("path:seat", path_seat_recycle);
 }
diff --git a/test/touchpad.c b/test/touchpad.c
index 48840b5..0169bd7 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -4745,10 +4745,10 @@ litest_setup_tests_touchpad(void)
 
 	litest_add("touchpad:time", touchpad_time_usec, LITEST_TOUCHPAD, LITEST_ANY);
 
-	litest_add_for_device("touchpad:jumps", touchpad_jump_finger_motion, LITEST_SYNAPTICS_CLICKPAD);
+	litest_add_for_device("touchpad:jumps", touchpad_jump_finger_motion, LITEST_SYNAPTICS_CLICKPAD_X220);
 
-	litest_add_for_device("touchpad:sendevents", touchpad_disabled_on_mouse, LITEST_SYNAPTICS_CLICKPAD);
-	litest_add_for_device("touchpad:sendevents", touchpad_disabled_on_mouse_suspend_mouse, LITEST_SYNAPTICS_CLICKPAD);
-	litest_add_for_device("touchpad:sendevents", touchpad_disabled_double_mouse, LITEST_SYNAPTICS_CLICKPAD);
-	litest_add_for_device("touchpad:sendevents", touchpad_disabled_double_mouse_one_suspended, LITEST_SYNAPTICS_CLICKPAD);
+	litest_add_for_device("touchpad:sendevents", touchpad_disabled_on_mouse, LITEST_SYNAPTICS_CLICKPAD_X220);
+	litest_add_for_device("touchpad:sendevents", touchpad_disabled_on_mouse_suspend_mouse, LITEST_SYNAPTICS_CLICKPAD_X220);
+	litest_add_for_device("touchpad:sendevents", touchpad_disabled_double_mouse, LITEST_SYNAPTICS_CLICKPAD_X220);
+	litest_add_for_device("touchpad:sendevents", touchpad_disabled_double_mouse_one_suspended, LITEST_SYNAPTICS_CLICKPAD_X220);
 }
diff --git a/test/udev.c b/test/udev.c
index 5a74436..ba6a10d 100644
--- a/test/udev.c
+++ b/test/udev.c
@@ -517,9 +517,9 @@ litest_setup_tests_udev(void)
 	litest_add_no_device("udev:seat", udev_added_seat_default);
 	litest_add_no_device("udev:seat", udev_change_seat);
 
-	litest_add_for_device("udev:suspend", udev_double_suspend, LITEST_SYNAPTICS_CLICKPAD);
-	litest_add_for_device("udev:suspend", udev_double_resume, LITEST_SYNAPTICS_CLICKPAD);
-	litest_add_for_device("udev:suspend", udev_suspend_resume, LITEST_SYNAPTICS_CLICKPAD);
-	litest_add_for_device("udev:device events", udev_device_sysname, LITEST_SYNAPTICS_CLICKPAD);
-	litest_add_for_device("udev:seat", udev_seat_recycle, LITEST_SYNAPTICS_CLICKPAD);
+	litest_add_for_device("udev:suspend", udev_double_suspend, LITEST_SYNAPTICS_CLICKPAD_X220);
+	litest_add_for_device("udev:suspend", udev_double_resume, LITEST_SYNAPTICS_CLICKPAD_X220);
+	litest_add_for_device("udev:suspend", udev_suspend_resume, LITEST_SYNAPTICS_CLICKPAD_X220);
+	litest_add_for_device("udev:device events", udev_device_sysname, LITEST_SYNAPTICS_CLICKPAD_X220);
+	litest_add_for_device("udev:seat", udev_seat_recycle, LITEST_SYNAPTICS_CLICKPAD_X220);
 }

commit b3e93034498ae7eb4ca86681b6ba4e44a4a6b2c7
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Sep 8 15:55:47 2016 +1000

    tools: prefix debug output with '-' on device changes
    
    We print the sysname, but it's not always obvious when there's an event from
    another device within the stream from another device. Prefix it so it's easier
    to spot and search for.
    
    See https://bugzilla.redhat.com/show_bug.cgi?id=1364850#c3 for an example of
    how such an event can hide.
    
    We only use last_device for comparing pointer values so we don't need a
    reference to the device, it doesn't matter if the device itself goes out of
    scope.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/tools/event-debug.c b/tools/event-debug.c
index 67432b7..0e95611 100644
--- a/tools/event-debug.c
+++ b/tools/event-debug.c
@@ -49,8 +49,11 @@ static unsigned int stop = 0;
 static void
 print_event_header(struct libinput_event *ev)
 {
+	/* use for pointer value only, do not dereference */
+	static struct libinput_device *last_device = NULL;
 	struct libinput_device *dev = libinput_event_get_device(ev);
 	const char *type = NULL;
+	char prefix;
 
 	switch(libinput_event_get_type(ev)) {
 	case LIBINPUT_EVENT_NONE:
@@ -132,7 +135,14 @@ print_event_header(struct libinput_event *ev)
 		break;
 	}
 
-	printf("%-7s	%-16s ", libinput_device_get_sysname(dev), type);
+	prefix = (last_device != dev) ? '-' : ' ';
+
+	printf("%c%-7s	%-16s ",
+	       prefix,
+	       libinput_device_get_sysname(dev),
+	       type);
+
+	last_device = dev;
 }
 
 static void

commit 14976069129c291dfafeeeda2ade79442673b492
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Sep 7 13:48:45 2016 +1000

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

diff --git a/configure.ac b/configure.ac
index 3658ed8..38b465d 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], [4])
-m4_define([libinput_micro_version], [0])
+m4_define([libinput_micro_version], [901])
 m4_define([libinput_version],
           [libinput_major_version.libinput_minor_version.libinput_micro_version])
 
@@ -35,7 +35,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=19:1:9
+LIBINPUT_LT_VERSION=20:0:10
 AC_SUBST(LIBINPUT_LT_VERSION)
 
 AM_SILENT_RULES([yes])

commit 18adfed4c14ae21d55164350d9f9e0a8b6142430
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Aug 18 10:48:31 2016 +1000

    Force the HP Stream 11 touchpad as a clickpad
    
    INPUT_PROP_BUTTONPAD is not set on this device and RMI4 which should fix this
    is a bit too far into the future at this point. Hack around it.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=97147
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: Hans de Goede <hdegoede@redhat.com>

diff --git a/src/evdev.c b/src/evdev.c
index 03384c8..f7f7230 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -2137,6 +2137,7 @@ evdev_read_model_flags(struct evdev_device *device)
 		MODEL(APPLE_INTERNAL_KEYBOARD),
 		MODEL(CYBORG_RAT),
 		MODEL(CYAPA),
+		MODEL(HP_STREAM11_TOUCHPAD),
 		MODEL(LENOVO_T450_TOUCHPAD),
 		MODEL(DELL_TOUCHPAD),
 		MODEL(TRACKBALL),
@@ -2717,6 +2718,12 @@ evdev_pre_configure_model_quirks(struct evdev_device *device)
 		libevdev_disable_event_code(device->evdev, EV_KEY, BTN_TOOL_DOUBLETAP);
 		libevdev_disable_event_code(device->evdev, EV_KEY, BTN_TOOL_TRIPLETAP);
 	}
+
+	/* Touchpad is a clickpad but INPUT_PROP_BUTTONPAD is not set, see
+	 * fdo bug 97147. Remove when RMI4 is commonplace */
+	if (device->model_flags & EVDEV_MODEL_HP_STREAM11_TOUCHPAD)
+		libevdev_enable_property(device->evdev,
+					 INPUT_PROP_BUTTONPAD);
 }
 
 struct evdev_device *
diff --git a/src/evdev.h b/src/evdev.h
index b240615..4e28e05 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -114,6 +114,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_HP_STREAM11_TOUCHPAD = (1 << 16),
 	EVDEV_MODEL_LENOVO_T450_TOUCHPAD= (1 << 17),
 	EVDEV_MODEL_DELL_TOUCHPAD = (1 << 18),
 	EVDEV_MODEL_TRACKBALL = (1 << 19),
diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb
index ee11fb7..ec71c26 100644
--- a/udev/90-libinput-model-quirks.hwdb
+++ b/udev/90-libinput-model-quirks.hwdb
@@ -95,6 +95,10 @@ libinput:name:Cypress APA Trackpad ?cyapa?:dmi:*
 libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnHewlett-Packard:*pnHPCompaq8510w*
  LIBINPUT_MODEL_HP8510_TOUCHPAD=1
 
+# HP Stream 11
+evdev:name:SYN1EDE:00 06CB:7442:dmi:*svnHewlett-Packard:pnHPStreamNotebookPC11*
+ LIBINPUT_MODEL_HP_STREAM11_TOUCHPAD=1
+
 ##########################################
 # LENOVO
 ##########################################

commit b519ea4ab52e76af585e800fd766bb188114a0b3
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Jun 28 11:28:34 2016 +1000

    tablet: add touch arbitration
    
    So far we've relied on the wacom kernel module to do touch arbitration for us
    but that won't be the case in upcoming kernels. Implement touch arbitration in
    userspace by pairing the two devices and suspending the touch device whenever
    a tool comes into proximity.
    
    In the future more sophisticated arbitration can be done (e.g. only touches
    which are close to the pen) but let's burn that bridge when we have to cross
    it.
    
    Note that touch arbitration is "device suspend light", i.e. we leave the
    device enabled and the fd is active. Tablet interactions are comparatively
    short-lived, so closing the fd and asking logind for a new one every time the
    pen changes proximity is suboptimal. Instead, we just keep a boolean around
    and discard all events while it is set.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com>

diff --git a/doc/tablet-support.dox b/doc/tablet-support.dox
index cda0d70..19c5d8f 100644
--- a/doc/tablet-support.dox
+++ b/doc/tablet-support.dox
@@ -331,4 +331,17 @@ button and ring events on the right. When one of the three mode toggle
 buttons on the right is pressed, the right mode switches to that button's
 mode but the left mode remains unchanged.
 
+@section tablet-touch-arbitration Tablet touch arbitration
+
+"Touch arbitration" is the terminology used when touch events are suppressed
+while the pen is in proximity. Since it is almost impossible to use a stylus
+or other tool without triggering touches with the hand holding the tool,
+touch arbitration serves to reduce the number of accidental inputs.
+The wacom kernel driver currently provides touch arbitration but for other
+devices arbitration has to be done in userspace.
+
+libinput uses the @ref libinput_device_group to decide on touch arbitration
+and automatically discards touch events whenever a tool is in proximity.
+The exact behavior is device-dependent.
+
 */
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 65b0abf..2354061 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1165,6 +1165,9 @@ tp_interface_process(struct evdev_dispatch *dispatch,
 	struct tp_dispatch *tp =
 		(struct tp_dispatch *)dispatch;
 
+	if (tp->ignore_events)
+		return;
+
 	switch (e->type) {
 	case EV_ABS:
 		if (tp->has_mt)
@@ -1679,6 +1682,23 @@ evdev_tag_touchpad(struct evdev_device *device,
 	}
 }
 
+static void
+tp_interface_toggle_touch(struct evdev_dispatch *dispatch,
+			  struct evdev_device *device,
+			  bool enable)
+{
+	struct tp_dispatch *tp = (struct tp_dispatch*)dispatch;
+	bool ignore_events = !enable;
+
+	if (ignore_events == tp->ignore_events)
+		return;
+
+	if (ignore_events)
+		tp_clear_state(tp);
+
+	tp->ignore_events = ignore_events;
+}
+
 static struct evdev_dispatch_interface tp_interface = {
 	tp_interface_process,
 	tp_interface_suspend,
@@ -1689,6 +1709,7 @@ static struct evdev_dispatch_interface tp_interface = {
 	tp_interface_device_removed, /* device_suspended, treat as remove */
 	tp_interface_device_added,   /* device_resumed, treat as add */
 	NULL,                        /* post_added */
+	tp_interface_toggle_touch,
 };
 
 static void
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 8a8d2db..de9bdb5 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -231,6 +231,10 @@ struct tp_dispatch {
 	bool semi_mt;
 	bool reports_distance;			/* does the device support true hovering */
 
+	/* true if we're reading events (i.e. not suspended) but we're
+	 * ignoring them */
+	bool ignore_events;
+
 	unsigned int num_slots;			/* number of slots */
 	unsigned int ntouches;			/* no slots inc. fakes */
 	struct tp_touch *touches;		/* len == ntouches */
diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c
index 0e95408..82542bc 100644
--- a/src/evdev-tablet-pad.c
+++ b/src/evdev-tablet-pad.c
@@ -512,6 +512,7 @@ static struct evdev_dispatch_interface pad_interface = {
 	NULL, /* device_suspended */
 	NULL, /* device_resumed */
 	NULL, /* post_added */
+	NULL, /* toggle_touch */
 };
 
 static void
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 254d669..14023b6 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -1434,6 +1434,39 @@ tablet_flush(struct tablet_dispatch *tablet,
 }
 
 static inline void
+tablet_set_touch_device_enabled(struct evdev_device *touch_device,
+				bool enable)
+{
+	struct evdev_dispatch *dispatch;
+
+	if (touch_device == NULL)
+		return;
+
+	dispatch = touch_device->dispatch;
+	if (dispatch->interface->toggle_touch)
+		dispatch->interface->toggle_touch(dispatch,
+						  touch_device,
+						  enable);
+}
+
+static inline void
+tablet_toggle_touch_device(struct tablet_dispatch *tablet,
+			   struct evdev_device *tablet_device)
+{
+	bool enable_events;
+
+	enable_events = tablet_has_status(tablet,
+					  TABLET_TOOL_OUT_OF_RANGE) ||
+			tablet_has_status(tablet, TABLET_NONE) ||
+			tablet_has_status(tablet,
+					  TABLET_TOOL_LEAVING_PROXIMITY) ||
+			tablet_has_status(tablet,
+					  TABLET_TOOL_OUT_OF_PROXIMITY);
+
+	tablet_set_touch_device_enabled(tablet->touch_device, enable_events);
+}
+
+static inline void
 tablet_reset_state(struct tablet_dispatch *tablet)
 {
 	/* Update state */
@@ -1466,6 +1499,7 @@ tablet_process(struct evdev_dispatch *dispatch,
 		break;
 	case EV_SYN:
 		tablet_flush(tablet, device, time);
+		tablet_toggle_touch_device(tablet, device);
 		tablet_reset_state(tablet);
 		break;
 	default:
@@ -1478,6 +1512,16 @@ tablet_process(struct evdev_dispatch *dispatch,
 }
 
 static void
+tablet_suspend(struct evdev_dispatch *dispatch,
+	       struct evdev_device *device)
+{
+	struct tablet_dispatch *tablet =
+		(struct tablet_dispatch *)dispatch;
+
+	tablet_set_touch_device_enabled(tablet->touch_device, true);
+}
+
+static void
 tablet_destroy(struct evdev_dispatch *dispatch)
 {
 	struct tablet_dispatch *tablet =
@@ -1492,6 +1536,35 @@ tablet_destroy(struct evdev_dispatch *dispatch)
 }
 
 static void
+tablet_device_added(struct evdev_device *device,
+		    struct evdev_device *added_device)
+{
+	struct tablet_dispatch *tablet =
+		(struct tablet_dispatch*)device->dispatch;
+
+	if (libinput_device_get_device_group(&device->base) !=
+	    libinput_device_get_device_group(&added_device->base))
+		return;
+
+	/* Touch screens or external touchpads only */
+	if (evdev_device_has_capability(added_device, LIBINPUT_DEVICE_CAP_TOUCH) ||
+	    (evdev_device_has_capability(added_device, LIBINPUT_DEVICE_CAP_POINTER) &&
+	     (added_device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD)))
+	    tablet->touch_device = added_device;
+}
+
+static void
+tablet_device_removed(struct evdev_device *device,
+		      struct evdev_device *removed_device)
+{
+	struct tablet_dispatch *tablet =
+		(struct tablet_dispatch*)device->dispatch;
+
+	if (tablet->touch_device == removed_device)
+		tablet->touch_device = NULL;
+}
+
+static void
 tablet_check_initial_proximity(struct evdev_device *device,
 			       struct evdev_dispatch *dispatch)
 {
@@ -1532,14 +1605,15 @@ tablet_check_initial_proximity(struct evdev_device *device,
 
 static struct evdev_dispatch_interface tablet_interface = {
 	tablet_process,
-	NULL, /* suspend */
+	tablet_suspend,
 	NULL, /* remove */
 	tablet_destroy,
-	NULL, /* device_added */
-	NULL, /* device_removed */
+	tablet_device_added,
+	tablet_device_removed,
 	NULL, /* device_suspended */
 	NULL, /* device_resumed */
 	tablet_check_initial_proximity,
+	NULL, /* toggle_touch */
 };
 
 static void
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index f66de5d..2279e03 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -71,6 +71,9 @@ struct tablet_dispatch {
 	uint32_t cursor_proximity_threshold;
 
 	struct libinput_device_config_calibration calibration;
+
+	/* The paired touch device on devices with both pen & touch */
+	struct evdev_device *touch_device;
 };
 
 static inline enum libinput_tablet_tool_axis
diff --git a/src/evdev.c b/src/evdev.c
index 3b48c3e..03384c8 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1055,6 +1055,9 @@ fallback_process(struct evdev_dispatch *evdev_dispatch,
 	struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch;
 	enum evdev_event_type sent;
 
+	if (dispatch->ignore_events)
+		return;
+
 	switch (event->type) {
 	case EV_REL:
 		fallback_process_relative(dispatch, device, event, time);
@@ -1184,6 +1187,23 @@ fallback_suspend(struct evdev_dispatch *evdev_dispatch,
 }
 
 static void
+fallback_toggle_touch(struct evdev_dispatch *evdev_dispatch,
+		      struct evdev_device *device,
+		      bool enable)
+{
+	struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch;
+	bool ignore_events = !enable;
+
+	if (ignore_events == dispatch->ignore_events)
+		return;
+
+	if (ignore_events)
+		fallback_return_to_neutral_state(dispatch, device);
+
+	dispatch->ignore_events = ignore_events;
+}
+
+static void
 fallback_destroy(struct evdev_dispatch *evdev_dispatch)
 {
 	struct fallback_dispatch *dispatch = (struct fallback_dispatch*)evdev_dispatch;
@@ -1243,6 +1263,7 @@ struct evdev_dispatch_interface fallback_interface = {
 	NULL, /* device_suspended */
 	NULL, /* device_resumed */
 	NULL, /* post_added */
+	fallback_toggle_touch, /* toggle_touch */
 };
 
 static uint32_t
diff --git a/src/evdev.h b/src/evdev.h
index 10b0e58..b240615 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -265,6 +265,10 @@ struct evdev_dispatch_interface {
 	 * was sent */
 	void (*post_added)(struct evdev_device *device,
 			   struct evdev_dispatch *dispatch);
+
+	void (*toggle_touch)(struct evdev_dispatch *dispatch,
+			     struct evdev_device *device,
+			     bool enable);
 };
 
 struct evdev_dispatch {
@@ -308,6 +312,10 @@ struct fallback_dispatch {
 	unsigned long hw_key_mask[NLONGS(KEY_CNT)];
 
 	enum evdev_event_type pending_event;
+
+	/* true if we're reading events (i.e. not suspended) but we're
+	   ignoring them */
+	bool ignore_events;
 };
 
 struct evdev_device *
diff --git a/test/tablet.c b/test/tablet.c
index 30588a4..212ef0c 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -3767,6 +3767,338 @@ START_TEST(relative_calibration)
 }
 END_TEST
 
+static void
+touch_arbitration(struct litest_device *dev,
+		  enum litest_device_type other,
+		  bool is_touchpad)
+{
+	struct litest_device *finger;
+	struct libinput *li = dev->libinput;
+	struct axis_replacement axes[] = {
+		{ ABS_DISTANCE, 10 },
+		{ ABS_PRESSURE, 0 },
+		{ -1, -1 }
+	};
+
+	finger = litest_add_device(li, other);
+	litest_drain_events(li);
+
+	litest_tablet_proximity_in(dev, 10, 10, axes);
+	litest_tablet_motion(dev, 10, 10, axes);
+	litest_tablet_motion(dev, 20, 40, axes);
+	litest_drain_events(li);
+
+	litest_touch_down(finger, 0, 30, 30);
+	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
+	litest_assert_empty_queue(li);
+
+	litest_tablet_motion(dev, 10, 10, axes);
+	litest_tablet_motion(dev, 20, 40, axes);
+	litest_assert_only_typed_events(li,
+					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+	litest_tablet_proximity_out(dev);
+	litest_assert_only_typed_events(li,
+					LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
+
+	/* finger still down */
+	litest_touch_move_to(finger, 0, 80, 80, 30, 30, 10, 1);
+	litest_touch_up(finger, 0);
+	litest_assert_empty_queue(li);
+
+	/* lift finger, expect expect events */
+	litest_touch_down(finger, 0, 30, 30);
+	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
+	litest_touch_up(finger, 0);
+	libinput_dispatch(li);
+
+	if (is_touchpad)
+		litest_assert_only_typed_events(li,
+						LIBINPUT_EVENT_POINTER_MOTION);
+	else
+		litest_assert_touch_sequence(li);
+
+	litest_delete_device(finger);
+}
+
+START_TEST(intuos_touch_arbitration)
+{
+	touch_arbitration(litest_current_device(), LITEST_WACOM_FINGER, true);
+}
+END_TEST
+
+START_TEST(cintiq_touch_arbitration)
+{
+	touch_arbitration(litest_current_device(),
+			  LITEST_WACOM_CINTIQ_13HDT_FINGER,
+			  false);
+}
+END_TEST
+
+static void
+touch_arbitration_stop_touch(struct litest_device *dev,
+			     enum litest_device_type other,
+			     bool is_touchpad)
+{
+	struct litest_device *finger;
+	struct libinput *li = dev->libinput;
+	struct axis_replacement axes[] = {
+		{ ABS_DISTANCE, 10 },
+		{ ABS_PRESSURE, 0 },
+		{ -1, -1 }
+	};
+
+	finger = litest_add_device(li, other);
+	litest_touch_down(finger, 0, 30, 30);
+	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
+
+	litest_tablet_proximity_in(dev, 10, 10, axes);
+	litest_tablet_motion(dev, 10, 10, axes);
+	litest_tablet_motion(dev, 20, 40, axes);
+	litest_drain_events(li);
+
+	litest_touch_move_to(finger, 0, 80, 80, 30, 30, 10, 1);
+	/* start another finger to make sure that one doesn't send events
+	   either */
+	litest_touch_down(finger, 1, 30, 30);
+	litest_touch_move_to(finger, 1, 30, 30, 80, 80, 10, 1);
+	litest_assert_empty_queue(li);
+
+	litest_tablet_motion(dev, 10, 10, axes);
+	litest_tablet_motion(dev, 20, 40, axes);
+	litest_assert_only_typed_events(li,
+					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+	litest_tablet_proximity_out(dev);
+	litest_drain_events(li);
+
+	/* Finger needs to be lifted for events to happen*/
+	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
+	litest_assert_empty_queue(li);
+	litest_touch_move_to(finger, 1, 80, 80, 30, 30, 10, 1);
+	litest_assert_empty_queue(li);
+	litest_touch_up(finger, 0);
+	litest_touch_move_to(finger, 1, 30, 30, 80, 80, 10, 1);
+	litest_assert_empty_queue(li);
+	litest_touch_up(finger, 1);
+	litest_touch_down(finger, 0, 30, 30);
+	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10, 1);
+	litest_touch_up(finger, 0);
+	libinput_dispatch(li);
+
+	if (is_touchpad)
+		litest_assert_only_typed_events(li,
+						LIBINPUT_EVENT_POINTER_MOTION);
+	else
+		litest_assert_touch_sequence(li);
+
+	litest_delete_device(finger);
+	litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
+}
+
+START_TEST(intuos_touch_arbitration_stop_touch)
+{
+	touch_arbitration_stop_touch(litest_current_device(),
+				     LITEST_WACOM_FINGER,
+				     true);
+}
+END_TEST
+
+START_TEST(cintiq_touch_arbitration_stop_touch)
+{
+	touch_arbitration_stop_touch(litest_current_device(),
+				     LITEST_WACOM_CINTIQ_13HDT_FINGER,
+				     false);
+}
+END_TEST
+
+static void
+touch_arbitration_suspend_touch(struct litest_device *dev,
+				enum litest_device_type other,
+				bool is_touchpad)
+{
+	struct litest_device *tablet;
+	struct libinput *li = dev->libinput;
+	enum libinput_config_status status;
+	struct axis_replacement axes[] = {
+		{ ABS_DISTANCE, 10 },
+		{ ABS_PRESSURE, 0 },
+		{ -1, -1 }
+	};
+
+	tablet = litest_add_device(li, other);
+


Reply to: