summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2013-03-07 18:09:33 +0000
committerEmmanuele Bassi <ebassi@gnome.org>2013-03-13 16:10:23 -0300
commitf8c129ae8189845c4163908f947ad9252b611314 (patch)
tree3ca786cb27236be5a30154bd5b7b0fa6a7afd168
parent3e53c1ff73f6566359e6fe037ca1f3162299af03 (diff)
downloadclutter-f8c129ae8189845c4163908f947ad9252b611314.tar.gz
actor: Keep track of clones
Instead of using signal notifications, we should be able to keep track of the clones of an actor from within ClutterActor itself, using private API. There's no point in pretending that people can actually create a Clone class out of tree, given the amount of invariants we have to punch through in order to implement a proper replicator node of the scene graph, so we can just skip the signal emissions and just do the right thing at the right time.
-rw-r--r--clutter/clutter-actor-private.h7
-rw-r--r--clutter/clutter-actor.c80
-rw-r--r--clutter/clutter-clone.c30
3 files changed, 91 insertions, 26 deletions
diff --git a/clutter/clutter-actor-private.h b/clutter/clutter-actor-private.h
index c5319e213..1c6f16524 100644
--- a/clutter/clutter-actor-private.h
+++ b/clutter/clutter-actor-private.h
@@ -312,6 +312,13 @@ ClutterActorAlign _clutter_actor_get_effective_x_align
void _clutter_actor_handle_event (ClutterActor *actor,
const ClutterEvent *event);
+void _clutter_actor_attach_clone (ClutterActor *actor,
+ ClutterActor *clone);
+void _clutter_actor_detach_clone (ClutterActor *actor,
+ ClutterActor *clone);
+void _clutter_actor_queue_redraw_on_clones (ClutterActor *actor);
+void _clutter_actor_queue_relayout_on_clones (ClutterActor *actor);
+
G_END_DECLS
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */
diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index 186f8a006..b02a106cf 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -771,7 +771,10 @@ struct _ClutterActorPrivate
gchar *debug_name;
#endif
- /* bitfields */
+ /* a set of clones of the actor */
+ GHashTable *clones;
+
+ /* bitfields: KEEP AT THE END */
/* fixed position and sizes */
guint position_set : 1;
@@ -2548,6 +2551,8 @@ _clutter_actor_signal_queue_redraw (ClutterActor *self,
* receive the signal so it can queue its own redraw.
*/
+ _clutter_actor_queue_redraw_on_clones (self);
+
/* calls klass->queue_redraw in default handler */
g_signal_emit (self, actor_signals[QUEUE_REDRAW], 0, origin);
}
@@ -5805,6 +5810,12 @@ clutter_actor_dispose (GObject *object)
g_clear_object (&priv->content);
}
+ if (priv->clones != NULL)
+ {
+ g_hash_table_unref (priv->clones);
+ priv->clones = NULL;
+ }
+
G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object);
}
@@ -8791,6 +8802,8 @@ _clutter_actor_queue_only_relayout (ClutterActor *self)
}
#endif /* CLUTTER_ENABLE_DEBUG */
+ _clutter_actor_queue_relayout_on_clones (self);
+
g_signal_emit (self, actor_signals[QUEUE_RELAYOUT], 0);
}
@@ -20128,3 +20141,68 @@ clutter_actor_get_child_transform (ClutterActor *self,
else
clutter_matrix_init_identity (transform);
}
+
+void
+_clutter_actor_attach_clone (ClutterActor *actor,
+ ClutterActor *clone)
+{
+ ClutterActorPrivate *priv = actor->priv;
+
+ g_assert (clone != NULL);
+
+ if (priv->clones == NULL)
+ priv->clones = g_hash_table_new (NULL, NULL);
+
+ g_hash_table_add (priv->clones, clone);
+}
+
+void
+_clutter_actor_detach_clone (ClutterActor *actor,
+ ClutterActor *clone)
+{
+ ClutterActorPrivate *priv = actor->priv;
+
+ g_assert (clone != NULL);
+
+ if (priv->clones == NULL ||
+ g_hash_table_lookup (priv->clones, clone) == NULL)
+ return;
+
+ g_hash_table_remove (priv->clones, clone);
+
+ if (g_hash_table_size (priv->clones) == 0)
+ {
+ g_hash_table_unref (priv->clones);
+ priv->clones = NULL;
+ }
+}
+
+void
+_clutter_actor_queue_redraw_on_clones (ClutterActor *self)
+{
+ ClutterActorPrivate *priv = self->priv;
+ GHashTableIter iter;
+ gpointer key;
+
+ if (priv->clones == NULL)
+ return;
+
+ g_hash_table_iter_init (&iter, priv->clones);
+ while (g_hash_table_iter_next (&iter, &key, NULL))
+ clutter_actor_queue_redraw (key);
+}
+
+void
+_clutter_actor_queue_relayout_on_clones (ClutterActor *self)
+{
+ ClutterActorPrivate *priv = self->priv;
+ GHashTableIter iter;
+ gpointer key;
+
+ if (priv->clones == NULL)
+ return;
+
+ g_hash_table_iter_init (&iter, priv->clones);
+ while (g_hash_table_iter_next (&iter, &key, NULL))
+ clutter_actor_queue_relayout (key);
+}
diff --git a/clutter/clutter-clone.c b/clutter/clutter-clone.c
index 6a82beb2b..1f94ab2b7 100644
--- a/clutter/clutter-clone.c
+++ b/clutter/clutter-clone.c
@@ -378,34 +378,17 @@ clutter_clone_new (ClutterActor *source)
}
static void
-clone_source_queue_redraw_cb (ClutterActor *source,
- ClutterActor *origin,
- ClutterClone *self)
-{
- clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
-}
-
-static void
-clone_source_queue_relayout_cb (ClutterActor *source,
- ClutterClone *self)
-{
- clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
-}
-
-static void
clutter_clone_set_source_internal (ClutterClone *self,
ClutterActor *source)
{
ClutterClonePrivate *priv = self->priv;
+ if (priv->clone_source == source)
+ return;
+
if (priv->clone_source != NULL)
{
- g_signal_handlers_disconnect_by_func (priv->clone_source,
- G_CALLBACK (clone_source_queue_redraw_cb),
- self);
- g_signal_handlers_disconnect_by_func (priv->clone_source,
- G_CALLBACK (clone_source_queue_relayout_cb),
- self);
+ _clutter_actor_detach_clone (priv->clone_source, CLUTTER_ACTOR (self));
g_object_unref (priv->clone_source);
priv->clone_source = NULL;
}
@@ -413,10 +396,7 @@ clutter_clone_set_source_internal (ClutterClone *self,
if (source != NULL)
{
priv->clone_source = g_object_ref (source);
- g_signal_connect (priv->clone_source, "queue-redraw",
- G_CALLBACK (clone_source_queue_redraw_cb), self);
- g_signal_connect (priv->clone_source, "queue-relayout",
- G_CALLBACK (clone_source_queue_relayout_cb), self);
+ _clutter_actor_attach_clone (priv->clone_source, CLUTTER_ACTOR (self));
}
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SOURCE]);