clutter/actor: Stop transitions in children when removing

When we remove a child, we stop its transitions (animations), but we
didn't stop animations on grand children. What we did, however, was to
clear the stage views of the grand children, and this caused a bunch of
orphaned transitions (ClutterTimeline) and accompanied warnings.

Make it so that if we stop transitions, and clear stage views, also stop
transitions for the grand children. Detached children don't have a way
to continue animating anyway, since they have no stage view (thus frame
clock) to be driven by.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2716>
This commit is contained in:
Jonas Ådahl 2022-11-24 16:18:04 +01:00 committed by Marge Bot
parent 61cc31c3ce
commit a897542876
3 changed files with 11 additions and 5 deletions

View File

@ -255,7 +255,8 @@ void _clutter_actor_attach_clone
void _clutter_actor_detach_clone (ClutterActor *actor,
ClutterActor *clone);
void _clutter_actor_queue_only_relayout (ClutterActor *actor);
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor);
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor,
gboolean stop_transitions);
float clutter_actor_get_real_resource_scale (ClutterActor *actor);

View File

@ -4200,7 +4200,7 @@ clutter_actor_remove_child_internal (ClutterActor *self,
* cleared as the child and its children leave the actor tree.
*/
if (clear_stage_views && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
clutter_actor_clear_stage_views_recursive (child);
clutter_actor_clear_stage_views_recursive (child, stop_transitions);
if (emit_parent_set && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
g_signal_emit (child, actor_signals[PARENT_SET], 0, self);
@ -15291,8 +15291,12 @@ clear_stage_views_cb (ClutterActor *actor,
int depth,
gpointer user_data)
{
gboolean stop_transitions = GPOINTER_TO_INT (user_data);
g_autoptr (GList) old_stage_views = NULL;
if (stop_transitions)
_clutter_actor_stop_transitions (actor);
actor->priv->needs_update_stage_views = TRUE;
old_stage_views = g_steal_pointer (&actor->priv->stage_views);
@ -15318,13 +15322,14 @@ maybe_emit_stage_views_changed_cb (ClutterActor *actor,
}
void
clutter_actor_clear_stage_views_recursive (ClutterActor *self)
clutter_actor_clear_stage_views_recursive (ClutterActor *self,
gboolean stop_transitions)
{
_clutter_actor_traverse (self,
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST,
clear_stage_views_cb,
NULL,
NULL);
GINT_TO_POINTER (stop_transitions));
_clutter_actor_traverse (self,
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST,
maybe_emit_stage_views_changed_cb,

View File

@ -3097,7 +3097,7 @@ clutter_stage_peek_stage_views (ClutterStage *stage)
void
clutter_stage_clear_stage_views (ClutterStage *stage)
{
clutter_actor_clear_stage_views_recursive (CLUTTER_ACTOR (stage));
clutter_actor_clear_stage_views_recursive (CLUTTER_ACTOR (stage), FALSE);
}
GList *