Index: gdk/gdkwindow.c
===================================================================
--- gdk/gdkwindow.c	(revision 20708)
+++ gdk/gdkwindow.c	(working copy)
@@ -2502,6 +2502,79 @@ static GSList *update_windows = NULL;
 static guint update_idle = 0;
 static gboolean debug_updates = FALSE;
 
+static inline gboolean
+gdk_window_is_ancestor (GdkWindow *window,
+                        GdkWindow *ancestor)
+{
+  while (window)
+    {
+      GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
+
+      if (parent == ancestor)
+        return TRUE;
+
+      window = parent;
+    }
+
+  return FALSE;
+}
+
+static void
+gdk_window_add_update_window (GdkWindow *window)
+{
+  GSList *tmp;
+  GSList *prev = NULL;
+  gboolean has_ancestor_in_list = FALSE;
+
+  for (tmp = update_windows; tmp; tmp = tmp->next)
+    {
+      /*  check if tmp is an ancestor of "window"; if it is, set a
+       *  flag indicating that all following windows are either
+       *  children of "window" or from a differen hierarchy
+       */
+      if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
+        has_ancestor_in_list = TRUE;
+
+      /*  if "window" has an ancestor in the list and tmp is one of
+       *  "window's" children, insert "window" before tmp
+       */
+      if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
+        {
+          tmp = g_slist_prepend (tmp, window);
+
+          if (prev)
+            prev->next = tmp;
+          else
+            update_windows = tmp;
+
+          return;
+        }
+
+      /*  if we're at the end of the list and had an ancestor it it,
+       *  append to the list
+       */
+      if (! tmp->next && has_ancestor_in_list)
+        {
+          tmp = g_slist_append (tmp, window);
+          return;
+        }
+
+      prev = tmp;
+    }
+
+  /*  if all above checks failed ("window" is from a different
+   *  hierarchy than what is already in the list) or the list is
+   *  empty, prepend
+   */
+  update_windows = g_slist_prepend (update_windows, window);
+}
+
+static void
+gdk_window_remove_update_window (GdkWindow *window)
+{
+  update_windows = g_slist_remove (update_windows, window);
+}
+
 static gboolean
 gdk_window_update_idle (gpointer data)
 {
@@ -2659,7 +2732,7 @@ gdk_window_process_all_updates (void)
         {
 	  if (private->update_freeze_count ||
 	      gdk_window_is_toplevel_frozen (tmp_list->data))
-	    update_windows = g_slist_prepend (update_windows, private);
+	    gdk_window_add_update_window ((GdkWindow *) private);
 	  else
 	    gdk_window_process_updates_internal (tmp_list->data);
 	}
@@ -2696,7 +2769,7 @@ gdk_window_process_updates (GdkWindow *w
 
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
-  
+
   if (GDK_IS_PAINTABLE (private->impl))
     {
       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
@@ -2712,7 +2785,7 @@ gdk_window_process_updates (GdkWindow *w
       !gdk_window_is_toplevel_frozen (window))
     {      
       gdk_window_process_updates_internal (window);
-      update_windows = g_slist_remove (update_windows, window);
+      gdk_window_remove_update_window (window);
     }
 
   if (update_children)
@@ -2916,7 +2989,7 @@ gdk_window_invalidate_maybe_recurse (Gdk
 	}
       else
 	{
-	  update_windows = g_slist_prepend (update_windows, window);
+	  gdk_window_add_update_window (window);
 	  private->update_area = gdk_region_copy (visible_region);
 	  
 	  gdk_window_schedule_update (window);
@@ -2995,8 +3068,8 @@ gdk_window_get_update_area (GdkWindow *w
       tmp_region = private->update_area;
       private->update_area = NULL;
 
-      update_windows = g_slist_remove (update_windows, window);
-      
+      gdk_window_remove_update_window (window);
+
       return tmp_region;
     }
   else
@@ -3020,8 +3093,8 @@ _gdk_window_clear_update_area (GdkWindow
 
   if (private->update_area)
     {
-      update_windows = g_slist_remove (update_windows, window);
-      
+      gdk_window_remove_update_window (window);
+
       gdk_region_destroy (private->update_area);
       private->update_area = NULL;
     }
