]> Pileus Git - ~andy/gtk/commitdiff
Fixes #426246.
authorKristian Rietveld <kris@imendio.com>
Wed, 12 Sep 2007 17:13:24 +0000 (17:13 +0000)
committerKristian Rietveld <kristian@src.gnome.org>
Wed, 12 Sep 2007 17:13:24 +0000 (17:13 +0000)
2007-09-12  Kristian Rietveld  <kris@imendio.com>

Fixes #426246.

* gdk/gdk.symbols:
* gdk/gdkwindow.[ch]
(gdk_window_freeze_toplevel_updates_libgtk_only),
(gdk_window_thaw_toplevel_updates_libgtk_only): new functions
to freeze a toplevel window and all its descendants.  To be made
public in 2.14,
(gdk_window_schedule_update): return if toplevel is frozen,
(gdk_window_process_all_updates): defer processing updates if toplevel
is frozen.

* gtk/gtkwindow.c (gtk_window_configure_event): directly size
allocate for override redirect windows, freeze toplevel and
descendants otherwise and wait until resizing is done.

svn path=/trunk/; revision=18802

ChangeLog
gdk/gdk.symbols
gdk/gdkwindow.c
gdk/gdkwindow.h
gtk/gtkwindow.c

index 5aba8a8bb38ea940acacd819438cb8b5c7377968..f9da226777b6cef9d52f74ba3ef12bd6cb6e7864 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2007-09-12  Kristian Rietveld  <kris@imendio.com>
+
+       Fixes #426246.
+
+       * gdk/gdk.symbols:
+       * gdk/gdkwindow.[ch]
+       (gdk_window_freeze_toplevel_updates_libgtk_only),
+       (gdk_window_thaw_toplevel_updates_libgtk_only): new functions
+       to freeze a toplevel window and all its descendants.  To be made
+       public in 2.14,
+       (gdk_window_schedule_update): return if toplevel is frozen,
+       (gdk_window_process_all_updates): defer processing updates if toplevel
+       is frozen.
+
+       * gtk/gtkwindow.c (gtk_window_configure_event): directly size
+       allocate for override redirect windows, freeze toplevel and
+       descendants otherwise and wait until resizing is done.
+
 2007-09-11  Michael Natterer  <mitch@imendio.com>
 
        * gtk/gtkfilechooserbutton.c: remove useless member "has_title"
index ef801d3e34debf8e82bbd4f877fc05842b469643..d7962109fe622da9e4c5eae51c89331a8c8fe05a 100644 (file)
@@ -649,6 +649,7 @@ gdk_window_constrain_size
 gdk_window_destroy
 gdk_window_end_paint
 gdk_window_foreign_new
+gdk_window_freeze_toplevel_updates_libgtk_only
 gdk_window_freeze_updates
 gdk_window_get_children
 gdk_window_get_internal_paint_info
@@ -673,6 +674,7 @@ gdk_window_process_updates
 gdk_window_remove_filter
 gdk_window_set_debug_updates
 gdk_window_set_user_data
+gdk_window_thaw_toplevel_updates_libgtk_only
 gdk_window_thaw_updates
 gdk_window_set_composited
 #endif
index 2028693cb08223498800aa52a73e86c4809f173a..fe4e7f674adc7a79c6598342ca39df5a6f20e493 100644 (file)
@@ -2290,10 +2290,22 @@ gdk_window_update_idle (gpointer data)
   return FALSE;
 }
 
