summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Walzer <kw@codebykevin.com>2014-08-04 21:14:19 (GMT)
committerKevin Walzer <kw@codebykevin.com>2014-08-04 21:14:19 (GMT)
commit07fd47d492c9a0c44ac5fcb2343b1d6973d1a072 (patch)
treeec8c8b981ebcdb150d0b1ce209e1332680554a50
parenta53043ff3a732cffd15c303124f3fb397c9a5c18 (diff)
downloadtk-07fd47d492c9a0c44ac5fcb2343b1d6973d1a072.zip
tk-07fd47d492c9a0c44ac5fcb2343b1d6973d1a072.tar.gz
tk-07fd47d492c9a0c44ac5fcb2343b1d6973d1a072.tar.bz2
Further refinement of Mac OS X scrolling; thanks to Marc Culler for an additional patch.
-rw-r--r--macosx/tkMacOSXDraw.c95
-rw-r--r--macosx/tkMacOSXSubwindows.c14
2 files changed, 43 insertions, 66 deletions
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index 6ec3e59..089097e 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -1458,12 +1458,12 @@ XMaxRequestSize(
* a damage region.
*
* Results:
- * Returns 0 if the scroll genereated no additional damage.
+ * Returns 0 if the scroll generated no additional damage.
* Otherwise, sets the region that needs to be repainted after
* scrolling and returns 1.
*
* Side effects:
- * Scrolls the bits in the window.
+ * Scrolls the rectangle in the window.
*
*----------------------------------------------------------------------
*/
@@ -1480,86 +1480,59 @@ TkScrollWindow(
Drawable drawable = Tk_WindowId(tkwin);
MacDrawable *macDraw = (MacDrawable *) drawable;
NSView *view = TkMacOSXDrawableView(macDraw);
- CGRect visRect, srcRect, dstRect, scroll_src, scroll_dst;
- HIShapeRef dmgRgn = NULL;
- NSRect bounds;
+ CGRect dmgRect, dstRect, visRectBL, srcRectBL, dstRectBL;
+ NSRect visible, frame;
+ HIShapeRef dmgRgn = NULL, dstRgn;
int result;
if ( view ) {
+ visible = [view visibleRect];
+
+ /* Find the frame for the Tk window within its NSview. */
+ frame = NSMakeRect(Tk_X(tkwin),
+ Tk_Y(tkwin) + visible.size.height - Tk_Height(tkwin),
+ Tk_Width(tkwin),
+ Tk_Height(tkwin));
+
/* Get the scroll area in NSView coordinates (origin at bottom left). */
- bounds = [view bounds];
- scroll_src = CGRectMake(
- macDraw->xOff + x,
- bounds.size.height - height - (macDraw->yOff + y),
+ srcRectBL = CGRectMake(frame.origin.x + x,
+ frame.origin.y + frame.size.height - height - y,
width, height);
- scroll_dst = CGRectOffset(scroll_src, dx, -dy);
+ dstRectBL = CGRectOffset(srcRectBL, dx, -dy);
+
/* Limit scrolling to the window content area. */
- visRect = NSRectToCGRect([view visibleRect]);
- scroll_src = CGRectIntersection(scroll_src, visRect);
- scroll_dst = CGRectIntersection(scroll_dst, visRect);
+ visRectBL = NSRectToCGRect(frame);
+ srcRectBL = CGRectIntersection(srcRectBL, visRectBL);
+ dstRectBL = CGRectIntersection(dstRectBL, visRectBL);
- if ( !CGRectIsEmpty(scroll_src) && !CGRectIsEmpty(scroll_dst) ) {
+ if ( !CGRectIsEmpty(srcRectBL) && !CGRectIsEmpty(dstRectBL) ) {
/*
- * Mark the difference between source and destination as damaged.
- * This region is described in the Tk coordinate system, after shifting by dy.
+ * Construct the damage region. We extend it to the top
+ * or bottom of the window, in order to avoid artifacts when
+ * scrolling.
*/
- srcRect = CGRectMake(x - macDraw->xOff, y - macDraw->yOff,
- width, height);
- dstRect = CGRectOffset(srcRect, dx, dy);
- dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
- HIShapeRef dstRgn = HIShapeCreateWithRect(&dstRect);
+ if ( dy < 0 ) { /* extend to bottom */
+ dmgRect = CGRectMake(x, y, Tk_Width(tkwin), Tk_Height(tkwin) - y);
+ } else { /* extend to top */
+ dmgRect = CGRectMake(x , 0, Tk_Width(tkwin), Tk_Height(tkwin) + y);
+ }
+ dstRect = CGRectMake(x+dx, y+dy, width, height);
+
+ dmgRgn = HIShapeCreateMutableWithRect(&dmgRect);
+ dstRgn = HIShapeCreateWithRect(&dstRect);
ChkErr(HIShapeDifference, dmgRgn, dstRgn, (HIMutableShapeRef) dmgRgn);
CFRelease(dstRgn);
/* Scroll the rectangle. */
- [view scrollRect:NSRectFromCGRect(scroll_src) by:NSMakeSize(dx, -dy)];
- [view displayRect:NSRectFromCGRect(scroll_dst)];
-
- /*
- * When a Text widget contains embedded images, scrolling generates
- * lots of artifacts involving multiple copies of the images
- * displayed on top of each other. Extensive experimentation, with
- * very little help from the Apple documentation, indicates that
- * whenever an image is displayed it gets added as a subview, which
- * then gets automatically redisplayed in its original location.
- *
- * We do two things to combat this. First, each subview that meets
- * the scroll area is added as a damage rectangle. Second, we
- * redisplay the subviews after the scroll.
- */
-
- /*
- * Step 1: Find any subviews that meet the scroll area and mark
- * them as damaged. Use Tk coordinates, shifted to account for the
- * future scrolling.
- */
-
- for (NSView *subview in [view subviews] ) {
- NSRect frame = [subview frame];
- CGRect subviewRect = CGRectMake(
- frame.origin.x - macDraw->xOff + dx,
- (bounds.size.height - frame.origin.y - frame.size.height) - macDraw->yOff + dy,
- frame.size.width, frame.size.height);
- // /* Rectangles with negative coordinates seem to cause trouble. */
- if (subviewRect.origin.y < 0 && subviewRect.origin.y + subviewRect.size.height > 0) {
- subviewRect.origin.y = 0;
- }
- CGRect intersection = CGRectIntersection(srcRect, subviewRect);
- if (! CGRectIsEmpty(intersection) ){
- dstRgn = HIShapeCreateWithRect(&subviewRect);
- ChkErr(HIShapeUnion, dmgRgn, dstRgn, (HIMutableShapeRef) dmgRgn);
- CFRelease(dstRgn);
- }
- }
+ [view scrollRect:NSRectFromCGRect(srcRectBL) by:NSMakeSize(dx, -dy)];
}
}
if ( dmgRgn == NULL ) {
dmgRgn = HIShapeCreateEmpty();
}
- //TkMacOSXInvalidateViewRegion(view, dmgRgn);
TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
CFRelease(dmgRgn);
diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c
index a08c56e..1e188e6 100644
--- a/macosx/tkMacOSXSubwindows.c
+++ b/macosx/tkMacOSXSubwindows.c
@@ -651,7 +651,7 @@ XConfigureWindow(
*
* TkMacOSXUpdateClipRgn --
*
- * This function updates the cliping regions for a given window and all of
+ * This function updates the clipping regions for a given window and all of
* its children. Once updated the TK_CLIP_INVALID flag in the subwindow
* data structure is unset. The TK_CLIP_INVALID flag should always be
* unset before any drawing is attempted.
@@ -677,7 +677,7 @@ TkMacOSXUpdateClipRgn(
macWin = winPtr->privatePtr;
if (macWin && macWin->flags & TK_CLIP_INVALID) {
TkWindow *win2Ptr;
-
+
#ifdef TK_MAC_DEBUG_CLIP_REGIONS
TkMacOSXDbgMsg("%s", winPtr->pathName);
#endif
@@ -817,7 +817,7 @@ TkMacOSXUpdateClipRgn(
*
* TkMacOSXVisableClipRgn --
*
- * This function returns the Macintosh cliping region for the given
+ * This function returns the Macintosh clipping region for the given
* window. The caller is responsible for disposing of the returned
* region via TkDestroyRegion().
*
@@ -912,7 +912,7 @@ TkMacOSXInvalidateWindow(
* TK_PARENT_WINDOW */
{
#ifdef TK_MAC_DEBUG_CLIP_REGIONS
- TkMacOSXDbgMsg("%s", winPtr->pathName);
+ TkMacOSXDbgMsg("%s", macWin->winPtr->pathName);
#endif
if (macWin->flags & TK_CLIP_INVALID) {
TkMacOSXUpdateClipRgn(macWin->winPtr);
@@ -1070,7 +1070,7 @@ TkMacOSXGetRootControl(
* None.
*
* Side effects:
- * The cliping regions for the window and its children are mark invalid.
+ * The clipping regions for the window and its children are marked invalid.
* (Make sure they are valid before drawing.)
*
*----------------------------------------------------------------------
@@ -1089,6 +1089,10 @@ TkMacOSXInvalClipRgns(
* be marked.
*/
+#ifdef TK_MAC_DEBUG_CLIP_REGIONS
+ TkMacOSXDbgMsg("%s", winPtr->pathName);
+#endif
+
if (!macWin || macWin->flags & TK_CLIP_INVALID) {
return;
}