[PATCH libinput 2/8 v2] tablet: Add a left handed mode and tests

Peter Hutterer peter.hutterer at who-t.net
Tue Feb 17 14:32:14 PST 2015


On Mon, Feb 16, 2015 at 10:48:40PM -0500, Stephen Chandler Paul wrote:
> On the majority of Wacom tablets, the buttons are on the left side, opposite of
> the side where the palm is meant to rest. Because of this, it's impossible to
> use the tablet with your left hand (comfortably, anyway) unless you flip it
> over, in which case the coordinates need to be inverted for it to match up with
> the screen properly. This is where left handed mode comes in. When enabled, it
> reverses all the coordinates so that the tablet may be rotated, and the palm
> rest on the tablet moved over to the left side.
> 
> Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>

thanks, merged with two minor additions to the test case, I added two
wait_for_event_of_type to make sure we don't accidentally skip over the
loop.

Cheers,
   Peter

> 
> ---
>  src/evdev-tablet.c |  29 +++++++++++++-
>  test/tablet.c      | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 136 insertions(+), 1 deletion(-)
> 
>                                     Changes
> - Fixed some indenting in test/tablet.c so that the line splitting was easier to
>   notice
> - Reworked the tests so that they make more sense. We now go with something
>   similar to what whot suggested: going bottom left to right, etc.
> 
> diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
> index 3d8363c..6a1b60c 100644
> --- a/src/evdev-tablet.c
> +++ b/src/evdev-tablet.c
> @@ -86,6 +86,21 @@ tablet_mark_all_axes_changed(struct tablet_dispatch *tablet,
>  }
>  
>  static void
> +tablet_change_to_left_handed(struct evdev_device *device)
> +{
> +	struct tablet_dispatch *tablet =
> +		(struct tablet_dispatch*)device->dispatch;
> +
> +	if (device->left_handed.enabled == device->left_handed.want_enabled)
> +		return;
> +
> +	if (!tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))
> +		return;
> +
> +	device->left_handed.enabled = device->left_handed.want_enabled;
> +}
> +
> +static void
>  tablet_update_tool(struct tablet_dispatch *tablet,
>  		   struct evdev_device *device,
>  		   enum libinput_tool_type tool,
> @@ -120,6 +135,11 @@ normalize_tilt(const struct input_absinfo * absinfo) {
>  	return (value * 2) - 1;
>  }
>  
> +static inline int32_t
> +invert_axis(const struct input_absinfo *absinfo) {
> +	return absinfo->maximum - (absinfo->value - absinfo->minimum);
> +}
> +
>  static void
>  tablet_check_notify_axes(struct tablet_dispatch *tablet,
>  			 struct evdev_device *device,
> @@ -142,7 +162,10 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet,
>  		switch (a) {
>  		case LIBINPUT_TABLET_AXIS_X:
>  		case LIBINPUT_TABLET_AXIS_Y:
> -			tablet->axes[a] = absinfo->value;
> +			if (device->left_handed.enabled)
> +				tablet->axes[a] = invert_axis(absinfo);
> +			else
> +				tablet->axes[a] = absinfo->value;
>  			break;
>  		case LIBINPUT_TABLET_AXIS_DISTANCE:
>  		case LIBINPUT_TABLET_AXIS_PRESSURE:
> @@ -481,6 +504,8 @@ tablet_flush(struct tablet_dispatch *tablet,
>  					    tablet->axes);
>  		tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
>  		tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
> +
> +		tablet_change_to_left_handed(device);
>  	}
>  
>  	/* Update state */
> @@ -585,5 +610,7 @@ evdev_tablet_create(struct evdev_device *device)
>  		return NULL;
>  	}
>  
> +	evdev_init_left_handed(device, tablet_change_to_left_handed);
> +
>  	return &tablet->base;
>  }
> diff --git a/test/tablet.c b/test/tablet.c
> index c38302a..baf36f4 100644
> --- a/test/tablet.c
> +++ b/test/tablet.c
> @@ -243,6 +243,113 @@ START_TEST(motion)
>  }
>  END_TEST
>  
> +START_TEST(left_handed)
> +{
> +	struct litest_device *dev = litest_current_device();
> +	struct libinput *li = dev->libinput;
> +	struct libinput_event *event;
> +	struct libinput_event_tablet *tablet_event;
> +	double libinput_max_x, libinput_max_y;
> +	double last_x, last_y;
> +	struct axis_replacement axes[] = {
> +		{ ABS_DISTANCE, 10 },
> +		{ -1, -1 }
> +	};
> +
> +	ck_assert(libinput_device_config_left_handed_is_available(dev->libinput_device));
> +
> +	libinput_device_get_size (dev->libinput_device,
> +				  &libinput_max_x,
> +				  &libinput_max_y);
> +
> +	/* Test that left-handed mode doesn't go into effect until the tool has
> +	 * left proximity of the tablet. In order to test this, we have to bring
> +	 * the tool into proximity and make sure libinput processes the
> +	 * proximity events so that it updates it's internal tablet state, and
> +	 * then try setting it to left-handed mode. */
> +	litest_tablet_proximity_in(dev, 0, 100, axes);
> +	libinput_dispatch(li);
> +	libinput_device_config_left_handed_set(dev->libinput_device, 1);
> +
> +	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TABLET_AXIS, -1);
> +
> +	while ((event = libinput_get_event(li))) {
> +		tablet_event = libinput_event_get_tablet_event(event);
> +
> +		last_x = libinput_event_tablet_get_axis_value(
> +				tablet_event, LIBINPUT_TABLET_AXIS_X);
> +		last_y = libinput_event_tablet_get_axis_value(
> +				tablet_event, LIBINPUT_TABLET_AXIS_Y);
> +
> +		litest_assert_double_eq(last_x, 0);
> +		litest_assert_double_eq(last_y, libinput_max_y);
> +
> +		libinput_event_destroy(event);
> +	}
> +
> +	litest_tablet_motion(dev, 100, 0, axes);
> +
> +	while ((event = libinput_get_event(li))) {
> +		double x, y;
> +		tablet_event = libinput_event_get_tablet_event(event);
> +
> +		x = libinput_event_tablet_get_axis_value(
> +			tablet_event, LIBINPUT_TABLET_AXIS_X);
> +		y = libinput_event_tablet_get_axis_value(
> +			tablet_event, LIBINPUT_TABLET_AXIS_Y);
> +
> +		litest_assert_double_eq(x, libinput_max_x);
> +		litest_assert_double_eq(y, 0);
> +
> +		litest_assert_double_gt(x, last_x);
> +		litest_assert_double_lt(y, last_y);
> +	}
> +
> +	litest_tablet_proximity_out(dev);
> +	litest_drain_events(li);
> +
> +	/* Since we've drained the events and libinput's aware the tool is out
> +	 * of proximity, it should have finally transitioned into left-handed
> +	 * mode, so the axes should be inverted once we bring it back into
> +	 * proximity */
> +	litest_tablet_proximity_in(dev, 0, 100, axes);
> +
> +	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TABLET_AXIS, -1);
> +
> +	while ((event = libinput_get_event(li))) {
> +		tablet_event = libinput_event_get_tablet_event(event);
> +
> +		last_x = libinput_event_tablet_get_axis_value(
> +				tablet_event, LIBINPUT_TABLET_AXIS_X);
> +		last_y = libinput_event_tablet_get_axis_value(
> +				tablet_event, LIBINPUT_TABLET_AXIS_Y);
> +
> +		litest_assert_double_eq(last_x, libinput_max_x);
> +		litest_assert_double_eq(last_y, 0);
> +
> +		libinput_event_destroy(event);
> +	}
> +
> +	litest_tablet_motion(dev, 100, 0, axes);
> +
> +	while ((event = libinput_get_event(li))) {
> +		double x, y;
> +		tablet_event = libinput_event_get_tablet_event(event);
> +
> +		x = libinput_event_tablet_get_axis_value(
> +			tablet_event, LIBINPUT_TABLET_AXIS_X);
> +		y = libinput_event_tablet_get_axis_value(
> +			tablet_event, LIBINPUT_TABLET_AXIS_Y);
> +
> +		litest_assert_double_eq(x, 0);
> +		litest_assert_double_eq(y, libinput_max_y);
> +
> +		litest_assert_double_lt(x, last_x);
> +		litest_assert_double_gt(y, last_y);
> +	}
> +}
> +END_TEST
> +
>  START_TEST(motion_event_state)
>  {
>  	struct litest_device *dev = litest_current_device();
> @@ -873,6 +980,7 @@ main(int argc, char **argv)
>  	litest_add("tablet:proximity", bad_distance_events, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
>  	litest_add("tablet:motion", motion, LITEST_TABLET, LITEST_ANY);
>  	litest_add("tablet:motion", motion_event_state, LITEST_TABLET, LITEST_ANY);
> +	litest_add("tablet:left_handed", left_handed, LITEST_TABLET, LITEST_ANY);
>  	litest_add("tablet:normalization", normalization, LITEST_TABLET, LITEST_ANY);
>  	litest_add("tablet:pad", pad_buttons_ignored, LITEST_TABLET, LITEST_ANY);
>  
> -- 
> 1.9.5
> 


More information about the wayland-devel mailing list