Better handling of window hierarchy changes from inside expose handler
If we move, resize or otherwise change a window from inside a (double buffered) expose handler we can run into issues with double buffered paints that have already been ended but have not yet been commited to the window from the implicit paint pixmap. For instance, any copies of source regions due to a window scroll need to take these into account, and any operation that causes some drawing at a destination covered by the implicit paint region would be overdrawn when the implicit paint is ended. So, before we do any window-hierarchy changing operation while an implicit paint is in effect we flush all moves and already commited paints.
This commit is contained in:
@ -3236,6 +3236,32 @@ gdk_window_flush (GdkWindow *window)
|
|||||||
gdk_window_flush_implicit_paint (window);
|
gdk_window_flush_implicit_paint (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we're about to move/resize or otherwise change the
|
||||||
|
* hierarchy of a client side window in an impl and we're
|
||||||
|
* called from an expose event handler then we need to
|
||||||
|
* flush any already painted parts of the implicit paint
|
||||||
|
* that are not part of the current paint, as these may
|
||||||
|
* be used when scrolling or may overdraw the changes
|
||||||
|
* caused by the hierarchy change.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
gdk_window_flush_if_exposing (GdkWindow *window)
|
||||||
|
{
|
||||||
|
GdkWindowObject *private;
|
||||||
|
GdkWindowObject *impl_window;
|
||||||
|
GList *l;
|
||||||
|
GdkWindowRegionMove *move;
|
||||||
|
|
||||||
|
private = (GdkWindowObject *) window;
|
||||||
|
impl_window = gdk_window_get_impl_window (private);
|
||||||
|
|
||||||
|
/* If we're in an implicit paint (i.e. in an expose handler, flush
|
||||||
|
all the already finished exposes to get things to an uptodate state. */
|
||||||
|
if (impl_window->implicit_paint)
|
||||||
|
gdk_window_flush (window);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_window_flush_recursive_helper (GdkWindowObject *window,
|
gdk_window_flush_recursive_helper (GdkWindowObject *window,
|
||||||
GdkWindow *impl)
|
GdkWindow *impl)
|
||||||
@ -6362,6 +6388,8 @@ gdk_window_raise (GdkWindow *window)
|
|||||||
if (private->destroyed)
|
if (private->destroyed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
gdk_window_flush_if_exposing (window);
|
||||||
|
|
||||||
old_region = NULL;
|
old_region = NULL;
|
||||||
if (gdk_window_is_viewable (window) &&
|
if (gdk_window_is_viewable (window) &&
|
||||||
!private->input_only)
|
!private->input_only)
|
||||||
@ -6498,6 +6526,8 @@ gdk_window_lower (GdkWindow *window)
|
|||||||
if (private->destroyed)
|
if (private->destroyed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
gdk_window_flush_if_exposing (window);
|
||||||
|
|
||||||
/* Keep children in (reverse) stacking order */
|
/* Keep children in (reverse) stacking order */
|
||||||
gdk_window_lower_internal (window);
|
gdk_window_lower_internal (window);
|
||||||
|
|
||||||
@ -6555,6 +6585,8 @@ gdk_window_restack (GdkWindow *window,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdk_window_flush_if_exposing (window);
|
||||||
|
|
||||||
if (gdk_window_is_toplevel (private))
|
if (gdk_window_is_toplevel (private))
|
||||||
{
|
{
|
||||||
g_return_if_fail (gdk_window_is_toplevel (GDK_WINDOW_OBJECT (sibling)));
|
g_return_if_fail (gdk_window_is_toplevel (GDK_WINDOW_OBJECT (sibling)));
|
||||||
@ -7023,6 +7055,8 @@ gdk_window_move_resize_internal (GdkWindow *window,
|
|||||||
private->y == y)))
|
private->y == y)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
gdk_window_flush_if_exposing (window);
|
||||||
|
|
||||||
/* Handle child windows */
|
/* Handle child windows */
|
||||||
|
|
||||||
expose = FALSE;
|
expose = FALSE;
|
||||||
@ -7284,6 +7318,8 @@ gdk_window_scroll (GdkWindow *window,
|
|||||||
if (private->destroyed)
|
if (private->destroyed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
gdk_window_flush_if_exposing (window);
|
||||||
|
|
||||||
old_native_child_region = collect_native_child_region (private, FALSE);
|
old_native_child_region = collect_native_child_region (private, FALSE);
|
||||||
if (old_native_child_region)
|
if (old_native_child_region)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user