[PATCH v2 libinput] tablet: support tool-specific pressure offsets

Peter Hutterer peter.hutterer at who-t.net
Thu Dec 10 01:31:52 PST 2015


If a tool wears out, it may have a pre-loaded pressure offset. In that case,
even when the tool is not physically in contact with the tablet surface it
will send pressure events.

Use automatic pressure offset detection, similar to what the X.Org wacom
driver does. On proximity-in, check the pressure and if the distance is above
50% of the range and the pressure is nonzero but below 20% of the range, use
that value as pressure offset.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Changes to v1:
- don't use a static udev property, try to detect the offset on proximity in

 doc/tablet-support.dox                   |  29 +++
 src/evdev-tablet.c                       |  84 ++++++++-
 src/evdev-tablet.h                       |  21 +++
 src/libinput-private.h                   |   2 +
 test/litest-device-wacom-intuos-tablet.c |   1 +
 test/tablet.c                            | 313 ++++++++++++++++++++++++++++++-
 6 files changed, 446 insertions(+), 4 deletions(-)

diff --git a/doc/tablet-support.dox b/doc/tablet-support.dox
index 24d08d2..5468c6f 100644
--- a/doc/tablet-support.dox
+++ b/doc/tablet-support.dox
@@ -92,4 +92,33 @@ if (value < min) {
 }
 @endcode
 
+ at section tablet-pressure-offset Pressure offset on worn-out tools
+
+When a tool is used for an extended period it can wear down physically. A
+worn-down tool may never return a zero pressure value. Even when hovering
+above the surface, the pressure value returned by the tool is nonzero,
+creating a fake surface touch and making interaction with the tablet less
+predictable.
+
+libinput automatically detects pressure offsets and rescales the remaining
+pressure range into the available range, making pressure-offsets transparent
+to the caller. A tool with a pressure offset will thus send a 0 pressure
+value for the detected offset and nonzero pressure values for values higher
+than that offset.
+
+Some limitations apply to avoid misdetection of pressure offsets,
+specifically:
+- pressure offset is only detected on proximity in, and if a device is
+  capable of detection distances,
+- pressure offset is only detected if the distance between the tool and the
+  tablet is high enough,
+- pressure offset is only used if it is 20% or less of the pressure range
+  available to the tool. A pressure offset higher than 20% indicates either
+  a misdetection or a tool that should be replaced, and
+- if a pressure value less than the current pressure offset is seen, the
+  offset resets to that value.
+
+Pressure offsets are not detected on @ref LIBINPUT_TABLET_TOOL_TYPE_MOUSE
+and @ref LIBINPUT_TABLET_TOOL_TYPE_LENS tools.
+
 */
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index cd208a8..909cc76 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -21,9 +21,11 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 #include "config.h"
+#include "libinput-version.h"
 #include "evdev-tablet.h"
 
 #include <assert.h>
+#include <inttypes.h>
 #include <stdbool.h>
 #include <string.h>
 
@@ -202,7 +204,7 @@ tablet_update_tool(struct tablet_dispatch *tablet,
 }
 
 static inline double
-normalize_pressure_dist_slider(const struct input_absinfo *absinfo)
+normalize_dist_slider(const struct input_absinfo *absinfo)
 {
 	double range = absinfo->maximum - absinfo->minimum;
 	double value = (absinfo->value - absinfo->minimum) / range;
@@ -211,6 +213,18 @@ normalize_pressure_dist_slider(const struct input_absinfo *absinfo)
 }
 
 static inline double
