[PATCH libinput 2/2 v2] tablet: Add libinput_tool_has_axis() and tests

Peter Hutterer peter.hutterer at who-t.net
Thu Aug 7 17:38:56 PDT 2014


On Thu, Aug 07, 2014 at 06:54:55PM -0400, Stephen Chandler Paul wrote:
> Because the axes that tool reports can change depending on the tool in use, we
> want to be able to provide functionality to determine which axes each tool can
> support.
> 
> Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>
> ---
> 
> Changes:
> 	- Added a description to the patch
> 	- Fixed all of the memory leaks, passes make check with flying
> 	  colors now
> 
>  src/evdev-tablet.c     | 42 +++++++++++++++++++++++++++++
>  src/evdev-tablet.h     |  1 +
>  src/libinput-private.h |  1 +
>  src/libinput.c         |  7 +++++
>  src/libinput.h         | 26 ++++++++++++++++++
>  test/tablet.c          | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 149 insertions(+)
> 
> diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
> index 43da67a..5f8a466 100644
> --- a/src/evdev-tablet.c
> +++ b/src/evdev-tablet.c
> @@ -298,6 +298,40 @@ tablet_get_tool(struct tablet_dispatch *tablet,
>  			.refcount = 1,
>  		};
>  
> +		/* Determine the axis capabilities of the tool. Here's a break
> +		 * down of the heuristics used here:
> +		 * - The Wacom art pen supports all of the extra axes, along
> +		 *   with rotation
> +		 * - All of normal pens and the airbrush support all of the
> +		 *   extra axes if the tablet can report them
> +		 * - All of the mouse like devices don't really report any of
> +		 *   the extra axes except for rotation.
> +		 * (as of writing this comment, rotation isn't supported, so you
> +		 * won't see the mouse or art pen here)
> +		 */
> +		switch (type) {
> +		case LIBINPUT_TOOL_PEN:
> +		case LIBINPUT_TOOL_ERASER:
> +		case LIBINPUT_TOOL_PENCIL:
> +		case LIBINPUT_TOOL_BRUSH:
> +		case LIBINPUT_TOOL_AIRBRUSH:
> +			if (bit_is_set(tablet->axis_caps,
> +				       LIBINPUT_TOOL_AXIS_FLAG_PRESSURE))
> +				set_bit(tool->axis_caps,
> +					LIBINPUT_TOOL_AXIS_FLAG_PRESSURE);
> +			if (bit_is_set(tablet->axis_caps,
> +				       LIBINPUT_TOOL_AXIS_FLAG_DISTANCE))
> +				set_bit(tool->axis_caps,
> +					LIBINPUT_TOOL_AXIS_FLAG_DISTANCE);
> +			if (bit_is_set(tablet->axis_caps,
> +				       LIBINPUT_TOOL_AXIS_FLAG_TILT))
> +				set_bit(tool->axis_caps,
> +					LIBINPUT_TOOL_AXIS_FLAG_TILT);
> +			break;
> +		default:
> +			break;
> +		}
> +
>  		list_insert(tool_list, &tool->link);
>  	}
>  
> @@ -512,6 +546,14 @@ tablet_init(struct tablet_dispatch *tablet,
>  	tablet->current_tool_type = LIBINPUT_TOOL_NONE;
>  	list_init(&tablet->tool_list);
>  
> +	if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_PRESSURE))
> +		set_bit(tablet->axis_caps, LIBINPUT_TOOL_AXIS_FLAG_PRESSURE);
> +	if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_DISTANCE))
> +		set_bit(tablet->axis_caps, LIBINPUT_TOOL_AXIS_FLAG_DISTANCE);
> +	if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_TILT_X) &&
> +	    libevdev_has_event_code(device->evdev, EV_ABS, ABS_TILT_Y))
> +		set_bit(tablet->axis_caps, LIBINPUT_TOOL_AXIS_FLAG_TILT);
> +
>  	tablet_mark_all_axes_changed(tablet, device);
>  
>  	return 0;
> diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
> index d16aef3..be2d09a 100644
> --- a/src/evdev-tablet.h
> +++ b/src/evdev-tablet.h
> @@ -49,6 +49,7 @@ struct tablet_dispatch {
>  	unsigned char status;
>  	unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_CNT)];
>  	double axes[LIBINPUT_TABLET_AXIS_CNT];
> +	unsigned char axis_caps[NCHARS(LIBINPUT_TOOL_AXIS_FLAG_CNT)];
>  
>  	/* Only used for tablets that don't report serial numbers */
>  	struct list tool_list;
> diff --git a/src/libinput-private.h b/src/libinput-private.h
> index 8187564..bdef330 100644
> --- a/src/libinput-private.h
> +++ b/src/libinput-private.h
> @@ -108,6 +108,7 @@ struct libinput_tool {
>  	struct list link;
>  	uint32_t serial;
>  	enum libinput_tool_type type;
> +	unsigned char axis_caps[NCHARS(LIBINPUT_TOOL_AXIS_FLAG_CNT)];
>  	int refcount;
>  	void *user_data;
>  };
> diff --git a/src/libinput.c b/src/libinput.c
> index 68187d8..560fedd 100644
> --- a/src/libinput.c
> +++ b/src/libinput.c
> @@ -599,6 +599,13 @@ libinput_tool_get_serial(struct libinput_tool *tool)
>  	return tool->serial;
>  }
>  
> +LIBINPUT_EXPORT int
> +libinput_tool_has_axis(struct libinput_tool *tool,
> +		       enum libinput_tool_axis_flag axis)
> +{
> +	return bit_is_set(tool->axis_caps, axis);
> +}
> +
>  LIBINPUT_EXPORT void
>  libinput_tool_set_user_data(struct libinput_tool *tool,
>  			    void *user_data)
> diff --git a/src/libinput.h b/src/libinput.h
> index 1d4952b..63c5ad3 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -214,6 +214,19 @@ enum libinput_tool_type {
>  };
>  
>  /**
> + * @ingroup device
> + *
> + * A series of flags for representing which kinds of axes a tablet tool can
> + * support.
> + */
> +enum libinput_tool_axis_flag {
> +	LIBINPUT_TOOL_AXIS_FLAG_PRESSURE = 0,
> +	LIBINPUT_TOOL_AXIS_FLAG_DISTANCE = 1,
> +	LIBINPUT_TOOL_AXIS_FLAG_TILT = 2,
> +	LIBINPUT_TOOL_AXIS_FLAG_CNT = 3,
> +};
> +
> +/**
>   * @ingroup base
>   *
>   * Event type for events returned by libinput_get_event().
> @@ -1010,6 +1023,19 @@ libinput_tool_ref(struct libinput_tool *tool);
>  /**
>   * @ingroup event_tablet
>   *
> + * Return whether or not a tablet tool supports the specified axis
> + *
> + * @param tool The tool to check the axis capabilities of
> + * @param axis The axis to check for support
> + * @return Whether or not the axis is supported
> + */
> +int
> +libinput_tool_has_axis(struct libinput_tool *tool,
> +		       enum libinput_tool_axis_flag axis);

