From cf01a3d41c96d1af1d386e10947da402d4a43767 Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Thu, 24 Jul 2014 02:30:12 +0000 Subject: Fix for display of images when scrolling a text widget on OS X; thanks to Marc Culler for patch --- macosx/tkMacOSXDraw.c | 116 +++++++++++++++++++++++++++++++++++------------- macosx/tkMacOSXRegion.c | 64 +++++++++++++------------- 2 files changed, 116 insertions(+), 64 deletions(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 1aba8f4..29b6d0a 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -217,8 +217,6 @@ XCopyArea( display->request++; - TkMacOSXDbgMsg("XCopyArea"); - if (!width || !height) { /* This happens all the time. TkMacOSXDbgMsg("Drawing of empty area requested"); @@ -239,7 +237,7 @@ XCopyArea( img = [bitmap_rep CGImage]; } } else { - TkMacOSXDbgMsg("Invalid source drawable"); + TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap."); } if (img) { @@ -249,11 +247,11 @@ XCopyArea( CGRectMake(dest_x, dest_y, width, height)); CFRelease(img); } else { - TkMacOSXDbgMsg("Invalid source drawable"); + TkMacOSXDbgMsg("Failed to construct CGImage."); } } else { - TkMacOSXDbgMsg("Invalid destination drawable"); + TkMacOSXDbgMsg("Invalid destination drawable - no context."); return; } @@ -1478,43 +1476,97 @@ TkScrollWindow( int dx, int dy, /* Distance rectangle should be moved. */ TkRegion damageRgn) /* Region to accumulate damage in. */ { - MacDrawable *macDraw = (MacDrawable *) Tk_WindowId(tkwin); + Drawable drawable = Tk_WindowId(tkwin); + MacDrawable *macDraw = (MacDrawable *) drawable; NSView *view = TkMacOSXDrawableView(macDraw); - CGRect visRect, srcRect, dstRect; - CGFloat boundsH; - HIShapeRef dmgRgn, dstRgn; + CGRect visRect, srcRect, dstRect, scroll_src, scroll_dst; + HIShapeRef dmgRgn = NULL; + NSRect bounds; int result; - if (view && !CGRectIsEmpty(visRect = NSRectToCGRect([view visibleRect]))) { - boundsH = [view bounds].size.height; - srcRect = CGRectMake(macDraw->xOff + x, boundsH - height - - (macDraw->yOff + y), width, height); - dstRect = CGRectIntersection(CGRectOffset(srcRect, dx, -dy), visRect); - srcRect = CGRectIntersection(srcRect, visRect); - if (!CGRectIsEmpty(srcRect) && !CGRectIsEmpty(dstRect)) { + if ( view ) { + /* 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), + width, height); + scroll_dst = CGRectOffset(scroll_src, 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); + + if ( !CGRectIsEmpty(scroll_src) && !CGRectIsEmpty(scroll_dst) ) { + /* - CGRect sRect = CGRectIntersection(CGRectOffset(dstRect, -dx, dy), - srcRect); - NSCopyBits(0, NSRectFromCGRect(sRect), - NSPointFromCGPoint(CGRectOffset(sRect, dx, -dy).origin)); - */ - [view scrollRect:NSRectFromCGRect(srcRect) by:NSMakeSize(dx, -dy)]; + * Mark the difference between source and destination as damaged. + * This region is described in the Tk coordinate system, after shifting by dy. + */ + + srcRect = CGRectMake(x - macDraw->xOff, y - macDraw->yOff, + width, height); + dstRect = CGRectOffset(srcRect, dx, dy); + dmgRgn = HIShapeCreateMutableWithRect(&srcRect); + HIShapeRef 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); + } + } + + /* Step 2: Redisplay all subviews */ + for (NSView *subview in [view subviews] ) { + [subview display]; + } } - srcRect.origin.y = boundsH - srcRect.size.height - srcRect.origin.y; - dstRect.origin.y = boundsH - dstRect.size.height - dstRect.origin.y; - srcRect = CGRectUnion(srcRect, dstRect); - dmgRgn = HIShapeCreateMutableWithRect(&srcRect); - dstRgn = HIShapeCreateWithRect(&dstRect); - ChkErr(HIShapeDifference, dmgRgn, dstRgn, (HIMutableShapeRef) dmgRgn); - CFRelease(dstRgn); - TkMacOSXInvalidateViewRegion(view, dmgRgn); - } else { + } + + if ( dmgRgn == NULL ) { dmgRgn = HIShapeCreateEmpty(); } + //TkMacOSXInvalidateViewRegion(view, dmgRgn); TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn); result = HIShapeIsEmpty(dmgRgn) ? 0 : 1; CFRelease(dmgRgn); - return result; } diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c index 8432299..c716ab7 100644 --- a/macosx/tkMacOSXRegion.c +++ b/macosx/tkMacOSXRegion.c @@ -158,6 +158,29 @@ TkUnionRectWithRegion( /* *---------------------------------------------------------------------- * + * TkMacOSXIsEmptyRegion -- + * + * Return native region for given tk region. + * + * Results: + * 1 if empty, 0 otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXIsEmptyRegion( + TkRegion r) +{ + return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0; +} + +/* + *---------------------------------------------------------------------- + * * TkRectInRegion -- * * Implements the equivelent of the X window function XRectInRegion. See @@ -181,12 +204,14 @@ TkRectInRegion( unsigned int width, unsigned int height) { - int result; - const CGRect r = CGRectMake(x, y, width, height); - - result = HIShapeIntersectsRect((HIShapeRef) region, &r) ? + if ( TkMacOSXIsEmptyRegion(region) ) { + return RectangleOut; + } + else { + const CGRect r = CGRectMake(x, y, width, height); + return HIShapeIntersectsRect((HIShapeRef) region, &r) ? RectanglePart : RectangleOut; - return result; + } } /* @@ -332,12 +357,11 @@ TkpReleaseRegion( { CFRelease(r); } -#if 0 /* *---------------------------------------------------------------------- * - * TkMacOSXEmtpyRegion -- + * TkMacOSXSetEmptyRegion -- * * Set region to emtpy. * @@ -351,7 +375,7 @@ TkpReleaseRegion( */ void -TkMacOSXEmtpyRegion( +TkMacOSXSetEmptyRegion( TkRegion r) { ChkErr(HIShapeSetEmpty, (HIMutableShapeRef) r); @@ -360,30 +384,6 @@ TkMacOSXEmtpyRegion( /* *---------------------------------------------------------------------- * - * TkMacOSXIsEmptyRegion -- - * - * Return native region for given tk region. - * - * Results: - * 1 if empty, 0 otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -TkMacOSXIsEmptyRegion( - TkRegion r) -{ - return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0; -} -#endif - -/* - *---------------------------------------------------------------------- - * * TkMacOSXGetNativeRegion -- * * Return native region for given tk region. -- cgit v0.12 From 42ed9ac756fe0fedb878602d401c858c0117ea22 Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Fri, 25 Jul 2014 17:04:07 +0000 Subject: Add copyright notice to Marc Culler for extensive patch to alpha rendering on Mac/Cocoa; remove private API calls to comply with platform requirements. --- macosx/tkMacOSXDraw.c | 1 + macosx/tkMacOSXKeyEvent.c | 20 ++++++++++---------- macosx/tkMacOSXPrivate.h | 8 +++++++- macosx/tkMacOSXScrlbr.c | 3 +++ macosx/tkMacOSXSubwindows.c | 11 ++++++----- macosx/tkMacOSXWindowEvent.c | 10 ++++++++++ macosx/tkMacOSXXStubs.c | 1 + 7 files changed, 38 insertions(+), 16 deletions(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 29b6d0a..9ec4e9a 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -8,6 +8,7 @@ * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright 2014 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 1d24960..0cfb663 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -241,7 +241,7 @@ static unsigned isFunctionKey(unsigned int code); finishedCompose = YES; /* first, clear any working text */ - if (_workingText != nil) + if (privateWorkingText != nil) [self deleteWorkingText]; /* now insert the string as keystrokes */ @@ -275,13 +275,13 @@ static unsigned isFunctionKey(unsigned int code); NSLog (@"setMarkedText '%@' len =%d range %d from %d", str, [str length], selRange.length, selRange.location); - if (_workingText != nil) + if (privateWorkingText != nil) [self deleteWorkingText]; if ([str length] == 0) return; processingCompose = YES; - _workingText = [str copy]; + privateWorkingText = [str copy]; //PENDING: insert workingText underlined } @@ -290,12 +290,12 @@ static unsigned isFunctionKey(unsigned int code); /* delete display of composing characters [not in ] */ - (void)deleteWorkingText { - if (_workingText == nil) + if (privateWorkingText == nil) return; if (NS_KEYLOG) - NSLog(@"deleteWorkingText len = %d\n", [_workingText length]); - [_workingText release]; - _workingText = nil; + NSLog(@"deleteWorkingText len = %d\n", [privateWorkingText length]); + [privateWorkingText release]; + privateWorkingText = nil; processingCompose = NO; //PENDING: delete working text @@ -304,14 +304,14 @@ static unsigned isFunctionKey(unsigned int code); - (BOOL)hasMarkedText { - return _workingText != nil; + return privateWorkingText != nil; } - (NSRange)markedRange { - NSRange rng = _workingText != nil - ? NSMakeRange (0, [_workingText length]) : NSMakeRange (NSNotFound, 0); + NSRange rng = privateWorkingText != nil + ? NSMakeRange (0, [privateWorkingText length]) : NSMakeRange (NSNotFound, 0); if (NS_KEYLOG) NSLog (@"markedRange request"); return rng; diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index b4e510f..42287c7 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -318,9 +318,12 @@ VISIBILITY_HIDDEN VISIBILITY_HIDDEN @interface TKContentView : NSView { @private + /*Remove private API calls.*/ + #if 0 id _savedSubviews; BOOL _subviewsSetAside; - NSString *_workingText; + #endif + NSString *privateWorkingText; } @end @@ -360,9 +363,12 @@ VISIBILITY_HIDDEN keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask; @end +//Remove private API calls here: not necessary for systems >= 10.7 +#if 0 /* From WebKit/WebKit/mac/WebCoreSupport/WebChromeClient.mm: */ @interface NSWindow(TKGrowBoxRect) - (NSRect)_growBoxRect; @end +#endif #endif /* _TKMACPRIV */ diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index 4b3bc31..b8c73bd 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -333,6 +333,8 @@ TkpDisplayScrollbar( NSWindow *w = [view window]; + //This uses a private API call that is no longer needed on systems >= 10.7. + #if 0 if ([w showsResizeIndicator]) { NSRect growBox = [view convertRect:[w _growBoxRect] fromView:nil]; @@ -348,6 +350,7 @@ TkpDisplayScrollbar( TkMacOSXSetScrollbarGrow(winPtr, true); } } + #endif if (!NSEqualRects(frame, [scroller frame])) { [scroller setFrame:frame]; } diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 915dea1..ac055e3 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -743,11 +743,12 @@ TkMacOSXUpdateClipRgn( NSWindow *w = TkMacOSXDrawableWindow(winPtr->window); if (w) { - bounds = NSRectToCGRect([w _growBoxRect]); - bounds.origin.y = [w contentRectForFrameRect: - [w frame]].size.height - bounds.size.height - - bounds.origin.y; - ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds); + // This call to private API not needed on systems >= 10.7 + // bounds = NSRectToCGRect([w _growBoxRect]); + // bounds.origin.y = [w contentRectForFrameRect: + // [w frame]].size.height - bounds.size.height - + // bounds.origin.y; + // ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds); } } macWin->aboveVisRgn = HIShapeCreateCopy(rgn); diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 87504b3..e6e27a4 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -808,6 +808,8 @@ ExposeRestrictProc( NSWindow *w = [self window]; + //remove private API calls here: not needed on systems >= 10.7 + #if 0 if ([self isOpaque] && [w showsResizeIndicator]) { NSRect bounds = [self convertRect:[w _growBoxRect] fromView:nil]; @@ -815,6 +817,7 @@ ExposeRestrictProc( NSEraseRect(bounds); } } + #endif CGFloat height = [self bounds].size.height; HIMutableShapeRef drawShape = HIShapeCreateMutable(); @@ -948,6 +951,9 @@ ExposeRestrictProc( @end +/*Remove private/non-documented API calls. This is strongly discouraged by Apple and may lead to breakage in the future.*/ + +#if 0 #pragma mark TKContentViewPrivate /* @@ -956,6 +962,7 @@ ExposeRestrictProc( * Overrides NSView internals. */ + @interface TKContentView(TKContentViewPrivate) - (id) initWithFrame: (NSRect) frame; - (void) _setAsideSubviews; @@ -1094,6 +1101,9 @@ ExposeRestrictProc( } @end +#endif + + /* * Local Variables: diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 075bd65..c227cd6 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -9,6 +9,7 @@ * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2005-2009 Daniel A. Steffen + * Copyright 2014 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. -- cgit v0.12 From c5695e766b9c40219e9280af36c65998d30e6eb7 Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Mon, 28 Jul 2014 02:44:57 +0000 Subject: Fine-tune scrolling, especially of text widgets with embedded windows, after removal of private API calls; performance is now better and within acceptable ranges. --- macosx/tkMacOSXDraw.c | 4 - macosx/tkMacOSXPrivate.h | 7 -- macosx/tkMacOSXScrlbr.c | 20 ----- macosx/tkMacOSXSubwindows.c | 9 --- macosx/tkMacOSXWindowEvent.c | 170 +------------------------------------------ 5 files changed, 1 insertion(+), 209 deletions(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 9ec4e9a..5512669 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1554,10 +1554,6 @@ TkScrollWindow( } } - /* Step 2: Redisplay all subviews */ - for (NSView *subview in [view subviews] ) { - [subview display]; - } } } diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 42287c7..4855635 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -363,12 +363,5 @@ VISIBILITY_HIDDEN keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask; @end -//Remove private API calls here: not necessary for systems >= 10.7 -#if 0 -/* From WebKit/WebKit/mac/WebCoreSupport/WebChromeClient.mm: */ -@interface NSWindow(TKGrowBoxRect) -- (NSRect)_growBoxRect; -@end -#endif #endif /* _TKMACPRIV */ diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index b8c73bd..0b4fa61 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -331,26 +331,6 @@ TkpDisplayScrollbar( frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset); frame.origin.y = viewHeight - (frame.origin.y + frame.size.height); - NSWindow *w = [view window]; - - //This uses a private API call that is no longer needed on systems >= 10.7. - #if 0 - if ([w showsResizeIndicator]) { - NSRect growBox = [view convertRect:[w _growBoxRect] fromView:nil]; - - if (NSIntersectsRect(growBox, frame)) { - if (scrollPtr->vertical) { - CGFloat y = frame.origin.y; - - frame.origin.y = growBox.origin.y + growBox.size.height; - frame.size.height -= frame.origin.y - y; - } else { - frame.size.width = growBox.origin.x - frame.origin.x; - } - TkMacOSXSetScrollbarGrow(winPtr, true); - } - } - #endif if (!NSEqualRects(frame, [scroller frame])) { [scroller setFrame:frame]; } diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index ac055e3..a08c56e 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -741,15 +741,6 @@ TkMacOSXUpdateClipRgn( } else if (winPtr->wmInfoPtr->attributes & kWindowResizableAttribute) { NSWindow *w = TkMacOSXDrawableWindow(winPtr->window); - - if (w) { - // This call to private API not needed on systems >= 10.7 - // bounds = NSRectToCGRect([w _growBoxRect]); - // bounds.origin.y = [w contentRectForFrameRect: - // [w frame]].size.height - bounds.size.height - - // bounds.origin.y; - // ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds); - } } macWin->aboveVisRgn = HIShapeCreateCopy(rgn); diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index e6e27a4..c458a89 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -764,10 +764,7 @@ Tk_MacOSXIsAppInFront(void) * Custom content view for Tk NSWindows, containing standard NSView subviews. * The goal is to emulate X11-style drawing in response to Expose events: * during the normal AppKit drawing cycle, we supress drawing of all subviews - * (using a technique adapted from WebKit's WebHTMLView) and instead send - * Expose events about the subviews that would be redrawn. Tk Expose event - * handling and drawing handlers then draw the subviews manually via their - * -displayRectIgnoringOpacity: + * and instead send Expose events about the subviews that would be redrawn. */ @interface TKContentView(TKWindowEvent) @@ -806,18 +803,6 @@ ExposeRestrictProc( NSCompositeSourceOver); #endif - NSWindow *w = [self window]; - - //remove private API calls here: not needed on systems >= 10.7 - #if 0 - if ([self isOpaque] && [w showsResizeIndicator]) { - NSRect bounds = [self convertRect:[w _growBoxRect] fromView:nil]; - - if ([self needsToDrawRect:bounds]) { - NSEraseRect(bounds); - } - } - #endif CGFloat height = [self bounds].size.height; HIMutableShapeRef drawShape = HIShapeCreateMutable(); @@ -950,159 +935,6 @@ ExposeRestrictProc( } @end - -/*Remove private/non-documented API calls. This is strongly discouraged by Apple and may lead to breakage in the future.*/ - -#if 0 -#pragma mark TKContentViewPrivate - -/* - * Technique adapted from WebKit/WebKit/mac/WebView/WebHTMLView.mm to supress - * normal AppKit subview drawing and make all drawing go through us. - * Overrides NSView internals. - */ - - -@interface TKContentView(TKContentViewPrivate) -- (id) initWithFrame: (NSRect) frame; -- (void) _setAsideSubviews; -- (void) _restoreSubviews; -@end - -@interface NSView(TKContentViewPrivate) -- (void) _recursiveDisplayRectIfNeededIgnoringOpacity: (NSRect) rect - isVisibleRect: (BOOL) isVisibleRect - rectIsVisibleRectForView: (NSView *) visibleView - topView: (BOOL) topView; -- (void) _recursiveDisplayAllDirtyWithLockFocus: (BOOL) needsLockFocus - visRect: (NSRect) visRect; -- (void) _recursive: (BOOL) recurse - displayRectIgnoringOpacity: (NSRect) displayRect - inContext: (NSGraphicsContext *) context topView: (BOOL) topView; -- (void) _lightWeightRecursiveDisplayInRect: (NSRect) visRect; -- (BOOL) _drawRectIfEmpty; -- (void) _drawRect: (NSRect) inRect clip: (BOOL) clip; -- (void) _setDrawsOwnDescendants: (BOOL) drawsOwnDescendants; -@end - -@implementation TKContentView(TKContentViewPrivate) - -- (id) initWithFrame: (NSRect) frame -{ - self = [super initWithFrame:frame]; - if (self) { - _savedSubviews = nil; - _subviewsSetAside = NO; - [self _setDrawsOwnDescendants:YES]; - } - return self; -} - -- (void) _setAsideSubviews -{ -#ifdef TK_MAC_DEBUG - if (_subviewsSetAside || _savedSubviews) { - Tcl_Panic("TKContentView _setAsideSubviews called incorrectly"); - } -#endif - _savedSubviews = _subviews; - _subviews = nil; - _subviewsSetAside = YES; -} - -- (void) _restoreSubviews -{ -#ifdef TK_MAC_DEBUG - if (!_subviewsSetAside || _subviews) { - Tcl_Panic("TKContentView _restoreSubviews called incorrectly"); - } -#endif - _subviews = _savedSubviews; - _savedSubviews = nil; - _subviewsSetAside = NO; -} - -- (void) _recursiveDisplayRectIfNeededIgnoringOpacity: (NSRect) rect - isVisibleRect: (BOOL) isVisibleRect - rectIsVisibleRectForView: (NSView *) visibleView - topView: (BOOL) topView -{ - [self _setAsideSubviews]; - [super _recursiveDisplayRectIfNeededIgnoringOpacity:rect - isVisibleRect:isVisibleRect rectIsVisibleRectForView:visibleView - topView:topView]; - [self _restoreSubviews]; -} - -- (void) _recursiveDisplayAllDirtyWithLockFocus: (BOOL) needsLockFocus - visRect: (NSRect) visRect -{ - BOOL needToSetAsideSubviews = !_subviewsSetAside; - - if (needToSetAsideSubviews) { - [self _setAsideSubviews]; - } - [super _recursiveDisplayAllDirtyWithLockFocus:needsLockFocus - visRect:visRect]; - if (needToSetAsideSubviews) { - [self _restoreSubviews]; - } -} - -- (void) _recursive: (BOOL) recurse - displayRectIgnoringOpacity: (NSRect) displayRect - inContext: (NSGraphicsContext *) context topView: (BOOL) topView -{ - [self _setAsideSubviews]; - [super _recursive:recurse - displayRectIgnoringOpacity:displayRect inContext:context - topView:topView]; - [self _restoreSubviews]; -} - -- (void) _lightWeightRecursiveDisplayInRect: (NSRect) visRect -{ - BOOL needToSetAsideSubviews = !_subviewsSetAside; - - if (needToSetAsideSubviews) { - [self _setAsideSubviews]; - } - [super _lightWeightRecursiveDisplayInRect:visRect]; - if (needToSetAsideSubviews) { - [self _restoreSubviews]; - } -} - -- (BOOL) _drawRectIfEmpty -{ - /* - * Our -drawRect manages subview drawing directly, so it needs to be called - * even if the area to be redrawn is completely obscured by subviews. - */ - - return YES; -} - -- (void) _drawRect: (NSRect) inRect clip: (BOOL) clip -{ -#ifdef TK_MAC_DEBUG_DRAWING - TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd, - NSStringFromRect(inRect)); -#endif - BOOL subviewsWereSetAside = _subviewsSetAside; - - if (subviewsWereSetAside) { - [self _restoreSubviews]; - } - [super _drawRect:inRect clip:clip]; - if (subviewsWereSetAside) { - [self _setAsideSubviews]; - } -} - -@end -#endif - /* -- cgit v0.12