[PATCH libinput] tablet: make the cursor/lens tool behave like a 1000dpi mouse

Peter Hutterer peter.hutterer at who-t.net
Mon Jun 27 04:53:01 UTC 2016


The current code tried to emulate the relative motion to be equivalent to the
absolute motion, except in screen coordinates. This is way too slow for the
cursor tool that we want to behave like a mouse.

Tablets have high resolution (e.g. an Intuos 4 is a 5080dpi mouse) and that
motion is way too fast to be usable. Scale it down to match a 1000dpi device
instead. Since the cursor and lens tool are still high precision devices leave
them in a flat acceleration profile without actual acceleration.

For the stylus-like devices leave the current accel, pointer acceleration on a
stylus is hard to handle.

This also adds the missing bits for actually using the speed factor set
through the config interface.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-tablet.c | 19 +++++++------
 src/filter.c       | 80 ++++++++++++++++++++++++++++++++++++++++++++++--------
 tools/Makefile.am  |  2 +-
 3 files changed, 80 insertions(+), 21 deletions(-)

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 395e5a0..940a1e0 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -386,22 +386,23 @@ tablet_handle_xy(struct tablet_dispatch *tablet,
 }
 
 static inline struct normalized_coords
-tablet_process_delta(struct tablet_dispatch *tablet,
-		     const struct evdev_device *device,
-		     const struct device_coords *delta,
-		     uint64_t time)
+tool_process_delta(struct libinput_tablet_tool *tool,
+		   const struct evdev_device *device,
+		   const struct device_coords *delta,
+		   uint64_t time)
 {
 	struct normalized_coords accel;
 
-	/* The tablet accel code uses mm as input */
-	accel.x = 1.0 * delta->x/device->abs.absinfo_x->resolution;
-	accel.y = 1.0 * delta->y/device->abs.absinfo_y->resolution;
+	accel.x = 1.0 * delta->x;
+	accel.y = 1.0 * delta->y;
 
 	if (normalized_is_zero(accel))
 		return accel;
 
 	return filter_dispatch(device->pointer.filter,
-			       &accel, tablet, time);
+			       &accel,
+			       tool,
+			       time);
 }
 
 static inline double
@@ -548,7 +549,7 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
 	axes.distance = tablet_handle_distance(tablet, device);
 	axes.slider = tablet_handle_slider(tablet, device);
 	axes.tilt = tablet_handle_tilt(tablet, device);
-	axes.delta = tablet_process_delta(tablet, device, &delta, time);
+	axes.delta = tool_process_delta(tool, device, &delta, time);
 
 	/* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are
 	 * already normalized and set if we have the mouse/lens tool */
diff --git a/src/filter.c b/src/filter.c
index cf8996d..0bb066c 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -168,6 +168,8 @@ struct tablet_accelerator_flat {
 
 	double factor;
 	int xres, yres;
+	double xres_scale, /* 1000dpi : tablet res */
+	       yres_scale; /* 1000dpi : tablet res */
 };
 
 static void
@@ -972,17 +974,39 @@ create_pointer_accelerator_filter_flat(int dpi)
 	return &filter->base;
 }
 
-/* The tablet accel code uses mm as input */
+static inline struct normalized_coords
+tablet_accelerator_filter_flat_mouse(struct tablet_accelerator_flat *filter,
+				     const struct normalized_coords *units)
+{
+	struct normalized_coords accelerated;
+
+	/*
+	   The input for and output of accel methods is usually a delta in
+	   1000dpi equivalents. Tablets are high res (Intuos 4 is 5080 dpi)
+	   and unmodified deltas are way too high. Slow it down to the
+	   equivalent of a 1000dpi mouse. The ratio of that is:
+		ratio = 1000/(resolution_per_mm * 25.4)
+
+	   i.e. on the Intuos4 it's a ratio of ~1/5.
+
+	 */
+
+	accelerated.x = units->x * filter->xres_scale;
+	accelerated.y = units->y * filter->yres_scale;
+
+	accelerated.x *= filter->factor;
+	accelerated.y *= filter->factor;
+
+	return accelerated;
+}
+
 static struct normalized_coords
