diff options
author | culler <culler> | 2021-04-29 22:09:38 (GMT) |
---|---|---|
committer | culler <culler> | 2021-04-29 22:09:38 (GMT) |
commit | a723a9e97cc86c5cbee7c26aca2d344ad18c12a1 (patch) | |
tree | c94197ad83fef8a461bca50e4da2e16e10ede0fa /macosx | |
parent | 0e9151d4eb452e294ed0a40869ad97a7c54eed3d (diff) | |
parent | a3be6c56b7742a8c7f8b8f3c193ae6304e2a2cb2 (diff) | |
download | tk-a723a9e97cc86c5cbee7c26aca2d344ad18c12a1.zip tk-a723a9e97cc86c5cbee7c26aca2d344ad18c12a1.tar.gz tk-a723a9e97cc86c5cbee7c26aca2d344ad18c12a1.tar.bz2 |
For Aqua, use an explicit backing CALayer for the TKContentView. Fixes [d281848f97] and other rendering issues.
Diffstat (limited to 'macosx')
-rw-r--r-- | macosx/tkMacOSXDraw.c | 56 | ||||
-rw-r--r-- | macosx/tkMacOSXFont.c | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXImage.c | 73 | ||||
-rw-r--r-- | macosx/tkMacOSXNotify.c | 8 | ||||
-rw-r--r-- | macosx/tkMacOSXPrivate.h | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXRegion.c | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXWindowEvent.c | 35 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.c | 19 |
8 files changed, 134 insertions, 63 deletions
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index bf6a4a7..d5396eb 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -27,6 +27,7 @@ #ifdef TK_MAC_DEBUG #define TK_MAC_DEBUG_DRAWING #define TK_MAC_DEBUG_IMAGE_DRAWING +#define TK_MAC_DEBUG_CG #endif */ @@ -1265,6 +1266,12 @@ TkMacOSXSetupDrawingContext( Bool canDraw = true; TKContentView *view = nil; TkMacOSXDrawingContext dc = {}; + CGFloat drawingHeight; + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "TkMacOSXSetupDrawingContext: %s\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None"); +#endif /* * If the drawable is not a pixmap, get the associated NSView. @@ -1296,13 +1303,10 @@ TkMacOSXSetupDrawingContext( */ dc.context = TkMacOSXGetCGContextForDrawable(d); - if (dc.context) { - dc.portBounds = CGContextGetClipBoundingBox(dc.context); - } else { + if (!dc.context) { NSRect drawingBounds, currentBounds; dc.view = view; dc.context = GET_CGCONTEXT; - dc.portBounds = NSRectToCGRect([view bounds]); if (dc.clipRgn) { CGRect clipBounds; CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, @@ -1354,15 +1358,20 @@ TkMacOSXSetupDrawingContext( * Finish configuring the drawing context. */ + drawingHeight = view ? [view bounds].size.height : + CGContextGetClipBoundingBox(dc.context).size.height; CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, - .ty = dc.portBounds.size.height + .ty = drawingHeight }; - dc.portBounds.origin.x += macDraw->xOff; - dc.portBounds.origin.y += macDraw->yOff; +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "TkMacOSXSetupDrawingContext: pushing GState for %s\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None"); +#endif + CGContextSaveGState(dc.context); CGContextSetTextDrawingMode(dc.context, kCGTextFill); CGContextConcatCTM(dc.context, t); @@ -1388,11 +1397,26 @@ TkMacOSXSetupDrawingContext( */ ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "Setting complex clip for %s to:\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None"); + TkMacOSXPrintRectsInRegion(dc.clipRgn); +#endif + CGContextEOClip(dc.context); - } - else { + } else { CGRect r; HIShapeGetBounds(dc.clipRgn, &r); + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "Current clip BBox is %s\n", + NSStringFromRect(CGContextGetClipBoundingBox(GET_CGCONTEXT)).UTF8String); + fprintf(stderr, "Setting clip for %s to rect %s:\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None", + NSStringFromRect(r).UTF8String); +#endif + CGContextClipToRect(dc.context, r); } } @@ -1413,8 +1437,8 @@ TkMacOSXSetupDrawingContext( TkMacOSXSetColorInContext(gc, gc->foreground, dc.context); if (view) { - CGContextSetPatternPhase(dc.context, - CGSizeMake(dc.portBounds.size.width, dc.portBounds.size.height)); + CGSize size = NSSizeToCGSize([view bounds].size); + CGContextSetPatternPhase(dc.context, size); } if (gc->function != GXcopy) { TkMacOSXDbgMsg("Logical functions other than GXcopy are " @@ -1491,13 +1515,21 @@ TkMacOSXRestoreDrawingContext( if (dcPtr->context) { CGContextSynchronize(dcPtr->context); CGContextRestoreGState(dcPtr->context); + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "TkMacOSXRestoreDrawingContext: popped GState\n"); +#endif + } if (dcPtr->clipRgn) { CFRelease(dcPtr->clipRgn); + dcPtr->clipRgn = NULL; } + #ifdef TK_MAC_DEBUG bzero(dcPtr, sizeof(TkMacOSXDrawingContext)); -#endif /* TK_MAC_DEBUG */ +#endif + } /* diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index feff3bf..d9c1c01 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -1219,7 +1219,7 @@ TkpDrawAngledCharsInContext( (CFAttributedStringRef)attributedString); textX += (CGFloat) macWin->xOff; textY += (CGFloat) macWin->yOff; - height = drawingContext.portBounds.size.height; + height = [drawingContext.view bounds].size.height; textY = height - textY; t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, height); if (angle != 0.0) { diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index 69967af..de19f2b 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -528,51 +528,42 @@ CreateCGImageFromDrawableRect( { MacDrawable *mac_drawable = (MacDrawable *)drawable; CGContextRef cg_context = NULL; + CGRect image_rect = CGRectMake(x, y, width, height); CGImageRef cg_image = NULL, result = NULL; - NSBitmapImageRep *bitmapRep = nil; - NSView *view = nil; + unsigned char *imageData = NULL; if (mac_drawable->flags & TK_IS_PIXMAP) { - /* - * This MacDrawable is a bitmap, so its view is NULL. - */ - - CGRect image_rect = CGRectMake(x, y, width, height); - cg_context = TkMacOSXGetCGContextForDrawable(drawable); - cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); - if (cg_image) { - result = CGImageCreateWithImageInRect(cg_image, image_rect); - CGImageRelease(cg_image); - } - } else if (TkMacOSXGetNSViewForDrawable(mac_drawable) != nil) { - - /* - * Convert Tk top-left to NSView bottom-left coordinates. - */ - - int view_height = [view bounds].size.height; - NSRect view_rect = NSMakeRect(x + mac_drawable->xOff, - view_height - height - y - mac_drawable->yOff, - width, height); - - /* - * Attempt to copy from the view to a bitmapImageRep. If the view does - * not have a valid CGContext, doing this will silently corrupt memory - * and make a big mess. So, in that case, we just return NULL. - */ - - if (view == [NSView focusView]) { - bitmapRep = [view bitmapImageRepForCachingDisplayInRect: view_rect]; - [view cacheDisplayInRect:view_rect toBitmapImageRep:bitmapRep]; - result = [bitmapRep CGImage]; - CFRelease(bitmapRep); - } else { - TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap."); - result = NULL; + if (cg_context) { + cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); } } else { - TkMacOSXDbgMsg("Invalid source drawable"); + NSView *view = TkMacOSXGetNSViewForDrawable(mac_drawable); + if (view == nil) { + TkMacOSXDbgMsg("Invalid source drawable"); + return NULL; + } + NSSize size = view.frame.size; + NSUInteger width = size.width, height = size.height; + NSUInteger bytesPerPixel = 4, + bytesPerRow = bytesPerPixel * width, + bitsPerComponent = 8; + imageData = ckalloc(height * bytesPerRow); + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + cg_context = CGBitmapContextCreate(imageData, width, height, + bitsPerComponent, bytesPerRow, colorSpace, + kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); + CFRelease(colorSpace); + [view.layer renderInContext:cg_context]; + } + if (cg_context) { + cg_image = CGBitmapContextCreateImage(cg_context); + CGContextRelease(cg_context); + } + if (cg_image) { + result = CGImageCreateWithImageInRect(cg_image, image_rect); + CGImageRelease(cg_image); } + ckfree(imageData); return result; } @@ -676,11 +667,11 @@ XGetImage( || bytes_per_row < 4 * width || size != bytes_per_row * height) { TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format"); - CFRelease(bitmapRep); + [bitmapRep release]; return NULL; } memcpy(bitmap, (char *)[bitmapRep bitmapData], size); - CFRelease(bitmapRep); + [bitmapRep release]; /* * When Apple extracts a bitmap from an NSView, it may be in either diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index f32fa76..208d846 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -340,8 +340,9 @@ TkMacOSXNotifyExitHandler( * for all views that need display before it returns. We call it with * deQueue=NO so that it will not change anything on the AppKit event * queue, because we only want the side effect that it runs drawRect. The - * only time when any NSViews have the needsDisplay property set to YES - * is during execution of this function. + * only times when any NSViews have the needsDisplay property set to YES + * are during execution of this function or in the addDirtyRect method + * of TKContentView. * * The reason for running this function as an idle task is to try to * arrange that all widgets will be fully configured before they are @@ -377,7 +378,8 @@ TkMacOSXDrawAllViews( if (dirtyCount) { continue; } - [view setNeedsDisplayInRect:[view tkDirtyRect]]; + [[view layer] setNeedsDisplayInRect:[view tkDirtyRect]]; + [view setNeedsDisplay:YES]; } } else { [window displayIfNeeded]; diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 0bd46c6..be2264f 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -27,6 +27,7 @@ #define TextStyle MacTextStyle #import <ApplicationServices/ApplicationServices.h> #import <Cocoa/Cocoa.h> +#import <QuartzCore/QuartzCore.h> #ifndef NO_CARBON_H #import <Carbon/Carbon.h> #endif @@ -203,7 +204,6 @@ typedef struct TkMacOSXDrawingContext { CGContextRef context; NSView *view; HIShapeRef clipRgn; - CGRect portBounds; } TkMacOSXDrawingContext; /* diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c index 3c168f1..fbb41cb 100644 --- a/macosx/tkMacOSXRegion.c +++ b/macosx/tkMacOSXRegion.c @@ -575,7 +575,7 @@ rectPrinter( void *ref) { if (rect) { - printf(" %s\n", NSStringFromRect(*rect).UTF8String); + fprintf(stderr, " %s\n", NSStringFromRect(*rect).UTF8String); } return noErr; } diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 0075fb8..f7a160a 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -915,11 +915,46 @@ ConfigureRestrictProc( @implementation TKContentView(TKWindowEvent) +- (id)initWithFrame:(NSRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + /* + * The layer must exist before we set wantsLayer to YES. + */ + + self.layer = [CALayer layer]; + self.wantsLayer = YES; + self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; + self.layer.contentsGravity = self.layer.contentsAreFlipped ? + kCAGravityTopLeft : kCAGravityBottomLeft; + + /* + * Nothing gets drawn at all if the layer does not have a delegate. + * Currently, we do not implement any methods of the delegate, however. + */ + + self.layer.delegate = (id) self; + } + return self; +} + +/* + * We will just use drawRect. + */ + +- (BOOL) wantsUpdateLayer +{ + return NO; +} + - (void) addTkDirtyRect: (NSRect) rect { _tkNeedsDisplay = YES; _tkDirtyRect = NSUnionRect(_tkDirtyRect, rect); [NSApp setNeedsToDraw:YES]; + [self setNeedsDisplay:YES]; + [[self layer] setNeedsDisplay]; } - (void) clearTkDirtyRect diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 4f073d8..e039072 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -5535,12 +5535,15 @@ Tk_MacOSXGetTkWindow( void *w) { Window window = None; - TkDisplay *dispPtr = TkGetDisplayList(); if ([(NSWindow *)w respondsToSelector: @selector (tkWindow)]) { window = [(TKWindow *)w tkWindow]; } - return (window != None ? - Tk_IdToWindow(dispPtr->display, window) : NULL); + if (window) { + TkDisplay *dispPtr = TkGetDisplayList(); + return Tk_IdToWindow(dispPtr->display, window); + } else { + return NULL; + } } /* @@ -6271,6 +6274,7 @@ TkMacOSXMakeRealWindowExist( Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts); ApplyContainerOverrideChanges(winPtr, NULL); } + [window display]; } /* @@ -6442,6 +6446,12 @@ TkpWmSetState( macWin = TkMacOSXGetNSWindowForDrawable(winPtr->window); + /* + * Make sure windows are updated before the state change. + */ + + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}; + if (state == WithdrawnState) { Tk_UnmapWindow((Tk_Window)winPtr); } else if (state == IconicState) { @@ -6462,8 +6472,9 @@ TkpWmSetState( [macWin orderFront:NSApp]; TkMacOSXZoomToplevel(macWin, state == NormalState ? inZoomIn : inZoomOut); } + /* - * Make sure windows are updated after the state change. + * Make sure windows are updated after the state change too. */ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){} |