+static gboolean
+gdk_window_is_toplevel_frozen (GdkWindow *window)
+{
+  GdkWindowObject *toplevel;
+
+  toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
+
+  return toplevel->update_and_descendants_freeze_count > 0;
+}
+
 static void
 gdk_window_schedule_update (GdkWindow *window)
 {
-  if (window && GDK_WINDOW_OBJECT (window)->update_freeze_count)
+  if (window &&
+      (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
+       gdk_window_is_toplevel_frozen (window)))
     return;
 
   if (!update_idle)
@@ -2423,7 +2435,8 @@ gdk_window_process_all_updates (void)
     {
       GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
       
-      if (private->update_freeze_count)
+      if (private->update_freeze_count ||
+         gdk_window_is_toplevel_frozen (tmp_list->data))
        update_windows = g_slist_prepend (update_windows, private);
       else
        gdk_window_process_updates_internal (tmp_list->data);
@@ -2471,7 +2484,9 @@ gdk_window_process_updates (GdkWindow *window,
       return;
     }
   
-  if (private->update_area && !private->update_freeze_count)
+  if (private->update_area &&
+      !private->update_freeze_count &&
+      !gdk_window_is_toplevel_frozen (window))
     {      
       gdk_window_process_updates_internal (window);
       update_windows = g_slist_remove (update_windows, window);
@@ -2815,6 +2830,58 @@ gdk_window_thaw_updates (GdkWindow *window)
     gdk_window_schedule_update (window);
 }
 
+/**
+ * gdk_window_freeze_toplevel_updates_libgtk_only:
+ * @window: a #GdkWindow
+ *
+ * Temporarily freezes a window and all its descendants such that it won't
+ * receive expose events.  The window will begin receiving expose events
+ * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
+ * gdk_window_freeze_toplevel_updates_libgtk_only()
+ * has been called more than once,
+ * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
+ * an equal number of times to begin processing exposes.
+ *
+ * This function is not part of the GDK public API and is only
+ * for use by GTK+.
+ **/
+void
+gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
+
+  private->update_and_descendants_freeze_count++;
+}
+
+/**
+ * gdk_window_thaw_toplevel_updates_libgtk_only:
+ * @window: a #GdkWindow
+ * 
+ * Thaws a window frozen with
+ * gdk_window_freeze_toplevel_updates_libgtk_only().
+ *
+ * This function is not part of the GDK public API and is only
+ * for use by GTK+.
+ **/
+void
+gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
+  g_return_if_fail (private->update_and_descendants_freeze_count > 0);
+
+  private->update_and_descendants_freeze_count--;
+
+  gdk_window_schedule_update (window);
+}
+
 /**
  * gdk_window_set_debug_updates:
  * @setting: %TRUE to turn on update debugging
index d50d3e6c9a2c126e687b5adc03543dd26d6fd9e2..3e169c43981858fde560df4e22508ae15305e8ad 100644 (file)
@@ -298,6 +298,8 @@ struct _GdkWindowObject
   guint shaped : 1;
   
   GdkEventMask event_mask;
+
+  guint update_and_descendants_freeze_count;
 };
 
 struct _GdkWindowObjectClass
@@ -605,6 +607,9 @@ GdkRegion *gdk_window_get_update_area     (GdkWindow    *window);
 void       gdk_window_freeze_updates      (GdkWindow    *window);
 void       gdk_window_thaw_updates        (GdkWindow    *window);
 
+void       gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window);
+void       gdk_window_thaw_toplevel_updates_libgtk_only   (GdkWindow *window);
+
 void       gdk_window_process_all_updates (void);
 void       gdk_window_process_updates     (GdkWindow    *window,
                                           gboolean      update_children);
index 590bf6bf12af3f6bcd68b6d28f98bc65643e49a6..78b34011c6c840d6b7defdca1326e8bdf2bcbf4e 100644 (file)
@@ -4819,7 +4819,10 @@ gtk_window_configure_event (GtkWidget         *widget,
    */
 
   if (window->configure_request_count > 0)
-    window->configure_request_count -= 1;
+    {
+      window->configure_request_count -= 1;
+      gdk_window_thaw_toplevel_updates_libgtk_only (widget->window);
+    }
   
   /* As an optimization, we avoid a resize when possible.
    *
@@ -6053,28 +6056,47 @@ gtk_window_move_resize (GtkWindow *window)
                             new_request.width, new_request.height);
        }
       
-      /* Increment the number of have-not-yet-received-notify requests */
-      window->configure_request_count += 1;
-
-      /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
-       * configure event in response to our resizing request.
-       * the configure event will cause a new resize with
-       * ->configure_notify_received=TRUE.
-       * until then, we want to
-       * - discard expose events
-       * - coalesce resizes for our children
-       * - defer any window resizes until the configure event arrived
-       * to achieve this, we queue a resize for the window, but remove its
-       * resizing handler, so resizing will not be handled from the next
-       * idle handler but when the configure event arrives.
-       *
-       * FIXME: we should also dequeue the pending redraws here, since
-       * we handle those ourselves upon ->configure_notify_received==TRUE.
-       */
-      if (container->resize_mode == GTK_RESIZE_QUEUE)
-       {
-         gtk_widget_queue_resize (widget);
-         _gtk_container_dequeue_resize_handler (container);
+      if (window->type == GTK_WINDOW_POPUP)
+        {
+         GtkAllocation allocation;
+
+         /* Directly size allocate for override redirect (popup) windows. */
+         allocation.width = new_request.width;
+         allocation.height = new_request.height;
+
+         gtk_widget_size_allocate (widget, &allocation);
+
+         gdk_window_process_updates (widget->window, TRUE);
+
+         if (container->resize_mode == GTK_RESIZE_QUEUE)
+           gtk_widget_queue_draw (widget);
+       }
+      else
+        {
+         /* Increment the number of have-not-yet-received-notify requests */
+         window->configure_request_count += 1;
+         gdk_window_freeze_toplevel_updates_libgtk_only (widget->window);
+
+         /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
+          * configure event in response to our resizing request.
+          * the configure event will cause a new resize with
+          * ->configure_notify_received=TRUE.
+          * until then, we want to
+          * - discard expose events
+          * - coalesce resizes for our children
+          * - defer any window resizes until the configure event arrived
+          * to achieve this, we queue a resize for the window, but remove its
+          * resizing handler, so resizing will not be handled from the next
+          * idle handler but when the configure event arrives.
+          *
+          * FIXME: we should also dequeue the pending redraws here, since
+          * we handle those ourselves upon ->configure_notify_received==TRUE.
+          */
+         if (container->resize_mode == GTK_RESIZE_QUEUE)
+           {
+             gtk_widget_queue_resize (widget);
+             _gtk_container_dequeue_resize_handler (container);
+           }
        }
     }
   else