-tablet_accelerator_filter_flat(struct motion_filter *filter,
-			       const struct normalized_coords *mm,
-			       void *data, uint64_t time)
+tablet_accelerator_filter_flat_pen(struct tablet_accelerator_flat *filter,
+				   const struct normalized_coords *units)
 {
-	struct tablet_accelerator_flat *accel_filter =
-		(struct tablet_accelerator_flat *)filter;
 	struct normalized_coords accelerated;
 
-	/* Tablet input is in mm, output is supposed to be in logical
+	/* Tablet input is in device units, output is supposed to be in logical
 	 * pixels roughly equivalent to a mouse/touchpad.
 	 *
 	 * This is a magical constant found by trial and error. On a 96dpi
@@ -990,12 +1014,43 @@ tablet_accelerator_filter_flat(struct motion_filter *filter,
 	 * is almost identical to the tablet mapped to screen in absolute
 	 * mode. Tested on a Intuos5, other tablets may vary.
 	 */
-	const double DPI_CONVERSION = 96.0/25.4 * 2.5; /* unitless factor */
+       const double DPI_CONVERSION = 96.0/25.4 * 2.5; /* unitless factor */
+       struct normalized_coords mm;
 
-	accelerated.x = mm->x * accel_filter->factor * DPI_CONVERSION;
-	accelerated.y = mm->y * accel_filter->factor * DPI_CONVERSION;
+       mm.x = 1.0 * units->x/filter->xres;
+       mm.y = 1.0 * units->y/filter->yres;
+       accelerated.x = mm.x * filter->factor * DPI_CONVERSION;
+       accelerated.y = mm.y * filter->factor * DPI_CONVERSION;
 
-	return accelerated;
+       return accelerated;
+}
+
+static struct normalized_coords
+tablet_accelerator_filter_flat(struct motion_filter *filter,
+			       const struct normalized_coords *units,
+			       void *data, uint64_t time)
+{
+	struct tablet_accelerator_flat *accel_filter =
+		(struct tablet_accelerator_flat *)filter;
+	struct libinput_tablet_tool *tool = (struct libinput_tablet_tool*)data;
+	enum libinput_tablet_tool_type type;
+	struct normalized_coords accel;
+
+	type = libinput_tablet_tool_get_type(tool);
+
+	switch (type) {
+	case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
+	case LIBINPUT_TABLET_TOOL_TYPE_LENS:
+		accel = tablet_accelerator_filter_flat_mouse(accel_filter,
+							     units);
+		break;
+	default:
+		accel = tablet_accelerator_filter_flat_pen(accel_filter,
+							   units);
+		break;
+	}
+
+	return accel;
 }
 
 static bool
@@ -1039,8 +1094,11 @@ create_tablet_filter_flat(int xres, int yres)
 	if (filter == NULL)
 		return NULL;
 
+	filter->factor = 1.0;
 	filter->xres = xres;
 	filter->yres = yres;
+	filter->xres_scale = DEFAULT_MOUSE_DPI/(25.4 * xres);
+	filter->yres_scale = DEFAULT_MOUSE_DPI/(25.4 * yres);
 
 	return filter;
 }
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 8f72db9..5fe169c 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -18,7 +18,7 @@ event_debug_LDFLAGS = -no-install
 event_debug_CFLAGS = $(LIBUDEV_CFLAGS) $(LIBEVDEV_CFLAGS)
 
 ptraccel_debug_SOURCES = ptraccel-debug.c
-ptraccel_debug_LDADD = ../src/libfilter.la
+ptraccel_debug_LDADD = ../src/libfilter.la ../src/libinput.la
 ptraccel_debug_LDFLAGS = -no-install
 
 libinput_list_devices_SOURCES = libinput-list-devices.c
-- 
2.7.4



More information about the wayland-devel mailing list