[clutter/wip/action-handle-event: 3/6] actor: Move event chain emission into ClutterActor



commit d8e17389ce8025f7ef22c76678a55807ba444826
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Sun Jun 24 09:58:12 2012 +0100

    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.

 clutter/clutter-actor-private.h |    3 +
 clutter/clutter-actor.c         |   52 ++++++++++++++++++++++++
 clutter/clutter-main.c          |   85 +++++++++++++-------------------------
 3 files changed, 84 insertions(+), 56 deletions(-)
---
diff --git a/clutter/clutter-actor-private.h b/clutter/clutter-actor-private.h
index 07e2960..866d6a0 100644
--- a/clutter/clutter-actor-private.h
+++ b/clutter/clutter-actor-private.h
@@ -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__ */
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index e0cfd23..12d5fda 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -18886,3 +18886,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);
+}
diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c
index 1e9e8a0..8ab0682 100644
--- a/clutter/clutter-main.c
+++ b/clutter/clutter-main.c
@@ -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"
@@ -2217,14 +2217,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)
     {
@@ -2241,42 +2236,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;
 }
@@ -2296,7 +2256,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
     {
@@ -2317,19 +2277,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);
     }
 }
 
@@ -2342,16 +2306,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);
         }
     }
@@ -2701,14 +2668,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;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]