From 66304f744b14ffc5eb42724284c279e91de9444d Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 22 Apr 2021 13:02:15 +0000 Subject: Remove BEGIN_DRAWING_OR_REDRAW which does not work. --- macosx/ttkMacOSXTheme.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index c4e1f33..8379812 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -42,15 +42,6 @@ return; \ } \ -#define BEGIN_DRAWING_OR_REDRAW(d) { \ - TkMacOSXDrawingContext dc; \ - if (!TkMacOSXSetupDrawingContext((d), NULL, &dc)) { \ - NSView *view = TkMacOSXGetNSViewForDrawable(d); \ - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} \ - [(TKContentView *)view addTkDirtyRect:[view bounds]]; \ - return; \ - } \ - #define END_DRAWING \ TkMacOSXRestoreDrawingContext(&dc);} @@ -1614,7 +1605,7 @@ static void TabElementDraw( .position = Ttk_StateTableLookup(TabPositionTable, state), }; - BEGIN_DRAWING_OR_REDRAW(d) + BEGIN_DRAWING(d) if (TkMacOSXInDarkMode(tkwin)) { DrawDarkTab(bounds, state, dc.context); } else { @@ -2806,7 +2797,7 @@ static void FillElementDraw( NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *bgColor; CGFloat fill[4]; - BEGIN_DRAWING_OR_REDRAW(d) + BEGIN_DRAWING(d) GetBackgroundColor(dc.context, tkwin, 0, fill); bgColor = [NSColor colorWithColorSpace: deviceRGB components: fill count: 4]; -- cgit v0.12 From 019923f12e5ac43053840de0701390146ae57907 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 22 Apr 2021 17:07:28 +0000 Subject: Remove unneeded portBounds field from TkMacOSXDrawingContext; add more graphics debugging tools. --- macosx/tkMacOSXDraw.c | 53 +++++++++++++++++++++++++++++++++++++----------- macosx/tkMacOSXFont.c | 2 +- macosx/tkMacOSXPrivate.h | 1 - macosx/tkMacOSXRegion.c | 2 +- macosx/ttkMacOSXTheme.c | 2 ++ 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index bf6a4a7..aa7523a 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 */ @@ -1266,6 +1267,11 @@ TkMacOSXSetupDrawingContext( TKContentView *view = nil; TkMacOSXDrawingContext dc = {}; +#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 +1302,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, @@ -1358,11 +1361,14 @@ TkMacOSXSetupDrawingContext( .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, - .ty = dc.portBounds.size.height + .ty = [view bounds].size.height }; - 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 +1394,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 +1434,8 @@ TkMacOSXSetupDrawingContext( TkMacOSXSetColorInContext(gc, gc->foreground, dc.context); if (view) { - CGContextSetPatternPhase(dc.context, - CGSizeMake(dc.portBounds.size.width, dc.portBounds.size.height)); + NSSize size = [view bounds].size; + CGContextSetPatternPhase(dc.context, size); } if (gc->function != GXcopy) { TkMacOSXDbgMsg("Logical functions other than GXcopy are " @@ -1491,13 +1512,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 2a28f73..8189bdb 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -1217,7 +1217,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/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 0bd46c6..29e7c53 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -203,7 +203,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/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 8379812..6b1aff6 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -555,6 +555,8 @@ static void SolidFillRoundedRectangle( CGContextSetFillColorWithColor(context, CGCOLOR(color)); CGContextBeginPath(context); CGContextAddPath(context, path); + fprintf(stderr, "Filling rounded rectangle at %s\n", + NSStringFromRect(bounds).UTF8String); CGContextFillPath(context); CFRelease(path); } -- cgit v0.12 From 64594c2a80336e1a00dc711942a4ed5fb5dd0e98 Mon Sep 17 00:00:00 2001 From: culler Date: Thu, 22 Apr 2021 19:21:00 +0000 Subject: Make debug printing conditional in ttkMacOSXTheme.c --- macosx/ttkMacOSXTheme.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 6b1aff6..ce098f4 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -555,8 +555,10 @@ static void SolidFillRoundedRectangle( CGContextSetFillColorWithColor(context, CGCOLOR(color)); CGContextBeginPath(context); CGContextAddPath(context, path); +#ifdef TK_MAC_DEBUG_CG fprintf(stderr, "Filling rounded rectangle at %s\n", NSStringFromRect(bounds).UTF8String); +#endif CGContextFillPath(context); CFRelease(path); } -- cgit v0.12 From e3f627385b02a29326439ffe0159930466944f6a Mon Sep 17 00:00:00 2001 From: culler Date: Sat, 24 Apr 2021 19:47:30 +0000 Subject: Possibly a genuine fix - use an explicit CALayer for the TKContentView. --- macosx/tkMacOSXNotify.c | 7 ++++--- macosx/tkMacOSXPrivate.h | 1 + macosx/tkMacOSXWindowEvent.c | 32 ++++++++++++++++++++++++++++++++ unix/configure | 2 +- unix/configure.in | 2 +- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index f32fa76..0438525 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,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 29e7c53..be2264f 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -27,6 +27,7 @@ #define TextStyle MacTextStyle #import #import +#import #ifndef NO_CARBON_H #import #endif diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 0075fb8..b6b58d8 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -915,11 +915,43 @@ 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; + + /* + * 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/unix/configure b/unix/configure index 45c215e..691d43b 100755 --- a/unix/configure +++ b/unix/configure @@ -9385,7 +9385,7 @@ cat >>confdefs.h <<\_ACEOF #define MAC_OSX_TK 1 _ACEOF - LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit" + LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit -framework QuartzCore" EXTRA_CC_SWITCHES='-std=gnu99 -x objective-c' TK_WINDOWINGSYSTEM=AQUA if test -n "${enable_symbols}" -a "${enable_symbols}" != no; then diff --git a/unix/configure.in b/unix/configure.in index 78dd688..9720b91 100644 --- a/unix/configure.in +++ b/unix/configure.in @@ -354,7 +354,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" + LIBS="$LIBS -framework Cocoa -framework Carbon -framework IOKit -framework QuartzCore" EXTRA_CC_SWITCHES='-std=gnu99 -x objective-c' TK_WINDOWINGSYSTEM=AQUA if test -n "${enable_symbols}" -a "${enable_symbols}" != no; then -- cgit v0.12 From 55bde88d25c729979dd328b7084bcb6ee2498255 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 25 Apr 2021 14:00:35 +0000 Subject: Bonus! Use the new CALayer to make XCopyArea work again! --- macosx/tkMacOSXImage.c | 66 +++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index 69967af..1dc4613 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -528,50 +528,44 @@ CreateCGImageFromDrawableRect( { MacDrawable *mac_drawable = (MacDrawable *)drawable; CGContextRef cg_context = NULL; - CGImageRef cg_image = NULL, result = NULL; - NSBitmapImageRep *bitmapRep = nil; - NSView *view = nil; + CGRect image_rect = CGRectMake(x, y, width, height); + CGImageRef cg_image = nil, result = nil; 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; - } } else { - TkMacOSXDbgMsg("Invalid source drawable"); + NSView *view = TkMacOSXGetNSViewForDrawable(mac_drawable); + if (view == nil) { + TkMacOSXDbgMsg("Invalid source drawable"); + return nil; + } + NSSize size = view.frame.size; + NSUInteger width = size.width, height = size.height; + NSUInteger bytesPerPixel = 4, + bytesPerRow = bytesPerPixel * width, + bitsPerComponent = 8; + unsigned char *rawData = malloc(height * bytesPerRow); + if (rawData) { + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + cg_context = CGBitmapContextCreate(rawData, width, height, + bitsPerComponent, bytesPerRow, colorSpace, + kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); + CFRelease(colorSpace); + if (cg_context) { + [view.layer renderInContext:cg_context]; + cg_image = CGBitmapContextCreateImage(cg_context); + CGContextRelease(cg_context); + } + free(rawData); + } + if (cg_image) { + result = CGImageCreateWithImageInRect(cg_image, image_rect); + CGImageRelease(cg_image); + } } return result; } -- cgit v0.12 From 8822888c8757a09d5a6322d1458512095ac1f2f0 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 25 Apr 2021 14:28:16 +0000 Subject: Add calls to update idletasks in scale-20.7 and scale-20.8. --- tests/scale.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/scale.test b/tests/scale.test index 34f2cd9..d7f3a75 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 -- cgit v0.12 From 79f3f632a93e76d6d696ae190b69c030f3bc3821 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 25 Apr 2021 15:36:39 +0000 Subject: Using the CALayer changes some timings -- make some small adjustments to a few tests to avoid sporadic timing-related failures. --- tests/entry.test | 1 + tests/font.test | 6 +++--- tests/textWind.test | 10 +++++++--- tests/unixEmbed.test | 1 + 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/entry.test b/tests/entry.test index ef70a9e..a72d36a 100644 --- a/tests/entry.test +++ b/tests/entry.test @@ -2968,6 +2968,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 6995a7b..5af2dbb 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/textWind.test b/tests/textWind.test index a11a418..11f8eb8 100644 --- a/tests/textWind.test +++ b/tests/textWind.test @@ -1526,13 +1526,15 @@ test textWind-17.9 {peer widget window configuration} -setup { destroy .t .tt } -body { pack [text .t] + update idletasks .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 ; update .tt.t window configure 1.2 -window [frame .tt.t.f -width 10 -height 20 -bg red] + update idletasks list [.t window configure 1.2 -window] [.tt.t window configure 1.2 -window] } -cleanup { destroy .tt .t @@ -1542,20 +1544,22 @@ test textWind-17.10 {peer widget window configuration} -setup { destroy .t .tt } -body { pack [text .t] + update idletasks .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] .tt.t window create 1.2 -window [frame .tt.t.f -width 25 -height 20 -bg blue] - update ; update + update idletasks .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 {} .t window configure 1.2 -window {} set res [list [.t window configure 1.2 -window] \ [.tt.t window configure 1.2 -window]] - update + update idletasks lappend res [.t window configure 1.2 -window] \ [.tt.t window configure 1.2 -window] } -cleanup { diff --git a/tests/unixEmbed.test b/tests/unixEmbed.test index bb7edc5..d5f6ee3 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] -- cgit v0.12 From 971268f241db43b649dd2387e352ec171b3e2703 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 25 Apr 2021 15:53:47 +0000 Subject: Use the release method instead of CFRelease for NSBitmapImageRep objects. --- macosx/tkMacOSXImage.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index 1dc4613..8160303 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -670,11 +670,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 -- cgit v0.12 From 312349dd711ba2bb4341ec16cc1b476351d6cbb9 Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 25 Apr 2021 22:03:02 +0000 Subject: Fix the flip transform for pixmaps. This makes bitmap buttons work again. --- macosx/tkMacOSXDraw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index aa7523a..f642bda 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1266,6 +1266,7 @@ TkMacOSXSetupDrawingContext( Bool canDraw = true; TKContentView *view = nil; TkMacOSXDrawingContext dc = {}; + CGFloat drawingHeight; #ifdef TK_MAC_DEBUG_CG fprintf(stderr, "TkMacOSXSetupDrawingContext: %s\n", @@ -1357,11 +1358,13 @@ 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 = [view bounds].size.height + .ty = drawingHeight }; #ifdef TK_MAC_DEBUG_CG -- cgit v0.12 From 45e129155eee3c174598146404e28b0cbdc02e5c Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 25 Apr 2021 22:48:28 +0000 Subject: Code cleanup. Thanks to Christopher Chavez for the careful review. --- macosx/tkMacOSXImage.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index 8160303..6f55171 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -529,44 +529,42 @@ CreateCGImageFromDrawableRect( MacDrawable *mac_drawable = (MacDrawable *)drawable; CGContextRef cg_context = NULL; CGRect image_rect = CGRectMake(x, y, width, height); - CGImageRef cg_image = nil, result = nil; + CGImageRef cg_image = NULL, result = NULL; + unsigned char *imageData = NULL; if (mac_drawable->flags & TK_IS_PIXMAP) { cg_context = TkMacOSXGetCGContextForDrawable(drawable); - cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); - if (cg_image) { - result = CGImageCreateWithImageInRect(cg_image, image_rect); - CGImageRelease(cg_image); + if (cg_context) { + cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); + CFRelease(cg_context); } } else { NSView *view = TkMacOSXGetNSViewForDrawable(mac_drawable); if (view == nil) { TkMacOSXDbgMsg("Invalid source drawable"); - return nil; + return NULL; } NSSize size = view.frame.size; NSUInteger width = size.width, height = size.height; NSUInteger bytesPerPixel = 4, bytesPerRow = bytesPerPixel * width, bitsPerComponent = 8; - unsigned char *rawData = malloc(height * bytesPerRow); - if (rawData) { - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - cg_context = CGBitmapContextCreate(rawData, width, height, - bitsPerComponent, bytesPerRow, colorSpace, - kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); - CFRelease(colorSpace); - if (cg_context) { - [view.layer renderInContext:cg_context]; - cg_image = CGBitmapContextCreateImage(cg_context); - CGContextRelease(cg_context); - } - free(rawData); - } - if (cg_image) { - result = CGImageCreateWithImageInRect(cg_image, image_rect); - CGImageRelease(cg_image); - } + 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; } -- cgit v0.12 From 2b4875f9a8a916fa7fc7c821b0a73d668ec35cdf Mon Sep 17 00:00:00 2001 From: culler Date: Sun, 25 Apr 2021 22:50:14 +0000 Subject: One more bit of code cleanup. --- macosx/tkMacOSXDraw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index f642bda..d5396eb 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1437,7 +1437,7 @@ TkMacOSXSetupDrawingContext( TkMacOSXSetColorInContext(gc, gc->foreground, dc.context); if (view) { - NSSize size = [view bounds].size; + CGSize size = NSSizeToCGSize([view bounds].size); CGContextSetPatternPhase(dc.context, size); } if (gc->function != GXcopy) { -- cgit v0.12 From 81a7dbc90f3961dc72cc728dc321d7e488e4d4c1 Mon Sep 17 00:00:00 2001 From: culler Date: Mon, 26 Apr 2021 01:29:54 +0000 Subject: Set the CALayer's contentsGravity property so that programmatic resizes look better. --- macosx/tkMacOSXWindowEvent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index b6b58d8..fe8a983 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -926,6 +926,8 @@ ConfigureRestrictProc( 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. -- cgit v0.12 From 5548b9384faa00a2bb51f6b6f1cb9533eeaf246c Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 27 Apr 2021 19:35:45 +0000 Subject: Try to avoid the rare crash in Tk_MacOSXGetTkWindow which has been seen at exit a few times. --- macosx/tkMacOSXWm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 4f073d8..77f7b09 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; + } } /* -- cgit v0.12 From 3387e9ef1780a37d84b726bbde72b62624730325 Mon Sep 17 00:00:00 2001 From: culler Date: Tue, 27 Apr 2021 20:04:35 +0000 Subject: Adjust textWind-17.10 --- tests/textWind.test | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/textWind.test b/tests/textWind.test index 11f8eb8..1329790 100644 --- a/tests/textWind.test +++ b/tests/textWind.test @@ -1526,15 +1526,13 @@ test textWind-17.9 {peer widget window configuration} -setup { destroy .t .tt } -body { pack [text .t] - update idletasks .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 ; update .tt.t window configure 1.2 -window [frame .tt.t.f -width 10 -height 20 -bg red] - update idletasks list [.t window configure 1.2 -window] [.tt.t window configure 1.2 -window] } -cleanup { destroy .tt .t @@ -1543,28 +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] - update idletasks .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 idletasks - .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 {} + .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]] + .tt.t window configure 1.2 -window {} update idletasks - lappend res [.t window configure 1.2 -window] \ - [.tt.t window configure 1.2 -window] + # 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 } -setup { catch {destroy .t .f .f2} -- cgit v0.12