[gtk+/gtk-2-24-quartz] win32: fix scrolling artifacts



commit 58cf235a1235ceb2f4f9ab9b64b9d9941ab4c554
Author: Dieter Verfaillie <dieterv optionexplicit be>
Date:   Mon Nov 7 12:30:19 2011 +0100

    win32: fix scrolling artifacts
    
    When scrolling a window partially obscured by another window,
    artifacts of the obsuring window where being blitted into
    the newly scrolled position. In other words, BitBlt copies
    the covered region (basically garbage instead of what we want)
    and does not cause a repaint (unlike how XCopyArea behaves).
    
    Replacing BitBlt() with the old ScrollDC gymnastics (removed from
    blit_inside_window() in commit e96a41be45f82af233f5171481c3fecbe95b5b6b)
    when being passed a Window for blit_inside_drawable() makes these
    artifacts go away.
    
    Thanks to Alexander Larsson for figuring out the cause and
    pointing out possible solutions.

 gdk/win32/gdkdrawable-win32.c |   56 ++++++++++++++++++++++++++++++++---------
 1 files changed, 44 insertions(+), 12 deletions(-)
---
diff --git a/gdk/win32/gdkdrawable-win32.c b/gdk/win32/gdkdrawable-win32.c
index 8e09be7..622200d 100644
--- a/gdk/win32/gdkdrawable-win32.c
+++ b/gdk/win32/gdkdrawable-win32.c
@@ -1540,20 +1540,50 @@ blit_from_pixmap (gboolean              use_fg_bg,
 }
 
 static void
-blit_inside_drawable (HDC      	hdc,
-		      GdkGCWin32 *gcwin32,
-		      gint     	xsrc,
-		      gint     	ysrc,
-		      gint     	xdest,
-		      gint     	ydest,
-		      gint     	width,
-		      gint     	height)
+blit_inside_drawable (HDC                   hdc,
+                      GdkGCWin32           *gcwin32,
+                      GdkDrawableImplWin32 *src,
+                      gint                  xsrc,
+                      gint                  ysrc,
+                      gint                  xdest,
+                      gint                  ydest,
+                      gint                  width,
+                      gint                  height)
 
 {
   GDK_NOTE (DRAW, g_print ("blit_inside_drawable\n"));
 
-  GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
-		     hdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
+  if GDK_IS_WINDOW_IMPL_WIN32 (src)
+    {
+      /* Simply calling BitBlt() instead of these ScrollDC() gymnastics might
+       * seem tempting, but we need to do this to prevent blitting garbage when
+       * scrolling a window that is partially obscured by another window. For
+       * example, GIMP's toolbox being over the editor window. */
+
+      RECT scrollRect, emptyRect;
+      HRGN updateRgn;
+
+      scrollRect.left = MIN (xsrc, xdest);
+      scrollRect.top = MIN (ysrc, ydest);
+      scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1);
+      scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1);
+
+      SetRectEmpty (&emptyRect);
+      updateRgn = CreateRectRgnIndirect (&emptyRect);
+
+      if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc, &scrollRect, NULL, updateRgn, NULL))
+        WIN32_GDI_FAILED ("ScrollDC");
+      else if (!InvalidateRgn (src->handle, updateRgn, FALSE))
+        WIN32_GDI_FAILED ("InvalidateRgn");
+
+      if (!DeleteObject (updateRgn))
+        WIN32_GDI_FAILED ("DeleteObject");
+    }
+  else
+    {
+      GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height,
+                         hdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2)));
+    }
 }
 
 static void
@@ -1743,13 +1773,15 @@ _gdk_win32_blit (gboolean              use_fg_bg,
     }
 
   if (draw_impl->handle == src_impl->handle)
-    blit_inside_drawable (hdc, GDK_GC_WIN32 (gc), xsrc, ysrc, xdest, ydest, width, height);
+    blit_inside_drawable (hdc, GDK_GC_WIN32 (gc), src_impl,
+                          xsrc, ysrc, xdest, ydest, width, height);
   else if (GDK_IS_PIXMAP_IMPL_WIN32 (src_impl))
     blit_from_pixmap (use_fg_bg, draw_impl, hdc,
 		      (GdkPixmapImplWin32 *) src_impl, gc,
 		      xsrc, ysrc, xdest, ydest, width, height);
   else
-    blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, xsrc, ysrc, xdest, ydest, width, height);
+    blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl,
+                      xsrc, ysrc, xdest, ydest, width, height);
 
   gdk_win32_hdc_release (&draw_impl->parent_instance, gc, GDK_GC_FOREGROUND);
 }



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