[gtk+] window: Make process_updates faster



commit 5fa0da42006b14017538fedca454ff4c99034ba6
Author: John Lindgren <john lindgren aol com>
Date:   Wed Jun 26 10:03:51 2013 +0200

    window: Make process_updates faster
    
    Only look at "impl" windows in gdk_window_process_updates_with_mode()
    since these are the only ones we care about.  This avoids a lot of
    unnecessary calls to g_list_copy() and g_object_ref().

 gdk/gdkwindow.c |   90 +++++++++++++++++++++++++++++++++----------------------
 1 files changed, 54 insertions(+), 36 deletions(-)
---
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 823e6fe..31842a7 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -3615,59 +3615,77 @@ enum {
   PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN
 };
 
+static GList *
+find_impl_windows_to_update (GList      *list,
+                             GdkWindow  *window,
+                             gint        recurse_mode)
+{
+  GList *node;
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return list;
+
+  /* Recurse first, so that we process updates in reverse stacking
+   * order so composition or painting over achieves the desired effect
+   * for offscreen windows
+   */
+  if (recurse_mode != PROCESS_UPDATES_NO_RECURSE)
+    {
+      for (node = window->children; node; node = node->next)
+        {
+          GdkWindow *child = node->data;
+
+          if (recurse_mode == PROCESS_UPDATES_WITH_ALL_CHILDREN ||
+              (recurse_mode == PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN &&
+               child->frame_clock == NULL))
+            {
+              list = find_impl_windows_to_update (list, child, recurse_mode);
+            }
+        }
+    }
+
+  /* add reference count so the window cannot be deleted in a callback */
+  if (window->impl_window == window)
+    list = g_list_prepend (list, g_object_ref (window));
+
+  return list;
+}
+
 static void
 gdk_window_process_updates_with_mode (GdkWindow     *window,
                                       int            recurse_mode)
 {
-  GdkWindow *impl_window;
+  GList *list = NULL;
+  GList *node;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  /* Make sure the window lives during the expose callouts */
-  g_object_ref (window);
-
-  impl_window = gdk_window_get_impl_window (window);
-  if ((impl_window->update_area) &&
-      !impl_window->update_freeze_count &&
-      !gdk_window_is_toplevel_frozen (window) &&
+  list = find_impl_windows_to_update (list, window, recurse_mode);
 
-      /* Don't recurse into process_updates_internal, we'll
-       * do the update later when idle instead. */
-      !impl_window->in_update)
-    {
-      gdk_window_process_updates_internal ((GdkWindow *)impl_window);
-      gdk_window_remove_update_window ((GdkWindow *)impl_window);
-    }
+  if (window->impl_window != window)
+    list = g_list_prepend (list, g_object_ref (window->impl_window));
 
-  if (recurse_mode != PROCESS_UPDATES_NO_RECURSE)
+  for (node = list; node; node = node->next)
     {
-      /* process updates in reverse stacking order so composition or
-       * painting over achieves the desired effect for offscreen windows
-       */
-      GList *node, *children;
+      GdkWindow *impl_window = node->data;
 
-      children = g_list_copy (window->children);
-      g_list_foreach (children, (GFunc)g_object_ref, NULL);
+      if (impl_window->update_area &&
+          !impl_window->update_freeze_count &&
+          !gdk_window_is_toplevel_frozen (impl_window) &&
 
-      for (node = g_list_last (children); node; node = node->prev)
-       {
-          GdkWindow *child = node->data;
-          if (recurse_mode == PROCESS_UPDATES_WITH_ALL_CHILDREN ||
-              (recurse_mode == PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN &&
-               child->frame_clock == NULL))
-            {
-              gdk_window_process_updates (child, TRUE);
-            }
-         g_object_unref (child);
-       }
-
-      g_list_free (children);
+          /* Don't recurse into process_updates_internal, we'll
+           * do the update later when idle instead. */
+          !impl_window->in_update)
+        {
+          gdk_window_process_updates_internal (impl_window);
+          gdk_window_remove_update_window (impl_window);
+        }
     }
 
-  g_object_unref (window);
+  g_list_free_full (list, g_object_unref);
 }
 
 /**


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