summaryrefslogtreecommitdiffstats
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
parent3518f5614a393f2761dc58f4baa386115cbda33d (diff)
parent0512da3facc4560d40d97a359c4a1ecefbee4da5 (diff)
downloadtk-2ce4830f8b177a13e360b787bba7b2b73adb8183.zip
tk-2ce4830f8b177a13e360b787bba7b2b73adb8183.tar.gz
tk-2ce4830f8b177a13e360b787bba7b2b73adb8183.tar.bz2
CALayer backing for 8.7
-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
-rw-r--r--tests/entry.test1
-rw-r--r--tests/font.test6
-rw-r--r--tests/scale.test2
-rw-r--r--tests/textWind.test28
-rw-r--r--tests/unixEmbed.test1
-rwxr-xr-xunix/configure2
-rw-r--r--unix/configure.ac2
16 files changed, 157 insertions, 81 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;
+ }
}
/*
diff --git a/tests/entry.test b/tests/entry.test
index aef509c..1b589d1 100644
--- a/tests/entry.test
+++ b/tests/entry.test
@@ -2995,6 +2995,7 @@ test entry-17.2 {EntryUpdateScrollbar procedure} -body {
test entry-17.3 {EntryUpdateScrollbar procedure} -body {
entry .e -width 10 -xscrollcommand scroll -font {Courier -12}
pack .e
+ update idletasks
set timeout [after 500 {set scrollInfo {-1000000 -1000000}}]
.e insert 0 abcdefghijklmnopqrs
.e xview 6
diff --git a/tests/font.test b/tests/font.test
index d490c64..8dce1f8 100644
--- a/tests/font.test
+++ b/tests/font.test
@@ -523,16 +523,16 @@ test font-12.2 {UpdateDependantFonts procedure: pings the widgets} -setup {
destroy .t.f
catch {font delete xyz}
pack [label .t.f]
- update
+ update idletasks
} -body {
font create xyz -family times -size 20
.t.f config -font xyz -text "abcd" -padx 0 -bd 0 -highlightthickness 0
set a1 [font measure xyz "abcd"]
- update
+ update idletasks
set b1 [winfo reqwidth .t.f]
font configure xyz -family helvetica -size 20
set a2 [font measure xyz "abcd"]
- update
+ update idletasks
set b2 [winfo reqwidth .t.f]
expr {$a1==$b1 && $a2==$b2}
} -cleanup {
diff --git a/tests/scale.test b/tests/scale.test
index 9c1ab21..69ef0d9 100644
--- a/tests/scale.test
+++ b/tests/scale.test
@@ -1522,6 +1522,7 @@ test scale-20.7 {Bug [2262543fff] - Scale widget unexpectedly fires command call
} -body {
scale .s -from 1 -to 50 -command {set commandedVar}
pack .s
+ update idletasks
.s set 10
set timeout [after 500 {set $commandedVar "timeout"}]
vwait commandedVar ; # -command callback shall fire
@@ -1538,6 +1539,7 @@ test scale-20.8 {Bug [2262543fff] - Scale widget unexpectedly fires command call
} -body {
scale .s -from 1 -to 50 -variable scaleVar -command {set commandedVar}
pack .s
+ update idletasks
.s set 10
set timeout [after 500 {set $commandedVar "timeout"}]
vwait commandedVar ; # -command callback shall fire
diff --git a/tests/textWind.test b/tests/textWind.test
index 55128be..a93febd 100644
--- a/tests/textWind.test
+++ b/tests/textWind.test
@@ -1541,26 +1541,34 @@ test textWind-17.9 {peer widget window configuration} -setup {
test textWind-17.10 {peer widget window configuration} -setup {
destroy .t .tt
} -body {
+ set res {}
pack [text .t]
.t delete 1.0 end
.t insert 1.0 "Some sample text"
toplevel .tt
pack [.t peer create .tt.t]
+ update idletasks
.t window create 1.2 -window [frame .t.f -width 10 -height 20 -bg blue]
+ update idletasks
+ # There should be a window in the main widget but not in the peer.
+ lappend res [.t window configure 1.2 -window]
+ lappend res [.tt.t window configure 1.2 -window]
.tt.t window create 1.2 -window [frame .tt.t.f -width 25 -height 20 -bg blue]
- update ; update
- .t window configure 1.2 -create \
- {destroy %W.f ; frame %W.f -width 50 -height 7 -bg red}
- .tt.t window configure 1.2 -window {}
+ update idletasks
+ .t window configure 1.2 -create {destroy %W.f ; frame %W.f -width 50 -height 7 -bg red}
+ update idletasks
+ # The main widget should not have changed.
+ lappend res [.t window configure 1.2 -window]
.t window configure 1.2 -window {}
- set res [list [.t window configure 1.2 -window] \
- [.tt.t window configure 1.2 -window]]
- update
- lappend res [.t window configure 1.2 -window] \
- [.tt.t window configure 1.2 -window]
+ .tt.t window configure 1.2 -window {}
+ update idletasks
+ # Nothing should have changed.
+ lappend res [.t window configure 1.2 -window]
+ lappend res [.tt.t window configure 1.2 -window]
} -cleanup {
destroy .tt .t
-} -result {{-window {} {} {} {}} {-window {} {} {} {}} {-window {} {} {} .t.f} {-window {} {} {} .tt.t.f}}
+} -result {{-window {} {} {} .t.f} {-window {} {} {} {}} {-window {} {} {} .t.f}\
+{-window {} {} {} .t.f} {-window {} {} {} .tt.t.f}}
test textWind-18.1 {embedded window deletion triggered by a script bound to <Map>} -setup {
catch {destroy .t .f .f2}
diff --git a/tests/unixEmbed.test b/tests/unixEmbed.test
index ea0063f..d4f7259 100644
--- a/tests/unixEmbed.test
+++ b/tests/unixEmbed.test
@@ -1301,6 +1301,7 @@ test unixEmbed-11.2 {mouse coordinates in embedded toplevels} -constraints {
wm geometry .main 200x400+100+100
update idletasks
focus -force .main
+ after 100
set x [expr {[winfo x .main ] + [winfo x .main.b] + 40}]
set y [expr {[winfo y .main ] + [winfo y .main.b] + 38}]
lappend result [winfo containing $x $y]
diff --git a/unix/configure b/unix/configure
index 579bd0d..c05d9b4 100755
--- a/unix/configure
+++ b/unix/configure
@@ -7665,7 +7665,7 @@ if test $tk_aqua = yes; then
printf "%s\n" "#define MAC_OSX_TK 1" >>confdefs.h
- LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit -framework Security"
+ LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit -framework QuartzCore -framework Security"
if test -d /System/Library/Frameworks/UserNotifications.framework; then
LIBS="$LIBS -framework UserNotifications"
fi
diff --git a/unix/configure.ac b/unix/configure.ac
index b6f602b..adbf461 100644
--- a/unix/configure.ac
+++ b/unix/configure.ac
@@ -303,7 +303,7 @@ fi
if test $tk_aqua = yes; then
AC_DEFINE(MAC_OSX_TK, 1, [Are we building TkAqua?])
- LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit -framework Security"
+ LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit -framework QuartzCore -framework Security"
if test -d /System/Library/Frameworks/UserNotifications.framework; then
LIBS="$LIBS -framework UserNotifications"
fi