summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
authorculler <culler>2021-04-28 05:26:46 (GMT)
committerculler <culler>2021-04-28 05:26:46 (GMT)
commit2ce4830f8b177a13e360b787bba7b2b73adb8183 (patch)
treea734886cbd761ecf745bbe45cc63ae447737c80a /macosx
parent3518f5614a393f2761dc58f4baa386115cbda33d (diff)
parent0512da3facc4560d40d97a359c4a1ecefbee4da5 (diff)
downloadtk-2ce4830f8b177a13e360b787bba7b2b73adb8183.zip
tk-2ce4830f8b177a13e360b787bba7b2b73adb8183.tar.gz
tk-2ce4830f8b177a13e360b787bba7b2b73adb8183.tar.bz2
CALayer backing for 8.7
Diffstat (limited to 'macosx')
-rw-r--r--macosx/tkMacOSXDraw.c61
-rw-r--r--macosx/tkMacOSXFont.c2
-rw-r--r--macosx/tkMacOSXImage.c73
-rw-r--r--macosx/tkMacOSXNotify.c7
-rw-r--r--macosx/tkMacOSXPrivate.h2
-rw-r--r--macosx/tkMacOSXRegion.c2
-rw-r--r--macosx/tkMacOSXSubwindows.c6
-rw-r--r--macosx/tkMacOSXWindowEvent.c34
-rw-r--r--macosx/tkMacOSXWm.c9
9 files changed, 130 insertions, 66 deletions
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index 6ef964c..9f6966a 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
*/
@@ -1242,6 +1243,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.
@@ -1273,13 +1280,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,
@@ -1331,18 +1335,22 @@ TkMacOSXSetupDrawingContext(
* Finish configuring the drawing context.
*/
+#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);
{ /* Restricted scope for t needed for C++ */
+ 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;
- CGContextSaveGState(dc.context);
- CGContextSetTextDrawingMode(dc.context, kCGTextFill);
CGContextConcatCTM(dc.context, t);
}
if (dc.clipRgn) {
@@ -1367,11 +1375,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);
}
}
@@ -1392,8 +1415,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 "
@@ -1470,13 +1493,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 ab13fd0..496dc35 100644
--- a/macosx/tkMacOSXFont.c
+++ b/macosx/tkMacOSXFont.c
@@ -1220,7 +1220,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 47e3b70..17a0df1 100644
--- a/macosx/tkMacOSXImage.c
+++ b/macosx/tkMacOSXImage.c
@@ -515,51 +515,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;
}
@@ -663,11 +654,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 1e78521..46496da 100644
--- a/macosx/tkMacOSXNotify.c
+++ b/macosx/tkMacOSXNotify.c
@@ -343,8 +343,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
@@ -380,7 +381,7 @@ TkMacOSXDrawAllViews(
if (dirtyCount) {
continue;
}
- [view setNeedsDisplayInRect:[view tkDirtyRect]];
+ [[view layer] setNeedsDisplayInRect:[view tkDirtyRect]];
}
} else {
[window displayIfNeeded];
diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h
index 5936eed..33df1d8 100644
--- a/macosx/tkMacOSXPrivate.h
+++ b/macosx/tkMacOSXPrivate.h
@@ -29,6 +29,7 @@
#import <ApplicationServices/ApplicationServices.h>
#undef Cursor
#import <Cocoa/Cocoa.h>
+#import <QuartzCore/QuartzCore.h>
#ifndef NO_CARBON_H
#import <Carbon/Carbon.h>
#endif
@@ -206,7 +207,6 @@ typedef struct TkMacOSXDrawingContext {
CGContextRef context;
NSView *view;
HIShapeRef clipRgn;
- CGRect portBounds;
} TkMacOSXDrawingContext;
/*
diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c
index 39f6821..b44073a 100644
--- a/macosx/tkMacOSXRegion.c
+++ b/macosx/tkMacOSXRegion.c
@@ -575,7 +575,7 @@ rectPrinter(
TCL_UNUSED(void *))
{
if (rect) {
- printf(" %s\n", NSStringFromRect(*rect).UTF8String);
+ fprintf(stderr, " %s\n", NSStringFromRect(*rect).UTF8String);
}
return noErr;
}
diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c
index 690b9fc..d9603d7 100644
--- a/macosx/tkMacOSXSubwindows.c
+++ b/macosx/tkMacOSXSubwindows.c
@@ -1440,7 +1440,11 @@ Tk_FreePixmap(
if (data) {
ckfree(data);
}
- CFRelease(macPix->context);
+ /*
+ * Releasing the context here causes a crash in the 8.7 regression
+ * tests, but not in 8.6.
+ * CFRelease(macPix->context);
+ */
}
ckfree(macPix);
}
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index d6923db..3305bd3 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -915,11 +915,45 @@ 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];
}
- (void) clearTkDirtyRect
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index aea25e4..7a40135 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.c
@@ -5516,12 +5516,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;
+ }
}
/*