Commit cc838ead authored by Carlos Garnacho's avatar Carlos Garnacho

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
parent 9a123847
......@@ -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);
......
......@@ -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;
}
......@@ -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__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment