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

libinput: Changes to 'upstream-unstable'



 configure.ac                       |    4 -
 src/evdev-mt-touchpad-gestures.c   |    1 
 src/evdev-mt-touchpad.c            |   34 +++++++++++++--
 src/evdev-mt-touchpad.h            |   12 +++++
 src/evdev-tablet.c                 |   82 ++++++++++++++++++++++---------------
 src/evdev-tablet.h                 |    2 
 src/evdev.c                        |    1 
 src/evdev.h                        |    1 
 src/libinput.c                     |    3 +
 test/path.c                        |   60 +++++++++++++++++++++++++++
 test/udev.c                        |    5 --
 udev/90-libinput-model-quirks.hwdb |    7 +++
 12 files changed, 168 insertions(+), 44 deletions(-)

New commits:
commit ae7b2f77720f19ce3b6924bb3ecf706cabd17587
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 15 10:23:42 2016 +1000

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

diff --git a/configure.ac b/configure.ac
index 71255ed..7d73183 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], [2])
-m4_define([libinput_micro_version], [1])
+m4_define([libinput_micro_version], [2])
 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=17:3:7
+LIBINPUT_LT_VERSION=17:4:7
 AC_SUBST(LIBINPUT_LT_VERSION)
 
 AM_SILENT_RULES([yes])

commit a608d9dc2c70c7915fc94466ed27c1684f65409e
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Mar 7 16:05:25 2016 +1000

    touchpad: add quirk for the T450 and T460 generation hardware
    
    The touchpad's sensors are too far apart (or the firmware interferes), causing
    in a jerky movement visible especially on slow motion. We get a bunch of
    normal motion events, then only ABS_MT_PRESSURE updates without x/y updates.
    After about one mm of movement x/y updates resume, with the first event
    covering the distance between the last motion event. That event is usually
    accelerated and thus causes a large jump. Subsequent events are sufficiently
    fine-grained again.
    
    This patch counts the number of non-motion events. Once we hit 10 in a row, we
    mark the first motion update as non-dirty, effectively discarding the motion
    and thus stopping the pointer jumps.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=94379
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 00d6539..d0a8e27 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -337,7 +337,7 @@ tp_process_absolute(struct tp_dispatch *tp,
 	case ABS_MT_PRESSURE:
 		t->pressure = e->value;
 		t->dirty = true;
-		tp->queued |= TOUCHPAD_EVENT_MOTION;
+		tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
 		break;
 	}
 }
@@ -880,8 +880,10 @@ tp_position_fake_touches(struct tp_dispatch *tp)
 }
 
 static inline bool
-tp_need_motion_history_reset(struct tp_dispatch *tp)
+tp_need_motion_history_reset(struct tp_dispatch *tp, uint64_t time)
 {
+	bool rc = false;
+
 	/* semi-mt finger postions may "jump" when nfingers changes */
 	if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
 		return true;
@@ -894,7 +896,29 @@ tp_need_motion_history_reset(struct tp_dispatch *tp)
 		 tp->old_nfingers_down > tp->num_slots))
 		return true;
 
-	return false;
+	/* Quirk: if we had multiple events without x/y axis
+	   information, the next x/y event is going to be a jump. So we
+	   reset that touch to non-dirty effectively swallowing that event
+	   and restarting with the next event again.
+	 */
+	if (tp->device->model_flags & EVDEV_MODEL_LENOVO_T450_TOUCHPAD) {
+		if (tp->queued & TOUCHPAD_EVENT_MOTION) {
+			if (tp->quirks.nonmotion_event_count > 10) {
+				struct tp_touch *t;
+
+				tp_for_each_touch(tp, t)
+				t->dirty = false;
+				rc = true;
+			}
+			tp->quirks.nonmotion_event_count = 0;
+		}
+
+		if ((tp->queued & (TOUCHPAD_EVENT_OTHERAXIS|TOUCHPAD_EVENT_MOTION)) ==
+		    TOUCHPAD_EVENT_OTHERAXIS)
+			tp->quirks.nonmotion_event_count++;
+	}
+
+	return rc;
 }
 
 static void
@@ -909,7 +933,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
 	tp_unhover_touches(tp, time);
 	tp_position_fake_touches(tp);
 
