[PATCH libinput v2 5/5] libinput: add orientation and size of touch point and pressure to the API

Peter Hutterer peter.hutterer at who-t.net
Sun Jun 21 18:37:50 PDT 2015


On Fri, Jun 19, 2015 at 03:24:38PM +0200, Andreas Pokorny wrote:
> This change adds four new properties to touch events.
> major: diameter of the touch ellipse along the major axis
> minor: diameter perpendicular to major axis
> pressure: a pressure value mapped into the range [0,1]
> orientation: the angle between major and the x axis
> 
> Those values are optionally supported by multi touch drivers, hence
> default values are provided if the information is missing.
> 
> Signed-off-by: Andreas Pokorny <andreas.pokorny at canonical.com>
> ---
>  src/evdev.c            | 158 ++++++++++++++++++++++++++++++++++------
>  src/evdev.h            |  37 ++++++++++
>  src/libinput-private.h |  12 ++-
>  src/libinput.c         | 128 +++++++++++++++++++++++++++++++-
>  src/libinput.h         | 194 +++++++++++++++++++++++++++++++++++++++++++++++++
>  src/libinput.sym       |  10 +++
>  test/touch.c           |  94 ++++++++++++++++++++++++
>  7 files changed, 606 insertions(+), 27 deletions(-)
> 
> diff --git a/src/evdev.c b/src/evdev.c
> index 6f457b8..0ae1b84 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -44,6 +44,10 @@
>  
>  #define DEFAULT_WHEEL_CLICK_ANGLE 15
>  #define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT 200
> +#define DEFAULT_TOUCH_PRESSURE 1
> +#define DEFAULT_TOUCH_ORIENTATION 0
> +#define DEFAULT_TOUCH_MAJOR 1
> +#define DEFAULT_TOUCH_MINOR 1
>  
>  enum evdev_key_type {
>  	EVDEV_KEY_TYPE_NONE,
> @@ -244,6 +248,70 @@ evdev_device_transform_y(struct evdev_device *device,
>  	return scale_axis(device->abs.absinfo_y, y, height);
>  }
>  
> +double
> +evdev_device_transform_major(struct evdev_device *device,
> +			     int32_t major,
> +			     int32_t orientation,
> +			     uint32_t width,
> +			     uint32_t height)
> +{
> +	/* Why orientation and height?
> +	 * If abisinfo_x.resolution differs from absinfo_y.resolution we

typo: abisinfo_x

> +	 * need those values to properly scale the touch point diameter.
> +	 *
> +	 * For now the implementation assumes that resolution matches.

you'll need to add a log_bug() here or fix this with the next version.

> +	 */
> +	return scale_axis(device->abs.absinfo_x, major, width);
> +}
> +
> +double
> +evdev_device_transform_minor(struct evdev_device *device,
> +			     int32_t minor,
> +			     int32_t orientation,
> +			     uint32_t width,
> +			     uint32_t height)
> +{
> +	return scale_axis(device->abs.absinfo_x, minor, width);
> +}
> +
> +double
> +evdev_device_transform_orientation(struct evdev_device *device,
> +				   int32_t orientation)
> +{
> +	const struct input_absinfo *orientation_info =
> +	    device->abs.absinfo_orientation;
> +
> +	/* ABS_MT_ORIENTATION is defined as a clockwise rotation - zero
> +	 * (instead of minimum) is mapped to the y-axis, and maximum is
> +	 * mapped to the x-axis.
> +	 * The following remaps x-axis to zero and y-axis to 90.0.
> +	 * */
> +	if (orientation_info) {
> +		if (orientation_info->maximum == 1 &&
> +		    orientation_info->maximum == 0)
> +			return orientation == 0?90.0:0.0;

spaces around ? and : 

> +		else
> +			return 90.0 * (orientation_info->maximum -
> +				       (double)orientation) /
> +				orientation_info->maximum;

use a tmp variable "max" so this becomes readable.

> +	}
> +	else
> +		return DEFAULT_TOUCH_ORIENTATION;

{ } for if + else when either of them requires it, please check the
CODING_STYLE document.

> +}
> +
> +double
> +evdev_device_transform_pressure(struct evdev_device *device,
> +				int32_t pressure)
> +{
> +	const struct input_absinfo *pressure_info = device->abs.absinfo_pressure;
> +
> +	if (pressure_info)
> +		return (double)(pressure - pressure_info->minimum) /
> +			(pressure_info->maximum - pressure_info->minimum);

tmp variable for min/max here too please

> +	else
> +		return DEFAULT_TOUCH_PRESSURE;
> +}
> +
>  static inline void
>  normalize_delta(struct evdev_device *device,
>  		const struct device_coords *delta,
> @@ -263,6 +331,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
>  	struct libinput_seat *seat = base->seat;
>  	struct normalized_coords accel, unaccel;
>  	struct device_coords point;
> +	struct mt_slot *slot_data;
>  
>  	slot = device->mt.slot;
>  
> @@ -314,25 +383,32 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
>  			break;
>  
>  		seat->slot_map |= 1 << seat_slot;
> -		point = device->mt.slots[slot].point;
> +		slot_data = &device->mt.slots[slot];
> +		point = slot_data->point;
>  		transform_absolute(device, &point);
>  
>  		touch_notify_touch_down(base, time, slot, seat_slot,
> -					&point);
> +					&point, slot_data->touch_major,
> +					slot_data->touch_minor, slot_data->orientation,

one per line

> +					slot_data->pressure);
>  		break;
>  	case EVDEV_ABSOLUTE_MT_MOTION:
>  		if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
>  			break;
>  
>  		seat_slot = device->mt.slots[slot].seat_slot;
> -		point = device->mt.slots[slot].point;
> +
> +		slot_data = &device->mt.slots[slot];
> +		point = slot_data->point;
>  
>  		if (seat_slot == -1)
>  			break;
>  
>  		transform_absolute(device, &point);
>  		touch_notify_touch_motion(base, time, slot, seat_slot,
> -					  &point);
> +					  &point, slot_data->touch_major,
> +					  slot_data->touch_minor, slot_data->orientation,

one per line

> +					  slot_data->pressure);
>  		break;
>  	case EVDEV_ABSOLUTE_MT_UP:
>  		if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
> @@ -371,7 +447,9 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
>  		point = device->abs.point;
>  		transform_absolute(device, &point);
>  
> -		touch_notify_touch_down(base, time, -1, seat_slot, &point);
> +		touch_notify_touch_down(base, time, -1, seat_slot, &point,
> +					DEFAULT_TOUCH_MAJOR,l DEFAULT_TOUCH_MINOR,

does this even compile?


> +					DEFAULT_TOUCH_ORIENTATION, DEFAULT_TOUCH_PRESSURE);

one arg per line.

>  		break;
>  	case EVDEV_ABSOLUTE_MOTION:
>  		point = device->abs.point;
> @@ -383,8 +461,10 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
>  			if (seat_slot == -1)
>  				break;
>  
> -			touch_notify_touch_motion(base, time, -1, seat_slot,
> -						  &point);
> +			touch_notify_touch_motion(base, time, -1, seat_slot, &point,
> +						  DEFAULT_TOUCH_MAJOR, DEFAULT_TOUCH_MINOR,
> +						  DEFAULT_TOUCH_ORIENTATION,
> +						  DEFAULT_TOUCH_PRESSURE);
>  		} else if (device->seat_caps & EVDEV_DEVICE_POINTER) {
>  			pointer_notify_motion_absolute(base, time, &point);
>  		}
> @@ -544,8 +624,9 @@ evdev_process_touch(struct evdev_device *device,
>  		    struct input_event *e,
>  		    uint64_t time)
>  {
> -	switch (e->code) {
> -	case ABS_MT_SLOT:
> +	struct mt_slot *current_slot = &device->mt.slots[device->mt.slot];
> +
> +	if (e->code == ABS_MT_SLOT) {
>  		if ((size_t)e->value >= device->mt.slots_len) {
>  			log_bug_libinput(device->base.seat->libinput,
>  					 "%s exceeds slots (%d of %d)\n",
> @@ -556,26 +637,53 @@ evdev_process_touch(struct evdev_device *device,
>  		}
>  		evdev_flush_pending_event(device, time);
>  		device->mt.slot = e->value;
> -		break;
> -	case ABS_MT_TRACKING_ID:
> +	} else if(e->code == ABS_MT_TRACKING_ID) {
>  		if (device->pending_event != EVDEV_NONE &&
>  		    device->pending_event != EVDEV_ABSOLUTE_MT_MOTION)
>  			evdev_flush_pending_event(device, time);
> -		if (e->value >= 0)
> +		if (e->value >= 0) {
>  			device->pending_event = EVDEV_ABSOLUTE_MT_DOWN;
> -		else
> +			current_slot->available_data = TOUCH_SLOT_DATA_NONE;
> +			current_slot->pressure = DEFAULT_TOUCH_PRESSURE;
> +			current_slot->orientation = DEFAULT_TOUCH_ORIENTATION;
> +			current_slot->touch_major = DEFAULT_TOUCH_MAJOR;
> +			current_slot->touch_minor = DEFAULT_TOUCH_MINOR;
> +		} else
>  			device->pending_event = EVDEV_ABSOLUTE_MT_UP;

{} needed

> -		break;
> -	case ABS_MT_POSITION_X:
> -		device->mt.slots[device->mt.slot].point.x = e->value;
> -		if (device->pending_event == EVDEV_NONE)
> -			device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
> -		break;
> -	case ABS_MT_POSITION_Y:
> -		device->mt.slots[device->mt.slot].point.y = e->value;
> -		if (device->pending_event == EVDEV_NONE)
> +	} else {
> +		bool needs_wake = true;
> +
> +		switch(e->code) {
> +		case ABS_MT_POSITION_X:
> +			current_slot->point.x = e->value;
> +			break;
> +		case ABS_MT_POSITION_Y:
> +			current_slot->point.y = e->value;
> +			break;
> +		case ABS_MT_TOUCH_MAJOR:
> +			current_slot->available_data |= TOUCH_SLOT_DATA_MAJOR;
> +			current_slot->touch_major = e->value;
> +			if (!(current_slot->available_data & TOUCH_SLOT_DATA_MINOR))
> +				current_slot->touch_minor = e->value;
> +			break;
> +		case ABS_MT_TOUCH_MINOR:
> +			current_slot->available_data |= TOUCH_SLOT_DATA_MINOR;
> +			current_slot->touch_minor = e->value;
> +			break;
> +		case ABS_MT_ORIENTATION:
> +			current_slot->available_data |= TOUCH_SLOT_DATA_ORIENTATION;
> +			current_slot->orientation = e->value;
> +			break;
> +		case ABS_MT_PRESSURE:
> +			current_slot->available_data |= TOUCH_SLOT_DATA_PRESSURE;
> +			current_slot->pressure = e->value;
> +			break;
> +                default:
> +                        needs_wake = false;

indentation

ok, I'm going to skip the rest. Please go through this patchset again and
make sure you adhere to the coding style before resubmitting. The odd issue
here and there is one thing, but having that many, including a compilation
errors should not happen.

Cheers,
   Peter

PS: In the documentation below you're using a \doxygen tag right below a
@doxygen tag (which are used everywhere else). Stuff like that is really
unnecessary.


> +			break;
> +		}
> +		if (needs_wake && device->pending_event == EVDEV_NONE)
>  			device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
> -		break;
>  	}
>  }
>  
> @@ -1879,6 +1987,10 @@ evdev_configure_device(struct evdev_device *device)
>  			return -1;
>  		}
>  	}
> +	if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_ORIENTATION))
> +		device->abs.absinfo_orientation = libevdev_get_abs_info(evdev, ABS_MT_ORIENTATION);
> +	if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_PRESSURE))
> +		device->abs.absinfo_pressure = libevdev_get_abs_info(evdev, ABS_MT_PRESSURE);
>  
>  	if (udev_tags & EVDEV_UDEV_TAG_TOUCHPAD) {
>  		device->dispatch = evdev_mt_touchpad_create(device);
> diff --git a/src/evdev.h b/src/evdev.h
> index ff35a8d..f6864d3 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -108,9 +108,23 @@ enum evdev_device_model {
>  	EVDEV_MODEL_WACOM_TOUCHPAD,
>  };
>  
> +/* optional slot data */
> +enum touch_slot_data {
> +	TOUCH_SLOT_DATA_NONE = 0,
> +	TOUCH_SLOT_DATA_MAJOR = (1 << 1),
> +	TOUCH_SLOT_DATA_MINOR = (1 << 2),
> +	TOUCH_SLOT_DATA_ORIENTATION = (1 << 3),
> +	TOUCH_SLOT_DATA_PRESSURE = (1 << 4),
> +};
> +
>  struct mt_slot {
>  	int32_t seat_slot;
>  	struct device_coords point;
> +	enum touch_slot_data available_data;
> +	int32_t touch_major;
> +	int32_t touch_minor;
> +	int32_t orientation;
> +	int32_t pressure;
>  };
>  
>  struct evdev_device {
> @@ -127,6 +141,7 @@ struct evdev_device {
>  	int fd;
>  	struct {
>  		const struct input_absinfo *absinfo_x, *absinfo_y;
> +		const struct input_absinfo *absinfo_pressure, *absinfo_orientation;
>  		int fake_resolution;
>  
>  		struct device_coords point;
> @@ -351,6 +366,28 @@ double
>  evdev_device_transform_y(struct evdev_device *device,
>  			 double y,
>  			 uint32_t height);
> +double
> +evdev_device_transform_major(struct evdev_device *device,
> +			     int32_t major,
> +			     int32_t orientation,
> +			     uint32_t width,
> +			     uint32_t height);
> +
> +double
> +evdev_device_transform_minor(struct evdev_device *device,
> +			     int32_t minor,
> +			     int32_t orientation,
> +			     uint32_t width,
> +			     uint32_t height);
> +
> +double
> +evdev_device_transform_orientation(struct evdev_device *device,
> +				   int32_t orientation);
> +
> +double
> +evdev_device_transform_pressure(struct evdev_device *device,
> +				int32_t pressure);
> +
>  int
>  evdev_device_suspend(struct evdev_device *device);
>  
> diff --git a/src/libinput-private.h b/src/libinput-private.h
> index a7c8838..5a2e2ea 100644
> --- a/src/libinput-private.h
> +++ b/src/libinput-private.h
> @@ -345,14 +345,22 @@ touch_notify_touch_down(struct libinput_device *device,
>  			uint64_t time,
>  			int32_t slot,
>  			int32_t seat_slot,
> -			const struct device_coords *point);
> +			const struct device_coords *point,
> +			int32_t touch_major,
> +			int32_t touch_minor,
> +			int32_t orientation,
> +			int32_t pressure);
>  
>  void
>  touch_notify_touch_motion(struct libinput_device *device,
>  			  uint64_t time,
>  			  int32_t slot,
>  			  int32_t seat_slot,
> -			  const struct device_coords *point);
> +			  const struct device_coords *point,
> +			  int32_t touch_major,
> +			  int32_t touch_minor,
> +			  int32_t orientation,
> +			  int32_t pressure);
>  
>  void
>  touch_notify_touch_up(struct libinput_device *device,
> diff --git a/src/libinput.c b/src/libinput.c
> index 7a097c0..aa5902d 100644
> --- a/src/libinput.c
> +++ b/src/libinput.c
> @@ -112,6 +112,10 @@ struct libinput_event_touch {
>  	int32_t slot;
>  	int32_t seat_slot;
>  	struct device_coords point;
> +	int32_t touch_major;
> +	int32_t touch_minor;
> +	int32_t orientation;
> +	int32_t pressure;
>  };
>  
>  static void
> @@ -637,6 +641,110 @@ libinput_event_touch_get_y(struct libinput_event_touch *event)
>  	return evdev_convert_to_mm(device->abs.absinfo_y, event->point.y);
>  }
>  
> +LIBINPUT_EXPORT double
> +libinput_event_touch_get_major(struct libinput_event_touch *event)
> +{
> +	struct evdev_device *device =
> +		(struct evdev_device *) event->base.device;
> +
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_TOUCH_DOWN,
> +			   LIBINPUT_EVENT_TOUCH_MOTION);
> +
> +	return evdev_convert_to_mm(device->abs.absinfo_x, event->touch_major);
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_touch_get_major_transformed(struct libinput_event_touch *event,
> +					   uint32_t width,
> +					   uint32_t height)
> +{
> +	struct evdev_device *device =
> +		(struct evdev_device *) event->base.device;
> +
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_TOUCH_DOWN,
> +			   LIBINPUT_EVENT_TOUCH_MOTION);
> +
> +	return evdev_device_transform_major(device,
> +					    event->touch_major,
> +					    event->orientation,
> +					    width,
> +					    height);
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_touch_get_minor(struct libinput_event_touch *event)
> +{
> +	struct evdev_device *device =
> +		(struct evdev_device *) event->base.device;
> +
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_TOUCH_DOWN,
> +			   LIBINPUT_EVENT_TOUCH_MOTION);
> +
> +	return evdev_convert_to_mm(device->abs.absinfo_x, event->touch_minor);
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_touch_get_minor_transformed(struct libinput_event_touch *event,
> +					   uint32_t width,
> +					   uint32_t height)
> +{
> +	struct evdev_device *device =
> +		(struct evdev_device *) event->base.device;
> +
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_TOUCH_DOWN,
> +			   LIBINPUT_EVENT_TOUCH_MOTION);
> +
> +	return evdev_device_transform_major(device,
> +					    event->touch_major,
> +					    event->orientation,
> +					    width,
> +					    height);
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_touch_get_orientation(struct libinput_event_touch *event)
> +{
> +	struct evdev_device *device =
> +		(struct evdev_device *) event->base.device;
> +
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_TOUCH_DOWN,
> +			   LIBINPUT_EVENT_TOUCH_MOTION);
> +
> +	return evdev_device_transform_orientation(device,
> +						  event->orientation);
> +}
> +
> +LIBINPUT_EXPORT double
> +libinput_event_touch_get_pressure(struct libinput_event_touch *event)
> +{
> +	struct evdev_device *device =
> +		(struct evdev_device *) event->base.device;
> +
> +	require_event_type(libinput_event_get_context(&event->base),
> +			   event->base.type,
> +			   0,
> +			   LIBINPUT_EVENT_TOUCH_DOWN,
> +			   LIBINPUT_EVENT_TOUCH_MOTION);
> +
> +	return evdev_device_transform_pressure(device,
> +					       event->pressure);
> +}
> +
>  struct libinput_source *
>  libinput_add_fd(struct libinput *libinput,
>  		int fd,
> @@ -1243,7 +1351,11 @@ touch_notify_touch_down(struct libinput_device *device,
>  			uint64_t time,
>  			int32_t slot,
>  			int32_t seat_slot,
> -			const struct device_coords *point)
> +			const struct device_coords *point,
> +			int32_t touch_major,
> +			int32_t touch_minor,
> +			int32_t orientation,
> +			int32_t pressure)
>  {
>  	struct libinput_event_touch *touch_event;
>  
> @@ -1259,6 +1371,10 @@ touch_notify_touch_down(struct libinput_device *device,
>  		.slot = slot,
>  		.seat_slot = seat_slot,
>  		.point = *point,
> +		.touch_major = touch_major,
> +		.touch_minor = touch_minor,
> +		.orientation = orientation,
> +		.pressure = pressure,
>  	};
>  
>  	post_device_event(device, time,
> @@ -1271,7 +1387,11 @@ touch_notify_touch_motion(struct libinput_device *device,
>  			  uint64_t time,
>  			  int32_t slot,
>  			  int32_t seat_slot,
> -			  const struct device_coords *point)
> +			  const struct device_coords *point,
> +			  int32_t touch_major,
> +			  int32_t touch_minor,
> +			  int32_t orientation,
> +			  int32_t pressure)
>  {
>  	struct libinput_event_touch *touch_event;
>  
> @@ -1287,6 +1407,10 @@ touch_notify_touch_motion(struct libinput_device *device,
>  		.slot = slot,
>  		.seat_slot = seat_slot,
>  		.point = *point,
> +		.touch_major = touch_major,
> +		.touch_minor = touch_minor,
> +		.orientation = orientation,
> +		.pressure = pressure,
>  	};
>  
>  	post_device_event(device, time,
> diff --git a/src/libinput.h b/src/libinput.h
> index e6a5642..a3e62a5 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -915,6 +915,200 @@ libinput_event_touch_get_y_transformed(struct libinput_event_touch *event,
>  /**
>   * @ingroup event_touch
>   *
> + * \verbatim
> + *                                   screen space
> + *        major
> + *  _______/\________
> + * /                 \
> + *       +++++++
> + *    +++       +++
> + *  ++             ++
> + * +     touch       +
> + * +       ellipse   +   ---> finger pointing direction
> + *  ++             ++
> + *    +++       +++
> + *       +++++++
> + * \endverbatim
> + *
> + * Return the diameter of the major axis of the touch ellipse in mm
> + * This value might not be provided by the device, in that case the value
> + * 1.0 is returned
> + *
> + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
> + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
> + *
> + * @note It is an application bug to call this function for events of type
> + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
> + *
> + * @param event The libinput touch event
> + * @return The current touch major value
> + */
> +double
> +libinput_event_touch_get_major(struct libinput_event_touch *event);
> +
> +/**
> + * @ingroup event_touch
> + *
> + * \verbatim
> + *                                   screen space
> + *        major
> + *  _______/\________
> + * /                 \
> + *       +++++++
> + *    +++       +++
> + *  ++             ++
> + * +     touch       +
> + * +       ellipse   +   ---> finger pointing direction
> + *  ++             ++
> + *    +++       +++
> + *       +++++++
> + * \endverbatim
> + *
> + * Return the diameter of the major axis of the touch ellipse in screen
> + * space This value might not be provided by the device, in that case the
> + * value 1.0 is returned
> + *
> + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
> + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
> + *
> + * @note It is an application bug to call this function for events of type
> + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
> + *
> + * @param event The libinput touch event
> + * @param width The current output screen width
> + * @param height The current output screen height
> + * @return The current touch major value
> + */
> +double
> +libinput_event_touch_get_major_transformed(struct libinput_event_touch *event,
> +					   uint32_t width,
> +					   uint32_t height);
> +
> +/**
> + * @ingroup event_touch
> + *
> + * \verbatim
> + *                                     screen space
> + *
> + *       +++++++       -
> + *    +++       +++     \
> + *  ++             ++   |
> + * +    touch        +  =- minor
> + * +      ellipse    +  |        ---> finger pointing direction
> + *  ++             ++   |
> + *    +++       +++     /
> + *       +++++++       -
> + *
> + * \endverbatim
> + *
> + * Return the diameter of the minor axis of the touch ellipse in mm.
> + * This value might not be provided by the device, in this case the value
> + * 1.0 is returned.
> + *
> + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
> + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
> + *
> + * @note It is an application bug to call this function for events of type
> + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
> + *
> + * @param event The libinput touch event
> + * @return The current touch minor value
> + */
> +double
> +libinput_event_touch_get_minor(struct libinput_event_touch *event);
> +
> +/**
> + * @ingroup event_touch
> + *
> + * \verbatim
> + *                                     screen space
> + *
> + *       +++++++       -
> + *    +++       +++     \
> + *  ++             ++   |
> + * +    touch        +  =- minor
> + * +      ellipse    +  |        ---> finger pointing direction
> + *  ++             ++   |
> + *    +++       +++     /
> + *       +++++++       -
> + *
> + * \endverbatim
> + *
> + * Return the diameter of the minor axis of the touch ellipse in screen
> + * space. This value might not be provided by the device, in this case
> + * the value 1.0 is returned.
> + *
> + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
> + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
> + *
> + * @note It is an application bug to call this function for events of type
> + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
> + *
> + * @param event The libinput touch event
> + * @param width The current output screen width
> + * @param height The current output screen height
> + * @return The current touch minor value
> + */
> +double
> +libinput_event_touch_get_minor_transformed(struct libinput_event_touch *event,
> +					   uint32_t width,
> +					   uint32_t height);
> +
> +/**
> + * @ingroup event_touch
> + *
> + * Return the current pressure value touch point normalized to the range
> + * [0,1]. If this value is not provided by the device, it always be 1.0,
> + * which denotes the maximum pressure on a touch point.
> + *
> + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
> + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
> + *
> + * @note It is an application bug to call this function for events of type
> + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
> + *
> + * @param event The libinput touch event
> + * @return The current pressure value
> + */
> +double
> +libinput_event_touch_get_pressure(struct libinput_event_touch *event);
> +
> +/**
> + * @ingroup event_touch
> + * \verbatim
> + *
> + *    major     ∧ y
> + *    axis \    |
> + *          \++ |
> + *         + \ ++
> + *         +  \ |+
> + *          +  \| +
> + *           +  0--+---------------> x
> + *            +     +
> + *             ++   +
> + *               +++
> + *
> + * \endverbatim
> + *
> + * Return the revolution of the major axis of the ellipse away from the X axis
> + * in degrees. This value might not be measured by the device, or only measured
> + * in coarse steps (e.g only indicating alignment with X or y axis).
> + *
> + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref
> + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0.
> + *
> + * @note It is an application bug to call this function for events of type
> + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION.
> + *
> + * @param event The libinput touch event
> + * @return The current orientation value
> + */
> +double
> +libinput_event_touch_get_orientation(struct libinput_event_touch *event);
> +
> +/**
> + * @ingroup event_touch
> + *
>   * @return The generic libinput_event of this event
>   */
>  struct libinput_event *
> diff --git a/src/libinput.sym b/src/libinput.sym
> index 9c11174..e9635ad 100644
> --- a/src/libinput.sym
> +++ b/src/libinput.sym
> @@ -140,3 +140,13 @@ LIBINPUT_0.15.0 {
>  global:
>  	libinput_device_keyboard_has_key;
>  } LIBINPUT_0.14.0;
> +
> +LIBINPUT_0.18.0 {
> +global:
> +	libinput_event_touch_get_minor;
> +	libinput_event_touch_get_major;
> +	libinput_event_touch_get_minor_transformed;
> +	libinput_event_touch_get_major_transformed;
> +	libinput_event_touch_get_orientation;
> +	libinput_event_touch_get_pressure;
> +} LIBINPUT_0.15.0;
> diff --git a/test/touch.c b/test/touch.c
> index b519613..317d4e9 100644
> --- a/test/touch.c
> +++ b/test/touch.c
> @@ -652,6 +652,94 @@ START_TEST(touch_initial_state)
>  }
>  END_TEST
>  
> +START_TEST(touch_point_properties)
> +{
> +	struct litest_device *dev = litest_current_device();
> +	struct libinput *li = dev->libinput;
> +	struct libinput_event *ev;
> +	struct libinput_event_touch *tev;
> +	struct axis_replacement down_values[] = {
> +		{ABS_MT_PRESSURE, 128},
> +		{ABS_MT_ORIENTATION, 64},
> +		{ABS_MT_TOUCH_MAJOR, 14},
> +		{ABS_MT_TOUCH_MINOR, 8}};
> +	struct axis_replacement move_values[] = {
> +		{ABS_MT_ORIENTATION, 128},
> +		{ABS_MT_TOUCH_MAJOR, 30}};
> +
> +
> +	litest_drain_events(li);
> +
> +	litest_touch_down_extended(dev, 0, 5, 95, down_values);
> +
> +	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_DOWN, -1);
> +
> +	ev = libinput_get_event(li);
> +	tev = libinput_event_get_touch_event(ev);
> +
> +	ck_assert_double_eq(libinput_event_touch_get_pressure(tev), 128.0/255.0);
> +	ck_assert_double_eq(libinput_event_touch_get_orientation(tev), 67.412);
> +	ck_assert_int_eq(libinput_event_touch_get_major(tev), 14);
> +	ck_assert_int_eq(libinput_event_touch_get_minor(tev), 8);
> +
> +	libinput_event_destroy(ev);
> +
> +	litest_touch_move_extended(dev, 0, 5, 95, move_values);
> +	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_MOTION, -1);
> +
> +	ev = libinput_get_event(li);
> +	tev = libinput_event_get_touch_event(ev);
> +
> +	ck_assert_double_eq(libinput_event_touch_get_pressure(tev), 128.0/255.0);
> +	ck_assert_double_eq(libinput_event_touch_get_orientation(tev), 44.823);
> +	ck_assert_int_eq(libinput_event_touch_get_major(tev), 30);
> +	ck_assert_int_eq(libinput_event_touch_get_minor(tev), 8);
> +
> +	libinput_event_destroy(ev);
> +}
> +END_TEST
> +
> +START_TEST(touch_point_wo_minor_or_orienation)
> +{
> +	struct litest_device *dev = litest_current_device();
> +	struct libinput *li = dev->libinput;
> +	struct libinput_event *ev;
> +	struct libinput_event_touch *tev;
> +	struct axis_replacement down_values[] = {
> +		{ABS_MT_PRESSURE, 128},
> +		{ABS_MT_TOUCH_MAJOR, 14}};
> +	struct axis_replacement move_values[] = {
> +		{ABS_MT_TOUCH_MAJOR, 30}};
> +
> +
> +	litest_drain_events(li);
> +
> +	litest_touch_down_extended(dev, 0, 5, 95, down_values);
> +
> +	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_DOWN, -1);
> +
> +	ev = libinput_get_event(li);
> +	tev = libinput_event_get_touch_event(ev);
> +
> +	ck_assert_double_eq(libinput_event_touch_get_orientation(tev), 0.0);
> +	ck_assert_int_eq(libinput_event_touch_get_major(tev), 14);
> +	ck_assert_int_eq(libinput_event_touch_get_minor(tev), 14);
> +
> +	libinput_event_destroy(ev);
> +
> +	litest_touch_move_extended(dev, 0, 5, 95, move_values);
> +	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_TOUCH_MOTION, -1);
> +
> +	ev = libinput_get_event(li);
> +	tev = libinput_event_get_touch_event(ev);
> +
> +	ck_assert_int_eq(libinput_event_touch_get_major(tev), 30);
> +	ck_assert_int_eq(libinput_event_touch_get_minor(tev), 30);
> +
> +	libinput_event_destroy(ev);
> +}
> +END_TEST
> +
>  void
>  litest_setup_tests(void)
>  {
> @@ -676,6 +764,12 @@ litest_setup_tests(void)
>  	litest_add("touch:protocol a", touch_protocol_a_init, LITEST_PROTOCOL_A, LITEST_ANY);
>  	litest_add("touch:protocol a", touch_protocol_a_touch, LITEST_PROTOCOL_A, LITEST_ANY);
>  	litest_add("touch:protocol a", touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY);
> +	litest_add_for_device("touch:touch point properties",
> +			      touch_point_properties,
> +			      LITEST_GENERIC_MULTITOUCH_SCREEN);
> +	litest_add_for_device("touch:touch point without minor or orientation",
> +			      touch_point_wo_minor_or_orienation,
> +			      LITEST_NEXUS4_TOUCH_SCREEN);
>  
>  	litest_add_ranged("touch:state", touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes);
>  }
> -- 
> 2.1.4
> 


More information about the wayland-devel mailing list