From cc838ead8bb38786c18e426e613df8de9c8cae33 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 8 Nov 2016 13:00:15 +0100 Subject: [PATCH] clutter/evdev: Add ClutterInputDeviceEvdev::device-matrix property And transform absolute events using this matrix. This property is akin to the "Coordinate Transformation Matrix" property in X11, and will be used to map tablets/touchscreens to outputs, favoured over the libinput matrix which is meant for calibration. https://bugzilla.gnome.org/show_bug.cgi?id=774115 --- .../evdev/clutter-device-manager-evdev.c | 7 ++ .../evdev/clutter-input-device-evdev.c | 88 +++++++++++++++++++ .../evdev/clutter-input-device-evdev.h | 7 ++ 3 files changed, 102 insertions(+) diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.c b/clutter/clutter/evdev/clutter-device-manager-evdev.c index 2a3c76861..23c43ad2f 100644 --- a/clutter/clutter/evdev/clutter-device-manager-evdev.c +++ b/clutter/clutter/evdev/clutter-device-manager-evdev.c @@ -312,6 +312,9 @@ new_absolute_motion_event (ClutterInputDevice *input_device, _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); event->motion.x = x; event->motion.y = y; + clutter_input_device_evdev_translate_coordinates (input_device, stage, + &event->motion.x, + &event->motion.y); event->motion.axes = axes; clutter_event_set_source_device (event, input_device); @@ -510,6 +513,10 @@ notify_touch_event (ClutterInputDevice *input_device, event->touch.device = seat->core_pointer; event->touch.x = x; event->touch.y = y; + clutter_input_device_evdev_translate_coordinates (input_device, stage, + &event->touch.x, + &event->touch.y); + /* "NULL" sequences are special cased in clutter */ event->touch.sequence = GINT_TO_POINTER (slot + 1); _clutter_xkb_translate_state (event, seat->xkb, seat->button_state); diff --git a/clutter/clutter/evdev/clutter-input-device-evdev.c b/clutter/clutter/evdev/clutter-input-device-evdev.c index c6f515f6e..c321d41e1 100644 --- a/clutter/clutter/evdev/clutter-input-device-evdev.c +++ b/clutter/clutter/evdev/clutter-input-device-evdev.c @@ -35,6 +35,8 @@ #include "clutter-input-device-evdev.h" #include "clutter-device-manager-evdev.h" +#include "cairo-gobject.h" + typedef struct _ClutterInputDeviceClass ClutterInputDeviceEvdevClass; #define clutter_input_device_evdev_get_type _clutter_input_device_evdev_get_type @@ -43,6 +45,14 @@ G_DEFINE_TYPE (ClutterInputDeviceEvdev, clutter_input_device_evdev, CLUTTER_TYPE_INPUT_DEVICE) +enum { + PROP_0, + PROP_DEVICE_MATRIX, + N_PROPS +}; + +static GParamSpec *obj_props[N_PROPS] = { 0 }; + static void clutter_input_device_evdev_finalize (GObject *object) { @@ -59,6 +69,47 @@ clutter_input_device_evdev_finalize (GObject *object) G_OBJECT_CLASS (clutter_input_device_evdev_parent_class)->finalize (object); } +static void +clutter_input_device_evdev_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterInputDeviceEvdev *device = CLUTTER_INPUT_DEVICE_EVDEV (object); + + switch (prop_id) + { + case PROP_DEVICE_MATRIX: + { + const cairo_matrix_t *matrix = g_value_get_boxed (value); + cairo_matrix_init_identity (&device->device_matrix); + cairo_matrix_multiply (&device->device_matrix, + &device->device_matrix, matrix); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +clutter_input_device_evdev_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterInputDeviceEvdev *device = CLUTTER_INPUT_DEVICE_EVDEV (object); + + switch (prop_id) + { + case PROP_DEVICE_MATRIX: + g_value_set_boxed (value, &device->device_matrix); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + static gboolean clutter_input_device_evdev_keycode_to_evdev (ClutterInputDevice *device, guint hardware_keycode, @@ -114,13 +165,26 @@ clutter_input_device_evdev_class_init (ClutterInputDeviceEvdevClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = clutter_input_device_evdev_finalize; + object_class->set_property = clutter_input_device_evdev_set_property; + object_class->get_property = clutter_input_device_evdev_get_property; + klass->keycode_to_evdev = clutter_input_device_evdev_keycode_to_evdev; klass->update_from_tool = clutter_input_device_evdev_update_from_tool; + + obj_props[PROP_DEVICE_MATRIX] = + g_param_spec_boxed ("device-matrix", + P_("Device input matrix"), + P_("Device input matrix"), + CAIRO_GOBJECT_TYPE_MATRIX, + CLUTTER_PARAM_READWRITE); + + g_object_class_install_properties (object_class, N_PROPS, obj_props); } static void clutter_input_device_evdev_init (ClutterInputDeviceEvdev *self) { + cairo_matrix_init_identity (&self->device_matrix); } /* @@ -313,3 +377,27 @@ clutter_evdev_event_sequence_get_slot (const ClutterEventSequence *sequence) return GPOINTER_TO_INT (sequence) - 1; } + +void +clutter_input_device_evdev_translate_coordinates (ClutterInputDevice *device, + ClutterStage *stage, + gfloat *x, + gfloat *y) +{ + ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device); + double min_x = 0, min_y = 0, max_x = 1, max_y = 1; + gdouble stage_width, stage_height; + double x_d, y_d; + + stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage)); + stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage)); + x_d = *x / stage_width; + y_d = *y / stage_height; + + cairo_matrix_transform_point (&device_evdev->device_matrix, &min_x, &min_y); + cairo_matrix_transform_point (&device_evdev->device_matrix, &max_x, &max_y); + cairo_matrix_transform_point (&device_evdev->device_matrix, &x_d, &y_d); + + *x = CLAMP (x_d, MIN (min_x, max_x), MAX (min_x, max_x)) * stage_width; + *y = CLAMP (y_d, MIN (min_y, max_y), MAX (min_y, max_y)) * stage_height; +} diff --git a/clutter/clutter/evdev/clutter-input-device-evdev.h b/clutter/clutter/evdev/clutter-input-device-evdev.h index be2c7ef8a..b462f0a0f 100644 --- a/clutter/clutter/evdev/clutter-input-device-evdev.h +++ b/clutter/clutter/evdev/clutter-input-device-evdev.h @@ -66,6 +66,8 @@ struct _ClutterInputDeviceEvdev struct libinput_device *libinput_device; ClutterSeatEvdev *seat; ClutterInputDeviceTool *last_tool; + + cairo_matrix_t device_matrix; }; GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST; @@ -102,6 +104,11 @@ void _clutter_evdev_event_set_relative_motion (ClutterEvent *event, double dx_unaccel, double dy_unaccel); +void clutter_input_device_evdev_translate_coordinates (ClutterInputDevice *device, + ClutterStage *stage, + gfloat *x, + gfloat *y); + G_END_DECLS #endif /* __CLUTTER_INPUT_DEVICE_EVDEV_H__ */