diff options
author | Emmanuele Bassi <ebassi@linux.intel.com> | 2011-01-27 17:26:16 +0000 |
---|---|---|
committer | Emmanuele Bassi <ebassi@linux.intel.com> | 2011-01-28 18:19:49 +0000 |
commit | 82d1e5a6ee081cf462999ea04fbd51cdb91f70c9 (patch) | |
tree | d835e13e6915582c3c7ca32886336d33c9608b09 | |
parent | b3784bd2b4c9aeac809cca70681bc248123133f8 (diff) | |
download | clutter-82d1e5a6ee081cf462999ea04fbd51cdb91f70c9.tar.gz |
Clean up crossing event synthesis code
Clutter should just require that the windowing system used by a backend
adds a device to the stage when the device enters, and removes it from
the stage when the device leaves; with this information, we can
synthesize every crossing event and update the device state without
other intervention from the backend-specific code.
The generation of additional crossing events for actors that are
covering the stage at the coordinates of the crossing event should be
delegated to the event processing code.
The x11 and win32 backends need to be modified to relay the enter and
leave events from the windowing system.
-rw-r--r-- | clutter/clutter-device-manager-private.h | 6 | ||||
-rw-r--r-- | clutter/clutter-device-manager.c | 2 | ||||
-rw-r--r-- | clutter/clutter-event.c | 1 | ||||
-rw-r--r-- | clutter/clutter-input-device.c | 152 | ||||
-rw-r--r-- | clutter/clutter-main.c | 90 | ||||
-rw-r--r-- | clutter/clutter-stage-private.h | 8 | ||||
-rw-r--r-- | clutter/clutter-stage.c | 48 | ||||
-rw-r--r-- | clutter/win32/clutter-event-win32.c | 19 | ||||
-rw-r--r-- | clutter/x11/clutter-device-manager-core-x11.c | 45 | ||||
-rw-r--r-- | clutter/x11/clutter-device-manager-xi2.c | 32 |
10 files changed, 242 insertions, 161 deletions
diff --git a/clutter/clutter-device-manager-private.h b/clutter/clutter-device-manager-private.h index eca8d119e..223cdde0f 100644 --- a/clutter/clutter-device-manager-private.h +++ b/clutter/clutter-device-manager-private.h @@ -136,8 +136,10 @@ void _clutter_input_device_set_time (ClutterInputDev void _clutter_input_device_set_stage (ClutterInputDevice *device, ClutterStage *stage); void _clutter_input_device_set_actor (ClutterInputDevice *device, - ClutterActor *actor); -ClutterActor * _clutter_input_device_update (ClutterInputDevice *device); + ClutterActor *actor, + gboolean emit_crossing); +ClutterActor * _clutter_input_device_update (ClutterInputDevice *device, + gboolean emit_crossing); void _clutter_input_device_set_n_keys (ClutterInputDevice *device, guint n_keys); guint _clutter_input_device_add_axis (ClutterInputDevice *device, diff --git a/clutter/clutter-device-manager.c b/clutter/clutter-device-manager.c index da6798334..53e812c83 100644 --- a/clutter/clutter-device-manager.c +++ b/clutter/clutter-device-manager.c @@ -423,7 +423,7 @@ _clutter_device_manager_update_devices (ClutterDeviceManager *device_manager) if (device->stage == NULL) continue; - _clutter_input_device_update (device); + _clutter_input_device_update (device, TRUE); } } diff --git a/clutter/clutter-event.c b/clutter/clutter-event.c index d0364953f..e645910bf 100644 --- a/clutter/clutter-event.c +++ b/clutter/clutter-event.c @@ -543,6 +543,7 @@ clutter_event_set_device (ClutterEvent *event, ClutterInputDevice *device) { g_return_if_fail (event != NULL); + g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device)); if (is_event_allocated (event)) { diff --git a/clutter/clutter-input-device.c b/clutter/clutter-input-device.c index cc804bda5..133abc4ee 100644 --- a/clutter/clutter-input-device.c +++ b/clutter/clutter-input-device.c @@ -445,49 +445,23 @@ void _clutter_input_device_set_stage (ClutterInputDevice *device, ClutterStage *stage) { - ClutterStage *old_stage; - - g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); + if (device->stage == stage) + return; - old_stage = device->stage; device->stage = stage; - /* if we left the stage then we also need to unset the - * cursor actor (and update its :has-pointer property) + /* we leave the ->cursor_actor in place in order to check + * if we left the stage without crossing it again; this way + * we can emit a leave event on the cursor actor right before + * we emit the leave event on the stage. */ - if (device->stage == NULL && - device->cursor_actor != NULL && - device->cursor_actor != CLUTTER_ACTOR (old_stage)) - { - ClutterEvent cev; - - cev.crossing.type = CLUTTER_LEAVE; - cev.crossing.time = device->current_time; - cev.crossing.flags = 0; - cev.crossing.stage = old_stage; - cev.crossing.source = device->cursor_actor; - cev.crossing.x = device->current_x; - cev.crossing.y = device->current_y; - cev.crossing.device = device; - cev.crossing.related = device->stage != NULL - ? CLUTTER_ACTOR (device->stage) - : CLUTTER_ACTOR (old_stage); - - _clutter_stage_queue_event (old_stage, &cev); - - _clutter_actor_set_has_pointer (device->cursor_actor, FALSE); - g_object_weak_unref (G_OBJECT (device->cursor_actor), - cursor_weak_unref, - device); - } - - device->cursor_actor = NULL; } /*< private > * clutter_input_device_set_actor: * @device: a #ClutterInputDevice * @actor: a #ClutterActor + * @emit_crossing: %TRUE to emit crossing events * * Sets the actor under the pointer coordinates of @device * @@ -504,34 +478,41 @@ _clutter_input_device_set_stage (ClutterInputDevice *device, */ void _clutter_input_device_set_actor (ClutterInputDevice *device, - ClutterActor *actor) + ClutterActor *actor, + gboolean emit_crossing) { ClutterActor *old_actor; - ClutterEvent cev; - g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); - - if (actor == device->cursor_actor) + if (device->cursor_actor == actor) return; old_actor = device->cursor_actor; + if (old_actor != NULL) { - cev.crossing.type = CLUTTER_LEAVE; - cev.crossing.time = device->current_time; - cev.crossing.flags = 0; - cev.crossing.stage = device->stage; - cev.crossing.source = device->cursor_actor; - cev.crossing.x = device->current_x; - cev.crossing.y = device->current_y; - cev.crossing.device = device; - cev.crossing.related = actor; - - /* we need to make sure that this event is processed before - * any other event we might have queued up until now, so we - * go on and synthesize the event emission - */ - _clutter_process_event (&cev); + if (emit_crossing) + { + ClutterEvent *event; + + event = clutter_event_new (CLUTTER_LEAVE); + event->crossing.time = device->current_time; + event->crossing.flags = 0; + event->crossing.stage = device->stage; + event->crossing.source = device->cursor_actor; + event->crossing.x = device->current_x; + event->crossing.y = device->current_y; + event->crossing.related = actor; + clutter_event_set_device (event, device); + + /* we need to make sure that this event is processed + * before any other event we might have queued up until + * now, so we go on, and synthesize the event emission + * ourselves + */ + _clutter_process_event (event); + + clutter_event_free (event); + } /* processing the event might have destroyed the actor */ if (device->cursor_actor != NULL) @@ -547,54 +528,28 @@ _clutter_input_device_set_actor (ClutterInputDevice *device, if (actor != NULL) { - cev.crossing.type = CLUTTER_ENTER; - cev.crossing.time = device->current_time; - cev.crossing.flags = 0; - cev.crossing.stage = device->stage; - cev.crossing.x = device->current_x; - cev.crossing.y = device->current_y; - cev.crossing.device = device; - - CLUTTER_NOTE (EVENT, "Device '%s' entering '%s' at %d, %d", - device->device_name, - clutter_actor_get_name (actor) != NULL - ? clutter_actor_get_name (actor) - : G_OBJECT_TYPE_NAME (actor), - device->current_x, - device->current_y); - - /* if there is an actor overlapping the Stage boundary and we - * don't do this check then we'll emit an ENTER event only on - * the actor instead of emitting it on the Stage *and* the - * actor - */ - if (old_actor == NULL && actor != CLUTTER_ACTOR (device->stage)) - { - cev.crossing.source = CLUTTER_ACTOR (device->stage); - cev.crossing.related = NULL; - - CLUTTER_NOTE (EVENT, "Adding Crossing[Enter] event for Stage"); - - _clutter_process_event (&cev); - - cev.crossing.source = actor; - cev.crossing.related = CLUTTER_ACTOR (device->stage); - } - else + if (emit_crossing) { - cev.crossing.source = actor; - cev.crossing.related = old_actor; + ClutterEvent *event; + + event = clutter_event_new (CLUTTER_ENTER); + event->crossing.time = device->current_time; + event->crossing.flags = 0; + event->crossing.stage = device->stage; + event->crossing.x = device->current_x; + event->crossing.y = device->current_y; + event->crossing.source = actor; + event->crossing.related = old_actor; + clutter_event_set_device (event, device); + + /* see above */ + _clutter_process_event (event); + + clutter_event_free (event); } - - /* as above: we need to make sure that this event is processed - * before any other event we might have queued up until now, so - * we go on and synthesize the event emission - */ - _clutter_process_event (&cev); } device->cursor_actor = actor; - if (device->cursor_actor != NULL) { g_object_weak_ref (G_OBJECT (device->cursor_actor), @@ -730,7 +685,8 @@ clutter_input_device_get_device_coords (ClutterInputDevice *device, * Since: 1.2 */ ClutterActor * -_clutter_input_device_update (ClutterInputDevice *device) +_clutter_input_device_update (ClutterInputDevice *device, + gboolean emit_crossing) { ClutterStage *stage; ClutterActor *new_cursor_actor; @@ -773,7 +729,7 @@ _clutter_input_device_update (ClutterInputDevice *device) if (new_cursor_actor == old_cursor_actor) return old_cursor_actor; - _clutter_input_device_set_actor (device, new_cursor_actor); + _clutter_input_device_set_actor (device, new_cursor_actor, emit_crossing); return device->cursor_actor; } diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index e622d2c2a..f24f0b510 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -2154,7 +2154,7 @@ emit_event (ClutterEvent *event, /* reentrancy check */ if (lock != FALSE) { - g_warning ("Tried emitting event during event delivery, bailing out.n"); + g_warning ("Tried emitting event during event delivery, bailing out."); return; } @@ -2248,10 +2248,14 @@ is_off_stage (ClutterActor *stage, gfloat x, gfloat y) { + gfloat width, height; + + clutter_actor_get_size (stage, &width, &height); + return (x < 0 || y < 0 || - x >= clutter_actor_get_width (stage) || - y >= clutter_actor_get_height (stage)); + x >= width || + y >= height); } /** @@ -2293,18 +2297,6 @@ _clutter_process_event_details (ClutterActor *stage, event->any.source = stage; break; - case CLUTTER_LEAVE: - case CLUTTER_ENTER: - emit_pointer_event (event, device); - break; - - case CLUTTER_DESTROY_NOTIFY: - case CLUTTER_DELETE: - event->any.source = stage; - /* the stage did not handle the event, so we just quit */ - clutter_stage_event (CLUTTER_STAGE (stage), event); - break; - case CLUTTER_KEY_PRESS: case CLUTTER_KEY_RELEASE: { @@ -2326,6 +2318,65 @@ _clutter_process_event_details (ClutterActor *stage, } break; + case CLUTTER_ENTER: + /* if we're entering from outside the stage we need + * to check whether the pointer is actually on another + * actor, and emit an additional pointer event + */ + if (event->any.source == stage && + event->crossing.related == NULL) + { + ClutterActor *actor = NULL; + + emit_pointer_event (event, device); + + actor = _clutter_input_device_update (device, FALSE); + if (actor != stage) + { + ClutterEvent *crossing; + + /* we emit the exact same event on the actor */ + crossing = clutter_event_copy (event); + crossing->crossing.related = stage; + crossing->crossing.source = actor; + + emit_pointer_event (crossing, device); + clutter_event_free (crossing); + } + } + else + emit_pointer_event (event, device); + break; + + case CLUTTER_LEAVE: + /* same as CLUTTER_ENTER above: when leaving the stage + * we need to also emit a CLUTTER_LEAVE event on the + * actor currently underneath the device, unless it's the + * stage + */ + if (event->any.source == stage && + event->crossing.related == NULL && + device->cursor_actor != stage) + { + ClutterEvent *crossing; + + crossing = clutter_event_copy (event); + crossing->crossing.related = stage; + crossing->crossing.source = device->cursor_actor; + + emit_pointer_event (crossing, device); + clutter_event_free (crossing); + } + emit_pointer_event (event, device); + break; + + case CLUTTER_DESTROY_NOTIFY: + case CLUTTER_DELETE: + event->any.source = stage; + /* the stage did not handle the event, so we just quit */ + clutter_stage_event (CLUTTER_STAGE (stage), event); + break; + case CLUTTER_MOTION: /* Only stage gets motion events if clutter_set_motion_events is TRUE, * and the event is not a synthetic event with source set. @@ -2413,7 +2464,7 @@ _clutter_process_event_details (ClutterActor *stage, * get the actor underneath */ if (device != NULL) - actor = _clutter_input_device_update (device); + actor = _clutter_input_device_update (device, TRUE); else { CLUTTER_NOTE (EVENT, "No device found: picking"); @@ -2434,11 +2485,6 @@ _clutter_process_event_details (ClutterActor *stage, actor = event->any.source; } - /* FIXME: for an optimisation should check if there are - * actually any reactive actors and avoid the pick all together - * (signalling just the stage). Should be big help for gles. - */ - CLUTTER_NOTE (EVENT, "Reactive event received at %.2f, %.2f - actor: %p", x, y, @@ -2507,7 +2553,7 @@ _clutter_process_event (ClutterEvent *event) * * Since: 0.6 */ -ClutterActor* +ClutterActor * clutter_get_actor_by_gid (guint32 id) { ClutterMainContext *context; diff --git a/clutter/clutter-stage-private.h b/clutter/clutter-stage-private.h index 879e162ae..f61fc9d32 100644 --- a/clutter/clutter-stage-private.h +++ b/clutter/clutter-stage-private.h @@ -24,6 +24,7 @@ #include <clutter/clutter-stage-window.h> #include <clutter/clutter-stage.h> +#include <clutter/clutter-input-device.h> G_BEGIN_DECLS @@ -82,6 +83,13 @@ ClutterStageQueueRedrawEntry *_clutter_stage_queue_actor_redraw (Clut ClutterPaintVolume *clip); void _clutter_stage_queue_redraw_entry_invalidate (ClutterStageQueueRedrawEntry *entry); +void _clutter_stage_add_device (ClutterStage *stage, + ClutterInputDevice *device); +void _clutter_stage_remove_device (ClutterStage *stage, + ClutterInputDevice *device); +gboolean _clutter_stage_has_device (ClutterStage *stage, + ClutterInputDevice *device); + G_END_DECLS #endif /* __CLUTTER_STAGE_PRIVATE_H__ */ diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 48935cb48..624967198 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -135,6 +135,8 @@ struct _ClutterStagePrivate ClutterPickMode pick_buffer_mode; + GHashTable *devices; + guint relayout_pending : 1; guint redraw_pending : 1; guint is_fullscreen : 1; @@ -1202,10 +1204,13 @@ clutter_stage_finalize (GObject *object) g_queue_foreach (priv->event_queue, (GFunc)clutter_event_free, NULL); g_queue_free (priv->event_queue); - g_free (stage->priv->title); + g_free (priv->title); g_array_free (priv->paint_volume_stack, TRUE); + if (priv->devices != NULL) + g_hash_table_destroy (priv->devices); + G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object); } @@ -3375,3 +3380,44 @@ clutter_stage_get_accept_focus (ClutterStage *stage) return stage->priv->accept_focus; } + +void +_clutter_stage_add_device (ClutterStage *stage, + ClutterInputDevice *device) +{ + ClutterStagePrivate *priv = stage->priv; + + if (G_UNLIKELY (priv->devices == NULL)) + priv->devices = g_hash_table_new (NULL, NULL); + + if (g_hash_table_lookup (priv->devices, device) != NULL) + return; + + g_hash_table_insert (priv->devices, device, GINT_TO_POINTER (1)); + _clutter_input_device_set_stage (device, stage); +} + +void +_clutter_stage_remove_device (ClutterStage *stage, + ClutterInputDevice *device) +{ + ClutterStagePrivate *priv = stage->priv; + + if (G_UNLIKELY (priv->devices == NULL)) + return; + + _clutter_input_device_set_stage (device, NULL); + g_hash_table_remove (priv->devices, device); +} + +gboolean +_clutter_stage_has_device (ClutterStage *stage, + ClutterInputDevice *device) +{ + ClutterStagePrivate *priv = stage->priv; + + if (priv->devices == NULL) + return FALSE; + + return g_hash_table_lookup (priv->devices, device) != NULL; +} diff --git a/clutter/win32/clutter-event-win32.c b/clutter/win32/clutter-event-win32.c index 8429fdd11..996ce36ac 100644 --- a/clutter/win32/clutter-event-win32.c +++ b/clutter/win32/clutter-event-win32.c @@ -548,6 +548,7 @@ clutter_win32_handle_event (const MSG *msg) we're not already */ if (!stage_win32->tracking_mouse) { + ClutterEvent *crossing = clutter_event_new (CLUTTER_ENTER); TRACKMOUSEEVENT tmevent; tmevent.cbSize = sizeof (tmevent); @@ -555,8 +556,18 @@ clutter_win32_handle_event (const MSG *msg) tmevent.hwndTrack = stage_win32->hwnd; TrackMouseEvent (&tmevent); + event->crossing.time = msg->time; + event->crossing.x = event->motion.x; + event->crossing.y = event->motion.y; + event->crossing.device = event->motion.device; + event->crossing.stage = stage; + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.related = NULL; + /* we entered the stage */ - _clutter_input_device_set_stage (event->motion.device, stage); + _clutter_stage_add_device (stage, event->crossing.device); + + take_and_queue_event (crossing); stage_win32->tracking_mouse = TRUE; } @@ -573,10 +584,12 @@ clutter_win32_handle_event (const MSG *msg) event->crossing.x = msg->pt.x; event->crossing.y = msg->pt.y; event->crossing.device = core_pointer; - event->any.stage = stage; + event->crossing.stage = stage; + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.related = NULL; /* we left the stage */ - _clutter_input_device_set_stage (event->crossing.device, NULL); + _clutter_stage_remove_device (stage, event->crossing.device); /* When we get a leave message the mouse tracking is automatically cancelled so we'll need to start it again when diff --git a/clutter/x11/clutter-device-manager-core-x11.c b/clutter/x11/clutter-device-manager-core-x11.c index 4614a07a9..2b55f42aa 100644 --- a/clutter/x11/clutter-device-manager-core-x11.c +++ b/clutter/x11/clutter-device-manager-core-x11.c @@ -220,7 +220,8 @@ translate_key_event (ClutterBackendX11 *backend_x11, event->key.type = xevent->xany.type == KeyPress ? CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE; event->key.time = xevent->xkey.time; - event->key.device = manager_x11->core_keyboard; + + clutter_event_set_device (event, manager_x11->core_keyboard); /* KeyEvents have platform specific data associated to them */ event_x11 = _clutter_event_x11_new (); @@ -406,7 +407,7 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator, event->scroll.x = xevent->xbutton.x; event->scroll.y = xevent->xbutton.y; event->scroll.modifier_state = xevent->xbutton.state; - event->scroll.device = manager_x11->core_pointer; + event->scroll.axes = NULL; break; default: @@ -416,11 +417,12 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator, event->button.y = xevent->xbutton.y; event->button.modifier_state = xevent->xbutton.state; event->button.button = xevent->xbutton.button; - event->button.device = manager_x11->core_pointer; event->button.axes = NULL; break; } + clutter_event_set_device (event, manager_x11->core_pointer); + _clutter_stage_x11_set_user_time (stage_x11, xevent->xbutton.time); res = CLUTTER_TRANSLATE_QUEUE; break; @@ -450,7 +452,7 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator, event->button.modifier_state = xevent->xbutton.state; event->button.button = xevent->xbutton.button; event->button.axes = NULL; - event->button.device = manager_x11->core_pointer; + clutter_event_set_device (event, manager_x11->core_pointer); res = CLUTTER_TRANSLATE_QUEUE; break; @@ -466,25 +468,25 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator, event->motion.x = xevent->xmotion.x; event->motion.y = xevent->xmotion.y; event->motion.modifier_state = xevent->xmotion.state; - event->motion.device = manager_x11->core_pointer; event->motion.axes = NULL; + clutter_event_set_device (event, manager_x11->core_pointer); res = CLUTTER_TRANSLATE_QUEUE; break; case EnterNotify: - /* we know that we are entering the stage here */ - _clutter_input_device_set_stage (manager_x11->core_pointer, stage); - CLUTTER_NOTE (EVENT, "Entering the stage"); + CLUTTER_NOTE (EVENT, "Entering the stage (time:%u)", + (unsigned int) xevent->xcrossing.time); + + event->crossing.type = CLUTTER_ENTER; + event->crossing.time = xevent->xcrossing.time; + event->crossing.x = xevent->xcrossing.x; + event->crossing.y = xevent->xcrossing.y; + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.related = NULL; + clutter_event_set_device (event, manager_x11->core_pointer); + + _clutter_stage_add_device (stage, manager_x11->core_pointer); - /* Convert enter notifies to motion events because X - doesn't emit the corresponding motion notify */ - event->motion.type = event->type = CLUTTER_MOTION; - event->motion.time = xevent->xcrossing.time; - event->motion.x = xevent->xcrossing.x; - event->motion.y = xevent->xcrossing.y; - event->motion.modifier_state = xevent->xcrossing.state; - event->motion.source = CLUTTER_ACTOR (stage); - event->motion.device = manager_x11->core_pointer; res = CLUTTER_TRANSLATE_QUEUE; break; @@ -498,16 +500,19 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator, } /* we know that we are leaving the stage here */ - _clutter_input_device_set_stage (manager_x11->core_pointer, NULL); CLUTTER_NOTE (EVENT, "Leaving the stage (time:%u)", - event->crossing.time); + (unsigned int) xevent->xcrossing.time); event->crossing.type = CLUTTER_LEAVE; event->crossing.time = xevent->xcrossing.time; event->crossing.x = xevent->xcrossing.x; event->crossing.y = xevent->xcrossing.y; event->crossing.source = CLUTTER_ACTOR (stage); - event->crossing.device = manager_x11->core_pointer; + event->crossing.related = NULL; + clutter_event_set_device (event, manager_x11->core_pointer); + + _clutter_stage_remove_device (stage, manager_x11->core_pointer); + res = CLUTTER_TRANSLATE_QUEUE; break; diff --git a/clutter/x11/clutter-device-manager-xi2.c b/clutter/x11/clutter-device-manager-xi2.c index 8924cf609..aff55cf10 100644 --- a/clutter/x11/clutter-device-manager-xi2.c +++ b/clutter/x11/clutter-device-manager-xi2.c @@ -847,22 +847,22 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, device = g_hash_table_lookup (manager_xi2->devices_by_id, GINT_TO_POINTER (xev->deviceid)); + source_device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->sourceid)); + if (xi_event->evtype == XI_Enter) { - _clutter_input_device_set_stage (device, stage); + event->crossing.type = event->type = CLUTTER_ENTER; - event->motion.type = event->type = CLUTTER_MOTION; + event->crossing.stage = stage; + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.related = NULL; - event->motion.stage = stage; - event->motion.source = CLUTTER_ACTOR (stage); + event->crossing.time = xev->time; + event->crossing.x = xev->event_x; + event->crossing.y = xev->event_y; - event->motion.time = xev->time; - event->motion.x = xev->event_x; - event->motion.y = xev->event_y; - event->motion.device = device; - event->motion.modifier_state = - _clutter_input_device_xi2_translate_state (&xev->mods, - &xev->buttons); + _clutter_stage_add_device (stage, device); } else { @@ -876,18 +876,22 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, break; } - _clutter_input_device_set_stage (device, NULL); - event->crossing.type = event->type = CLUTTER_LEAVE; + event->crossing.stage = stage; event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.related = NULL; event->crossing.time = xev->time; event->crossing.x = xev->event_x; event->crossing.y = xev->event_y; - event->crossing.device = device; + + _clutter_stage_remove_device (stage, device); } + clutter_event_set_device (event, device); + _clutter_event_set_source_device (event, source_device); + retval = CLUTTER_TRANSLATE_QUEUE; } break; |