summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2015-01-09 17:38:42 +0100
committerCarlos Garnacho <carlosg@gnome.org>2016-04-05 18:56:35 +0200
commit69e32ad20a06e909b22087770c8e9b0451056372 (patch)
tree42a92c07189b4edb38c9dd3a2f8d7447ed385ed4
parentfa1f5db5978c678194c656db2442b024151627ae (diff)
downloadclutter-69e32ad20a06e909b22087770c8e9b0451056372.tar.gz
evdev: Implement tablet events
Tablet proximity, motion and button events are translated into ClutterEvents, and the device state is updated accordingly.
-rw-r--r--clutter/evdev/clutter-device-manager-evdev.c293
-rw-r--r--clutter/evdev/clutter-input-device-evdev.h1
2 files changed, 282 insertions, 12 deletions
diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c
index 9c682754c..3645d287b 100644
--- a/clutter/evdev/clutter-device-manager-evdev.c
+++ b/clutter/evdev/clutter-device-manager-evdev.c
@@ -53,6 +53,7 @@
#include "clutter-backend-private.h"
#include "clutter-evdev.h"
#include "clutter-stage-private.h"
+#include "clutter-input-device-tool-evdev.h"
#include "clutter-device-manager-evdev.h"
@@ -450,7 +451,8 @@ new_absolute_motion_event (ClutterInputDevice *input_device,
event = clutter_event_new (CLUTTER_MOTION);
- if (manager_evdev->priv->constrain_callback)
+ if (manager_evdev->priv->constrain_callback &&
+ clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
{
manager_evdev->priv->constrain_callback (seat->core_pointer,
us2ms (time_us),
@@ -473,9 +475,16 @@ new_absolute_motion_event (ClutterInputDevice *input_device,
event->motion.x = x;
event->motion.y = y;
event->motion.axes = axes;
- clutter_event_set_device (event, seat->core_pointer);
clutter_event_set_source_device (event, input_device);
+ if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+ {
+ clutter_event_set_device_tool (event, device_evdev->last_tool);
+ clutter_event_set_device (event, input_device);
+ }
+ else
+ clutter_event_set_device (event, seat->core_pointer);
+
_clutter_input_device_set_stage (seat->core_pointer, stage);
seat->pointer_x = x;
@@ -683,20 +692,26 @@ notify_button (ClutterInputDevice *input_device,
switch (button)
{
case BTN_LEFT:
+ case BTN_TOUCH:
button_nr = CLUTTER_BUTTON_PRIMARY;
break;
case BTN_RIGHT:
+ case BTN_STYLUS:
button_nr = CLUTTER_BUTTON_SECONDARY;
break;
case BTN_MIDDLE:
+ case BTN_STYLUS2:
button_nr = CLUTTER_BUTTON_MIDDLE;
break;
default:
/* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */
- button_nr = button - (BTN_LEFT - 1) + 4;
+ if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+ button_nr = button - BTN_TOOL_PEN + 4;
+ else
+ button_nr = button - (BTN_LEFT - 1) + 4;
break;
}
@@ -711,25 +726,47 @@ notify_button (ClutterInputDevice *input_device,
else
event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
- /* Update the modifiers */
- if (state)
- seat->button_state |= maskmap[button - BTN_LEFT];
- else
- seat->button_state &= ~maskmap[button - BTN_LEFT];
+ if (button_nr < G_N_ELEMENTS (maskmap))
+ {
+ /* Update the modifiers */
+ if (state)
+ seat->button_state |= maskmap[button_nr - 1];
+ else
+ seat->button_state &= ~maskmap[button_nr - 1];
+ }
_clutter_evdev_event_set_time_usec (event, time_us);
event->button.time = us2ms (time_us);
event->button.stage = CLUTTER_STAGE (stage);
- event->button.device = seat->core_pointer;
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
event->button.button = button_nr;
- event->button.x = seat->pointer_x;
- event->button.y = seat->pointer_y;
- clutter_event_set_device (event, seat->core_pointer);
+
+ if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+ {
+ ClutterPoint point;
+
+ clutter_input_device_get_coords (input_device, NULL, &point);
+ event->button.x = point.x;
+ event->button.y = point.y;
+ }
+ else
+ {
+ event->button.x = seat->pointer_x;
+ event->button.y = seat->pointer_y;
+ }
+
clutter_event_set_source_device (event, input_device);
_clutter_evdev_event_set_event_code (event, button);
+ if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+ {
+ clutter_event_set_device_tool (event, device_evdev->last_tool);
+ clutter_event_set_device (event, input_device);
+ }
+ else
+ clutter_event_set_device (event, seat->core_pointer);
+
_clutter_input_device_set_stage (seat->core_pointer, stage);
queue_event (event);
@@ -872,6 +909,44 @@ notify_swipe_gesture_event (ClutterInputDevice *input_device,
}
static void
+notify_proximity (ClutterInputDevice *input_device,
+ guint64 time_us,
+ gboolean in)
+{
+ ClutterInputDeviceEvdev *device_evdev;
+ ClutterSeatEvdev *seat;
+ ClutterStage *stage;
+ ClutterEvent *event = NULL;
+
+ /* We can drop the event on the floor if no stage has been
+ * associated with the device yet. */
+ stage = _clutter_input_device_get_stage (input_device);
+ if (stage == NULL)
+ return;
+
+ device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
+ seat = _clutter_input_device_evdev_get_seat (device_evdev);
+
+ if (in)
+ event = clutter_event_new (CLUTTER_PROXIMITY_IN);
+ else
+ event = clutter_event_new (CLUTTER_PROXIMITY_OUT);
+
+ _clutter_evdev_event_set_time_usec (event, time_us);
+
+ event->proximity.time = us2ms (time_us);
+ event->proximity.stage = CLUTTER_STAGE (stage);
+ event->proximity.device = seat->core_pointer;
+ clutter_event_set_device_tool (event, device_evdev->last_tool);
+ clutter_event_set_device (event, seat->core_pointer);
+ clutter_event_set_source_device (event, input_device);
+
+ _clutter_input_device_set_stage (seat->core_pointer, stage);
+
+ queue_event (event);
+}
+
+static void
dispatch_libinput (ClutterDeviceManagerEvdev *manager_evdev)
{
ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
@@ -1433,6 +1508,122 @@ translate_scroll_source (enum libinput_pointer_axis_source source)
}
}
+static ClutterInputDeviceToolType
+translate_tool_type (struct libinput_tablet_tool *libinput_tool)
+{
+ enum libinput_tablet_tool_type tool;
+
+ tool = libinput_tablet_tool_get_type (libinput_tool);
+
+ switch (tool)
+ {
+ case LIBINPUT_TABLET_TOOL_TYPE_PEN:
+ return CLUTTER_INPUT_DEVICE_TOOL_PEN;
+ case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
+ return CLUTTER_INPUT_DEVICE_TOOL_ERASER;
+ case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
+ return CLUTTER_INPUT_DEVICE_TOOL_BRUSH;
+ case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
+ return CLUTTER_INPUT_DEVICE_TOOL_PENCIL;
+ case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
+ return CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH;
+ case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
+ return CLUTTER_INPUT_DEVICE_TOOL_MOUSE;
+ case LIBINPUT_TABLET_TOOL_TYPE_LENS:
+ return CLUTTER_INPUT_DEVICE_TOOL_LENS;
+ default:
+ return CLUTTER_INPUT_DEVICE_TOOL_NONE;
+ }
+}
+
+static void
+input_device_update_tool (ClutterInputDevice *input_device,
+ struct libinput_tablet_tool *libinput_tool)
+{
+ ClutterInputDeviceEvdev *evdev_device = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
+ ClutterInputDeviceTool *tool = NULL;
+ ClutterInputDeviceToolType tool_type;
+ guint64 tool_serial;
+
+ if (libinput_tool)
+ {
+ tool_serial = libinput_tablet_tool_get_serial (libinput_tool);
+ tool_type = translate_tool_type (libinput_tool);
+ tool = clutter_input_device_lookup_tool (input_device,
+ tool_serial, tool_type);
+
+ if (!tool)
+ {
+ tool = clutter_input_device_tool_evdev_new (libinput_tool,
+ tool_serial, tool_type);
+ clutter_input_device_add_tool (input_device, tool);
+ }
+ }
+
+ evdev_device->last_tool = tool;
+}
+
+static gdouble *
+translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event)
+{
+ GArray *axes = g_array_new (FALSE, FALSE, sizeof (gdouble));
+ struct libinput_tablet_tool *libinput_tool;
+ gdouble value;
+
+ libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event);
+
+ value = libinput_event_tablet_tool_get_x (tablet_event);
+ g_array_append_val (axes, value);
+ value = libinput_event_tablet_tool_get_y (tablet_event);
+ g_array_append_val (axes, value);
+
+ if (libinput_tablet_tool_has_distance (libinput_tool))
+ {
+ value = libinput_event_tablet_tool_get_distance (tablet_event);
+ g_array_append_val (axes, value);
+ }
+
+ if (libinput_tablet_tool_has_pressure (libinput_tool))
+ {
+ value = libinput_event_tablet_tool_get_pressure (tablet_event);
+ g_array_append_val (axes, value);
+ }
+
+ if (libinput_tablet_tool_has_tilt (libinput_tool))
+ {
+ value = libinput_event_tablet_tool_get_tilt_x (tablet_event);
+ g_array_append_val (axes, value);
+ value = libinput_event_tablet_tool_get_tilt_y (tablet_event);
+ g_array_append_val (axes, value);
+ }
+
+ if (libinput_tablet_tool_has_rotation (libinput_tool))
+ {
+ value = libinput_event_tablet_tool_get_rotation (tablet_event);
+ g_array_append_val (axes, value);
+ }
+
+ if (libinput_tablet_tool_has_slider (libinput_tool))
+ {
+ value = libinput_event_tablet_tool_get_slider_position (tablet_event);
+ g_array_append_val (axes, value);
+ }
+
+ if (libinput_tablet_tool_has_wheel (libinput_tool))
+ {
+ value = libinput_event_tablet_tool_get_wheel_delta (tablet_event);
+ g_array_append_val (axes, value);
+ }
+
+ if (axes->len == 0)
+ {
+ g_array_free (axes, TRUE);
+ return NULL;
+ }
+ else
+ return (gdouble *) g_array_free (axes, FALSE);
+}
+
static gboolean
process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
struct libinput_event *event)
@@ -1812,6 +2003,84 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
time_us, n_fingers, dx, dy);
break;
}
+ case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
+ {
+ guint64 time;
+ double x, y, *axes;
+ gfloat stage_width, stage_height;
+ ClutterStage *stage;
+ struct libinput_event_tablet_tool *tablet_event =
+ libinput_event_get_tablet_tool_event (event);
+ device = libinput_device_get_user_data (libinput_device);
+
+ stage = _clutter_input_device_get_stage (device);
+ if (!stage)
+ break;
+
+ axes = translate_tablet_axes (tablet_event);
+ if (!axes)
+ break;
+
+ stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
+ stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
+
+ time = libinput_event_tablet_tool_get_time_usec (tablet_event);
+ x = libinput_event_tablet_tool_get_x_transformed (tablet_event, stage_width);
+ y = libinput_event_tablet_tool_get_y_transformed (tablet_event, stage_height);
+
+ notify_absolute_motion (device, time, x, y, axes);
+ break;
+ }
+ case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
+ {
+ guint64 time;
+ struct libinput_event_tablet_tool *tablet_event =
+ libinput_event_get_tablet_tool_event (event);
+ struct libinput_tablet_tool *libinput_tool = NULL;
+ enum libinput_tablet_tool_proximity_state state;
+
+ state = libinput_event_tablet_tool_get_proximity_state (tablet_event);
+ time = libinput_event_tablet_tool_get_time_usec (tablet_event);
+ device = libinput_device_get_user_data (libinput_device);
+
+ libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event);
+
+ input_device_update_tool (device, libinput_tool);
+ notify_proximity (device, time, state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
+ break;
+ }
+ case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
+ {
+ guint64 time;
+ guint32 button_state;
+ struct libinput_event_tablet_tool *tablet_event =
+ libinput_event_get_tablet_tool_event (event);
+ guint tablet_button;
+
+ device = libinput_device_get_user_data (libinput_device);
+ time = libinput_event_tablet_tool_get_time_usec (tablet_event);
+ tablet_button = libinput_event_tablet_tool_get_button (tablet_event);
+
+ button_state = libinput_event_tablet_tool_get_button_state (tablet_event) ==
+ LIBINPUT_BUTTON_STATE_PRESSED;
+ notify_button (device, time, tablet_button, button_state);
+ break;
+ }
+ case LIBINPUT_EVENT_TABLET_TOOL_TIP:
+ {
+ guint64 time;
+ guint32 button_state;
+ struct libinput_event_tablet_tool *tablet_event =
+ libinput_event_get_tablet_tool_event (event);
+
+ device = libinput_device_get_user_data (libinput_device);
+ time = libinput_event_tablet_tool_get_time_usec (tablet_event);
+
+ button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) ==
+ LIBINPUT_TABLET_TOOL_TIP_DOWN;
+ notify_button (device, time, BTN_TOUCH, button_state);
+ break;
+ }
default:
handled = FALSE;
}
diff --git a/clutter/evdev/clutter-input-device-evdev.h b/clutter/evdev/clutter-input-device-evdev.h
index c5c3eff5f..88d98d92d 100644
--- a/clutter/evdev/clutter-input-device-evdev.h
+++ b/clutter/evdev/clutter-input-device-evdev.h
@@ -65,6 +65,7 @@ struct _ClutterInputDeviceEvdev
struct libinput_device *libinput_device;
ClutterSeatEvdev *seat;
+ ClutterInputDeviceTool *last_tool;
};
GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST;