[gtk+] Handle expose events moving or resizing windows



commit 6d84fcab760f1aa96eb147ceb749d02dc090ce67
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Sep 14 13:38:47 2009 +0200

    Handle expose events moving or resizing windows
    
    When a window is moved or resized from a double-buffered expose handler
    we can't really just copy the window region around, as the window
    will be overdrawn with the double buffered region when the expose returns.
    
    Instead we remove all regions with outstanding implicit paints from the
    region to be copied and just mark this area as invalid to be redrawn
    later.
    
    This fixes bug 594880.

 gdk/gdkwindow.c |   23 +++++++++++++++++++----
 1 files changed, 19 insertions(+), 4 deletions(-)
---
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 121b810..2a44e7f 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -3136,12 +3136,10 @@ append_move_region (GdkWindowObject *impl_window,
 /* Moves bits and update area by dx/dy in impl window.
    Takes ownership of region to avoid copy (because we may change it) */
 static void
-move_region_on_impl (GdkWindowObject *private,
+move_region_on_impl (GdkWindowObject *impl_window,
 		     GdkRegion *region, /* In impl window coords */
 		     int dx, int dy)
 {
-  GdkWindowObject *impl_window;
-
   if ((dx == 0 && dy == 0) ||
       gdk_region_empty (region))
     {
@@ -3149,12 +3147,13 @@ move_region_on_impl (GdkWindowObject *private,
       return;
     }
 
-  impl_window = gdk_window_get_impl_window (private);
+  g_assert (impl_window == gdk_window_get_impl_window (impl_window));
 
   /* Move any old invalid regions in the copy source area by dx/dy */
   if (impl_window->update_area)
     {
       GdkRegion *update_area;
+
       update_area = gdk_region_copy (region);
 
       /* Convert from target to source */
@@ -3176,6 +3175,22 @@ move_region_on_impl (GdkWindowObject *private,
       gdk_region_destroy (update_area);
     }
 
+  /* If we're currently exposing this window, don't copy to this
+     destination, as it will be overdrawn when the expose is done,
+     instead invalidate it and repaint later. */
+  if (impl_window->implicit_paint)
+    {
+      GdkWindowPaint *implicit_paint = impl_window->implicit_paint;
+      GdkRegion *exposing;
+
+      exposing = gdk_region_copy (implicit_paint->region);
+      gdk_region_intersect (exposing, region);
+      gdk_region_subtract (region, exposing);
+
+      impl_window_add_update_area (impl_window, exposing);
+      gdk_region_destroy (exposing);
+    }
+
   if (1) /* Enable flicker free handling of moves. */
     append_move_region (impl_window, region, dx, dy);
   else



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]