-	want_motion_reset = tp_need_motion_history_reset(tp);
+	want_motion_reset = tp_need_motion_history_reset(tp, time);
 
 	for (i = 0; i < tp->ntouches; i++) {
 		t = tp_get_touch(tp, i);
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index eae327b..1f05a03 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -41,6 +41,7 @@ enum touchpad_event {
 	TOUCHPAD_EVENT_MOTION		= (1 << 0),
 	TOUCHPAD_EVENT_BUTTON_PRESS	= (1 << 1),
 	TOUCHPAD_EVENT_BUTTON_RELEASE	= (1 << 2),
+	TOUCHPAD_EVENT_OTHERAXIS	= (1 << 3),
 };
 
 enum touchpad_model {
@@ -353,6 +354,17 @@ struct tp_dispatch {
 		int upper_thumb_line;
 		int lower_thumb_line;
 	} thumb;
+
+	struct {
+		/* A quirk used on the T450 series Synaptics hardware.
+		 * Slowly moving the finger causes multiple events with only
+		 * ABS_MT_PRESSURE but no x/y information. When the x/y
+		 * event comes, it will be a jump of ~20 units. We use the
+		 * below to count non-motion events to discard that first
+		 * event with the jump.
+		 */
+		unsigned int nonmotion_event_count;
+	} quirks;
 };
 
 #define tp_for_each_touch(_tp, _t) \
diff --git a/src/evdev.c b/src/evdev.c
index 51768fe..a5c965d 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1680,6 +1680,7 @@ evdev_read_model_flags(struct evdev_device *device)
 		{ "LIBINPUT_MODEL_CYBORG_RAT", EVDEV_MODEL_CYBORG_RAT },
 		{ "LIBINPUT_MODEL_CYAPA", EVDEV_MODEL_CYAPA },
 		{ "LIBINPUT_MODEL_ALPS_RUSHMORE", EVDEV_MODEL_ALPS_RUSHMORE },
+		{ "LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD", EVDEV_MODEL_LENOVO_T450_TOUCHPAD },
 		{ NULL, EVDEV_MODEL_DEFAULT },
 	};
 	const struct model_map *m = model_map;
diff --git a/src/evdev.h b/src/evdev.h
index 482712b..4a5d807 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -113,6 +113,7 @@ enum evdev_device_model {
 	EVDEV_MODEL_CYBORG_RAT = (1 << 14),
 	EVDEV_MODEL_CYAPA = (1 << 15),
 	EVDEV_MODEL_ALPS_RUSHMORE = (1 << 16),
+	EVDEV_MODEL_LENOVO_T450_TOUCHPAD= (1 << 17),
 };
 
 struct mt_slot {
diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb
index eb2859e..d5978f7 100644
--- a/udev/90-libinput-model-quirks.hwdb
+++ b/udev/90-libinput-model-quirks.hwdb
@@ -100,6 +100,13 @@ libinput:name:Cypress APA Trackpad (cyapa):dmi:*
 libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX230*
  LIBINPUT_MODEL_LENOVO_X230=1
 
+# Lenovo T450/T460 and all other Lenovos of the *50 and *60 generation,
+# including the X1 Carbon 3rd gen
+libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPad??50*:
+libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPad??60*:
+libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX1Carbon3rd:*
+ LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD=1
+
 ##########################################
 # Synaptics
 ##########################################

commit 5d904b63191538b46d7fe8443990b55c42de0205
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Mar 7 10:12:13 2016 +1000

    tablet: reject mislabelled tablet devices
    
    The HUION 580 has a "consumer control" event node that has an ABS_VOLUME, keys
    and a REL_HWHEEL. It has the same VID/PID as the pen tablet and libwacom
    labels it as ID_INPUT_TABLET. This causes a crash later when we try to init
    pointer acceleration for a device that doesn't have axes.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1314955
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 0f6fa2c..7359881 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -1613,6 +1613,31 @@ tablet_init_left_handed(struct evdev_device *device)
 }
 
 static int
