From 3f732cdc2b3de58b611174e4266e175f9b1e431e Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Sat, 21 Jul 2012 13:33:02 -0400 Subject: [PATCH] actor: Ensure that we remove only implicit transitions The transitions we create implicitly should be removed from the set of transitions associated to an actor; the transitions explicitly associated to an actor, though, have to survive the emission of their 'stopped' signal. --- clutter/clutter-actor.c | 112 ++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 49 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 39f6f38ac..172847fbb 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -977,6 +977,7 @@ typedef struct _TransitionClosure ClutterTransition *transition; gchar *name; gulong completed_id; + guint is_implicit : 1; } TransitionClosure; static void clutter_container_iface_init (ClutterContainerIface *iface); @@ -18252,14 +18253,17 @@ on_transition_stopped (ClutterTransition *transition, t_quark = g_quark_from_string (clos->name); t_name = g_strdup (clos->name); - /* we take a reference here because removing the closure - * will release the reference on the transition, and we - * want the transition to survive the signal emission; - * the master clock will release the last reference at - * the end of the frame processing. - */ - g_object_ref (transition); - g_hash_table_remove (info->transitions, clos->name); + if (clos->is_implicit) + { + /* we take a reference here because removing the closure + * will release the reference on the transition, and we + * want the transition to survive the signal emission; + * the master clock will release the last reference at + * the end of the frame processing. + */ + g_object_ref (transition); + g_hash_table_remove (info->transitions, clos->name); + } /* we emit the ::transition-stopped after removing the * transition, so that we can chain up new transitions @@ -18284,6 +18288,55 @@ on_transition_stopped (ClutterTransition *transition, } } +static void +clutter_actor_add_transition_internal (ClutterActor *self, + const gchar *name, + ClutterTransition *transition, + gboolean is_implicit) +{ + ClutterTimeline *timeline; + TransitionClosure *clos; + ClutterAnimationInfo *info; + + info = _clutter_actor_get_animation_info (self); + + if (info->transitions == NULL) + info->transitions = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, + transition_closure_free); + + if (g_hash_table_lookup (info->transitions, name) != NULL) + { + g_warning ("A transition with name '%s' already exists for " + "the actor '%s'", + name, + _clutter_actor_get_debug_name (self)); + return; + } + + clutter_transition_set_animatable (transition, CLUTTER_ANIMATABLE (self)); + + timeline = CLUTTER_TIMELINE (transition); + + clos = g_slice_new (TransitionClosure); + clos->actor = self; + clos->transition = g_object_ref (transition); + clos->name = g_strdup (name); + clos->is_implicit = is_implicit; + clos->completed_id = g_signal_connect (timeline, "stopped", + G_CALLBACK (on_transition_stopped), + clos); + + CLUTTER_NOTE (ANIMATION, + "Adding transition '%s' [%p] to actor '%s'", + clos->name, + clos->transition, + _clutter_actor_get_debug_name (self)); + + g_hash_table_insert (info->transitions, clos->name, clos); + clutter_timeline_start (timeline); +} + /*< private >* * _clutter_actor_create_transition: * @actor: a #ClutterActor @@ -18418,7 +18471,7 @@ _clutter_actor_create_transition (ClutterActor *actor, #endif /* CLUTTER_ENABLE_DEBUG */ /* this will start the transition as well */ - clutter_actor_add_transition (actor, pspec->name, res); + clutter_actor_add_transition_internal (actor, pspec->name, res, TRUE); /* the actor now owns the transition */ g_object_unref (res); @@ -18488,50 +18541,11 @@ clutter_actor_add_transition (ClutterActor *self, const char *name, ClutterTransition *transition) { - ClutterTimeline *timeline; - TransitionClosure *clos; - ClutterAnimationInfo *info; - g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (name != NULL); g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); - info = _clutter_actor_get_animation_info (self); - - if (info->transitions == NULL) - info->transitions = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, - transition_closure_free); - - if (g_hash_table_lookup (info->transitions, name) != NULL) - { - g_warning ("A transition with name '%s' already exists for " - "the actor '%s'", - name, - _clutter_actor_get_debug_name (self)); - return; - } - - clutter_transition_set_animatable (transition, CLUTTER_ANIMATABLE (self)); - - timeline = CLUTTER_TIMELINE (transition); - - clos = g_slice_new (TransitionClosure); - clos->actor = self; - clos->transition = g_object_ref (transition); - clos->name = g_strdup (name); - clos->completed_id = g_signal_connect (timeline, "stopped", - G_CALLBACK (on_transition_stopped), - clos); - - CLUTTER_NOTE (ANIMATION, - "Adding transition '%s' [%p] to actor '%s'", - clos->name, - clos->transition, - _clutter_actor_get_debug_name (self)); - - g_hash_table_insert (info->transitions, clos->name, clos); - clutter_timeline_start (timeline); + clutter_actor_add_transition_internal (self, name, transition, FALSE); } /**