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.
This commit is contained in:
parent
b3784bd2b4
commit
82d1e5a6ee
@ -136,8 +136,10 @@ void _clutter_input_device_set_time (ClutterInputDev
|
|||||||
void _clutter_input_device_set_stage (ClutterInputDevice *device,
|
void _clutter_input_device_set_stage (ClutterInputDevice *device,
|
||||||
ClutterStage *stage);
|
ClutterStage *stage);
|
||||||
void _clutter_input_device_set_actor (ClutterInputDevice *device,
|
void _clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||||
ClutterActor *actor);
|
ClutterActor *actor,
|
||||||
ClutterActor * _clutter_input_device_update (ClutterInputDevice *device);
|
gboolean emit_crossing);
|
||||||
|
ClutterActor * _clutter_input_device_update (ClutterInputDevice *device,
|
||||||
|
gboolean emit_crossing);
|
||||||
void _clutter_input_device_set_n_keys (ClutterInputDevice *device,
|
void _clutter_input_device_set_n_keys (ClutterInputDevice *device,
|
||||||
guint n_keys);
|
guint n_keys);
|
||||||
guint _clutter_input_device_add_axis (ClutterInputDevice *device,
|
guint _clutter_input_device_add_axis (ClutterInputDevice *device,
|
||||||
|
@ -423,7 +423,7 @@ _clutter_device_manager_update_devices (ClutterDeviceManager *device_manager)
|
|||||||
if (device->stage == NULL)
|
if (device->stage == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_clutter_input_device_update (device);
|
_clutter_input_device_update (device, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,6 +543,7 @@ clutter_event_set_device (ClutterEvent *event,
|
|||||||
ClutterInputDevice *device)
|
ClutterInputDevice *device)
|
||||||
{
|
{
|
||||||
g_return_if_fail (event != NULL);
|
g_return_if_fail (event != NULL);
|
||||||
|
g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
|
||||||
|
|
||||||
if (is_event_allocated (event))
|
if (is_event_allocated (event))
|
||||||
{
|
{
|
||||||
|
@ -445,49 +445,23 @@ void
|
|||||||
_clutter_input_device_set_stage (ClutterInputDevice *device,
|
_clutter_input_device_set_stage (ClutterInputDevice *device,
|
||||||
ClutterStage *stage)
|
ClutterStage *stage)
|
||||||
{
|
{
|
||||||
ClutterStage *old_stage;
|
if (device->stage == stage)
|
||||||
|
return;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
|
||||||
|
|
||||||
old_stage = device->stage;
|
|
||||||
device->stage = stage;
|
device->stage = stage;
|
||||||
|
|
||||||
/* if we left the stage then we also need to unset the
|
/* we leave the ->cursor_actor in place in order to check
|
||||||
* cursor actor (and update its :has-pointer property)
|
* 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 >
|
/*< private >
|
||||||
* clutter_input_device_set_actor:
|
* clutter_input_device_set_actor:
|
||||||
* @device: a #ClutterInputDevice
|
* @device: a #ClutterInputDevice
|
||||||
* @actor: a #ClutterActor
|
* @actor: a #ClutterActor
|
||||||
|
* @emit_crossing: %TRUE to emit crossing events
|
||||||
*
|
*
|
||||||
* Sets the actor under the pointer coordinates of @device
|
* Sets the actor under the pointer coordinates of @device
|
||||||
*
|
*
|
||||||
@ -504,34 +478,41 @@ _clutter_input_device_set_stage (ClutterInputDevice *device,
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
_clutter_input_device_set_actor (ClutterInputDevice *device,
|
_clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||||
ClutterActor *actor)
|
ClutterActor *actor,
|
||||||
|
gboolean emit_crossing)
|
||||||
{
|
{
|
||||||
ClutterActor *old_actor;
|
ClutterActor *old_actor;
|
||||||
ClutterEvent cev;
|
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
if (device->cursor_actor == actor)
|
||||||
|
|
||||||
if (actor == device->cursor_actor)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
old_actor = device->cursor_actor;
|
old_actor = device->cursor_actor;
|
||||||
|
|
||||||
if (old_actor != NULL)
|
if (old_actor != NULL)
|
||||||
{
|
{
|
||||||
cev.crossing.type = CLUTTER_LEAVE;
|
if (emit_crossing)
|
||||||
cev.crossing.time = device->current_time;
|
{
|
||||||
cev.crossing.flags = 0;
|
ClutterEvent *event;
|
||||||
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
|
event = clutter_event_new (CLUTTER_LEAVE);
|
||||||
* any other event we might have queued up until now, so we
|
event->crossing.time = device->current_time;
|
||||||
* go on and synthesize the event emission
|
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 (&cev);
|
_clutter_process_event (event);
|
||||||
|
|
||||||
|
clutter_event_free (event);
|
||||||
|
}
|
||||||
|
|
||||||
/* processing the event might have destroyed the actor */
|
/* processing the event might have destroyed the actor */
|
||||||
if (device->cursor_actor != NULL)
|
if (device->cursor_actor != NULL)
|
||||||
@ -547,54 +528,28 @@ _clutter_input_device_set_actor (ClutterInputDevice *device,
|
|||||||
|
|
||||||
if (actor != NULL)
|
if (actor != NULL)
|
||||||
{
|
{
|
||||||
cev.crossing.type = CLUTTER_ENTER;
|
if (emit_crossing)
|
||||||
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);
|
ClutterEvent *event;
|
||||||
cev.crossing.related = NULL;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (EVENT, "Adding Crossing[Enter] event for Stage");
|
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);
|
||||||
|
|
||||||
_clutter_process_event (&cev);
|
/* see above */
|
||||||
|
_clutter_process_event (event);
|
||||||
|
|
||||||
cev.crossing.source = actor;
|
clutter_event_free (event);
|
||||||
cev.crossing.related = CLUTTER_ACTOR (device->stage);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
cev.crossing.source = actor;
|
|
||||||
cev.crossing.related = old_actor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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;
|
device->cursor_actor = actor;
|
||||||
|
|
||||||
if (device->cursor_actor != NULL)
|
if (device->cursor_actor != NULL)
|
||||||
{
|
{
|
||||||
g_object_weak_ref (G_OBJECT (device->cursor_actor),
|
g_object_weak_ref (G_OBJECT (device->cursor_actor),
|
||||||
@ -730,7 +685,8 @@ clutter_input_device_get_device_coords (ClutterInputDevice *device,
|
|||||||
* Since: 1.2
|
* Since: 1.2
|
||||||
*/
|
*/
|
||||||
ClutterActor *
|
ClutterActor *
|
||||||
_clutter_input_device_update (ClutterInputDevice *device)
|
_clutter_input_device_update (ClutterInputDevice *device,
|
||||||
|
gboolean emit_crossing)
|
||||||
{
|
{
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
ClutterActor *new_cursor_actor;
|
ClutterActor *new_cursor_actor;
|
||||||
@ -773,7 +729,7 @@ _clutter_input_device_update (ClutterInputDevice *device)
|
|||||||
if (new_cursor_actor == old_cursor_actor)
|
if (new_cursor_actor == old_cursor_actor)
|
||||||
return 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;
|
return device->cursor_actor;
|
||||||
}
|
}
|
||||||
|
@ -2154,7 +2154,7 @@ emit_event (ClutterEvent *event,
|
|||||||
/* reentrancy check */
|
/* reentrancy check */
|
||||||
if (lock != FALSE)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2248,10 +2248,14 @@ is_off_stage (ClutterActor *stage,
|
|||||||
gfloat x,
|
gfloat x,
|
||||||
gfloat y)
|
gfloat y)
|
||||||
{
|
{
|
||||||
|
gfloat width, height;
|
||||||
|
|
||||||
|
clutter_actor_get_size (stage, &width, &height);
|
||||||
|
|
||||||
return (x < 0 ||
|
return (x < 0 ||
|
||||||
y < 0 ||
|
y < 0 ||
|
||||||
x >= clutter_actor_get_width (stage) ||
|
x >= width ||
|
||||||
y >= clutter_actor_get_height (stage));
|
y >= height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2293,18 +2297,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
event->any.source = stage;
|
event->any.source = stage;
|
||||||
break;
|
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_PRESS:
|
||||||
case CLUTTER_KEY_RELEASE:
|
case CLUTTER_KEY_RELEASE:
|
||||||
{
|
{
|
||||||
@ -2326,6 +2318,65 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
case CLUTTER_MOTION:
|
||||||
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
|
/* Only stage gets motion events if clutter_set_motion_events is TRUE,
|
||||||
* and the event is not a synthetic event with source set.
|
* 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
|
* get the actor underneath
|
||||||
*/
|
*/
|
||||||
if (device != NULL)
|
if (device != NULL)
|
||||||
actor = _clutter_input_device_update (device);
|
actor = _clutter_input_device_update (device, TRUE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (EVENT, "No device found: picking");
|
CLUTTER_NOTE (EVENT, "No device found: picking");
|
||||||
@ -2434,11 +2485,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
|||||||
actor = event->any.source;
|
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,
|
CLUTTER_NOTE (EVENT,
|
||||||
"Reactive event received at %.2f, %.2f - actor: %p",
|
"Reactive event received at %.2f, %.2f - actor: %p",
|
||||||
x, y,
|
x, y,
|
||||||
@ -2507,7 +2553,7 @@ _clutter_process_event (ClutterEvent *event)
|
|||||||
*
|
*
|
||||||
* Since: 0.6
|
* Since: 0.6
|
||||||
*/
|
*/
|
||||||
ClutterActor*
|
ClutterActor *
|
||||||
clutter_get_actor_by_gid (guint32 id)
|
clutter_get_actor_by_gid (guint32 id)
|
||||||
{
|
{
|
||||||
ClutterMainContext *context;
|
ClutterMainContext *context;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <clutter/clutter-stage-window.h>
|
#include <clutter/clutter-stage-window.h>
|
||||||
#include <clutter/clutter-stage.h>
|
#include <clutter/clutter-stage.h>
|
||||||
|
#include <clutter/clutter-input-device.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -82,6 +83,13 @@ ClutterStageQueueRedrawEntry *_clutter_stage_queue_actor_redraw (Clut
|
|||||||
ClutterPaintVolume *clip);
|
ClutterPaintVolume *clip);
|
||||||
void _clutter_stage_queue_redraw_entry_invalidate (ClutterStageQueueRedrawEntry *entry);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
|
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
|
||||||
|
@ -135,6 +135,8 @@ struct _ClutterStagePrivate
|
|||||||
|
|
||||||
ClutterPickMode pick_buffer_mode;
|
ClutterPickMode pick_buffer_mode;
|
||||||
|
|
||||||
|
GHashTable *devices;
|
||||||
|
|
||||||
guint relayout_pending : 1;
|
guint relayout_pending : 1;
|
||||||
guint redraw_pending : 1;
|
guint redraw_pending : 1;
|
||||||
guint is_fullscreen : 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_foreach (priv->event_queue, (GFunc)clutter_event_free, NULL);
|
||||||
g_queue_free (priv->event_queue);
|
g_queue_free (priv->event_queue);
|
||||||
|
|
||||||
g_free (stage->priv->title);
|
g_free (priv->title);
|
||||||
|
|
||||||
g_array_free (priv->paint_volume_stack, TRUE);
|
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);
|
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;
|
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;
|
||||||
|
}
|
||||||
|
@ -548,6 +548,7 @@ clutter_win32_handle_event (const MSG *msg)
|
|||||||
we're not already */
|
we're not already */
|
||||||
if (!stage_win32->tracking_mouse)
|
if (!stage_win32->tracking_mouse)
|
||||||
{
|
{
|
||||||
|
ClutterEvent *crossing = clutter_event_new (CLUTTER_ENTER);
|
||||||
TRACKMOUSEEVENT tmevent;
|
TRACKMOUSEEVENT tmevent;
|
||||||
|
|
||||||
tmevent.cbSize = sizeof (tmevent);
|
tmevent.cbSize = sizeof (tmevent);
|
||||||
@ -555,8 +556,18 @@ clutter_win32_handle_event (const MSG *msg)
|
|||||||
tmevent.hwndTrack = stage_win32->hwnd;
|
tmevent.hwndTrack = stage_win32->hwnd;
|
||||||
TrackMouseEvent (&tmevent);
|
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 */
|
/* 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;
|
stage_win32->tracking_mouse = TRUE;
|
||||||
}
|
}
|
||||||
@ -573,10 +584,12 @@ clutter_win32_handle_event (const MSG *msg)
|
|||||||
event->crossing.x = msg->pt.x;
|
event->crossing.x = msg->pt.x;
|
||||||
event->crossing.y = msg->pt.y;
|
event->crossing.y = msg->pt.y;
|
||||||
event->crossing.device = core_pointer;
|
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 */
|
/* 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
|
/* When we get a leave message the mouse tracking is
|
||||||
automatically cancelled so we'll need to start it again when
|
automatically cancelled so we'll need to start it again when
|
||||||
|
@ -220,7 +220,8 @@ translate_key_event (ClutterBackendX11 *backend_x11,
|
|||||||
event->key.type = xevent->xany.type == KeyPress ? CLUTTER_KEY_PRESS
|
event->key.type = xevent->xany.type == KeyPress ? CLUTTER_KEY_PRESS
|
||||||
: CLUTTER_KEY_RELEASE;
|
: CLUTTER_KEY_RELEASE;
|
||||||
event->key.time = xevent->xkey.time;
|
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 */
|
/* KeyEvents have platform specific data associated to them */
|
||||||
event_x11 = _clutter_event_x11_new ();
|
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.x = xevent->xbutton.x;
|
||||||
event->scroll.y = xevent->xbutton.y;
|
event->scroll.y = xevent->xbutton.y;
|
||||||
event->scroll.modifier_state = xevent->xbutton.state;
|
event->scroll.modifier_state = xevent->xbutton.state;
|
||||||
event->scroll.device = manager_x11->core_pointer;
|
event->scroll.axes = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -416,11 +417,12 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
|
|||||||
event->button.y = xevent->xbutton.y;
|
event->button.y = xevent->xbutton.y;
|
||||||
event->button.modifier_state = xevent->xbutton.state;
|
event->button.modifier_state = xevent->xbutton.state;
|
||||||
event->button.button = xevent->xbutton.button;
|
event->button.button = xevent->xbutton.button;
|
||||||
event->button.device = manager_x11->core_pointer;
|
|
||||||
event->button.axes = NULL;
|
event->button.axes = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clutter_event_set_device (event, manager_x11->core_pointer);
|
||||||
|
|
||||||
_clutter_stage_x11_set_user_time (stage_x11, xevent->xbutton.time);
|
_clutter_stage_x11_set_user_time (stage_x11, xevent->xbutton.time);
|
||||||
res = CLUTTER_TRANSLATE_QUEUE;
|
res = CLUTTER_TRANSLATE_QUEUE;
|
||||||
break;
|
break;
|
||||||
@ -450,7 +452,7 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
|
|||||||
event->button.modifier_state = xevent->xbutton.state;
|
event->button.modifier_state = xevent->xbutton.state;
|
||||||
event->button.button = xevent->xbutton.button;
|
event->button.button = xevent->xbutton.button;
|
||||||
event->button.axes = NULL;
|
event->button.axes = NULL;
|
||||||
event->button.device = manager_x11->core_pointer;
|
clutter_event_set_device (event, manager_x11->core_pointer);
|
||||||
res = CLUTTER_TRANSLATE_QUEUE;
|
res = CLUTTER_TRANSLATE_QUEUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -466,25 +468,25 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
|
|||||||
event->motion.x = xevent->xmotion.x;
|
event->motion.x = xevent->xmotion.x;
|
||||||
event->motion.y = xevent->xmotion.y;
|
event->motion.y = xevent->xmotion.y;
|
||||||
event->motion.modifier_state = xevent->xmotion.state;
|
event->motion.modifier_state = xevent->xmotion.state;
|
||||||
event->motion.device = manager_x11->core_pointer;
|
|
||||||
event->motion.axes = NULL;
|
event->motion.axes = NULL;
|
||||||
|
clutter_event_set_device (event, manager_x11->core_pointer);
|
||||||
res = CLUTTER_TRANSLATE_QUEUE;
|
res = CLUTTER_TRANSLATE_QUEUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EnterNotify:
|
case EnterNotify:
|
||||||
/* we know that we are entering the stage here */
|
CLUTTER_NOTE (EVENT, "Entering the stage (time:%u)",
|
||||||
_clutter_input_device_set_stage (manager_x11->core_pointer, stage);
|
(unsigned int) xevent->xcrossing.time);
|
||||||
CLUTTER_NOTE (EVENT, "Entering the stage");
|
|
||||||
|
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;
|
res = CLUTTER_TRANSLATE_QUEUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -498,16 +500,19 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* we know that we are leaving the stage here */
|
/* 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)",
|
CLUTTER_NOTE (EVENT, "Leaving the stage (time:%u)",
|
||||||
event->crossing.time);
|
(unsigned int) xevent->xcrossing.time);
|
||||||
|
|
||||||
event->crossing.type = CLUTTER_LEAVE;
|
event->crossing.type = CLUTTER_LEAVE;
|
||||||
event->crossing.time = xevent->xcrossing.time;
|
event->crossing.time = xevent->xcrossing.time;
|
||||||
event->crossing.x = xevent->xcrossing.x;
|
event->crossing.x = xevent->xcrossing.x;
|
||||||
event->crossing.y = xevent->xcrossing.y;
|
event->crossing.y = xevent->xcrossing.y;
|
||||||
event->crossing.source = CLUTTER_ACTOR (stage);
|
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;
|
res = CLUTTER_TRANSLATE_QUEUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -847,22 +847,22 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
|||||||
device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||||
GINT_TO_POINTER (xev->deviceid));
|
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)
|
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->crossing.time = xev->time;
|
||||||
event->motion.source = CLUTTER_ACTOR (stage);
|
event->crossing.x = xev->event_x;
|
||||||
|
event->crossing.y = xev->event_y;
|
||||||
|
|
||||||
event->motion.time = xev->time;
|
_clutter_stage_add_device (stage, device);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -876,18 +876,22 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_clutter_input_device_set_stage (device, NULL);
|
|
||||||
|
|
||||||
event->crossing.type = event->type = CLUTTER_LEAVE;
|
event->crossing.type = event->type = CLUTTER_LEAVE;
|
||||||
|
|
||||||
|
event->crossing.stage = stage;
|
||||||
event->crossing.source = CLUTTER_ACTOR (stage);
|
event->crossing.source = CLUTTER_ACTOR (stage);
|
||||||
|
event->crossing.related = NULL;
|
||||||
|
|
||||||
event->crossing.time = xev->time;
|
event->crossing.time = xev->time;
|
||||||
event->crossing.x = xev->event_x;
|
event->crossing.x = xev->event_x;
|
||||||
event->crossing.y = xev->event_y;
|
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;
|
retval = CLUTTER_TRANSLATE_QUEUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user