+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"
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
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
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)
{
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);
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);
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
guint shaped : 1;
GdkEventMask event_mask;
+
+ guint update_and_descendants_freeze_count;
};
struct _GdkWindowObjectClass
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);
*/
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.
*
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