mirror of
https://github.com/brl/mutter.git
synced 2024-12-27 05:12:15 +00:00
actor: Move event chain emission into ClutterActor
By moving the function that builds the event emission chain we can avoid a bunch of checks and function calls.
This commit is contained in:
parent
67cbb56ab8
commit
9b7287e897
@ -298,6 +298,9 @@ void _clutter_actor_shader_post_paint (ClutterActor *actor);
|
||||
|
||||
ClutterActorAlign _clutter_actor_get_effective_x_align (ClutterActor *self);
|
||||
|
||||
void _clutter_actor_handle_event (ClutterActor *actor,
|
||||
const ClutterEvent *event);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */
|
||||
|
@ -18913,3 +18913,55 @@ clutter_actor_get_content_repeat (ClutterActor *self)
|
||||
|
||||
return self->priv->content_repeat;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_actor_handle_event (ClutterActor *self,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
GPtrArray *event_tree;
|
||||
ClutterActor *iter;
|
||||
gboolean is_key_event;
|
||||
gint i = 0;
|
||||
|
||||
/* XXX - for historical reasons that are now lost in the mists of time,
|
||||
* key events are delivered regardless of whether an actor is set as
|
||||
* reactive; this should be changed for 2.0.
|
||||
*/
|
||||
is_key_event = event->type == CLUTTER_KEY_PRESS ||
|
||||
event->type == CLUTTER_KEY_RELEASE;
|
||||
|
||||
event_tree = g_ptr_array_sized_new (64);
|
||||
g_ptr_array_set_free_func (event_tree, (GDestroyNotify) g_object_unref);
|
||||
|
||||
/* build the list of of emitters for the event */
|
||||
iter = self;
|
||||
while (iter != NULL)
|
||||
{
|
||||
ClutterActor *parent = iter->priv->parent;
|
||||
|
||||
if (CLUTTER_ACTOR_IS_REACTIVE (iter) || /* an actor must be reactive */
|
||||
parent == NULL || /* unless it's the stage */
|
||||
is_key_event) /* or this is a key event */
|
||||
{
|
||||
/* keep a reference on the actor, so that it remains valid
|
||||
* for the duration of the signal emission
|
||||
*/
|
||||
g_ptr_array_add (event_tree, g_object_ref (iter));
|
||||
}
|
||||
|
||||
iter = parent;
|
||||
}
|
||||
|
||||
/* Capture: from top-level downwards */
|
||||
for (i = event_tree->len - 1; i >= 0; i--)
|
||||
if (clutter_actor_event (g_ptr_array_index (event_tree, i), event, TRUE))
|
||||
goto done;
|
||||
|
||||
/* Bubble: from source upwards */
|
||||
for (i = 0; i < event_tree->len; i++)
|
||||
if (clutter_actor_event (g_ptr_array_index (event_tree, i), event, FALSE))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
g_ptr_array_free (event_tree, TRUE);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include "clutter-actor.h"
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-backend-private.h"
|
||||
#include "clutter-config.h"
|
||||
#include "clutter-debug.h"
|
||||
@ -2241,14 +2241,9 @@ event_click_count_generate (ClutterEvent *event)
|
||||
}
|
||||
|
||||
static inline void
|
||||
emit_event (ClutterEvent *event,
|
||||
gboolean is_key_event)
|
||||
emit_event_chain (ClutterEvent *event)
|
||||
{
|
||||
static gboolean lock = FALSE;
|
||||
|
||||
GPtrArray *event_tree = NULL;
|
||||
ClutterActor *actor;
|
||||
gint i = 0;
|
||||
static gboolean lock = FALSE;
|
||||
|
||||
if (event->any.source == NULL)
|
||||
{
|
||||
@ -2265,42 +2260,7 @@ emit_event (ClutterEvent *event,
|
||||
|
||||
lock = TRUE;
|
||||
|
||||
event_tree = g_ptr_array_sized_new (64);
|
||||
|
||||
actor = event->any.source;
|
||||
|
||||
/* Build 'tree' of emitters for the event */
|
||||
while (actor)
|
||||
{
|
||||
ClutterActor *parent;
|
||||
|
||||
parent = clutter_actor_get_parent (actor);
|
||||
|
||||
if (clutter_actor_get_reactive (actor) ||
|
||||
parent == NULL || /* stage gets all events */
|
||||
is_key_event) /* keyboard events are always emitted */
|
||||
{
|
||||
g_ptr_array_add (event_tree, g_object_ref (actor));
|
||||
}
|
||||
|
||||
actor = parent;
|
||||
}
|
||||
|
||||
/* Capture */
|
||||
for (i = event_tree->len - 1; i >= 0; i--)
|
||||
if (clutter_actor_event (g_ptr_array_index (event_tree, i), event, TRUE))
|
||||
goto done;
|
||||
|
||||
/* Bubble */
|
||||
for (i = 0; i < event_tree->len; i++)
|
||||
if (clutter_actor_event (g_ptr_array_index (event_tree, i), event, FALSE))
|
||||
goto done;
|
||||
|
||||
done:
|
||||
for (i = 0; i < event_tree->len; i++)
|
||||
g_object_unref (g_ptr_array_index (event_tree, i));
|
||||
|
||||
g_ptr_array_free (event_tree, TRUE);
|
||||
_clutter_actor_handle_event (event->any.source, event);
|
||||
|
||||
lock = FALSE;
|
||||
}
|
||||
@ -2320,7 +2280,7 @@ emit_pointer_event (ClutterEvent *event,
|
||||
(device == NULL || device->pointer_grab_actor == NULL))
|
||||
{
|
||||
/* no grab, time to capture and bubble */
|
||||
emit_event (event, FALSE);
|
||||
emit_event_chain (event);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2341,19 +2301,23 @@ static inline void
|
||||
emit_touch_event (ClutterEvent *event,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
ClutterActor *grab_actor;
|
||||
ClutterActor *grab_actor = NULL;
|
||||
|
||||
if ((device->sequence_grab_actors != NULL) &&
|
||||
((grab_actor = g_hash_table_lookup (device->sequence_grab_actors,
|
||||
event->touch.sequence)) != NULL))
|
||||
if (device->sequence_grab_actors != NULL)
|
||||
{
|
||||
/* sequence grab */
|
||||
grab_actor = g_hash_table_lookup (device->sequence_grab_actors,
|
||||
event->touch.sequence);
|
||||
}
|
||||
|
||||
if (grab_actor != NULL)
|
||||
{
|
||||
/* per-device sequence grab */
|
||||
clutter_actor_event (grab_actor, event, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no grab, time to capture and bubble */
|
||||
emit_event (event, FALSE);
|
||||
emit_event_chain (event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2366,16 +2330,19 @@ emit_keyboard_event (ClutterEvent *event,
|
||||
if (context->keyboard_grab_actor == NULL &&
|
||||
(device == NULL || device->keyboard_grab_actor == NULL))
|
||||
{
|
||||
emit_event (event, TRUE);
|
||||
/* no grab, time to capture and bubble */
|
||||
emit_event_chain (event);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context->keyboard_grab_actor != NULL)
|
||||
{
|
||||
/* global key grab */
|
||||
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
|
||||
}
|
||||
else if (device != NULL && device->keyboard_grab_actor != NULL)
|
||||
{
|
||||
/* per-device key grab */
|
||||
clutter_actor_event (context->keyboard_grab_actor, event, FALSE);
|
||||
}
|
||||
}
|
||||
@ -2725,14 +2692,20 @@ _clutter_process_event (ClutterEvent *event)
|
||||
|
||||
stage = CLUTTER_ACTOR (event->any.stage);
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
CLUTTER_NOTE (EVENT, "Event received");
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "Discarding event withou a stage set");
|
||||
return;
|
||||
}
|
||||
|
||||
/* keep a pointer to the event and time, so that we don't need to
|
||||
* add an event parameter to all signals that can be emitted within
|
||||
* an event chain
|
||||
*/
|
||||
context->last_event_time = clutter_event_get_time (event);
|
||||
|
||||
context->current_event = event;
|
||||
|
||||
_clutter_process_event_details (stage, context, event);
|
||||
|
||||
context->current_event = NULL;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user