[mutter] MetaLater: Invoke later callbacks queued by earlier ones



commit 35da6a907854afb38556edb01fac4b3dbf55deb5
Author: Jonas Ådahl <jadahl gmail com>
Date:   Mon Sep 14 22:31:32 2015 +0800

    MetaLater: Invoke later callbacks queued by earlier ones
    
    If a MetaLater callback queued another MetaLater with a scheduling
    later than the one currently being invoked, make it so that the newly
    scheduled callback will actually be invoked.
    
    The fact that it doesn't already do this is a regression from
    cd7a9680932868d1d2ef5447c77712cef9a443dd.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=755605

 src/core/util.c |  103 ++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 68 insertions(+), 35 deletions(-)
---
diff --git a/src/core/util.c b/src/core/util.c
index f4e56b9..22d4674 100644
--- a/src/core/util.c
+++ b/src/core/util.c
@@ -49,6 +49,9 @@ meta_topic_real_valist (MetaDebugTopic topic,
                         va_list        args) G_GNUC_PRINTF(2, 0);
 #endif
 
+static gboolean
+meta_later_remove_from_list (guint later_id, GSList **laters_list);
+
 static gint verbose_topics = 0;
 static gboolean is_debugging = FALSE;
 static gboolean replace_current = FALSE;
@@ -739,7 +742,14 @@ typedef struct
   gboolean run_once;
 } MetaLater;
 
-static GSList *laters = NULL;
+static GSList *laters[] = {
+  NULL, /* META_LATER_RESIZE */
+  NULL, /* META_LATER_CALC_SHOWING */
+  NULL, /* META_LATER_CHECK_FULLSCREEN */
+  NULL, /* META_LATER_SYNC_STACK */
+  NULL, /* META_LATER_BEFORE_REDRAW */
+  NULL, /* META_LATER_IDLE */
+};
 /* This is a dummy timeline used to get the Clutter master clock running */
 static ClutterTimeline *later_timeline;
 static guint later_repaint_func = 0;
@@ -772,25 +782,14 @@ destroy_later (MetaLater *later)
   unref_later (later);
 }
 
-/* Used to sort the list of laters with the highest priority
- * functions first.
- */
-static int
-compare_laters (gconstpointer a,
-                gconstpointer b)
-{
-  return ((const MetaLater *)a)->when - ((const MetaLater *)b)->when;
-}
-
-static gboolean
-run_repaint_laters (gpointer data)
+static void
+run_repaint_laters (GSList **laters_list)
 {
   GSList *laters_copy;
   GSList *l;
-  gboolean keep_timeline_running = FALSE;
 
   laters_copy = NULL;
-  for (l = laters; l; l = l->next)
+  for (l = *laters_list; l; l = l->next)
     {
       MetaLater *later = l->data;
       if (later->source == 0 ||
@@ -806,22 +805,41 @@ run_repaint_laters (gpointer data)
     {
       MetaLater *later = l->data;
 
-      if (later->func && later->func (later->data))
+      if (!later->func || !later->func (later->data))
+        meta_later_remove_from_list (later->id, laters_list);
+      unref_later (later);
+    }
+
+  g_slist_free (laters_copy);
+}
+
+static gboolean
+run_all_repaint_laters (gpointer data)
+{
+  guint i;
+  GSList *l;
+  gboolean keep_timeline_running = FALSE;
+
+  for (i = 0; i < G_N_ELEMENTS (laters); i++)
+    {
+      run_repaint_laters (&laters[i]);
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (laters); i++)
+    {
+      for (l = laters[i]; l; l = l->next)
         {
+          MetaLater *later = l->data;
+
           if (later->source == 0)
             keep_timeline_running = TRUE;
         }
-      else
-        meta_later_remove (later->id);
-      unref_later (later);
     }
 
   if (!keep_timeline_running)
     clutter_timeline_stop (later_timeline);
 
-  g_slist_free (laters_copy);
-
-  /* Just keep the repaint func around - it's cheap if the list is empty */
+  /* Just keep the repaint func around - it's cheap if the lists are empty */
   return TRUE;
 }
 
@@ -832,7 +850,7 @@ ensure_later_repaint_func (void)
     later_timeline = clutter_timeline_new (G_MAXUINT);
 
   if (later_repaint_func == 0)
-    later_repaint_func = clutter_threads_add_repaint_func (run_repaint_laters,
+    later_repaint_func = clutter_threads_add_repaint_func (run_all_repaint_laters,
                                                            NULL, NULL);
 
   /* Make sure the repaint function gets run */
@@ -888,7 +906,7 @@ meta_later_add (MetaLaterType  when,
   later->data = data;
   later->notify = notify;
 
-  laters = g_slist_insert_sorted (laters, later, compare_laters);
+  laters[when] = g_slist_prepend (laters[when], later);
 
   switch (when)
     {
@@ -920,30 +938,45 @@ meta_later_add (MetaLaterType  when,
   return later->id;
 }
 
-/**
- * meta_later_remove:
- * @later_id: the integer ID returned from meta_later_add()
- *
- * Removes a callback added with meta_later_add()
- */
-void
-meta_later_remove (guint later_id)
+static gboolean
+meta_later_remove_from_list (guint later_id, GSList **laters_list)
 {
   GSList *l;
 
-  for (l = laters; l; l = l->next)
+  for (l = *laters_list; l; l = l->next)
     {
       MetaLater *later = l->data;
+
       if (later->id == later_id)
         {
-          laters = g_slist_delete_link (laters, l);
+          *laters_list = g_slist_delete_link (*laters_list, l);
           /* If this was a "repaint func" later, we just let the
            * repaint func run and get removed
            */
           destroy_later (later);
-          return;
+          return TRUE;
         }
     }
+
+  return FALSE;
+}
+
+/**
+ * meta_later_remove:
+ * @later_id: the integer ID returned from meta_later_add()
+ *
+ * Removes a callback added with meta_later_add()
+ */
+void
+meta_later_remove (guint later_id)
+{
+  guint i;
+
+  for (i = 0; i < G_N_ELEMENTS (laters); i++)
+    {
+      if (meta_later_remove_from_list (later_id, &laters[i]))
+        return;
+    }
 }
 
 MetaLocaleDirection


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]