clutter/evdev: Move keyboard and pointer notification into seat

We notify per seat; so lets move the logic there. Touch and tablets to
follow later.

https://bugzilla.gnome.org/show_bug.cgi?id=765009
This commit is contained in:
Jonas Ådahl 2016-06-17 17:42:16 -04:00 committed by Carlos Garnacho
parent e38a8363e4
commit 94016f7257
4 changed files with 458 additions and 290 deletions

View File

@ -61,8 +61,6 @@
#define DISCRETE_SCROLL_STEP 10.0 #define DISCRETE_SCROLL_STEP 10.0
#define AUTOREPEAT_VALUE 2
/* /*
* Clutter makes the assumption that two core devices have ID's 2 and 3 (core * Clutter makes the assumption that two core devices have ID's 2 and 3 (core
@ -154,24 +152,6 @@ static const char *option_xkb_layout = "us";
static const char *option_xkb_variant = ""; static const char *option_xkb_variant = "";
static const char *option_xkb_options = ""; static const char *option_xkb_options = "";
static inline guint64
us (guint64 us)
{
return us;
}
static inline guint64
ms2us (guint64 ms)
{
return us (ms * 1000);
}
static inline guint32
us2ms (guint64 us)
{
return (guint32) (us / 1000);
}
static void static void
clutter_device_manager_evdev_copy_event_data (ClutterEventExtender *event_extender, clutter_device_manager_evdev_copy_event_data (ClutterEventExtender *event_extender,
const ClutterEvent *src, const ClutterEvent *src,
@ -255,120 +235,34 @@ queue_event (ClutterEvent *event)
_clutter_event_push (event, FALSE); _clutter_event_push (event, FALSE);
} }
static gboolean void
keyboard_repeat (gpointer data); _clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev,
ClutterInputDevice *core_pointer,
static void uint64_t time_us,
notify_key_device (ClutterInputDevice *input_device, float x,
guint64 time_us, float y,
guint32 key, float *new_x,
guint32 state, float *new_y)
gboolean update_keys)
{ {
ClutterInputDeviceEvdev *device_evdev = if (manager_evdev->priv->constrain_callback)
CLUTTER_INPUT_DEVICE_EVDEV (input_device);
ClutterSeatEvdev *seat = _clutter_input_device_evdev_get_seat (device_evdev);
ClutterStage *stage;
ClutterEvent *event = NULL;
enum xkb_state_component changed_state;
/* 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)
{ {
clutter_seat_evdev_clear_repeat_timer (seat); manager_evdev->priv->constrain_callback (core_pointer,
return; us2ms (time_us),
} x, y,
new_x, new_y,
event = _clutter_key_event_new_from_evdev (input_device, manager_evdev->priv->constrain_data);
seat->core_keyboard,
stage,
seat->xkb,
seat->button_state,
us2ms (time_us), key, state);
_clutter_evdev_event_set_event_code (event, key);
/* We must be careful and not pass multiple releases to xkb, otherwise it gets
confused and locks the modifiers */
if (state != AUTOREPEAT_VALUE)
{
changed_state = xkb_state_update_key (seat->xkb,
event->key.hardware_keycode,
state ? XKB_KEY_DOWN : XKB_KEY_UP);
} }
else else
{ {
changed_state = 0; ClutterActor *stage = CLUTTER_ACTOR (manager_evdev->priv->stage);
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC); float stage_width = clutter_actor_get_width (stage);
} float stage_height = clutter_actor_get_height (stage);
queue_event (event); x = CLAMP (x, 0.f, stage_width - 1);
y = CLAMP (y, 0.f, stage_height - 1);
if (update_keys && (changed_state & XKB_STATE_LEDS))
clutter_seat_evdev_sync_leds (seat);
if (state == 0 || /* key release */
!seat->repeat ||
!xkb_keymap_key_repeats (xkb_state_get_keymap (seat->xkb), event->key.hardware_keycode))
{
clutter_seat_evdev_clear_repeat_timer (seat);
return;
}
if (state == 1) /* key press */
seat->repeat_count = 0;
seat->repeat_count += 1;
seat->repeat_key = key;
switch (seat->repeat_count)
{
case 1:
case 2:
{
guint32 interval;
clutter_seat_evdev_clear_repeat_timer (seat);
seat->repeat_device = g_object_ref (input_device);
if (seat->repeat_count == 1)
interval = seat->repeat_delay;
else
interval = seat->repeat_interval;
seat->repeat_timer =
clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS,
interval,
keyboard_repeat,
seat,
NULL);
return;
}
default:
return;
} }
} }
static gboolean
keyboard_repeat (gpointer data)
{
ClutterSeatEvdev *seat = data;
GSource *source;
guint32 time_ms;
g_return_val_if_fail (seat->repeat_device != NULL, G_SOURCE_REMOVE);
source = g_main_context_find_source_by_id (NULL, seat->repeat_timer);
time_ms = g_source_get_time (source) / 1000;
notify_key_device (seat->repeat_device,
ms2us (time_ms),
seat->repeat_key,
AUTOREPEAT_VALUE,
FALSE);
return G_SOURCE_CONTINUE;
}
static ClutterEvent * static ClutterEvent *
new_absolute_motion_event (ClutterInputDevice *input_device, new_absolute_motion_event (ClutterInputDevice *input_device,
@ -453,45 +347,6 @@ notify_absolute_motion (ClutterInputDevice *input_device,
queue_event (event); queue_event (event);
} }
static void
notify_relative_motion (ClutterInputDevice *input_device,
struct libinput_event_pointer *pointer_event)
{
guint64 time_us;
double dx;
double dy;
double dx_unaccel;
double dy_unaccel;
gfloat new_x, new_y;
ClutterInputDeviceEvdev *device_evdev;
ClutterSeatEvdev *seat;
ClutterEvent *event;
/* We can drop the event on the floor if no stage has been
* associated with the device yet. */
if (!_clutter_input_device_get_stage (input_device))
return;
device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
seat = _clutter_input_device_evdev_get_seat (device_evdev);
dx = libinput_event_pointer_get_dx (pointer_event);
dy = libinput_event_pointer_get_dy (pointer_event);
new_x = seat->pointer_x + dx;
new_y = seat->pointer_y + dy;
time_us = libinput_event_pointer_get_time_usec (pointer_event);
event = new_absolute_motion_event (input_device, time_us, new_x, new_y, NULL);
dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event);
dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event);
_clutter_evdev_event_set_relative_motion (event,
dx, dy,
dx_unaccel, dy_unaccel);
queue_event (event);
}
static void static void
notify_relative_tool_motion (ClutterInputDevice *input_device, notify_relative_tool_motion (ClutterInputDevice *input_device,
guint64 time_us, guint64 time_us,
@ -624,118 +479,6 @@ notify_scroll (ClutterInputDevice *input_device,
queue_event (event); queue_event (event);
} }
static void
notify_button (ClutterInputDevice *input_device,
guint64 time_us,
guint32 button,
guint32 state)
{
ClutterInputDeviceEvdev *device_evdev;
ClutterSeatEvdev *seat;
ClutterStage *stage;
ClutterEvent *event = NULL;
gint button_nr;
static gint maskmap[8] =
{
CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK,
CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0
};
/* 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);
/* The evdev button numbers don't map sequentially to clutter button
* numbers (the right and middle mouse buttons are in the opposite
* order) so we'll map them directly with a switch statement */
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 */
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;
}
if (button_nr < 1 || button_nr > 12)
{
g_warning ("Unhandled button event 0x%x", button);
return;
}
if (state)
event = clutter_event_new (CLUTTER_BUTTON_PRESS);
else
event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
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);
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
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.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);
}
static void static void
notify_touch_event (ClutterInputDevice *input_device, notify_touch_event (ClutterInputDevice *input_device,
ClutterEventType evtype, ClutterEventType evtype,
@ -1529,6 +1272,14 @@ translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event)
return (gdouble *) g_array_free (axes, FALSE); return (gdouble *) g_array_free (axes, FALSE);
} }
static ClutterSeatEvdev *
seat_from_device (ClutterInputDevice *device)
{
ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
return _clutter_input_device_evdev_get_seat (device_evdev);
}
static gboolean static gboolean
process_device_event (ClutterDeviceManagerEvdev *manager_evdev, process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
struct libinput_event *event) struct libinput_event *event)
@ -1545,8 +1296,8 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
guint64 time_us; guint64 time_us;
struct libinput_event_keyboard *key_event = struct libinput_event_keyboard *key_event =
libinput_event_get_keyboard_event (event); libinput_event_get_keyboard_event (event);
device = libinput_device_get_user_data (libinput_device);
device = libinput_device_get_user_data (libinput_device);
time_us = libinput_event_keyboard_get_time_usec (key_event); time_us = libinput_event_keyboard_get_time_usec (key_event);
key = libinput_event_keyboard_get_key (key_event); key = libinput_event_keyboard_get_key (key_event);
key_state = libinput_event_keyboard_get_key_state (key_event) == key_state = libinput_event_keyboard_get_key_state (key_event) ==
@ -1561,18 +1312,35 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
seat_key_count != 0)) seat_key_count != 0))
break; break;
notify_key_device (device, time_us, key, key_state, TRUE); clutter_seat_evdev_notify_key (seat_from_device (device),
device,
time_us, key, key_state, TRUE);
break; break;
} }
case LIBINPUT_EVENT_POINTER_MOTION: case LIBINPUT_EVENT_POINTER_MOTION:
{ {
struct libinput_event_pointer *motion_event = struct libinput_event_pointer *pointer_event =
libinput_event_get_pointer_event (event); libinput_event_get_pointer_event (event);
device = libinput_device_get_user_data (libinput_device); uint64_t time_us;
double dx;
double dy;
double dx_unaccel;
double dy_unaccel;
notify_relative_motion (device, motion_event); device = libinput_device_get_user_data (libinput_device);
time_us = libinput_event_pointer_get_time_usec (pointer_event);
dx = libinput_event_pointer_get_dx (pointer_event);
dy = libinput_event_pointer_get_dy (pointer_event);
dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event);
dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event);
clutter_seat_evdev_notify_relative_motion (seat_from_device (device),
device,
time_us,
dx, dy,
dx_unaccel, dy_unaccel);
break; break;
} }
@ -1599,7 +1367,12 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
stage_width); stage_width);
y = libinput_event_pointer_get_absolute_y_transformed (motion_event, y = libinput_event_pointer_get_absolute_y_transformed (motion_event,
stage_height); stage_height);
notify_absolute_motion (device, time_us, x, y, NULL);
clutter_seat_evdev_notify_absolute_motion (seat_from_device (device),
device,
time_us,
x, y,
NULL);
break; break;
} }
@ -1626,8 +1399,8 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
seat_button_count != 0)) seat_button_count != 0))
break; break;
notify_button (device, time_us, button, button_state); clutter_seat_evdev_notify_button (seat_from_device (device), device,
time_us, button, button_state);
break; break;
} }
@ -1980,34 +1753,38 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
} }
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
{ {
guint64 time; guint64 time_us;
guint32 button_state; guint32 button_state;
struct libinput_event_tablet_tool *tablet_event = struct libinput_event_tablet_tool *tablet_event =
libinput_event_get_tablet_tool_event (event); libinput_event_get_tablet_tool_event (event);
guint tablet_button; guint tablet_button;
device = libinput_device_get_user_data (libinput_device); device = libinput_device_get_user_data (libinput_device);
time = libinput_event_tablet_tool_get_time_usec (tablet_event); time_us = libinput_event_tablet_tool_get_time_usec (tablet_event);
tablet_button = libinput_event_tablet_tool_get_button (tablet_event); tablet_button = libinput_event_tablet_tool_get_button (tablet_event);
button_state = libinput_event_tablet_tool_get_button_state (tablet_event) == button_state = libinput_event_tablet_tool_get_button_state (tablet_event) ==
LIBINPUT_BUTTON_STATE_PRESSED; LIBINPUT_BUTTON_STATE_PRESSED;
notify_button (device, time, tablet_button, button_state);
clutter_seat_evdev_notify_button (seat_from_device (device), device,
time_us, tablet_button, button_state);
break; break;
} }
case LIBINPUT_EVENT_TABLET_TOOL_TIP: case LIBINPUT_EVENT_TABLET_TOOL_TIP:
{ {
guint64 time; guint64 time_us;
guint32 button_state; guint32 button_state;
struct libinput_event_tablet_tool *tablet_event = struct libinput_event_tablet_tool *tablet_event =
libinput_event_get_tablet_tool_event (event); libinput_event_get_tablet_tool_event (event);
device = libinput_device_get_user_data (libinput_device); device = libinput_device_get_user_data (libinput_device);
time = libinput_event_tablet_tool_get_time_usec (tablet_event); time_us = libinput_event_tablet_tool_get_time_usec (tablet_event);
button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) == button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) ==
LIBINPUT_TABLET_TOOL_TIP_DOWN; LIBINPUT_TABLET_TOOL_TIP_DOWN;
notify_button (device, time, BTN_TOUCH, button_state);
clutter_seat_evdev_notify_button (seat_from_device (device), device,
time_us, BTN_TOUCH, button_state);
break; break;
} }
case LIBINPUT_EVENT_TABLET_PAD_BUTTON: case LIBINPUT_EVENT_TABLET_PAD_BUTTON:

