Commit eab3ef31 authored by Kristian Rietveld's avatar Kristian Rietveld Committed by Kristian Rietveld

Fixes #426246.

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
parent cfd5eaaa
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> 2007-09-11 Michael Natterer <mitch@imendio.com>
* gtk/gtkfilechooserbutton.c: remove useless member "has_title" * gtk/gtkfilechooserbutton.c: remove useless member "has_title"
......
...@@ -649,6 +649,7 @@ gdk_window_constrain_size ...@@ -649,6 +649,7 @@ gdk_window_constrain_size
gdk_window_destroy gdk_window_destroy
gdk_window_end_paint gdk_window_end_paint
gdk_window_foreign_new gdk_window_foreign_new
gdk_window_freeze_toplevel_updates_libgtk_only
gdk_window_freeze_updates gdk_window_freeze_updates
gdk_window_get_children gdk_window_get_children
gdk_window_get_internal_paint_info gdk_window_get_internal_paint_info
...@@ -673,6 +674,7 @@ gdk_window_process_updates ...@@ -673,6 +674,7 @@ gdk_window_process_updates
gdk_window_remove_filter gdk_window_remove_filter
gdk_window_set_debug_updates gdk_window_set_debug_updates
gdk_window_set_user_data gdk_window_set_user_data
gdk_window_thaw_toplevel_updates_libgtk_only
gdk_window_thaw_updates gdk_window_thaw_updates
gdk_window_set_composited gdk_window_set_composited
#endif #endif
......
...@@ -2290,10 +2290,22 @@ gdk_window_update_idle (gpointer data) ...@@ -2290,10 +2290,22 @@ gdk_window_update_idle (gpointer data)
return FALSE; 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 static void
gdk_window_schedule_update (GdkWindow *window) 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; return;
if (!update_idle) if (!update_idle)
...@@ -2423,7 +2435,8 @@ gdk_window_process_all_updates (void) ...@@ -2423,7 +2435,8 @@ gdk_window_process_all_updates (void)
{ {
GdkWindowObject *private = (GdkWindowObject *)tmp_list->data; 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); update_windows = g_slist_prepend (update_windows, private);
else else
gdk_window_process_updates_internal (tmp_list->data); gdk_window_process_updates_internal (tmp_list->data);
...@@ -2471,7 +2484,9 @@ gdk_window_process_updates (GdkWindow *window, ...@@ -2471,7 +2484,9 @@ gdk_window_process_updates (GdkWindow *window,
return; 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); gdk_window_process_updates_internal (window);
update_windows = g_slist_remove (update_windows, window); update_windows = g_slist_remove (update_windows, window);
...@@ -2815,6 +2830,58 @@ gdk_window_thaw_updates (GdkWindow *window) ...@@ -2815,6 +2830,58 @@ gdk_window_thaw_updates (GdkWindow *window)
gdk_window_schedule_update (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: * gdk_window_set_debug_updates:
* @setting: %TRUE to turn on update debugging * @setting: %TRUE to turn on update debugging
......
...@@ -298,6 +298,8 @@ struct _GdkWindowObject ...@@ -298,6 +298,8 @@ struct _GdkWindowObject
guint shaped : 1; guint shaped : 1;
GdkEventMask event_mask; GdkEventMask event_mask;
guint update_and_descendants_freeze_count;
}; };
struct _GdkWindowObjectClass struct _GdkWindowObjectClass
...@@ -605,6 +607,9 @@ GdkRegion *gdk_window_get_update_area (GdkWindow *window); ...@@ -605,6 +607,9 @@ GdkRegion *gdk_window_get_update_area (GdkWindow *window);
void gdk_window_freeze_updates (GdkWindow *window); void gdk_window_freeze_updates (GdkWindow *window);
void gdk_window_thaw_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_all_updates (void);
void gdk_window_process_updates (GdkWindow *window, void gdk_window_process_updates (GdkWindow *window,
gboolean update_children); gboolean update_children);
......
...@@ -4819,7 +4819,10 @@ gtk_window_configure_event (GtkWidget *widget, ...@@ -4819,7 +4819,10 @@ gtk_window_configure_event (GtkWidget *widget,
*/ */
if (window->configure_request_count > 0) 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. /* As an optimization, we avoid a resize when possible.
* *
...@@ -6053,28 +6056,47 @@ gtk_window_move_resize (GtkWindow *window) ...@@ -6053,28 +6056,47 @@ gtk_window_move_resize (GtkWindow *window)
new_request.width, new_request.height); new_request.width, new_request.height);
} }
/* Increment the number of have-not-yet-received-notify requests */ if (window->type == GTK_WINDOW_POPUP)
window->configure_request_count += 1; {
GtkAllocation allocation;
/* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new
* configure event in response to our resizing request. /* Directly size allocate for override redirect (popup) windows. */
* the configure event will cause a new resize with allocation.width = new_request.width;
* ->configure_notify_received=TRUE. allocation.height = new_request.height;
* until then, we want to
* - discard expose events gtk_widget_size_allocate (widget, &allocation);
* - coalesce resizes for our children
* - defer any window resizes until the configure event arrived gdk_window_process_updates (widget->window, TRUE);
* to achieve this, we queue a resize for the window, but remove its
* resizing handler, so resizing will not be handled from the next if (container->resize_mode == GTK_RESIZE_QUEUE)
* idle handler but when the configure event arrives. gtk_widget_queue_draw (widget);
* }
* FIXME: we should also dequeue the pending redraws here, since else
* we handle those ourselves upon ->configure_notify_received==TRUE. {
*/ /* Increment the number of have-not-yet-received-notify requests */
if (container->resize_mode == GTK_RESIZE_QUEUE) window->configure_request_count += 1;
{ gdk_window_freeze_toplevel_updates_libgtk_only (widget->window);
gtk_widget_queue_resize (widget);
_gtk_container_dequeue_resize_handler (container); /* 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 else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment