backends/x11: Use new event constructors

Use the new event constructors to create input events, instead
of creating them through clutter_event_new (CLUTTER_NOTHING) and
struct field fiddling.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3153>
This commit is contained in:
Carlos Garnacho 2023-08-02 20:50:26 +02:00
parent 845277f7fb
commit 75e8bab1c1
3 changed files with 319 additions and 355 deletions

View File

@ -67,17 +67,12 @@ meta_backend_x11_handle_event (MetaBackend *backend,
META_STAGE_X11 (clutter_backend_get_stage_window (clutter_backend)); META_STAGE_X11 (clutter_backend_get_stage_window (clutter_backend));
meta_stage_x11_handle_event (stage_x11, xevent); meta_stage_x11_handle_event (stage_x11, xevent);
event = clutter_event_new (CLUTTER_NOTHING);
seat_x11 = META_SEAT_X11 (meta_backend_get_default_seat (backend)); seat_x11 = META_SEAT_X11 (meta_backend_get_default_seat (backend));
if (meta_seat_x11_translate_event (seat_x11, xevent, event)) event = meta_seat_x11_translate_event (seat_x11, xevent);
{ if (!event)
_clutter_event_push (event, FALSE); goto out;
}
else _clutter_event_push (event, FALSE);
{
clutter_event_free (event);
goto out;
}
/* /*
* Motion events can generate synthetic enter and leave events, so if we * Motion events can generate synthetic enter and leave events, so if we

View File

@ -876,15 +876,14 @@ device_get_tool_serial (MetaSeatX11 *seat_x11,
return serial_id; return serial_id;
} }
static gboolean static ClutterEvent *
translate_hierarchy_event (ClutterBackend *clutter_backend, translate_hierarchy_event (ClutterBackend *clutter_backend,
MetaSeatX11 *seat_x11, MetaSeatX11 *seat_x11,
XIHierarchyEvent *ev, XIHierarchyEvent *ev)
ClutterEvent *event)
{ {
Display *xdisplay = xdisplay_from_seat (seat_x11); Display *xdisplay = xdisplay_from_seat (seat_x11);
int i; int i;
gboolean retval = FALSE; ClutterEvent *event = NULL;
for (i = 0; i < ev->num_info; i++) for (i = 0; i < ev->num_info; i++)
{ {
@ -908,11 +907,10 @@ translate_hierarchy_event (ClutterBackend *clutter_backend,
device = add_device (seat_x11, clutter_backend, &info[0]); device = add_device (seat_x11, clutter_backend, &info[0]);
event->any.type = CLUTTER_DEVICE_ADDED; event = clutter_event_device_notify_new (CLUTTER_DEVICE_ADDED,
event->any.time = ev->time; CLUTTER_EVENT_NONE,
clutter_event_set_device (event, device); ms2us (ev->time),
device);
retval = TRUE;
XIFreeDeviceInfo (info); XIFreeDeviceInfo (info);
} }
} }
@ -930,11 +928,10 @@ translate_hierarchy_event (ClutterBackend *clutter_backend,
{ {
remove_device (seat_x11, device); remove_device (seat_x11, device);
event->any.type = CLUTTER_DEVICE_REMOVED; event = clutter_event_device_notify_new (CLUTTER_DEVICE_REMOVED,
event->any.time = ev->time; CLUTTER_EVENT_NONE,
clutter_event_set_device (event, device); ms2us (ev->time),
device);
retval = TRUE;
} }
} }
else if ((ev->info[i].flags & XISlaveAttached) || else if ((ev->info[i].flags & XISlaveAttached) ||
@ -947,7 +944,7 @@ translate_hierarchy_event (ClutterBackend *clutter_backend,
} }
} }
return retval; return event;
} }
static void static void
@ -1005,17 +1002,18 @@ emulate_motion (MetaSeatX11 *seat_x11,
{ {
ClutterInputDevice *pointer; ClutterInputDevice *pointer;
ClutterEvent *event; ClutterEvent *event;
ClutterStage *stage;
pointer = clutter_seat_get_pointer (CLUTTER_SEAT (seat_x11)); pointer = clutter_seat_get_pointer (CLUTTER_SEAT (seat_x11));
stage = CLUTTER_STAGE (meta_backend_get_stage (seat_x11->backend));
event = clutter_event_new (CLUTTER_MOTION); event = clutter_event_motion_new (CLUTTER_EVENT_FLAG_SYNTHETIC,
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC); CLUTTER_CURRENT_TIME,
clutter_event_set_coords (event, x, y); pointer,
clutter_event_set_device (event, pointer); NULL, 0,
clutter_event_set_source_device (event, NULL); GRAPHENE_POINT_INIT (x, y),
clutter_event_set_stage (event, stage); GRAPHENE_POINT_INIT (0, 0),
GRAPHENE_POINT_INIT (0, 0),
GRAPHENE_POINT_INIT (0, 0),
NULL);
clutter_event_put (event); clutter_event_put (event);
clutter_event_free (event); clutter_event_free (event);
@ -1127,17 +1125,17 @@ translate_pad_axis (ClutterInputDevice *device,
return FALSE; return FALSE;
} }
static gboolean static ClutterEvent *
translate_pad_event (ClutterEvent *event, translate_pad_axis_event (XIDeviceEvent *xev,
XIDeviceEvent *xev, ClutterInputDevice *device)
ClutterInputDevice *device)
{ {
double value; double value;
uint32_t number, mode = 0; uint32_t number, mode = 0;
ClutterEventType evtype;
ClutterEvent *event = NULL;
if (!translate_pad_axis (device, &xev->valuators, if (!translate_pad_axis (device, &xev->valuators,
&event->any.type, &evtype, &number, &value))
&number, &value))
return FALSE; return FALSE;
/* When touching a ring/strip a first XI_Motion event /* When touching a ring/strip a first XI_Motion event
@ -1151,34 +1149,40 @@ translate_pad_event (ClutterEvent *event,
mode = meta_input_device_x11_get_pad_group_mode (device, number); mode = meta_input_device_x11_get_pad_group_mode (device, number);
#endif #endif
if (event->any.type == CLUTTER_PAD_RING) if (evtype == CLUTTER_PAD_RING)
{ {
event->pad_ring.ring_number = number; event = clutter_event_pad_ring_new (CLUTTER_EVENT_NONE,
event->pad_ring.angle = value; ms2us (xev->time),
event->pad_ring.mode = mode; device,
CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN,
number,
0,
value,
mode);
} }
else else
{ {
event->pad_strip.strip_number = number; event = clutter_event_pad_strip_new (CLUTTER_EVENT_NONE,
event->pad_strip.value = value; ms2us (xev->time),
event->pad_strip.mode = mode; device,
CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN,
number,
0,
value,
mode);
} }
event->any.time = xev->time; g_debug ("%s: win:0x%x, device:%d '%s', time:%lu "
clutter_event_set_device (event, device);
clutter_event_set_source_device (event, device);
g_debug ("%s: win:0x%x, device:%d '%s', time:%d "
"(value:%f)", "(value:%f)",
event->any.type == CLUTTER_PAD_RING evtype == CLUTTER_PAD_RING
? "pad ring " ? "pad ring "
: "pad strip", : "pad strip",
(unsigned int) xev->event, (unsigned int) xev->event,
meta_input_device_x11_get_device_id (device), meta_input_device_x11_get_device_id (device),
clutter_input_device_get_device_name (device), clutter_input_device_get_device_name (device),
event->any.time, value); xev->time, value);
return TRUE; return event;
} }
static ClutterStage * static ClutterStage *
@ -1476,9 +1480,10 @@ meta_seat_x11_notify_devices (MetaSeatX11 *seat_x11,
{ {
ClutterEvent *event; ClutterEvent *event;
event = clutter_event_new (CLUTTER_DEVICE_ADDED); event = clutter_event_device_notify_new (CLUTTER_DEVICE_ADDED,
clutter_event_set_device (event, device); CLUTTER_EVENT_NONE,
clutter_event_set_stage (event, stage); CLUTTER_CURRENT_TIME,
device);
clutter_event_put (event); clutter_event_put (event);
clutter_event_free (event); clutter_event_free (event);
} }
@ -1998,41 +2003,60 @@ evdev_button_code (uint32_t x_button)
return button; return button;
} }
gboolean static ClutterModifierType
get_modifier_for_button (int i)
{
switch (i)
{
case 1:
return CLUTTER_BUTTON1_MASK;
case 2:
return CLUTTER_BUTTON2_MASK;
case 3:
return CLUTTER_BUTTON3_MASK;
case 4:
return CLUTTER_BUTTON4_MASK;
case 5:
return CLUTTER_BUTTON5_MASK;
default:
return 0;
}
}
ClutterEvent *
meta_seat_x11_translate_event (MetaSeatX11 *seat, meta_seat_x11_translate_event (MetaSeatX11 *seat,
XEvent *xevent, XEvent *xevent)
ClutterEvent *event)
{ {
Display *xdisplay = xdisplay_from_seat (seat); Display *xdisplay = xdisplay_from_seat (seat);
ClutterBackend *clutter_backend = ClutterBackend *clutter_backend =
meta_backend_get_clutter_backend (seat->backend); meta_backend_get_clutter_backend (seat->backend);
gboolean retval = FALSE;
ClutterStage *stage = NULL; ClutterStage *stage = NULL;
MetaStageX11 *stage_x11 = NULL; MetaStageX11 *stage_x11 = NULL;
ClutterInputDevice *device, *source_device; ClutterInputDevice *device, *source_device;
XGenericEventCookie *cookie; XGenericEventCookie *cookie;
ClutterEvent *event = NULL;
XIEvent *xi_event; XIEvent *xi_event;
if (meta_keymap_x11_handle_event (seat->keymap, xevent)) if (meta_keymap_x11_handle_event (seat->keymap, xevent))
return FALSE; return NULL;
cookie = &xevent->xcookie; cookie = &xevent->xcookie;
if (cookie->type != GenericEvent || if (cookie->type != GenericEvent ||
cookie->extension != seat->opcode) cookie->extension != seat->opcode)
return FALSE; return NULL;
xi_event = (XIEvent *) cookie->data; xi_event = (XIEvent *) cookie->data;
if (!xi_event) if (!xi_event)
return FALSE; return NULL;
if (cookie->evtype == XI_RawMotion || if (cookie->evtype == XI_RawMotion ||
cookie->evtype == XI_RawButtonPress || cookie->evtype == XI_RawButtonPress ||
cookie->evtype == XI_RawButtonRelease) cookie->evtype == XI_RawButtonRelease)
{ {
translate_raw_event (seat, xevent); translate_raw_event (seat, xevent);
return FALSE; return NULL;
} }
if (!(xi_event->evtype == XI_DeviceChanged || if (!(xi_event->evtype == XI_DeviceChanged ||
@ -2040,20 +2064,18 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
{ {
stage = get_event_stage (seat, xi_event); stage = get_event_stage (seat, xi_event);
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
return FALSE; return NULL;
else else
stage_x11 = META_STAGE_X11 (_clutter_stage_get_window (stage)); stage_x11 = META_STAGE_X11 (_clutter_stage_get_window (stage));
} }
event->any.stage = stage;
switch (xi_event->evtype) switch (xi_event->evtype)
{ {
case XI_HierarchyChanged: case XI_HierarchyChanged:
{ {
XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event; XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event;
retval = translate_hierarchy_event (clutter_backend, seat, xev, event); event = translate_hierarchy_event (clutter_backend, seat, xev);
} }
break; break;
@ -2077,7 +2099,6 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
if (source_device) if (source_device)
meta_input_device_x11_reset_scroll_info (source_device); meta_input_device_x11_reset_scroll_info (source_device);
} }
retval = FALSE;
break; break;
case XI_KeyPress: case XI_KeyPress:
case XI_KeyRelease: case XI_KeyRelease:
@ -2085,56 +2106,58 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
MetaKeymapX11 *keymap_x11 = seat->keymap; MetaKeymapX11 *keymap_x11 = seat->keymap;
char buffer[7] = { 0, }; char buffer[7] = { 0, };
gunichar n; uint32_t keyval, evcode, keycode;
ClutterModifierType state;
int len;
gunichar unicode_value;
source_device = get_source_device_checked (seat, xev); source_device = get_source_device_checked (seat, xev);
if (!source_device) if (!source_device)
return FALSE; return NULL;
event->key.type = event->type = (xev->evtype == XI_KeyPress) state = translate_state (&xev->buttons, &xev->mods, &xev->group);
? CLUTTER_KEY_PRESS
: CLUTTER_KEY_RELEASE;
if (xev->evtype == XI_KeyPress && xev->flags & XIKeyRepeat) keycode = xev->detail;
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_REPEATED);
event->key.time = xev->time;
event->key.stage = stage;
meta_input_device_x11_translate_state (event, &xev->mods, &xev->buttons, &xev->group);
event->key.hardware_keycode = xev->detail;
/* clutter-xkb-utils.c adds a fixed offset of 8 to go into XKB's /* clutter-xkb-utils.c adds a fixed offset of 8 to go into XKB's
* range, so we do the reverse here. */ * range, so we do the reverse here. */
event->key.evdev_code = event->key.hardware_keycode - 8; evcode = keycode - 8;
/* keyval is the key ignoring all modifiers ('1' vs. '!') */ /* keyval is the key ignoring all modifiers ('1' vs. '!') */
event->key.keyval = keyval = meta_keymap_x11_translate_key_state (keymap_x11,
meta_keymap_x11_translate_key_state (keymap_x11, keycode,
event->key.hardware_keycode, &state,
&event->key.modifier_state, NULL);
NULL);
clutter_event_set_source_device (event, source_device);
device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
clutter_event_set_device (event, device);
/* XXX keep this in sync with the evdev device manager */ /* XXX keep this in sync with the evdev device manager */
n = print_keysym (event->key.keyval, buffer, sizeof (buffer)); len = print_keysym (keyval, buffer, sizeof (buffer));
if (n == 0) if (len == 0)
{ {
/* not printable */ /* not printable */
event->key.unicode_value = (gunichar) '\0'; unicode_value = (gunichar) '\0';
} }
else else
{ {
event->key.unicode_value = g_utf8_get_char_validated (buffer, n); unicode_value = g_utf8_get_char_validated (buffer, len);
if (event->key.unicode_value == -1 || if (unicode_value == -1 ||
event->key.unicode_value == -2) unicode_value == -2)
event->key.unicode_value = (gunichar) '\0'; unicode_value = (gunichar) '\0';
} }
event = clutter_event_key_new ((xev->evtype == XI_KeyPress) ?
CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE,
(xev->evtype == XI_KeyPress &&
xev->flags & XIKeyRepeat) ?
CLUTTER_EVENT_FLAG_REPEATED :
CLUTTER_EVENT_NONE,
ms2us (xev->time),
source_device,
state,
keyval,
evcode,
keycode,
unicode_value);
g_debug ("%s: win:0x%x device:%d source:%d, key: %12s (%d)", g_debug ("%s: win:0x%x device:%d source:%d, key: %12s (%d)",
event->any.type == CLUTTER_KEY_PRESS event->any.type == CLUTTER_KEY_PRESS
? "key press " ? "key press "
@ -2142,13 +2165,11 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
(unsigned int) stage_x11->xwin, (unsigned int) stage_x11->xwin,
xev->deviceid, xev->deviceid,
xev->sourceid, xev->sourceid,
event->key.keyval ? buffer : "(none)", keyval ? buffer : "(none)",
event->key.keyval); keyval);
if (xi_event->evtype == XI_KeyPress) if (xi_event->evtype == XI_KeyPress)
meta_stage_x11_set_user_time (stage_x11, event->key.time); meta_stage_x11_set_user_time (stage_x11, xev->time);
retval = TRUE;
} }
break; break;
@ -2156,37 +2177,35 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
case XI_ButtonRelease: case XI_ButtonRelease:
{ {
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
ClutterScrollDirection scroll_direction;
ClutterModifierType state;
ClutterInputDeviceTool *tool;
float x, y;
int button;
uint32_t evdev_code;
double *axes;
source_device = get_source_device_checked (seat, xev); source_device = get_source_device_checked (seat, xev);
if (!source_device) if (!source_device)
return FALSE; return NULL;
device = g_hash_table_lookup (seat->devices_by_id, device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->deviceid)); GINT_TO_POINTER (xev->deviceid));
if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE) if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE)
{ {
uint32_t button, group, mode;
/* We got these events because of the passive button grab */ /* We got these events because of the passive button grab */
XIAllowEvents (xdisplay, xev->sourceid, XIAsyncDevice, xev->time); XIAllowEvents (xdisplay, xev->sourceid, XIAsyncDevice, xev->time);
event->any.stage = stage;
if (xev->detail >= 4 && xev->detail <= 7) if (xev->detail >= 4 && xev->detail <= 7)
{ {
retval = FALSE; if (xi_event->evtype == XI_ButtonPress)
event = translate_pad_axis_event (xev, source_device);
if (xi_event->evtype == XI_ButtonPress &&
translate_pad_event (event, xev, source_device))
retval = TRUE;
break; break;
} }
event->any.type =
(xi_event->evtype == XI_ButtonPress) ? CLUTTER_PAD_BUTTON_PRESS
: CLUTTER_PAD_BUTTON_RELEASE;
event->any.time = xev->time;
/* The 4-7 button range is taken as non-existent on pad devices, /* The 4-7 button range is taken as non-existent on pad devices,
* let the buttons above that take over this range. * let the buttons above that take over this range.
*/ */
@ -2194,28 +2213,36 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
xev->detail -= 4; xev->detail -= 4;
/* Pad buttons are 0-indexed */ /* Pad buttons are 0-indexed */
event->pad_button.button = xev->detail - 1; button = xev->detail - 1;
#ifdef HAVE_LIBWACOM #ifdef HAVE_LIBWACOM
meta_input_device_x11_update_pad_state (device, meta_input_device_x11_update_pad_state (device,
event->pad_button.button, button,
(xi_event->evtype == XI_ButtonPress), (xi_event->evtype == XI_ButtonPress),
&event->pad_button.group, &group,
&event->pad_button.mode); &mode);
#endif #endif
clutter_event_set_device (event, device);
clutter_event_set_source_device (event, source_device);
g_debug ("%s: win:0x%x, device:%d '%s', time:%d " event = clutter_event_pad_button_new ((xi_event->evtype == XI_ButtonPress) ?
CLUTTER_PAD_BUTTON_PRESS :
CLUTTER_PAD_BUTTON_RELEASE,
CLUTTER_EVENT_NONE,
us2ms (xev->time),
source_device,
button,
group,
mode);
g_debug ("%s: win:0x%x, device:%d '%s', time:%lu "
"(button:%d)", "(button:%d)",
event->any.type == CLUTTER_BUTTON_PRESS (xi_event->evtype == XI_ButtonPress)
? "pad button press " ? "pad button press "
: "pad button release", : "pad button release",
(unsigned int) stage_x11->xwin, (unsigned int) stage_x11->xwin,
meta_input_device_x11_get_device_id (device), meta_input_device_x11_get_device_id (device),
clutter_input_device_get_device_name (device), clutter_input_device_get_device_name (device),
event->any.time, xev->time,
event->pad_button.button); button);
retval = TRUE;
break; break;
} }
@ -2227,35 +2254,29 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
case 7: case 7:
/* we only generate Scroll events on ButtonPress */ /* we only generate Scroll events on ButtonPress */
if (xi_event->evtype == XI_ButtonRelease) if (xi_event->evtype == XI_ButtonRelease)
return FALSE; return NULL;
event->scroll.type = event->type = CLUTTER_SCROLL;
if (xev->detail == 4) if (xev->detail == 4)
event->scroll.direction = CLUTTER_SCROLL_UP; scroll_direction = CLUTTER_SCROLL_UP;
else if (xev->detail == 5) else if (xev->detail == 5)
event->scroll.direction = CLUTTER_SCROLL_DOWN; scroll_direction = CLUTTER_SCROLL_DOWN;
else if (xev->detail == 6) else if (xev->detail == 6)
event->scroll.direction = CLUTTER_SCROLL_LEFT; scroll_direction = CLUTTER_SCROLL_LEFT;
else else
event->scroll.direction = CLUTTER_SCROLL_RIGHT; scroll_direction = CLUTTER_SCROLL_RIGHT;
event->scroll.stage = stage; translate_coords (stage_x11, xev->event_x, xev->event_y, &x, &y);
state = translate_state (&xev->buttons, &xev->mods, &xev->group);
tool = meta_input_device_x11_get_current_tool (source_device);
event->scroll.time = xev->time; event = clutter_event_scroll_discrete_new (CLUTTER_EVENT_NONE,
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->scroll.x, &event->scroll.y); ms2us (xev->time),
meta_input_device_x11_translate_state (event, source_device,
&xev->mods, tool,
&xev->buttons, state,
&xev->group); GRAPHENE_POINT_INIT (x, y),
scroll_direction);
clutter_event_set_source_device (event, source_device);
clutter_event_set_device (event, device);
event->scroll.axes = translate_axes (event->scroll.device,
event->scroll.x,
event->scroll.y,
&xev->valuators);
g_debug ("scroll: win:0x%x, device:%d '%s', time:%d " g_debug ("scroll: win:0x%x, device:%d '%s', time:%d "
"(direction:%s, " "(direction:%s, "
"x:%.2f, y:%.2f, " "x:%.2f, y:%.2f, "
@ -2275,57 +2296,66 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
break; break;
default: default:
event->button.type = event->type = translate_coords (stage_x11, xev->event_x, xev->event_y, &x, &y);
(xi_event->evtype == XI_ButtonPress) ? CLUTTER_BUTTON_PRESS button = xev->detail;
: CLUTTER_BUTTON_RELEASE; evdev_code = evdev_button_code (xev->detail);
state = translate_state (&xev->buttons, &xev->mods, &xev->group);
tool = meta_input_device_x11_get_current_tool (source_device);
axes = translate_axes (device, x, y, &xev->valuators);
event->button.stage = stage; /* The XIButtonState sent in the event specifies the
* state of the buttons before the event. In order to
* get the current state of the buttons, we need to
* filter out the current button.
*/
switch (xi_event->evtype)
{
case XI_ButtonPress:
state |= (get_modifier_for_button (button));
break;
case XI_ButtonRelease:
state &= ~(get_modifier_for_button (button));
break;
default:
break;
}
event->button.time = xev->time; event = clutter_event_button_new ((xi_event->evtype == XI_ButtonPress) ?
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->button.x, &event->button.y); CLUTTER_BUTTON_PRESS :
event->button.button = xev->detail; CLUTTER_BUTTON_RELEASE,
event->button.evdev_code = evdev_button_code (xev->detail); (xev->flags & XIPointerEmulated) ?
meta_input_device_x11_translate_state (event, CLUTTER_EVENT_FLAG_POINTER_EMULATED :
&xev->mods, CLUTTER_EVENT_NONE,
&xev->buttons, ms2us (xev->time),
&xev->group); source_device,
tool,
state,
GRAPHENE_POINT_INIT (x, y),
button,
evdev_code,
axes);
clutter_event_set_source_device (event, source_device); g_debug ("%s: win:0x%x, device:%d '%s', time:%lu "
clutter_event_set_device (event, device);
clutter_event_set_device_tool (event,
meta_input_device_x11_get_current_tool (source_device));
event->button.axes = translate_axes (event->button.device,
event->button.x,
event->button.y,
&xev->valuators);
g_debug ("%s: win:0x%x, device:%d '%s', time:%d "
"(button:%d, " "(button:%d, "
"x:%.2f, y:%.2f, " "x:%.2f, y:%.2f, "
"axes:%s, " "axes:%s, "
"emulated:%s)", "emulated:%s)",
event->any.type == CLUTTER_BUTTON_PRESS (xi_event->evtype == XI_ButtonPress)
? "button press " ? "button press "
: "button release", : "button release",
(unsigned int) stage_x11->xwin, (unsigned int) stage_x11->xwin,
meta_input_device_x11_get_device_id (device), meta_input_device_x11_get_device_id (device),
clutter_input_device_get_device_name (device), clutter_input_device_get_device_name (device),
event->any.time, xev->time,
event->button.button, xev->detail,
event->button.x, x, y,
event->button.y, axes != NULL ? "yes" : "no",
event->button.axes != NULL ? "yes" : "no",
(xev->flags & XIPointerEmulated) ? "yes" : "no"); (xev->flags & XIPointerEmulated) ? "yes" : "no");
break; break;
} }
if (xev->flags & XIPointerEmulated)
event->any.flags |= CLUTTER_EVENT_FLAG_POINTER_EMULATED;
if (xi_event->evtype == XI_ButtonPress) if (xi_event->evtype == XI_ButtonPress)
meta_stage_x11_set_user_time (stage_x11, event->button.time); meta_stage_x11_set_user_time (stage_x11, xev->time);
retval = TRUE;
} }
break; break;
@ -2333,213 +2363,172 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
{ {
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
double delta_x, delta_y; double delta_x, delta_y;
ClutterModifierType state;
ClutterInputDeviceTool *tool;
float x, y;
double *axes;
source_device = get_source_device_checked (seat, xev); source_device = get_source_device_checked (seat, xev);
if (!source_device) if (!source_device)
return FALSE; break;
device = g_hash_table_lookup (seat->devices_by_id, device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->deviceid)); GINT_TO_POINTER (xev->deviceid));
if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE) if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE)
{ {
event->any.stage = stage; event = translate_pad_axis_event (xev, source_device);
if (translate_pad_event (event, xev, source_device))
retval = TRUE;
break; break;
} }
translate_coords (stage_x11, xev->event_x, xev->event_y, &x, &y);
state = translate_state (&xev->buttons, &xev->mods, &xev->group);
tool = meta_input_device_x11_get_current_tool (source_device);
if (scroll_valuators_changed (source_device, if (scroll_valuators_changed (source_device,
&xev->valuators, &xev->valuators,
&delta_x, &delta_y)) &delta_x, &delta_y))
{ {
event->scroll.type = event->type = CLUTTER_SCROLL; event = clutter_event_scroll_smooth_new (CLUTTER_EVENT_NONE,
event->scroll.direction = CLUTTER_SCROLL_SMOOTH; ms2us (xev->time),
source_device,
event->scroll.stage = stage; tool,
event->scroll.time = xev->time; state,
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->scroll.x, &event->scroll.y); GRAPHENE_POINT_INIT (x, y),
meta_input_device_x11_translate_state (event, GRAPHENE_POINT_INIT (delta_x, delta_y),
&xev->mods, CLUTTER_SCROLL_SOURCE_UNKNOWN,
&xev->buttons, CLUTTER_SCROLL_FINISHED_NONE);
&xev->group);
clutter_event_set_scroll_delta (event, delta_x, delta_y);
clutter_event_set_source_device (event, source_device);
clutter_event_set_device (event, device);
g_debug ("smooth scroll: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, delta:%f, %f)", g_debug ("smooth scroll: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, delta:%f, %f)",
(unsigned int) stage_x11->xwin, (unsigned int) stage_x11->xwin,
meta_input_device_x11_get_device_id (event->scroll.device), meta_input_device_x11_get_device_id (event->scroll.device),
clutter_input_device_get_device_name (event->scroll.device), clutter_input_device_get_device_name (event->scroll.device),
event->scroll.x, x, y,
event->scroll.y,
delta_x, delta_y); delta_x, delta_y);
retval = TRUE;
break; break;
} }
event->motion.type = event->type = CLUTTER_MOTION; axes = translate_axes (device, x, y, &xev->valuators);
event = clutter_event_motion_new ((xev->flags & XIPointerEmulated) ?
event->motion.stage = stage; CLUTTER_EVENT_FLAG_POINTER_EMULATED :
CLUTTER_EVENT_NONE,
event->motion.time = xev->time; ms2us (xev->time),
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->motion.x, &event->motion.y); source_device,
meta_input_device_x11_translate_state (event, tool,
&xev->mods, state,
&xev->buttons, GRAPHENE_POINT_INIT (x, y),
&xev->group); GRAPHENE_POINT_INIT (0, 0),
GRAPHENE_POINT_INIT (0, 0),
clutter_event_set_source_device (event, source_device); GRAPHENE_POINT_INIT (0, 0),
clutter_event_set_device (event, device); axes);
clutter_event_set_device_tool (event,
meta_input_device_x11_get_current_tool (source_device));
event->motion.axes = translate_axes (event->motion.device,
event->motion.x,
event->motion.y,
&xev->valuators);
if (xev->flags & XIPointerEmulated)
event->any.flags |= CLUTTER_EVENT_FLAG_POINTER_EMULATED;
g_debug ("motion: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, axes:%s)", g_debug ("motion: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, axes:%s)",
(unsigned int) stage_x11->xwin, (unsigned int) stage_x11->xwin,
meta_input_device_x11_get_device_id (event->motion.device), meta_input_device_x11_get_device_id (event->motion.device),
clutter_input_device_get_device_name (event->motion.device), clutter_input_device_get_device_name (event->motion.device),
event->motion.x, x, y,
event->motion.y, axes != NULL ? "yes" : "no");
event->motion.axes != NULL ? "yes" : "no");
retval = TRUE;
} }
break; break;
case XI_TouchBegin: case XI_TouchBegin:
{
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
}
/* Fall through */
case XI_TouchEnd: case XI_TouchEnd:
{ {
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
ClutterEventType evtype;
ClutterModifierType state;
ClutterEventSequence *sequence;
float x, y;
device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
source_device = g_hash_table_lookup (seat->devices_by_id, source_device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->sourceid)); GINT_TO_POINTER (xev->sourceid));
if (xi_event->evtype == XI_TouchBegin) if (xi_event->evtype == XI_TouchBegin)
event->touch.type = event->type = CLUTTER_TOUCH_BEGIN; evtype = CLUTTER_TOUCH_BEGIN;
else else
event->touch.type = event->type = CLUTTER_TOUCH_END; evtype = CLUTTER_TOUCH_END;
event->touch.stage = stage; translate_coords (stage_x11, xev->event_x, xev->event_y, &x, &y);
event->touch.time = xev->time; state = translate_state (&xev->buttons, &xev->mods, &xev->group);
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->touch.x, &event->touch.y); /* "NULL" sequences are special cased in clutter */
meta_input_device_x11_translate_state (event, sequence = GINT_TO_POINTER (MAX (1, xev->detail + 1));
&xev->mods,
&xev->buttons,
&xev->group);
clutter_event_set_source_device (event, source_device);
device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
clutter_event_set_device (event, device);
event->touch.axes = translate_axes (event->touch.device,
event->motion.x,
event->motion.y,
&xev->valuators);
if (xi_event->evtype == XI_TouchBegin) if (xi_event->evtype == XI_TouchBegin)
{ {
event->touch.modifier_state |= CLUTTER_BUTTON1_MASK; state |= CLUTTER_BUTTON1_MASK;
meta_stage_x11_set_user_time (stage_x11, event->touch.time); meta_stage_x11_set_user_time (stage_x11, xev->time);
meta_seat_x11_update_touchpoint (seat, meta_seat_x11_update_touchpoint (seat,
GUINT_TO_POINTER (xev->detail), sequence,
xev->root_x, xev->root_x,
xev->root_y); xev->root_y);
} }
else if (xi_event->evtype == XI_TouchEnd) else if (xi_event->evtype == XI_TouchEnd)
{ {
meta_seat_x11_remove_touchpoint (seat, meta_seat_x11_remove_touchpoint (seat, sequence);
GUINT_TO_POINTER (xev->detail));
} }
/* "NULL" sequences are special cased in clutter */ event = clutter_event_touch_new (evtype,
event->touch.sequence = GINT_TO_POINTER (MAX (1, xev->detail + 1)); (xev->flags & XITouchEmulatingPointer) ?
CLUTTER_EVENT_FLAG_POINTER_EMULATED :
CLUTTER_EVENT_NONE,
ms2us (xev->time),
source_device,
sequence,
state,
GRAPHENE_POINT_INIT (x, y));
if (xev->flags & XITouchEmulatingPointer) g_debug ("touch %s: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f)",
event->any.flags |= CLUTTER_EVENT_FLAG_POINTER_EMULATED; evtype == CLUTTER_TOUCH_BEGIN ? "begin" : "end",
g_debug ("touch %s: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f, axes:%s)",
event->type == CLUTTER_TOUCH_BEGIN ? "begin" : "end",
(unsigned int) stage_x11->xwin, (unsigned int) stage_x11->xwin,
meta_input_device_x11_get_device_id (event->touch.device), meta_input_device_x11_get_device_id (device),
clutter_input_device_get_device_name (event->touch.device), clutter_input_device_get_device_name (device),
GPOINTER_TO_UINT (event->touch.sequence), GPOINTER_TO_UINT (sequence),
event->touch.x, x, y);
event->touch.y,
event->touch.axes != NULL ? "yes" : "no");
retval = TRUE;
} }
break; break;
case XI_TouchUpdate: case XI_TouchUpdate:
{ {
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
ClutterEventSequence *sequence;
source_device = g_hash_table_lookup (seat->devices_by_id, ClutterModifierType state;
GINT_TO_POINTER (xev->sourceid)); float x, y;
event->touch.type = event->type = CLUTTER_TOUCH_UPDATE;
event->touch.stage = stage;
event->touch.time = xev->time;
/* "NULL" sequences are special cased in clutter */
event->touch.sequence = GINT_TO_POINTER (MAX (1, xev->detail + 1));
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->touch.x, &event->touch.y);
clutter_event_set_source_device (event, source_device);
device = g_hash_table_lookup (seat->devices_by_id, device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->deviceid)); GINT_TO_POINTER (xev->deviceid));
clutter_event_set_device (event, device); source_device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->sourceid));
event->touch.axes = translate_axes (event->touch.device, /* "NULL" sequences are special cased in clutter */
event->motion.x, sequence = GINT_TO_POINTER (MAX (1, xev->detail + 1));
event->motion.y, translate_coords (stage_x11, xev->event_x, xev->event_y, &x, &y);
&xev->valuators); state = translate_state (&xev->buttons, &xev->mods, &xev->group);
state |= CLUTTER_BUTTON1_MASK;
meta_input_device_x11_translate_state (event,
&xev->mods,
&xev->buttons,
&xev->group);
event->touch.modifier_state |= CLUTTER_BUTTON1_MASK;
if (xev->flags & XITouchEmulatingPointer)
event->any.flags |= CLUTTER_EVENT_FLAG_POINTER_EMULATED;
meta_seat_x11_update_touchpoint (seat, meta_seat_x11_update_touchpoint (seat,
event->touch.sequence, sequence,
xev->root_x, xev->root_x,
xev->root_y); xev->root_y);
g_debug ("touch update: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f, axes:%s)", event = clutter_event_touch_new (CLUTTER_TOUCH_UPDATE,
(unsigned int) stage_x11->xwin, (xev->flags & XITouchEmulatingPointer) ?
meta_input_device_x11_get_device_id (event->touch.device), CLUTTER_EVENT_FLAG_POINTER_EMULATED :
clutter_input_device_get_device_name (event->touch.device), CLUTTER_EVENT_NONE,
GPOINTER_TO_UINT (event->touch.sequence), ms2us (xev->time),
event->touch.x, source_device,
event->touch.y, sequence,
event->touch.axes != NULL ? "yes" : "no"); state,
GRAPHENE_POINT_INIT (x, y));
retval = TRUE; g_debug ("touch update: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f)",
(unsigned int) stage_x11->xwin,
meta_input_device_x11_get_device_id (device),
clutter_input_device_get_device_name (device),
GPOINTER_TO_UINT (sequence),
x, y);
} }
break; break;
@ -2547,6 +2536,7 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
case XI_Leave: case XI_Leave:
{ {
XIEnterEvent *xev = (XIEnterEvent *) xi_event; XIEnterEvent *xev = (XIEnterEvent *) xi_event;
float x, y;
device = g_hash_table_lookup (seat->devices_by_id, device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->deviceid)); GINT_TO_POINTER (xev->deviceid));
@ -2554,53 +2544,33 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
source_device = g_hash_table_lookup (seat->devices_by_id, source_device = g_hash_table_lookup (seat->devices_by_id,
GINT_TO_POINTER (xev->sourceid)); GINT_TO_POINTER (xev->sourceid));
if (xi_event->evtype == XI_Enter) translate_coords (stage_x11, xev->event_x, xev->event_y, &x, &y);
{
event->crossing.type = event->type = CLUTTER_ENTER;
event->crossing.stage = stage; event = clutter_event_crossing_new ((xi_event->evtype == XI_Enter) ?
event->crossing.related = NULL; CLUTTER_ENTER : CLUTTER_LEAVE,
CLUTTER_EVENT_NONE,
ms2us (xev->time),
device,
NULL,
GRAPHENE_POINT_INIT (x, y),
CLUTTER_ACTOR (stage), NULL);
event->crossing.time = xev->time; if (xev->deviceid == seat->pointer_id)
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y); seat->has_pointer_focus = (xi_event->evtype == XI_Enter);
if (xev->deviceid == seat->pointer_id)
seat->has_pointer_focus = TRUE;
}
else
{
event->crossing.type = event->type = CLUTTER_LEAVE;
event->crossing.stage = stage;
event->crossing.related = NULL;
event->crossing.time = xev->time;
translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y);
if (xev->deviceid == seat->pointer_id)
seat->has_pointer_focus = FALSE;
}
meta_input_device_x11_reset_scroll_info (source_device); meta_input_device_x11_reset_scroll_info (source_device);
clutter_event_set_device (event, device);
clutter_event_set_source_device (event, source_device);
retval = TRUE;
} }
break; break;
case XI_FocusIn: case XI_FocusIn:
case XI_FocusOut: case XI_FocusOut:
retval = FALSE;
break; break;
case XI_PropertyEvent: case XI_PropertyEvent:
translate_property_event (seat, xi_event); translate_property_event (seat, xi_event);
retval = FALSE;
break; break;
} }
return retval; return event;
} }
ClutterInputDevice * ClutterInputDevice *

View File

@ -33,9 +33,8 @@ MetaSeatX11 * meta_seat_x11_new (MetaBackend *backend,
MetaBackend * meta_seat_x11_get_backend (MetaSeatX11 *seat_x11); MetaBackend * meta_seat_x11_get_backend (MetaSeatX11 *seat_x11);
gboolean meta_seat_x11_translate_event (MetaSeatX11 *seat, ClutterEvent * meta_seat_x11_translate_event (MetaSeatX11 *seat,
XEvent *xevent, XEvent *xevent);
ClutterEvent *event);
ClutterInputDevice * meta_seat_x11_lookup_device_id (MetaSeatX11 *seat_x11, ClutterInputDevice * meta_seat_x11_lookup_device_id (MetaSeatX11 *seat_x11,
int device_id); int device_id);
void meta_seat_x11_select_stage_events (MetaSeatX11 *seat, void meta_seat_x11_select_stage_events (MetaSeatX11 *seat,