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

Andreas Pokorny andreas.pokorny at canonical.com
Fri Jun 19 06:24:38 PDT 2015


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
+	 * need those values to properly scale the touch point diameter.
+	 *
+	 * For now the implementation assumes that resolution matches.
+	 */
+	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;
+		else
+			return 90.0 * (orientation_info->maximum -
+				       (double)orientation) /
+				orientation_info->maximum;
+	}
+	else
+		return DEFAULT_TOUCH_ORIENTATION;
+}
+
+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);
+	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,
+					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,
+					  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,
+					DEFAULT_TOUCH_ORIENTATION, DEFAULT_TOUCH_PRESSURE);
 		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;
-		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;
+			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