+tablet_reject_device(struct evdev_device *device)
+{
+	struct libevdev *evdev = device->evdev;
+	int rc = -1;
+
+	if (!libevdev_has_event_code(evdev, EV_ABS, ABS_X) ||
+	    !libevdev_has_event_code(evdev, EV_ABS, ABS_Y))
+		goto out;
+
+	if (!libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN))
+		goto out;
+
+	rc = 0;
+
+out:
+	if (rc) {
+		log_bug_libinput(device->base.seat->libinput,
+				 "Device '%s' does not meet tablet criteria. "
+				 "Ignoring this device.\n",
+				 device->devname);
+	}
+	return rc;
+}
+
+static int
 tablet_init(struct tablet_dispatch *tablet,
 	    struct evdev_device *device)
 {
@@ -1625,6 +1650,9 @@ tablet_init(struct tablet_dispatch *tablet,
 	tablet->current_tool_type = LIBINPUT_TOOL_NONE;
 	list_init(&tablet->tool_list);
 
+	if (tablet_reject_device(device))
+		return -1;
+
 	tablet_init_calibration(tablet, device);
 	tablet_init_proximity_threshold(tablet, device);
 	rc = tablet_init_accel(tablet, device);

commit b4a74bcebc8f1d37b2ed78db3440435ead03299a
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri Mar 4 07:50:49 2016 +1000

    Assert that the interface is actually filled in.
    
    Had this in a private bug report recently. Missing hooks for open/close just
    segfault with little information to debug. Add an assert, this is definitely a
    bug in the caller and we don't need to recover from that.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/src/libinput.c b/src/libinput.c
index 3c78905..1480878 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -1517,6 +1517,9 @@ libinput_init(struct libinput *libinput,
 	      const struct libinput_interface_backend *interface_backend,
 	      void *user_data)
 {
+	assert(interface->open_restricted != NULL);
+	assert(interface->close_restricted != NULL);
+
 	libinput->epoll_fd = epoll_create1(EPOLL_CLOEXEC);;
 	if (libinput->epoll_fd < 0)
 		return -1;
diff --git a/test/udev.c b/test/udev.c
index 30ae118..9296e94 100644
--- a/test/udev.c
+++ b/test/udev.c
@@ -52,7 +52,6 @@ const struct libinput_interface simple_interface = {
 START_TEST(udev_create_NULL)
 {
 	struct libinput *li;
-	const struct libinput_interface interface;
 	struct udev *udev;
 
 	udev = udev_new();
@@ -60,13 +59,13 @@ START_TEST(udev_create_NULL)
 	li = libinput_udev_create_context(NULL, NULL, NULL);
 	ck_assert(li == NULL);
 
-	li = libinput_udev_create_context(&interface, NULL, NULL);
+	li = libinput_udev_create_context(&simple_interface, NULL, NULL);
 	ck_assert(li == NULL);
 
 	li = libinput_udev_create_context(NULL, NULL, udev);
 	ck_assert(li == NULL);
 
-	li = libinput_udev_create_context(&interface, NULL, udev);
+	li = libinput_udev_create_context(&simple_interface, NULL, udev);
 	ck_assert(li != NULL);
 	ck_assert_int_eq(libinput_udev_assign_seat(li, NULL), -1);
 

commit 00a9b05da71c9071cc910a1c5975165f2a8db9c6
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Thu Mar 3 08:33:22 2016 +1000

    test: add two path tests for invalid devices
    
    One test for an actual file (so far we only tested /tmp, the directory) and
    one for a kernel dev that returns a udev device and thus gets one step further
    in the error handling code.
    
    Plus, I saw test code doing this (opening /dev/uinput) and it crashed (for
    other reasons), so we might as well test it.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/test/path.c b/test/path.c
index 0b04b19..7d7c445 100644
--- a/test/path.c
+++ b/test/path.c
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <libinput.h>
+#include <stdio.h>
 #include <unistd.h>
 
 #include "litest.h"
@@ -98,6 +99,63 @@ START_TEST(path_create_invalid)
 }
 END_TEST
 
+START_TEST(path_create_invalid_kerneldev)
+{
+	struct libinput *li;
+	struct libinput_device *device;
+	const char *path = "/dev/uinput";
+
+	open_func_count = 0;
+	close_func_count = 0;
+
+	li = libinput_path_create_context(&simple_interface, NULL);
+	ck_assert(li != NULL);
+	device = libinput_path_add_device(li, path);
+	ck_assert(device == NULL);
+
+	ck_assert_int_eq(open_func_count, 1);
+	ck_assert_int_eq(close_func_count, 1);
+
+	libinput_unref(li);
+	ck_assert_int_eq(close_func_count, 1);
+
+	open_func_count = 0;
+	close_func_count = 0;
+}
+END_TEST
+
+START_TEST(path_create_invalid_file)
+{
+	struct libinput *li;
+	struct libinput_device *device;
+	char path[] = "/tmp/litest_path_XXXXXX";
+	int fd;
+
+	fd = mkstemp(path);
+	ck_assert_int_ge(fd, 0);
+	close(fd);
+
+	open_func_count = 0;
+	close_func_count = 0;
+
+	li = libinput_path_create_context(&simple_interface, NULL);
+	unlink(path);
+
+	ck_assert(li != NULL);
+	device = libinput_path_add_device(li, path);
+	ck_assert(device == NULL);
+
+	ck_assert_int_eq(open_func_count, 0);
+	ck_assert_int_eq(close_func_count, 0);
+
+	libinput_unref(li);
+	ck_assert_int_eq(close_func_count, 0);
+
+	open_func_count = 0;
+	close_func_count = 0;
+}
+END_TEST
+
 START_TEST(path_create_destroy)
 {
 	struct libinput *li;
@@ -882,6 +940,8 @@ litest_setup_tests(void)
 {
 	litest_add_no_device("path:create", path_create_NULL);
 	litest_add_no_device("path:create", path_create_invalid);
+	litest_add_no_device("path:create", path_create_invalid_file);
+	litest_add_no_device("path:create", path_create_invalid_kerneldev);
 	litest_add_no_device("path:create", path_create_destroy);
 	litest_add_no_device("path:create", path_set_user_data);
 	litest_add_no_device("path:suspend", path_suspend);

commit a60afbeec39f7de4a03103dab26701b506dc93d0
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Mar 2 11:48:59 2016 +1000

    touchpad: use the udev property over a compile-time vendor ID check
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 95d650a..00d6539 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1299,7 +1299,7 @@ tp_dwt_device_is_blacklisted(struct evdev_device *device)
 		return true;
 
 	/* Wacom makes touchpads, but not internal ones */
-	if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_WACOM)
+	if (device->model_flags & EVDEV_MODEL_WACOM_TOUCHPAD)
 		return true;
 
 	return false;

commit 2bb0678a00f9c089dc865d6ecd20be36446d1c06
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Feb 10 09:24:51 2016 +1000

    tablet: sanitize button mask passing
    
    We have a struct, use it. Better than passing arrays and array lengths around.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 22ea1eb..0f6fa2c 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -38,34 +38,27 @@
 
 static inline void
 tablet_get_pressed_buttons(struct tablet_dispatch *tablet,
-			   unsigned char *buttons,
-			   unsigned int buttons_len)
+			   struct button_state *buttons)
 {
 	size_t i;
 	const struct button_state *state = &tablet->button_state,
 			          *prev_state = &tablet->prev_button_state;
 
-	assert(buttons_len <= ARRAY_LENGTH(state->stylus_buttons));
-
-	for (i = 0; i < buttons_len; i++)
-		buttons[i] = state->stylus_buttons[i] &
-					~(prev_state->stylus_buttons[i]);
+	for (i = 0; i < sizeof(buttons->bits); i++)
+		buttons->bits[i] = state->bits[i] & ~(prev_state->bits[i]);
 }
 
 static inline void
 tablet_get_released_buttons(struct tablet_dispatch *tablet,
-			    unsigned char *buttons,
-			    unsigned int buttons_len)
+			    struct button_state *buttons)
 {
 	size_t i;
 	const struct button_state *state = &tablet->button_state,
 			          *prev_state = &tablet->prev_button_state;
 
-	assert(buttons_len <= ARRAY_LENGTH(state->stylus_buttons));
-
-	for (i = 0; i < buttons_len; i++)
-		buttons[i] = prev_state->stylus_buttons[i] &
-					~(state->stylus_buttons[i]);
+	for (i = 0; i < sizeof(buttons->bits); i++)
+		buttons->bits[i] = prev_state->bits[i] &
+					~(state->bits[i]);
 }
 
 /* Merge the previous state with the current one so all buttons look like
@@ -77,10 +70,9 @@ tablet_force_button_presses(struct tablet_dispatch *tablet)
 			    *prev_state = &tablet->prev_button_state;
 	size_t i;
 
-	for (i = 0; i < sizeof(state->stylus_buttons); i++) {
-		state->stylus_buttons[i] = state->stylus_buttons[i] |
-						prev_state->stylus_buttons[i];
-		prev_state->stylus_buttons[i] = 0;
+	for (i = 0; i < sizeof(state->bits); i++) {
+		state->bits[i] = state->bits[i] | prev_state->bits[i];
+		prev_state->bits[i] = 0;
 	}
 }
 
@@ -566,10 +558,10 @@ tablet_update_button(struct tablet_dispatch *tablet,
 	}
 
 	if (enable) {
-		set_bit(tablet->button_state.stylus_buttons, evcode);
+		set_bit(tablet->button_state.bits, evcode);
 		tablet_set_status(tablet, TABLET_BUTTONS_PRESSED);
 	} else {
-		clear_bit(tablet->button_state.stylus_buttons, evcode);
+		clear_bit(tablet->button_state.bits, evcode);
 		tablet_set_status(tablet, TABLET_BUTTONS_RELEASED);
 	}
 }
@@ -936,20 +928,19 @@ tablet_notify_button_mask(struct tablet_dispatch *tablet,
 			  struct evdev_device *device,
 			  uint64_t time,
 			  struct libinput_tablet_tool *tool,
-			  const unsigned char *buttons,
-			  unsigned int buttons_len,
+			  const struct button_state *buttons,
 			  enum libinput_button_state state)
 {
 	struct libinput_device *base = &device->base;
 	size_t i;
-	size_t nbits = 8 * sizeof(buttons[0]) * buttons_len;
+	size_t nbits = 8 * sizeof(buttons->bits);
 	enum libinput_tablet_tool_tip_state tip_state;
 
 	tip_state = tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT) ?
 			LIBINPUT_TABLET_TOOL_TIP_DOWN : LIBINPUT_TABLET_TOOL_TIP_UP;
 
 	for (i = 0; i < nbits; i++) {
-		if (!bit_is_set(buttons, i))
+		if (!bit_is_set(buttons->bits, i))
 			continue;
 
 		tablet_notify_button(base,
@@ -969,21 +960,18 @@ tablet_notify_buttons(struct tablet_dispatch *tablet,
 		      struct libinput_tablet_tool *tool,
 		      enum libinput_button_state state)
 {
-	unsigned char buttons[ARRAY_LENGTH(tablet->button_state.stylus_buttons)];
+	struct button_state buttons;
 
 	if (state == LIBINPUT_BUTTON_STATE_PRESSED)
-		tablet_get_pressed_buttons(tablet, buttons, sizeof(buttons));
+		tablet_get_pressed_buttons(tablet, &buttons);
 	else
-		tablet_get_released_buttons(tablet,
-					    buttons,
-					    sizeof(buttons));
+		tablet_get_released_buttons(tablet, &buttons);
 
 	tablet_notify_button_mask(tablet,
 				  device,
 				  time,
 				  tool,
-				  buttons,
-				  sizeof(buttons),
+				  &buttons,
 				  state);
 }
 
@@ -1332,9 +1320,9 @@ tablet_flush(struct tablet_dispatch *tablet,
 
 	if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
 		/* Release all stylus buttons */
-		memset(tablet->button_state.stylus_buttons,
+		memset(tablet->button_state.bits,
 		       0,
-		       sizeof(tablet->button_state.stylus_buttons));
+		       sizeof(tablet->button_state.bits));
 		tablet_set_status(tablet, TABLET_BUTTONS_RELEASED);
 		if (tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT))
 			tablet_set_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index 1d6fc93..880d523 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -45,7 +45,7 @@ enum tablet_status {
 };
 
 struct button_state {
-	unsigned char stylus_buttons[NCHARS(KEY_CNT)];
+	unsigned char bits[NCHARS(KEY_CNT)];
 };
 
 struct tablet_dispatch {

commit 21fe11fb11a4d79aabb208f5839679a52a74678b
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri Feb 26 15:19:57 2016 +1000

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

diff --git a/configure.ac b/configure.ac
index d400f21..71255ed 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], [2])
-m4_define([libinput_micro_version], [0])
+m4_define([libinput_micro_version], [1])
 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=17:2:7
+LIBINPUT_LT_VERSION=17:3:7
 AC_SUBST(LIBINPUT_LT_VERSION)
 
 AM_SILENT_RULES([yes])

commit dbb85f67396ce47ca0fb66b610b3818f9a041ca0
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Feb 24 13:46:48 2016 +1000

    touchpad: only trigger immediate pinch detection for three fingers
    
    If the fingers are vertically apart by more than 20mm we used to assume a
    pinch gesture immediately. This is too close together for some users during
    two-finger scrolling. Since we should always bias towards scrolling, only
    trigger this detection for three fingers, the rest has to go through the
    movement detection.
    
    The reason for the pinch detection here was to differentiate from 3fg swipe
    gestures (83f3dbd1), hence we're still in spirit of that patch.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=94264
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Tested-by: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
    Reviewed-by: Hans de Goede <hdegoede@redhat.com>

diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c
index dc8d606..3c8f5a7 100644
--- a/src/evdev-mt-touchpad-gestures.c
+++ b/src/evdev-mt-touchpad-gestures.c
@@ -339,6 +339,7 @@ tp_gesture_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
 	/* Else check if one finger is > 20mm below the others */
 	vert_distance = abs(first->point.y - second->point.y);
 	if (vert_distance > 20 * yres &&
+	    tp->gesture.finger_count > 2 &&
 	    tp->gesture.enabled) {
 		tp_gesture_init_pinch(tp);
 		return GESTURE_STATE_PINCH;


Reply to: