[gtk+/gtk-2-24] quartz: correct deficiencies in the gdk_draw_drawable() implementation



commit e982461ad63c7ce1f052378dbf5c28f7208f396a
Author: Kristian Rietveld <kris lanedo com>
Date:   Sat Oct 27 17:11:59 2012 +0200

    quartz: correct deficiencies in the gdk_draw_drawable() implementation
    
    The call to scrollRect: must be accompanied by a call to redraw the
    newly exposed area, otherwise the scrollRect: will have no effect.
    Secondly, compute the newly exposed area correctly.
    Thirdly, also expose the lower window border or the area moved from
    the lower window border if applicable, to make sure rounded corners
    are properly drawn or don't leave garbage.

 gdk/quartz/gdkdrawable-quartz.c |   93 +++++++++++++++++++++++++++++++++++----
 1 files changed, 84 insertions(+), 9 deletions(-)
---
diff --git a/gdk/quartz/gdkdrawable-quartz.c b/gdk/quartz/gdkdrawable-quartz.c
index 1bbf7c9..503ea83 100644
--- a/gdk/quartz/gdkdrawable-quartz.c
+++ b/gdk/quartz/gdkdrawable-quartz.c
@@ -361,15 +361,90 @@ gdk_quartz_draw_drawable (GdkDrawable *drawable,
         {
           NSRect rect = NSMakeRect (xsrc, ysrc, width, height);
           NSSize offset = NSMakeSize (xdest - xsrc, ydest - ysrc);
+          GdkRectangle tmp_rect;
+          GdkRegion *orig_region, *offset_region, *need_display_region;
+          GdkWindow *window = GDK_DRAWABLE_IMPL_QUARTZ (drawable)->wrapper;
 
-          [window_impl->view scrollRect:rect by:offset];
+          /* Origin region */
+          tmp_rect.x = xsrc;
+          tmp_rect.y = ysrc;
+          tmp_rect.width = width;
+          tmp_rect.height = height;
+          orig_region = gdk_region_rectangle (&tmp_rect);
 
-          /* The scrollRect only "takes effect" on the next redraw, we must
-           * set that the offset rectangle needs display.
-           */
-          rect.origin.x += offset.width;
-          rect.origin.y += offset.height;
-          [window_impl->view setNeedsDisplayInRect:rect];
+          /* Destination region (or the offset region) */
+          offset_region = gdk_region_copy (orig_region);
+          gdk_region_offset (offset_region, offset.width, offset.height);
+
+          need_display_region = gdk_region_copy (orig_region);
+
+          if (window_impl->in_paint_rect_count == 0)
+            {
+              GdkRegion *bottom_border_region;
+
+              /* If we are not in drawRect:, we can use scrollRect:.
+               * We apply scrollRect on the rectangle to be moved and
+               * subtract this area from the rectangle that needs display.
+               *
+               * Note: any area in this moved region that already needed
+               * display will be handled by GDK (queue translation).
+               *
+               * Queuing the redraw below is important, otherwise the
+               * results from scrollRect will not take effect!
+               */
+              [window_impl->view scrollRect:rect by:offset];
+
+              gdk_region_subtract (need_display_region, offset_region);
+
+              /* Here we take special care with the bottom window border,
+               * which extents 4 pixels and typically draws rounded corners.
+               */
+              tmp_rect.x = 0;
+              tmp_rect.y = gdk_window_get_height (window) - 4;
+              tmp_rect.width = gdk_window_get_width (window);
+              tmp_rect.height = 4;
+
+              if (gdk_region_rect_in (offset_region, &tmp_rect) !=
+                  GDK_OVERLAP_RECTANGLE_OUT)
+                {
+                  /* We are copying pixels to the bottom border, we need
+                   * to submit this area for redisplay to get the rounded
+                   * corners drawn.
+                   */
+                  gdk_region_union_with_rect (need_display_region,
+                                              &tmp_rect);
+                }
+
+              /* Compute whether the bottom border is moved elsewhere.
+               * Because this part will have rounded corners, we have
+               * to fill the contents of where the rounded corners used
+               * to be. We post this area for redisplay.
+               */
+              bottom_border_region = gdk_region_rectangle (&tmp_rect);
+              gdk_region_intersect (bottom_border_region,
+                                    orig_region);
+
+              gdk_region_offset (bottom_border_region,
+                                 offset.width, offset.height);
+
+              gdk_region_union (need_display_region, bottom_border_region);
+
+              gdk_region_destroy (bottom_border_region);
+            }
+          else
+            {
+              /* If we cannot handle things with a scroll, we must redisplay
+               * the union of the source area and the destination area.
+               */
+              gdk_region_union (need_display_region, offset_region);
+            }
+
+          _gdk_quartz_window_set_needs_display_in_region (window,
+                                                          need_display_region);
+
+          gdk_region_destroy (orig_region);
+          gdk_region_destroy (offset_region);
+          gdk_region_destroy (need_display_region);
         }
       else
         g_warning ("Drawing with window source != dest is not supported");



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