View File

@ -68,6 +68,32 @@ struct xkb_keymap * _clutter_device_manager_evdev_get_keymap (ClutterDeviceManag
ClutterStage * _clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev); ClutterStage * _clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev);
void _clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev,
ClutterInputDevice *core_pointer,
uint64_t time_us,
float x,
float y,
float *new_x,
float *new_y);
static inline guint64
us (guint64 us)
{
return us;
}
static inline guint64
ms2us (guint64 ms)
{
return us (ms * 1000);
}
static inline guint32
us2ms (guint64 us)
{
return (guint32) (us / 1000);
}
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_DEVICE_MANAGER_EVDEV_H__ */ #endif /* __CLUTTER_DEVICE_MANAGER_EVDEV_H__ */

View File

@ -28,13 +28,19 @@
#include "clutter-seat-evdev.h" #include "clutter-seat-evdev.h"
#include <linux/input.h>
#include "clutter-event-private.h"
#include "clutter-input-device-evdev.h" #include "clutter-input-device-evdev.h"
#include "clutter-main.h"
/* Try to keep the pointer inside the stage. Hopefully no one is using /* Try to keep the pointer inside the stage. Hopefully no one is using
* this backend with stages smaller than this. */ * this backend with stages smaller than this. */
#define INITIAL_POINTER_X 16 #define INITIAL_POINTER_X 16
#define INITIAL_POINTER_Y 16 #define INITIAL_POINTER_Y 16
#define AUTOREPEAT_VALUE 2
void void
clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat, clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat,
struct libinput_seat *libinput_seat) struct libinput_seat *libinput_seat)
@ -172,6 +178,337 @@ clutter_seat_evdev_clear_repeat_timer (ClutterSeatEvdev *seat)
} }
} }
static gboolean
keyboard_repeat (gpointer data)
{
ClutterSeatEvdev *seat = data;
GSource *source;
guint32 time_ms;
g_return_val_if_fail (seat->repeat_device != NULL, G_SOURCE_REMOVE);
source = g_main_context_find_source_by_id (NULL, seat->repeat_timer);
time_ms = g_source_get_time (source) / 1000;
clutter_seat_evdev_notify_key (seat,
seat->repeat_device,
ms2us (time_ms),
seat->repeat_key,
AUTOREPEAT_VALUE,
FALSE);
return G_SOURCE_CONTINUE;
}
static void
queue_event (ClutterEvent *event)
{
_clutter_event_push (event, FALSE);
}
void
clutter_seat_evdev_notify_key (ClutterSeatEvdev *seat,
ClutterInputDevice *device,
uint64_t time_us,
uint32_t key,
uint32_t state,
gboolean update_keys)
{
ClutterStage *stage;
ClutterEvent *event = NULL;
enum xkb_state_component changed_state;
/* We can drop the event on the floor if no stage has been
* associated with the device yet. */
stage = _clutter_input_device_get_stage (device);
if (stage == NULL)
{
clutter_seat_evdev_clear_repeat_timer (seat);
return;
}
event = _clutter_key_event_new_from_evdev (device,
seat->core_keyboard,
stage,
seat->xkb,
seat->button_state,
us2ms (time_us), key, state);
_clutter_evdev_event_set_event_code (event, key);
/* We must be careful and not pass multiple releases to xkb, otherwise it gets
confused and locks the modifiers */
if (state != AUTOREPEAT_VALUE)
{
changed_state = xkb_state_update_key (seat->xkb,
event->key.hardware_keycode,
state ? XKB_KEY_DOWN : XKB_KEY_UP);
}
else
{
changed_state = 0;
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC);
}
queue_event (event);
if (update_keys && (changed_state & XKB_STATE_LEDS))
clutter_seat_evdev_sync_leds (seat);
if (state == 0 || /* key release */
!seat->repeat ||
!xkb_keymap_key_repeats (xkb_state_get_keymap (seat->xkb),
event->key.hardware_keycode))
{
clutter_seat_evdev_clear_repeat_timer (seat);
return;
}
if (state == 1) /* key press */
seat->repeat_count = 0;
seat->repeat_count += 1;
seat->repeat_key = key;
switch (seat->repeat_count)
{
case 1:
case 2:
{
guint32 interval;
clutter_seat_evdev_clear_repeat_timer (seat);
seat->repeat_device = g_object_ref (device);
if (seat->repeat_count == 1)
interval = seat->repeat_delay;
else
interval = seat->repeat_interval;
seat->repeat_timer =
clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS,
interval,
keyboard_repeat,
seat,
NULL);
return;
}
default:
return;
}
}
static ClutterEvent *
new_absolute_motion_event (ClutterSeatEvdev *seat,
ClutterInputDevice *input_device,
guint64 time_us,
gfloat x,
gfloat y,
gdouble *axes)
{
ClutterStage *stage = _clutter_input_device_get_stage (input_device);
ClutterEvent *event;
event = clutter_event_new (CLUTTER_MOTION);
if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
_clutter_device_manager_evdev_constrain_pointer (seat->manager_evdev,
seat->core_pointer,
time_us,
seat->pointer_x,
seat->pointer_y,
&x, &y);
_clutter_evdev_event_set_time_usec (event, time_us);
event->motion.time = us2ms (time_us);
event->motion.stage = stage;
event->motion.device = seat->core_pointer;
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
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)
{
ClutterInputDeviceEvdev *device_evdev =
CLUTTER_INPUT_DEVICE_EVDEV (input_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);
if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
{
seat->pointer_x = x;
seat->pointer_y = y;
}
return event;
}
void
clutter_seat_evdev_notify_relative_motion (ClutterSeatEvdev *seat,
ClutterInputDevice *input_device,
uint64_t time_us,
float dx,
float dy,
float dx_unaccel,
float dy_unaccel)
{
gfloat new_x, new_y;
ClutterEvent *event;
/* We can drop the event on the floor if no stage has been
* associated with the device yet. */
if (!_clutter_input_device_get_stage (input_device))
return;
new_x = seat->pointer_x + dx;
new_y = seat->pointer_y + dy;
event = new_absolute_motion_event (seat, input_device,
time_us, new_x, new_y, NULL);
_clutter_evdev_event_set_relative_motion (event,
dx, dy,
dx_unaccel, dy_unaccel);
queue_event (event);
}
void clutter_seat_evdev_notify_absolute_motion (ClutterSeatEvdev *seat,
ClutterInputDevice *input_device,
uint64_t time_us,
float x,
float y,
double *axes)
{
ClutterEvent *event;
event = new_absolute_motion_event (seat, input_device, time_us, x, x, axes);
queue_event (event);
}
void
clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat,
ClutterInputDevice *input_device,
uint64_t time_us,
uint32_t button,
uint32_t state)
{
ClutterStage *stage;
ClutterEvent *event = NULL;
gint button_nr;
static gint maskmap[8] =
{
CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK,
CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0
};
/* 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;
/* The evdev button numbers don't map sequentially to clutter button
* numbers (the right and middle mouse buttons are in the opposite
* order) so we'll map them directly with a switch statement */
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 */
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;
}
if (button_nr < 1 || button_nr > 12)
{
g_warning ("Unhandled button event 0x%x", button);
return;
}
if (state)
event = clutter_event_new (CLUTTER_BUTTON_PRESS);
else
event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
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);
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
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.y = seat->pointer_y;
}
clutter_event_set_device (event, seat->core_pointer);
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)
{
ClutterInputDeviceEvdev *device_evdev =
CLUTTER_INPUT_DEVICE_EVDEV (input_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);
}
void void
clutter_seat_evdev_free (ClutterSeatEvdev *seat) clutter_seat_evdev_free (ClutterSeatEvdev *seat)
{ {

View File

@ -76,6 +76,34 @@ struct _ClutterSeatEvdev
gfloat accum_scroll_dy; gfloat accum_scroll_dy;
}; };
void clutter_seat_evdev_notify_key (ClutterSeatEvdev *seat,
ClutterInputDevice *device,
uint64_t time_us,
uint32_t key,
uint32_t state,
gboolean update_keys);
void clutter_seat_evdev_notify_relative_motion (ClutterSeatEvdev *seat_evdev,
ClutterInputDevice *input_device,
uint64_t time_us,
float dx,
float dy,
float dx_unaccel,
float dy_unaccel);
void clutter_seat_evdev_notify_absolute_motion (ClutterSeatEvdev *seat_evdev,
ClutterInputDevice *input_device,
uint64_t time_us,
float x,
float y,
double *axes);
void clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat,
ClutterInputDevice *input_device,
uint64_t time_us,
uint32_t button,
uint32_t state);
void clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat, void clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat,
struct libinput_seat *libinput_seat); struct libinput_seat *libinput_seat);