evdev: Implement tablet events
Tablet proximity, motion and button events are translated into ClutterEvents, and the device state is updated accordingly.
This commit is contained in:
parent
bc8b3d9f39
commit
7004818508
2 changed files with 282 additions and 12 deletions
|
@ -53,6 +53,7 @@
|
||||||
#include "clutter-backend-private.h"
|
#include "clutter-backend-private.h"
|
||||||
#include "clutter-evdev.h"
|
#include "clutter-evdev.h"
|
||||||
#include "clutter-stage-private.h"
|
#include "clutter-stage-private.h"
|
||||||
|
#include "clutter-input-device-tool-evdev.h"
|
||||||
|
|
||||||
#include "clutter-device-manager-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);
|
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,
|
manager_evdev->priv->constrain_callback (seat->core_pointer,
|
||||||
us2ms (time_us),
|
us2ms (time_us),
|
||||||
|
@ -473,9 +475,16 @@ new_absolute_motion_event (ClutterInputDevice *input_device,
|
||||||
event->motion.x = x;
|
event->motion.x = x;
|
||||||
event->motion.y = y;
|
event->motion.y = y;
|
||||||
event->motion.axes = axes;
|
event->motion.axes = axes;
|
||||||
clutter_event_set_device (event, seat->core_pointer);
|
|
||||||
clutter_event_set_source_device (event, input_device);
|
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);
|
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||||
|
|
||||||
seat->pointer_x = x;
|
seat->pointer_x = x;
|
||||||
|
@ -683,19 +692,25 @@ notify_button (ClutterInputDevice *input_device,
|
||||||
switch (button)
|
switch (button)
|
||||||
{
|
{
|
||||||
case BTN_LEFT:
|
case BTN_LEFT:
|
||||||
|
case BTN_TOUCH:
|
||||||
button_nr = CLUTTER_BUTTON_PRIMARY;
|
button_nr = CLUTTER_BUTTON_PRIMARY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BTN_RIGHT:
|
case BTN_RIGHT:
|
||||||
|
case BTN_STYLUS:
|
||||||
button_nr = CLUTTER_BUTTON_SECONDARY;
|
button_nr = CLUTTER_BUTTON_SECONDARY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BTN_MIDDLE:
|
case BTN_MIDDLE:
|
||||||
|
case BTN_STYLUS2:
|
||||||
button_nr = CLUTTER_BUTTON_MIDDLE;
|
button_nr = CLUTTER_BUTTON_MIDDLE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */
|
/* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */
|
||||||
|
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;
|
button_nr = button - (BTN_LEFT - 1) + 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -711,25 +726,47 @@ notify_button (ClutterInputDevice *input_device,
|
||||||
else
|
else
|
||||||
event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
|
event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
|
||||||
|
|
||||||
|
if (button_nr < G_N_ELEMENTS (maskmap))
|
||||||
|
{
|
||||||
/* Update the modifiers */
|
/* Update the modifiers */
|
||||||
if (state)
|
if (state)
|
||||||
seat->button_state |= maskmap[button - BTN_LEFT];
|
seat->button_state |= maskmap[button_nr - 1];
|
||||||
else
|
else
|
||||||
seat->button_state &= ~maskmap[button - BTN_LEFT];
|
seat->button_state &= ~maskmap[button_nr - 1];
|
||||||
|
}
|
||||||
|
|
||||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||||
event->button.time = us2ms (time_us);
|
event->button.time = us2ms (time_us);
|
||||||
event->button.stage = CLUTTER_STAGE (stage);
|
event->button.stage = CLUTTER_STAGE (stage);
|
||||||
event->button.device = seat->core_pointer;
|
|
||||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||||
event->button.button = button_nr;
|
event->button.button = button_nr;
|
||||||
|
|
||||||
|
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.x = seat->pointer_x;
|
||||||
event->button.y = seat->pointer_y;
|
event->button.y = seat->pointer_y;
|
||||||
clutter_event_set_device (event, seat->core_pointer);
|
}
|
||||||
|
|
||||||
clutter_event_set_source_device (event, input_device);
|
clutter_event_set_source_device (event, input_device);
|
||||||
|
|
||||||
_clutter_evdev_event_set_event_code (event, button);
|
_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);
|
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||||
|
|
||||||
queue_event (event);
|
queue_event (event);
|
||||||
|
@ -871,6 +908,44 @@ notify_swipe_gesture_event (ClutterInputDevice *input_device,
|
||||||
queue_event (event);
|
queue_event (event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
dispatch_libinput (ClutterDeviceManagerEvdev *manager_evdev)
|
dispatch_libinput (ClutterDeviceManagerEvdev *manager_evdev)
|
||||||
{
|
{
|
||||||
|
@ -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
|
static gboolean
|
||||||
process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||||
struct libinput_event *event)
|
struct libinput_event *event)
|
||||||
|
@ -1812,6 +2003,84 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||||
time_us, n_fingers, dx, dy);
|
time_us, n_fingers, dx, dy);
|
||||||
break;
|
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:
|
default:
|
||||||
handled = FALSE;
|
handled = FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ struct _ClutterInputDeviceEvdev
|
||||||
|
|
||||||
struct libinput_device *libinput_device;
|
struct libinput_device *libinput_device;
|
||||||
ClutterSeatEvdev *seat;
|
ClutterSeatEvdev *seat;
|
||||||
|
ClutterInputDeviceTool *last_tool;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST;
|
GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST;
|
||||||
|
|
Loading…
Reference in a new issue