looking at that again, I don't think we need the flags here. passing a flag
in here doesn't make esnese unless you define what to return if multiple
flags are set. It's easier to just pass the libinput_tablet_axis enum in
here and check for a single axis at a time. this means you can drop the flag
enum above. sorry, should've picked that up yesterday.

> +
> +/**
> + * @ingroup event_tablet
> + *
>   * Decrement the ref count of tool by one. When the ref count of tool reaches 0,
>   * the memory allocated for tool will be freed.
>   *
> diff --git a/test/tablet.c b/test/tablet.c
> index 2de0989..657251e 100644
> --- a/test/tablet.c
> +++ b/test/tablet.c
> @@ -766,10 +766,82 @@ START_TEST(tools_without_serials)
>  }
>  END_TEST
>  
> +START_TEST(tool_capabilities)
> +{
> +	struct libinput *li = litest_create_context();
> +	struct litest_device *intuos;
> +	struct litest_device *bamboo;
> +	struct libinput_event *event;
> +
> +	/* The axis capabilities of a tool can differ depending on the type of
> +	 * tablet the tool is being used with */
> +	bamboo = litest_create_device_with_overrides(LITEST_WACOM_BAMBOO,
> +						     NULL,
> +						     NULL,
> +						     NULL,
> +						     NULL);
> +	intuos = litest_create_device_with_overrides(LITEST_WACOM_INTUOS,
> +						     NULL,
> +						     NULL,
> +						     NULL,
> +						     NULL);
> +
> +	litest_event(bamboo, EV_KEY, BTN_TOOL_PEN, 1);
> +	litest_event(bamboo, EV_SYN, SYN_REPORT, 0);
> +
> +	libinput_dispatch(li);
> +	while ((event = libinput_get_event(li))) {
> +		if (libinput_event_get_type(event) ==
> +		    LIBINPUT_EVENT_TABLET_PROXIMITY_IN) {
> +			struct libinput_event_tablet *t =
> +				libinput_event_get_tablet_event(event);
> +			struct libinput_tool *tool =
> +				libinput_event_tablet_get_tool(t);
> +
> +			ck_assert(libinput_tool_has_axis(
> +				tool, LIBINPUT_TOOL_AXIS_FLAG_PRESSURE));

urgh, this indentation just looks awkward, and it aligns it badly. try for
this one instead, so it's more obvious what's an argument to what.

                        ck_assert(libinput_tool_has_axis(tool,
                                        LIBINPUT_TOOL_AXIS_FLAG_PRESSURE));

despite Jonas' disagreement on the line width, I think this is a case where
going over 80 would make sense too

                        ck_assert(libinput_tool_has_axis(tool,
                                                         LIBINPUT_TOOL_AXIS_FLAG_PRESSURE));

same below.

Cheers,
   Peter

> +			ck_assert(!libinput_tool_has_axis(
> +				tool, LIBINPUT_TOOL_AXIS_FLAG_TILT));
> +			ck_assert(libinput_tool_has_axis(
> +				tool, LIBINPUT_TOOL_AXIS_FLAG_DISTANCE));
> +		}
> +
> +		libinput_event_destroy(event);
> +	}
> +
> +	litest_event(intuos, EV_KEY, BTN_TOOL_PEN, 1);
> +	litest_event(intuos, EV_SYN, SYN_REPORT, 0);
> +
> +	while ((event = libinput_get_event(li))) {
> +		if (libinput_event_get_type(event) ==
> +		    LIBINPUT_EVENT_TABLET_PROXIMITY_IN) {
> +			struct libinput_event_tablet *t =
> +				libinput_event_get_tablet_event(event);
> +			struct libinput_tool *tool =
> +				libinput_event_tablet_get_tool(t);
> +
> +			ck_assert(libinput_tool_has_axis(
> +				tool, LIBINPUT_TOOL_AXIS_FLAG_PRESSURE));
> +			ck_assert(libinput_tool_has_axis(
> +				tool, LIBINPUT_TOOL_AXIS_FLAG_DISTANCE));
> +			ck_assert(libinput_tool_has_axis(
> +				tool, LIBINPUT_TOOL_AXIS_FLAG_TILT));
> +		}
> +
> +		libinput_event_destroy(event);
> +	}
> +
> +	litest_delete_device(bamboo);
> +	litest_delete_device(intuos);
> +	libinput_unref(li);
> +}
> +END_TEST
> +
>  int
>  main(int argc, char **argv)
>  {
>  	litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
> +	litest_add_no_device("tablet:tool", tool_capabilities);
>  	litest_add("tablet:tool_serial", tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
>  	litest_add("tablet:tool_serial", serial_changes_tool, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
>  	litest_add("tablet:tool_serial", invalid_serials, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
> -- 
> 1.8.5.5
> 


More information about the wayland-devel mailing list