diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index 6cbec0b70..2c69f0ad6 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -843,6 +843,7 @@ struct _ClutterActorPrivate guint needs_paint_volume_update : 1; guint had_effects_on_last_paint_volume_update : 1; guint needs_update_stage_views : 1; + guint clear_stage_views_needs_stage_views_changed : 1; }; enum @@ -15708,7 +15709,21 @@ clear_stage_views_cb (ClutterActor *actor, old_stage_views = g_steal_pointer (&actor->priv->stage_views); if (old_stage_views) - g_signal_emit (actor, actor_signals[STAGE_VIEWS_CHANGED], 0); + actor->priv->clear_stage_views_needs_stage_views_changed = TRUE; + + return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE; +} + +static ClutterActorTraverseVisitFlags +maybe_emit_stage_views_changed_cb (ClutterActor *actor, + int depth, + gpointer user_data) +{ + if (actor->priv->clear_stage_views_needs_stage_views_changed) + { + actor->priv->clear_stage_views_needs_stage_views_changed = FALSE; + g_signal_emit (actor, actor_signals[STAGE_VIEWS_CHANGED], 0); + } return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE; } @@ -15721,6 +15736,11 @@ clutter_actor_clear_stage_views_recursive (ClutterActor *self) clear_stage_views_cb, NULL, NULL); + _clutter_actor_traverse (self, + CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST, + maybe_emit_stage_views_changed_cb, + NULL, + NULL); } float @@ -16033,7 +16053,7 @@ clutter_actor_pick_frame_clock (ClutterActor *self, for (l = stage_views_list; l; l = l->next) { - ClutterStageView *view = l->data; + ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data); float refresh_rate; refresh_rate = clutter_stage_view_get_refresh_rate (view); diff --git a/src/tests/stage-view-tests.c b/src/tests/stage-view-tests.c index abb2cebb0..198b6cd49 100644 --- a/src/tests/stage-view-tests.c +++ b/src/tests/stage-view-tests.c @@ -1255,6 +1255,57 @@ meta_test_timeline_actor_destroyed (void) clutter_actor_destroy (persistent_actor); } +static void +meta_test_timeline_actor_tree_clear (void) +{ + ClutterActor *stage; + ClutterActor *container1; + ClutterActor *container2; + g_autoptr (ClutterActor) floating = NULL; + g_autoptr (ClutterTimeline) timeline = NULL; + GList *stage_views; + + stage = meta_backend_get_stage (meta_context_get_backend (test_context)); + + ensure_view_count (1); + + container1 = clutter_actor_new (); + clutter_actor_set_size (container1, 100, 100); + clutter_actor_add_child (stage, container1); + + wait_for_paint (stage); + + container2 = clutter_actor_new (); + clutter_actor_set_size (container2, 100, 100); + clutter_actor_add_child (stage, container2); + + floating = g_object_ref_sink (clutter_actor_new ()); + clutter_actor_set_size (floating, 100, 100); + + clutter_actor_add_child (container2, floating); + timeline = clutter_timeline_new_for_actor (floating, 100); + clutter_actor_remove_child (container2, floating); + + clutter_actor_add_child (container1, floating); + + ensure_view_count (1); + + is_on_stage_views (container1, 0); + is_on_stage_views (container2, 0); + is_on_stage_views (floating, 0); + + wait_for_paint (stage); + + stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); + is_on_stage_views (container1, 1, stage_views->data); + is_on_stage_views (container2, 1, stage_views->data); + is_on_stage_views (floating, 1, stage_views->data); + + clutter_actor_destroy (floating); + clutter_actor_destroy (container1); + clutter_actor_destroy (container2); +} + static void init_tests (void) { @@ -1286,6 +1337,8 @@ init_tests (void) meta_test_actor_stage_views_queue_frame_drawn); g_test_add_func ("/stage-views/timeline/actor-destroyed", meta_test_timeline_actor_destroyed); + g_test_add_func ("/stage-views/timeline/tree-clear", + meta_test_timeline_actor_tree_clear); } int