+normalize_pressure(const struct input_absinfo *absinfo,
+		   struct libinput_tablet_tool *tool)
+{
+	double range = absinfo->maximum - absinfo->minimum;
+	int offset = tool->pressure_offset != INT_MIN ?
+			tool->pressure_offset : 0;
+	double value = (absinfo->value - offset - absinfo->minimum) / range;
+
+	return value;
+}
+
+static inline double
 normalize_tilt(const struct input_absinfo *absinfo)
 {
 	double range = absinfo->maximum - absinfo->minimum;
@@ -405,10 +419,12 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
 			else
 				tablet->axes[a] = absinfo->value;
 			break;
-		case LIBINPUT_TABLET_TOOL_AXIS_DISTANCE:
 		case LIBINPUT_TABLET_TOOL_AXIS_PRESSURE:
+			tablet->axes[a] = normalize_pressure(absinfo, tool);
+			break;
+		case LIBINPUT_TABLET_TOOL_AXIS_DISTANCE:
 		case LIBINPUT_TABLET_TOOL_AXIS_SLIDER:
-			tablet->axes[a] = normalize_pressure_dist_slider(absinfo);
+			tablet->axes[a] = normalize_dist_slider(absinfo);
 			break;
 		case LIBINPUT_TABLET_TOOL_AXIS_TILT_X:
 		case LIBINPUT_TABLET_TOOL_AXIS_TILT_Y:
@@ -816,6 +832,7 @@ tablet_get_tool(struct tablet_dispatch *tablet,
 			.refcount = 1,
 		};
 
+		tool->pressure_offset = INT_MIN;
 		tool_set_bits(tablet, tool);
 
 		list_insert(tool_list, &tool->link);
@@ -929,6 +946,66 @@ sanitize_tablet_axes(struct tablet_dispatch *tablet)
 		set_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z);
 }
 
+static inline int
+axis_range_percentage(const struct input_absinfo *a, int percent)
+{
+	return (a->maximum - a->minimum) * percent/100 + a->minimum;
+}
+
+static void
+detect_pressure_offset(struct tablet_dispatch *tablet,
+		       struct evdev_device *device,
+		       struct libinput_tablet_tool *tool)
+{
+	const struct input_absinfo *pressure, *distance;
+	int offset;
+
+	if (!bit_is_set(tablet->changed_axes,
+			LIBINPUT_TABLET_TOOL_AXIS_PRESSURE))
+		return;
+
+	pressure = libevdev_get_abs_info(device->evdev, ABS_PRESSURE);
+	distance = libevdev_get_abs_info(device->evdev, ABS_DISTANCE);
+
+	if (!pressure || !distance)
+		return;
+
+	offset = pressure->value - pressure->minimum;
+
+	if (tool->pressure_offset != INT_MIN) {
+		if (offset < tool->pressure_offset)
+			tool->pressure_offset = offset;
+		return;
+	}
+
+	/* we only set a pressure offset on proximity in */
+	if (!tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY))
+		return;
+
+	/* If we're closer than 50% of the distance axis, skip pressure
+	 * offset detection, too likely to be wrong */
+	if (distance->value < axis_range_percentage(distance, 50))
+		return;
+
+	if (offset > axis_range_percentage(pressure, 20)) {
+		log_error(device->base.seat->libinput,
+			 "Ignoring pressure offset greater than 20%% detected on tool %s (serial %#x). "
+			 "See http://wayland.freedesktop.org/libinput/doc/%s/tablet-support.html\n",
+			 tablet_tool_type_to_string(tool->type),
+			 tool->serial,
+			 LIBINPUT_VERSION);
+		return;
+	}
+
+	log_info(device->base.seat->libinput,
+		 "Pressure offset detected on tool %s (serial %#x).  "
+		 "See http://wayland.freedesktop.org/libinput/doc/%s/tablet-support.html\n",
+		 tablet_tool_type_to_string(tool->type),
+		 tool->serial,
+		 LIBINPUT_VERSION);
+	tool->pressure_offset = offset;
+}
+
 static void
 tablet_flush(struct tablet_dispatch *tablet,
 	     struct evdev_device *device,
@@ -953,6 +1030,7 @@ tablet_flush(struct tablet_dispatch *tablet,
 			tablet_set_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
 	} else if (tablet_has_status(tablet, TABLET_AXES_UPDATED) ||
 		   tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY)) {
+		detect_pressure_offset(tablet, device, tool);
 		sanitize_tablet_axes(tablet);
 		tablet_check_notify_axes(tablet, device, time, tool);
 
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index 162b536..4dcbccc 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -178,4 +178,25 @@ tablet_tool_to_evcode(enum libinput_tablet_tool_type type)
 
 	return code;
 }
