Blob Blame History Raw
From 8f2044e41222e2f5360f7ee7386d4ce0903ed786 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
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