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
This commit is contained in:
Kristian Rietveld 2007-09-12 17:13:24 +00:00 committed by Kristian Rietveld
parent cfd5eaaa8c
commit eab3ef3145
5 changed files with 139 additions and 25 deletions

View File

@ -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"

View 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

View 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

View 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);

View 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;
if (window->type == GTK_WINDOW_POPUP)
{
GtkAllocation allocation;
/* 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);
/* 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