+
+static inline const char *
+tablet_tool_type_to_string(enum libinput_tablet_tool_type type)
+{
+	const char *str;
+
+	switch (type) {
+	case LIBINPUT_TABLET_TOOL_TYPE_PEN:	  str = "pen";		break;
+	case LIBINPUT_TABLET_TOOL_TYPE_ERASER:	  str = "eraser";	break;
+	case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:	  str = "brush";	break;
+	case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:	  str = "pencil";	break;
+	case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:  str = "airbrush";	break;
+	case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:	  str = "mouse";	break;
+	case LIBINPUT_TABLET_TOOL_TYPE_LENS:	  str = "lens";		break;
+	default:
+		abort();
+	}
+
+	return str;
+}
+
 #endif
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 38a14b8..091fd98 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -259,6 +259,8 @@ struct libinput_tablet_tool {
 	unsigned char buttons[NCHARS(KEY_MAX) + 1];
 	int refcount;
 	void *user_data;
+
+	int pressure_offset;
 };
 
 struct libinput_event {
diff --git a/test/litest-device-wacom-intuos-tablet.c b/test/litest-device-wacom-intuos-tablet.c
index e0e1d44..ef0a1f1 100644
--- a/test/litest-device-wacom-intuos-tablet.c
+++ b/test/litest-device-wacom-intuos-tablet.c
@@ -37,6 +37,7 @@ static struct input_event proximity_in[] = {
 	{ .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_DISTANCE, .value = LITEST_AUTO_ASSIGN },
+	{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
 	{ .type = EV_ABS, .code = ABS_TILT_X, .value = LITEST_AUTO_ASSIGN },
 	{ .type = EV_ABS, .code = ABS_TILT_Y, .value = LITEST_AUTO_ASSIGN },
 	{ .type = EV_ABS, .code = ABS_MISC, .value = 1050626 },
diff --git a/test/tablet.c b/test/tablet.c
index 18f08b2..9cfc42f 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -2313,7 +2313,7 @@ START_TEST(tablet_pressure_distance_exclusive)
 	struct libinput_event_tablet_tool *tev;
 	struct axis_replacement axes[] = {
 		{ ABS_DISTANCE, 10 },
-		{ ABS_PRESSURE, 20 },
+		{ ABS_PRESSURE, 20 }, /* see the litest device */
 		{ -1, -1 },
 	};
 	double pressure, distance;
@@ -2530,6 +2530,310 @@ START_TEST(tablet_calibration_set_matrix)
 }
 END_TEST
 
+START_TEST(tablet_pressure_offset)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_tablet_tool *tev;
+	struct axis_replacement axes[] = {
+		{ ABS_DISTANCE, 70 },
+		{ ABS_PRESSURE, 20 },
+		{ -1, -1 },
+	};
+	double pressure;
+
+	litest_tablet_proximity_in(dev, 5, 100, axes);
+	litest_drain_events(li);
+
+	axes[0].value = 0;
+	axes[1].value = 21;
+	litest_push_event_frame(dev);
+	litest_tablet_motion(dev, 70, 70, axes);
+	litest_event(dev, EV_KEY, BTN_TOUCH, 1);
+	litest_pop_event_frame(dev);
+	libinput_dispatch(li);
+	litest_drain_events(li);
+
+	axes[1].value = 20;
+	litest_tablet_motion(dev, 70, 70, axes);
+	libinput_dispatch(li);
+
+	event = libinput_get_event(li);
+	tev = litest_is_tablet_event(event,
+				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+	ck_assert_double_eq(pressure, 0.0);
+
+	libinput_event_destroy(event);
+	litest_drain_events(li);
+
+	axes[1].value = 21;
+	litest_tablet_motion(dev, 70, 70, axes);
+
+	libinput_dispatch(li);
+	event = libinput_get_event(li);
+	tev = litest_is_tablet_event(event,
+				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+
+	/* can't use the double_eq here, the pressure value is too tiny */
+	ck_assert(pressure > 0.0);
+	ck_assert(pressure < 1.0);
+	libinput_event_destroy(event);
+}
+END_TEST
+
+START_TEST(tablet_pressure_offset_decrease)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_tablet_tool *tev;
+	struct axis_replacement axes[] = {
+		{ ABS_DISTANCE, 70 },
+		{ ABS_PRESSURE, 20 },
+		{ -1, -1 },
+	};
+	double pressure;
+
+	/* offset 20 on prox in */
+	litest_tablet_proximity_in(dev, 5, 100, axes);
+	litest_drain_events(li);
+
+	/* a reduced pressure value must reduce the offset */
+	axes[0].value = 0;
+	axes[1].value = 10;
+	litest_push_event_frame(dev);
+	litest_tablet_motion(dev, 70, 70, axes);
+	litest_event(dev, EV_KEY, BTN_TOUCH, 1);
+	litest_pop_event_frame(dev);
+	libinput_dispatch(li);
+
+	event = libinput_get_event(li);
+	tev = litest_is_tablet_event(event,
+				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+	ck_assert_double_eq(pressure, 0.0);
+
+	libinput_event_destroy(event);
+	litest_drain_events(li);
+
+	axes[1].value = 11;
+	litest_tablet_motion(dev, 70, 70, axes);
+	libinput_dispatch(li);
+
+	event = libinput_get_event(li);
+	tev = litest_is_tablet_event(event,
+				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+
+	/* can't use the double_eq here, the pressure value is too tiny */
+	ck_assert(pressure > 0.0);
+	ck_assert(pressure < 1.0);
+	libinput_event_destroy(event);
+}
+END_TEST
+
+START_TEST(tablet_pressure_offset_increase)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_tablet_tool *tev;
+	struct axis_replacement axes[] = {
+		{ ABS_DISTANCE, 70 },
+		{ ABS_PRESSURE, 20 },
+		{ -1, -1 },
+	};
+	double pressure;
+
+	/* offset 20 on first prox in */
+	litest_tablet_proximity_in(dev, 5, 100, axes);
+	litest_tablet_proximity_out(dev);
+	litest_drain_events(li);
+
+	/* offset 30 on second prox in - must not change the offset */
+	axes[1].value = 30;
+	litest_tablet_proximity_in(dev, 5, 100, axes);
+	litest_drain_events(li);
+
+	axes[0].value = 0;
+	axes[1].value = 31;
+	litest_push_event_frame(dev);
+	litest_tablet_motion(dev, 70, 70, axes);
+	litest_event(dev, EV_KEY, BTN_TOUCH, 1);
+	litest_pop_event_frame(dev);
+	libinput_dispatch(li);
+	litest_drain_events(li);
+
+	axes[1].value = 30;
+	litest_tablet_motion(dev, 70, 70, axes);
+	libinput_dispatch(li);
+
+	event = libinput_get_event(li);
+	tev = litest_is_tablet_event(event,
+				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+	/* can't use the double_eq here, the pressure value is too tiny */
+	ck_assert(pressure > 0.0);
+	ck_assert(pressure < 1.0);
+	libinput_event_destroy(event);
+
+	litest_drain_events(li);
+
+	axes[1].value = 20;
+	litest_tablet_motion(dev, 70, 70, axes);
+	libinput_dispatch(li);
+
+	event = libinput_get_event(li);
+	tev = litest_is_tablet_event(event,
+				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+
+	ck_assert_double_eq(pressure, 0.0);
+	libinput_event_destroy(event);
+}
+END_TEST
+
+START_TEST(tablet_pressure_offset_exceed_threshold)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_tablet_tool *tev;
+	struct axis_replacement axes[] = {
+		{ ABS_DISTANCE, 70 },
+		{ ABS_PRESSURE, 30 },
+		{ -1, -1 },
+	};
+	double pressure;
+
+	litest_drain_events(li);
+
+	litest_disable_log_handler(li);
+	litest_tablet_proximity_in(dev, 5, 100, axes);
+	libinput_dispatch(li);
+	event = libinput_get_event(li);
+	tev = litest_is_tablet_event(event,
+				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+	ck_assert_double_eq(pressure, 0.0);
+	libinput_event_destroy(event);
+	litest_restore_log_handler(li);
+
+	axes[0].value = 0;
+	axes[1].value = 31;
+	litest_push_event_frame(dev);
+	litest_tablet_motion(dev, 70, 70, axes);
+	litest_event(dev, EV_KEY, BTN_TOUCH, 1);
+	litest_pop_event_frame(dev);
+	libinput_dispatch(li);
+	litest_drain_events(li);
+
+	axes[1].value = 30;
+	litest_tablet_motion(dev, 70, 70, axes);
+	libinput_dispatch(li);
+
+	event = libinput_get_event(li);
+	tev = litest_is_tablet_event(event,
+				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+	ck_assert_double_gt(pressure, 0.0);
+
+	libinput_event_destroy(event);
+}
+END_TEST
+
+START_TEST(tablet_pressure_offset_none_for_zero_distance)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_tablet_tool *tev;
+	struct axis_replacement axes[] = {
+		{ ABS_DISTANCE, 0 },
+		{ ABS_PRESSURE, 20 },
+		{ -1, -1 },
+	};
+	double pressure;
+
+	litest_drain_events(li);
+
+	/* we're going straight to touch on proximity, make sure we don't
+	 * offset the pressure here */
+	litest_push_event_frame(dev);
+	litest_tablet_proximity_in(dev, 5, 100, axes);
+	litest_event(dev, EV_KEY, BTN_TOUCH, 1);
+	litest_pop_event_frame(dev);
+	libinput_dispatch(li);
+
+	event = libinput_get_event(li);
+	tev = litest_is_tablet_event(event,
+				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+	ck_assert_double_gt(pressure, 0.0);
+
+	libinput_event_destroy(event);
+}
+END_TEST
+
+START_TEST(tablet_pressure_offset_none_for_small_distance)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct libinput_event *event;
+	struct libinput_event_tablet_tool *tev;
+	struct axis_replacement axes[] = {
+		{ ABS_DISTANCE, 20 },
+		{ ABS_PRESSURE, 20 },
+		{ -1, -1 },
+	};
+	double pressure;
+
+	/* stylus too close to the tablet on the proximity in, ignore any
+	 * pressure offset */
+	litest_tablet_proximity_in(dev, 5, 100, axes);
+	litest_drain_events(li);
+	libinput_dispatch(li);
+
+	axes[0].value = 0;
+	axes[1].value = 21;
+	litest_push_event_frame(dev);
+	litest_tablet_motion(dev, 70, 70, axes);
+	litest_event(dev, EV_KEY, BTN_TOUCH, 1);
+	litest_pop_event_frame(dev);
+	litest_drain_events(li);
+
+	axes[1].value = 20;
+	litest_tablet_motion(dev, 70, 70, axes);
+	libinput_dispatch(li);
+
+	litest_wait_for_event_of_type(li,
+				      LIBINPUT_EVENT_TABLET_TOOL_AXIS,
+				      -1);
+	event = libinput_get_event(li);
+	tev = libinput_event_get_tablet_tool_event(event);
+	pressure = libinput_event_tablet_tool_get_axis_value(tev,
+							     LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
+	ck_assert_double_gt(pressure, 0.0);
+
+	libinput_event_destroy(event);
+}
+END_TEST
+
 void
 litest_setup_tests(void)
 {
@@ -2578,4 +2882,11 @@ litest_setup_tests(void)
 	litest_add("tablet:calibration", tablet_calibration_has_matrix, LITEST_TABLET, LITEST_ANY);
 	litest_add("tablet:calibration", tablet_calibration_set_matrix, LITEST_TABLET, LITEST_ANY);
 	litest_add("tablet:calibration", tablet_calibration_set_matrix_delta, LITEST_TABLET, LITEST_ANY);
+
+	litest_add_for_device("tablet:pressure", tablet_pressure_offset, LITEST_WACOM_INTUOS);
+	litest_add_for_device("tablet:pressure", tablet_pressure_offset_decrease, LITEST_WACOM_INTUOS);
+	litest_add_for_device("tablet:pressure", tablet_pressure_offset_increase, LITEST_WACOM_INTUOS);
+	litest_add_for_device("tablet:pressure", tablet_pressure_offset_exceed_threshold, LITEST_WACOM_INTUOS);
+	litest_add_for_device("tablet:pressure", tablet_pressure_offset_none_for_zero_distance, LITEST_WACOM_INTUOS);
+	litest_add_for_device("tablet:pressure", tablet_pressure_offset_none_for_small_distance, LITEST_WACOM_INTUOS);
 }
-- 
2.5.0



More information about the wayland-devel mailing list