From 8f2044e41222e2f5360f7ee7386d4ce0903ed786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 25 Jul 2019 01:14:37 +0200 Subject: [PATCH 12/28] clutter/stage-manager: Pause the master clock when all stages have been removed The clutter master clock is used by the stage during redraws, but never stopped when the last stage is destroyed, potentially causing calls to dead objects. So, set it paused (destroying the underlying GSource) when the last stage is disposed. https://gitlab.gnome.org/GNOME/mutter/merge_requests/682 --- clutter/clutter/clutter-stage-manager.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clutter/clutter/clutter-stage-manager.c b/clutter/clutter/clutter-stage-manager.c index 3a44c8209..185e3e2ce 100644 --- a/clutter/clutter/clutter-stage-manager.c +++ b/clutter/clutter/clutter-stage-manager.c @@ -267,57 +267,65 @@ clutter_stage_manager_list_stages (ClutterStageManager *stage_manager) /** * clutter_stage_manager_peek_stages: * @stage_manager: a #ClutterStageManager * * Lists all currently used stages. * * Return value: (transfer none) (element-type Clutter.Stage): a pointer * to the internal list of #ClutterStage objects. The returned list * is owned by the #ClutterStageManager and should never be modified * or freed * * Since: 1.0 */ const GSList * clutter_stage_manager_peek_stages (ClutterStageManager *stage_manager) { return stage_manager->stages; } void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager, ClutterStage *stage) { if (g_slist_find (stage_manager->stages, stage)) { g_warning ("Trying to add a stage to the list of managed stages, " "but it is already in it, aborting."); return; } + _clutter_master_clock_set_paused (_clutter_master_clock_get_default (), FALSE); + g_object_ref_sink (stage); stage_manager->stages = g_slist_append (stage_manager->stages, stage); g_signal_emit (stage_manager, manager_signals[STAGE_ADDED], 0, stage); } void _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager, ClutterStage *stage) { /* this might be called multiple times from a ::dispose, so it * needs to just return without warning */ if (!g_slist_find (stage_manager->stages, stage)) return; stage_manager->stages = g_slist_remove (stage_manager->stages, stage); /* if the default stage is being destroyed then we unset the pointer */ if (default_stage == stage) default_stage = NULL; g_signal_emit (stage_manager, manager_signals[STAGE_REMOVED], 0, stage); g_object_unref (stage); + + if (!stage_manager->stages) + { + ClutterMasterClock *master_clock = _clutter_master_clock_get_default (); + _clutter_master_clock_set_paused (master_clock, TRUE); + } } -- 2.26.2