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

Jason Gerecke killertofu at gmail.com
Mon Jun 27 19:54:55 UTC 2016


On 06/26/2016 09:53 PM, Peter Hutterer wrote:
> 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>

Looks good to me --
Reviewed-by: Jason Gerecke <jason.gerecke at wacom.com>

> ---
>  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
> 


-- 
Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....


More information about the wayland-devel mailing list