- libinput commit name: add orientation and size of touch point and pressure to the API
Change-Id: Icfd09c132b51bf15837f11bdd662181e666960b5
BuildRequires: pkgconfig(libevent)
BuildRequires: pkgconfig(libudev)
BuildRequires: pkgconfig(mtdev)
+BuildRequires: pkgconfig(wacom)
%description
evdev_transform_absolute(device, &point);
touch_notify_touch_down(base, time, slot_idx, seat_slot,
- &point);
+ &point, &slot->area, slot->pressure);
return true;
}
evdev_transform_absolute(device, &point);
touch_notify_touch_motion(base, time, slot_idx, seat_slot,
- &point);
+ &point, &slot->area, slot->pressure);
return true;
}
struct libinput_seat *seat = base->seat;
struct device_coords point;
int seat_slot;
+ struct ellipse default_touch = {
+ .major = DEFAULT_TOUCH_MAJOR,
+ .minor = DEFAULT_TOUCH_MINOR,
+ .orientation = DEFAULT_TOUCH_ORIENTATION
+ };
if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
return false;
point = dispatch->abs.point;
evdev_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, DEFAULT_TOUCH_PRESSURE);
return true;
}
struct libinput_device *base = &device->base;
struct device_coords point;
int seat_slot;
+ struct ellipse default_touch = {
+ .major = DEFAULT_TOUCH_MAJOR,
+ .minor = DEFAULT_TOUCH_MINOR,
+ .orientation = DEFAULT_TOUCH_ORIENTATION
+ };
point = dispatch->abs.point;
evdev_transform_absolute(device, &point);
if (seat_slot == -1)
return false;
- touch_notify_touch_motion(base, time, -1, seat_slot, &point);
+ touch_notify_touch_motion(base, time, -1, seat_slot, &point, &default_touch, DEFAULT_TOUCH_PRESSURE);
return true;
}
dispatch->pending_event |= EVDEV_ABSOLUTE_MT;
slot->dirty = true;
break;
+ case ABS_MT_TOUCH_MAJOR:
+ dispatch->mt.slots[dispatch->mt.slot].area.major = e->value;
+ if (dispatch->pending_event == EVDEV_NONE)
+ dispatch->pending_event = EVDEV_ABSOLUTE_MT;
+ break;
+ case ABS_MT_TOUCH_MINOR:
+ dispatch->mt.slots[dispatch->mt.slot].area.minor = e->value;
+ if (dispatch->pending_event == EVDEV_NONE)
+ dispatch->pending_event = EVDEV_ABSOLUTE_MT;
+ break;
+ case ABS_MT_ORIENTATION:
+ dispatch->mt.slots[dispatch->mt.slot].area.orientation = e->value;
+ if (dispatch->pending_event == EVDEV_NONE)
+ dispatch->pending_event = EVDEV_ABSOLUTE_MT;
+ break;
+ default:
+ break;
}
}
slots[slot].point.y = libevdev_get_slot_value(evdev,
slot,
ABS_MT_POSITION_Y);
+ slots[slot].area.major = libevdev_get_slot_value(evdev,
+ slot,
+ ABS_MT_TOUCH_MAJOR);
+ slots[slot].area.minor = libevdev_get_slot_value(evdev,
+ slot,
+ ABS_MT_TOUCH_MINOR);
+ slots[slot].area.orientation = libevdev_get_slot_value(evdev,
+ slot,
+ ABS_MT_ORIENTATION);
+ slots[slot].pressure = libevdev_get_slot_value(evdev,
+ slot,
+ ABS_MT_PRESSURE);
}
dispatch->mt.slots = slots;
dispatch->mt.slots_len = num_slots;
struct device_coords point;
struct device_coords hysteresis_center;
enum palm_state palm_state;
+ struct ellipse area;
+ int32_t pressure;
};
struct fallback_dispatch {
#include "libinput-private.h"
#include "quirks.h"
#include "util-input-event.h"
+#include "stdio.h"
#if HAVE_LIBWACOM
#include <libwacom/libwacom.h>
return scale_axis(device->abs.absinfo_y, y, height);
}
+double
+evdev_device_transform_orientation(struct evdev_device *device,
+ int32_t orientation)
+{
+ const struct input_absinfo *orientation_info =
+ device->abs.absinfo_orientation;
+
+ double angle = DEFAULT_TOUCH_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. So minimum is likely to be negative but
+ * plays no role in scaling the value to degrees.*/
+ if (orientation_info)
+ angle = (90.0 * orientation) / orientation_info->maximum;
+
+ return fmod(360.0 + angle, 360.0);
+}
+
+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) {
+ double max_pressure = pressure_info->maximum;
+ double min_pressure = pressure_info->minimum;
+ return (pressure - min_pressure) /
+ (max_pressure - min_pressure);
+ } else {
+ return DEFAULT_TOUCH_PRESSURE;
+ }
+}
+
void
evdev_notify_axis(struct evdev_device *device,
uint64_t time,
device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y);
+ device->abs.absinfo_orientation = libevdev_get_abs_info(evdev, ABS_MT_ORIENTATION);
+ device->abs.absinfo_pressure = libevdev_get_abs_info(evdev, ABS_MT_PRESSURE);
+ device->abs.absinfo_major = libevdev_get_abs_info(evdev, ABS_MT_TOUCH_MAJOR);
+ device->abs.absinfo_minor = libevdev_get_abs_info(evdev, ABS_MT_TOUCH_MINOR);
+
device->abs.dimensions.x = abs(device->abs.absinfo_x->maximum -
device->abs.absinfo_x->minimum);
device->abs.dimensions.y = abs(device->abs.absinfo_y->maximum -
/* The fake resolution value for abs devices without resolution */
#define EVDEV_FAKE_RESOLUTION 1
+#define DEFAULT_TOUCH_PRESSURE 1.0
+#define DEFAULT_TOUCH_ORIENTATION 0.0
+#define DEFAULT_TOUCH_MAJOR 0.0
+#define DEFAULT_TOUCH_MINOR 0.0
+
enum evdev_event_type {
EVDEV_NONE,
EVDEV_ABSOLUTE_TOUCH_DOWN = bit(0),
struct {
const struct input_absinfo *absinfo_x, *absinfo_y;
+ const struct input_absinfo *absinfo_major, *absinfo_minor, *absinfo_pressure, *absinfo_orientation;
bool is_fake_resolution;
int apply_calibration;
evdev_device_transform_y(struct evdev_device *device,
double y,
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);
+
void
evdev_device_suspend(struct evdev_device *device);
double minor;
};
+/* Ellipse parameters in device coordinates */
+struct ellipse {
+ int major, minor, orientation;
+};
+
struct libinput_interface_backend {
int (*resume)(struct libinput *libinput);
void (*suspend)(struct libinput *libinput);
uint64_t time,
int32_t slot,
int32_t seat_slot,
- const struct device_coords *point);
+ const struct device_coords *point,
+ const struct ellipse *area,
+ 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,
+ const struct ellipse *area,
+ int32_t pressure);
void
touch_notify_touch_up(struct libinput_device *device,
check_event_type(struct libinput *libinput,
const char *function_name,
unsigned int type_in,
- ...)
+ ...)
{
bool rc = false;
va_list args;
if (!rc)
log_bug_client(libinput,
- "Invalid event type %d passed to %s()\n",
+ "Invalid event type %d passed to %s()\n",
type_in, function_name);
-
+
return rc;
}
-static inline const char *
+ static inline const char *
event_type_to_str(enum libinput_event_type type)
{
switch(type) {
return NULL;
}
-struct libinput_source {
+ struct libinput_source {
libinput_source_dispatch_t dispatch;
void *user_data;
int fd;
uint64_t time;
int32_t slot;
int32_t seat_slot;
- struct device_coords point;
-};
+ struct device_coords point;
+ struct ellipse area;
+ int32_t pressure;
+ };
struct libinput_event_gesture {
struct libinput_event base;
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)
+ {
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_TOUCH_DOWN,
+ LIBINPUT_EVENT_TOUCH_MOTION);
+
+ return event->area.major;
+ }
+
+ LIBINPUT_EXPORT double
+ libinput_event_touch_get_major_transformed(struct libinput_event_touch *event,
+ uint32_t width,
+ uint32_t height)
+ {
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_TOUCH_DOWN,
+ LIBINPUT_EVENT_TOUCH_MOTION);
+
+ return event->area.major;
+ }
+
+ LIBINPUT_EXPORT int
+ libinput_event_touch_has_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 device->abs.absinfo_major != 0;
+ }
+
+ LIBINPUT_EXPORT double
+ libinput_event_touch_get_minor(struct libinput_event_touch *event)
+ {
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_TOUCH_DOWN,
+ LIBINPUT_EVENT_TOUCH_MOTION);
+
+ return event->area.minor;
+ }
+
+ LIBINPUT_EXPORT double
+ libinput_event_touch_get_minor_transformed(struct libinput_event_touch *event,
+ uint32_t width,
+ uint32_t height)
+ {
+ require_event_type(libinput_event_get_context(&event->base),
+ event->base.type,
+ 0,
+ LIBINPUT_EVENT_TOUCH_DOWN,
+ LIBINPUT_EVENT_TOUCH_MOTION);
+
+ return event->area.minor;
+ }
+
+ LIBINPUT_EXPORT int
+ libinput_event_touch_has_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 device->abs.absinfo_minor != 0;
+ }
+
+ 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->area.orientation);
+ }
+
+ LIBINPUT_EXPORT int
+ libinput_event_touch_has_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 device->abs.absinfo_orientation != 0;
+ }
+
+ 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);
+ }
+
+ LIBINPUT_EXPORT int
+ libinput_event_touch_has_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 device->abs.absinfo_pressure != 0;
+ }
+
LIBINPUT_EXPORT uint32_t
libinput_event_gesture_get_time(struct libinput_event_gesture *event)
{
uint64_t time,
int32_t slot,
int32_t seat_slot,
- const struct device_coords *point)
+ const struct device_coords *point,
+ const struct ellipse *area,
+ int32_t pressure)
{
struct libinput_event_touch *touch_event;
.slot = slot,
.seat_slot = seat_slot,
.point = *point,
+ .area = *area,
+ .pressure = pressure,
};
post_device_event(device, time,
uint64_t time,
int32_t slot,
int32_t seat_slot,
- const struct device_coords *point)
+ const struct device_coords *point,
+ const struct ellipse *area,
+ int32_t pressure)
{
struct libinput_event_touch *touch_event;
.slot = slot,
.seat_slot = seat_slot,
.point = *point,
+ .area = *area,
+ .pressure = pressure,
};
post_device_event(device, time,
libinput_event_touch_get_y_transformed(struct libinput_event_touch *event,
uint32_t height);
+/**
+ * @ingroup event_touch
+ *
+ * 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
+ * 0.0 is returned.
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * 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
+ * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION.
+ *
+ * @param event The libinput touch event
+ * @return The current major axis diameter
+ */
+double
+libinput_event_touch_get_major(struct libinput_event_touch *event);
+
+/**
+ * @ingroup event_touch
+ *
+ * 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 0.0 is returned.
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION this function returns 0.
+ *
+ * @note It is an application bug to call this function for events of type
+ * other than @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 major axis diameter
+ */
+double
+libinput_event_touch_get_major_transformed(struct libinput_event_touch *event,
+ uint32_t width,
+ uint32_t height);
+
+/**
+ * @ingroup event_touch
+ *
+ * Return whether the event contains a major axis value of the touch ellipse.
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * 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
+ * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION.
+ *
+ * @param event The libinput touch event
+ * @return Non-zero when a major diameter is available
+ */
+int
+libinput_event_touch_has_major(struct libinput_event_touch *event);
+
+/**
+ * @ingroup event_touch
+ *
+ * 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
+ * 0.0 is returned.
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION this function returns 0.
+ *
+ * @note It is an application bug to call this function for events of type
+ * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION.
+ *
+ * @param event The libinput touch event
+ * @return The current minor diameter
+ */
+double
+libinput_event_touch_get_minor(struct libinput_event_touch *event);
+
+/**
+ * @ingroup event_touch
+ *
+ * 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 0.0 is returned.
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION this function returns 0.
+ *
+ * @note It is an application bug to call this function for events of type
+ * other than @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 minor diameter
+ */
+double
+libinput_event_touch_get_minor_transformed(struct libinput_event_touch *event,
+ uint32_t width,
+ uint32_t height);
+/**
+ * @ingroup event_touch
+ *
+ * Return whether the event contains a minor axis value of the touch ellipse.
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * 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
+ * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION.
+ *
+ * @param event The libinput touch event
+ * @return Non-zero when a minor diameter is available
+ */
+int
+libinput_event_touch_has_minor(struct libinput_event_touch *event);
+
+/**
+ * @ingroup event_touch
+ *
+ * Return the pressure value applied to the touch contact normalized to the
+ * range [0, 1]. If this value is not available the function returns the maximum
+ * value 1.0.
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION this function returns 0.
+ *
+ * @note It is an application bug to call this function for events of type
+ * other than @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
+ *
+ * Return whether the event contains a pressure value for the touch contact.
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * 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
+ * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION.
+ *
+ * @param event The libinput touch event
+ * @return Non-zero when a pressure value is available
+ */
+int
+libinput_event_touch_has_pressure(struct libinput_event_touch *event);
+
+/**
+ * @ingroup event_touch
+ *
+ * Return the major axis rotation in degrees, clockwise from the logical north
+ * of the touch screen.
+ *
+ * @note Even when the orientation is measured by the device, it might be only
+ * available in coarse steps (e.g only indicating alignment with either of the
+ * axes).
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * 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
+ * other than @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 whether the event contains a orientation value for the touch contact.
+ *
+ * A more detailed explanation can be found in @ref touch_event_properties.
+ *
+ * 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
+ * other than @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref
+ * LIBINPUT_EVENT_TOUCH_MOTION.
+ *
+ * @param event The libinput touch event
+ * @return Non-zero when an orientation value is available
+ */
+int
+libinput_event_touch_has_orientation(struct libinput_event_touch *event);
+
/**
* @ingroup event_touch
*
libinput_device_config_accel_get_profiles;
libinput_device_config_accel_get_default_profile;
libinput_device_config_accel_set_profile;
+ libinput_event_touch_get_major;
+ libinput_event_touch_get_major_transformed;
+ libinput_event_touch_get_minor;
+ libinput_event_touch_get_minor_transformed;
+ libinput_event_touch_get_orientation;
+ libinput_event_touch_get_pressure;
+ libinput_event_touch_has_major;
+ libinput_event_touch_has_minor;
+ libinput_event_touch_has_orientation;
+ libinput_event_touch_has_pressure;
} LIBINPUT_0.21.0;
LIBINPUT_1.2 {