[clutter/wip/evdev-tablet-support: 4/6] evdev: Implement tablet events
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/wip/evdev-tablet-support: 4/6] evdev: Implement tablet events
- Date: Tue, 10 Feb 2015 22:33:43 +0000 (UTC)
commit 165efd86ae335904de256898669a41868fc85070
Author: Carlos Garnacho <carlosg gnome org>
Date: Fri Jan 9 17:38:42 2015 +0100
evdev: Implement tablet events
Tablet proximity, motion and button events are translated into ClutterEvents,
and the device state is updated accordingly.
clutter/evdev/clutter-device-manager-evdev.c | 246 ++++++++++++++++++++++++--
clutter/evdev/clutter-input-device-evdev.h | 1 +
2 files changed, 235 insertions(+), 12 deletions(-)
---
diff --git a/clutter/evdev/clutter-device-manager-evdev.c b/clutter/evdev/clutter-device-manager-evdev.c
index 2f53ea0..6bacb9d 100644
--- a/clutter/evdev/clutter-device-manager-evdev.c
+++ b/clutter/evdev/clutter-device-manager-evdev.c
@@ -373,7 +373,8 @@ notify_absolute_motion (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,
time_, &x, &y,
@@ -392,9 +393,16 @@ notify_absolute_motion (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);
queue_event (event);
@@ -506,23 +514,29 @@ 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:
- button_nr = button - BTN_MOUSE + 1;
+ if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+ button_nr = button - BTN_TOOL_PEN + 4;
+ else
+ button_nr = button - BTN_MOUSE + 1;
break;
}
- if (G_UNLIKELY (button_nr < 1 || button_nr > 8))
+ if (G_UNLIKELY (button_nr < 1 || button_nr > 11))
{
g_warning ("Unhandled button event 0x%x", button);
return;
@@ -533,23 +547,37 @@ 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];
+ }
event->button.time = time_;
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;
- clutter_input_device_get_coords (seat->core_pointer, NULL, &point);
+
+ if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
+ clutter_input_device_get_coords (input_device, NULL, &point);
+ else
+ clutter_input_device_get_coords (seat->core_pointer, NULL, &point);
+
event->button.x = point.x;
event->button.y = point.y;
- 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);
queue_event (event);
@@ -599,6 +627,42 @@ notify_touch_event (ClutterInputDevice *input_device,
}
static void
+notify_proximity (ClutterInputDevice *input_device,
+ guint32 time_,
+ 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)
+ 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);
+
+ event->proximity.time = time_;
+ 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;
@@ -1106,6 +1170,93 @@ _device_seat_get_touch (ClutterInputDevice *input_device,
return g_hash_table_lookup (seat->touches, GUINT_TO_POINTER (id));
}
+static ClutterInputDeviceToolType
+translate_tool_type (struct libinput_tool *libinput_tool)
+{
+ enum libinput_tool_type tool;
+
+ tool = libinput_tool_get_type (libinput_tool);
+
+ switch (tool)
+ {
+ case LIBINPUT_TOOL_PEN:
+ return CLUTTER_INPUT_DEVICE_TOOL_PEN;
+ case LIBINPUT_TOOL_ERASER:
+ return CLUTTER_INPUT_DEVICE_TOOL_ERASER;
+ case LIBINPUT_TOOL_BRUSH:
+ return CLUTTER_INPUT_DEVICE_TOOL_BRUSH;
+ case LIBINPUT_TOOL_PENCIL:
+ return CLUTTER_INPUT_DEVICE_TOOL_PENCIL;
+ case LIBINPUT_TOOL_AIRBRUSH:
+ return CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH;
+ case LIBINPUT_TOOL_FINGER:
+ return CLUTTER_INPUT_DEVICE_TOOL_FINGER;
+ case LIBINPUT_TOOL_MOUSE:
+ return CLUTTER_INPUT_DEVICE_TOOL_MOUSE;
+ case LIBINPUT_TOOL_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_tool *libinput_tool)
+{
+ ClutterInputDeviceEvdev *evdev_device = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
+ ClutterInputDeviceTool *tool = NULL;
+ ClutterInputDeviceToolType tool_type;
+ guint tool_serial;
+
+ if (libinput_tool)
+ {
+ tool_serial = libinput_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_new (tool_serial, tool_type,
+ libinput_tool_ref (libinput_tool),
+ (GDestroyNotify) libinput_tool_unref);
+ _clutter_input_device_add_tool (input_device, tool);
+ }
+ }
+
+ evdev_device->last_tool = tool;
+}
+
+static gdouble *
+translate_tablet_axes (struct libinput_event_tablet *tablet_event)
+{
+ GArray *axes = g_array_new (FALSE, FALSE, sizeof (gdouble));
+ struct libinput_tool *libinput_tool;
+ guint i;
+
+ libinput_tool = libinput_event_tablet_get_tool (tablet_event);
+
+ for (i = LIBINPUT_TABLET_AXIS_X; i <= LIBINPUT_TABLET_AXIS_TILT_Y; i++)
+ {
+ gdouble value;
+
+ if (!libinput_tool_has_axis (libinput_tool, i))
+ continue;
+
+ value = libinput_event_tablet_get_axis_value (tablet_event, i);
+ 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)
@@ -1370,6 +1521,77 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
break;
}
+ case LIBINPUT_EVENT_TABLET_AXIS:
+ {
+ guint32 time;
+ double x, y, *axes;
+ gfloat stage_width, stage_height;
+ ClutterStage *stage;
+ struct libinput_event_tablet *tablet_event =
+ libinput_event_get_tablet_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_get_time (tablet_event);
+ x = libinput_event_tablet_get_x_transformed (tablet_event, stage_width);
+ y = libinput_event_tablet_get_y_transformed (tablet_event, stage_height);
+
+ notify_absolute_motion (device, time, x, y, axes);
+ break;
+ }
+ case LIBINPUT_EVENT_TABLET_PROXIMITY_IN:
+ {
+ guint32 time;
+ struct libinput_event_tablet *tablet_event =
+ libinput_event_get_tablet_event (event);
+ struct libinput_tool *libinput_tool;
+
+ time = libinput_event_tablet_get_time (tablet_event);
+ libinput_tool = libinput_event_tablet_get_tool (tablet_event);
+
+ device = libinput_device_get_user_data (libinput_device);
+ input_device_update_tool (device, libinput_tool);
+ notify_proximity (device, time, TRUE);
+ break;
+ }
+ case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
+ {
+ guint32 time;
+ struct libinput_event_tablet *tablet_event =
+ libinput_event_get_tablet_event (event);
+
+ time = libinput_event_tablet_get_time (tablet_event);
+ device = libinput_device_get_user_data (libinput_device);
+ input_device_update_tool (device, NULL);
+ notify_proximity (device, time, FALSE);
+ break;
+ }
+ case LIBINPUT_EVENT_TABLET_BUTTON:
+ {
+ guint32 time, button_state;
+ struct libinput_event_tablet *tablet_event =
+ libinput_event_get_tablet_event (event);
+ guint tablet_button;
+
+ device = libinput_device_get_user_data (libinput_device);
+ time = libinput_event_tablet_get_time (tablet_event);
+ tablet_button = libinput_event_tablet_get_button (tablet_event);
+
+ button_state = libinput_event_tablet_get_button_state (tablet_event) ==
+ LIBINPUT_BUTTON_STATE_PRESSED;
+ notify_button (device, time, tablet_button, 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 06f3d86..3caefc2 100644
--- a/clutter/evdev/clutter-input-device-evdev.h
+++ b/clutter/evdev/clutter-input-device-evdev.h
@@ -64,6 +64,7 @@ struct _ClutterInputDeviceEvdev
struct libinput_device *libinput_device;
ClutterSeatEvdev *seat;
+ ClutterInputDeviceTool *last_tool;
};
GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]