Attachment "doubleclickbug.diff" to
ticket [317643cf]
added by
anonymous
2019-07-23 08:12:44.
diff --git a/changes b/changes
index 81108a5a7..29e992a5d 100644
--- a/changes
+++ b/changes
@@ -7568,4 +7568,4 @@ Tk Cocoa 2.0: More drawing internals refinements (culler,walzer)
2018-11-04 (bug)[6b22d4] [treeview] binding fix (ohagan)
-- Released 8.6.9, November 9, 2018 - http://core.tcl-lang.org/tk/ for details -
+- Released 8.6.9, November 16, 2018 - http://core.tcl-lang.org/tk/ for details -
diff --git a/generic/tkImgPhInstance.c b/generic/tkImgPhInstance.c
index ec9ee0438..fb106b17e 100644
--- a/generic/tkImgPhInstance.c
+++ b/generic/tkImgPhInstance.c
@@ -30,8 +30,10 @@ extern int _XInitImageFuncPtrs(XImage *image);
* Forward declarations
*/
+#ifndef MAC_OSX_TK
static void BlendComplexAlpha(XImage *bgImg, PhotoInstance *iPtr,
int xOffset, int yOffset, int width, int height);
+#endif
static int IsValidPalette(PhotoInstance *instancePtr,
const char *palette);
static int CountBits(pixel mask);
@@ -409,7 +411,7 @@ TkImgPhotoGet(
*
*----------------------------------------------------------------------
*/
-
+#ifndef MAC_OSX_TK
#ifndef _WIN32
#define GetRValue(rgb) (UCHAR(((rgb) & red_mask) >> red_shift))
#define GetGValue(rgb) (UCHAR(((rgb) & green_mask) >> green_shift))
@@ -418,13 +420,6 @@ TkImgPhotoGet(
(UCHAR(r) << red_shift) | \
(UCHAR(g) << green_shift) | \
(UCHAR(b) << blue_shift) ))
-#ifdef MAC_OSX_TK
-#define RGBA(r, g, b, a) ((unsigned)( \
- (UCHAR(r) << red_shift) | \
- (UCHAR(g) << green_shift) | \
- (UCHAR(b) << blue_shift) | \
- (UCHAR(a) << alpha_shift) ))
-#endif
#define RGB15(r, g, b) ((unsigned)( \
(((r) * red_mask / 255) & red_mask) | \
(((g) * green_mask / 255) & green_mask) | \
@@ -443,16 +438,7 @@ BlendComplexAlpha(
unsigned long pixel;
unsigned char r, g, b, alpha, unalpha, *masterPtr;
unsigned char *alphaAr = iPtr->masterPtr->pix32;
-#if defined(MAC_OSX_TK)
- /* Background "pixels" are actually 2^pp x 2^pp blocks of subpixels. Each
- * block gets blended with the color of one image pixel. Since we iterate
- * over the background subpixels, we reset the width and height to the
- * subpixel dimensions of the background image we are using.
- */
- int pp = bgImg->pixelpower;
- width = width << pp;
- height = height << pp;
-#endif
+
/*
* This blending is an integer version of the Source-Over compositing rule
* (see Porter&Duff, "Compositing Digital Images", proceedings of SIGGRAPH
@@ -492,13 +478,6 @@ BlendComplexAlpha(
while ((0x0001 & (blue_mask >> blue_shift)) == 0) {
blue_shift++;
}
-#ifdef MAC_OSX_TK
- unsigned long alpha_mask = visual->alpha_mask;
- unsigned long alpha_shift = 0;
- while ((0x0001 & (alpha_mask >> alpha_shift)) == 0) {
- alpha_shift++;
- }
-#endif
#endif /* !_WIN32 */
/*
@@ -558,16 +537,9 @@ BlendComplexAlpha(
#endif /* !_WIN32 && !MAC_OSX_TK */
for (y = 0; y < height; y++) {
-# if !defined(MAC_OSX_TK)
line = (y + yOffset) * iPtr->masterPtr->width;
for (x = 0; x < width; x++) {
masterPtr = alphaAr + ((line + x + xOffset) * 4);
-#else
- /* Repeat each image row and column 2^pp times. */
- line = ((y>>pp) + yOffset) * iPtr->masterPtr->width;
- for (x = 0; x < width; x++) {
- masterPtr = alphaAr + ((line + (x>>pp) + xOffset) * 4);
-#endif
alpha = masterPtr[3];
/*
@@ -599,16 +571,13 @@ BlendComplexAlpha(
g = ALPHA_BLEND(ga, g, alpha, unalpha);
b = ALPHA_BLEND(ba, b, alpha, unalpha);
}
-#ifndef MAC_OSX_TK
XPutPixel(bgImg, x, y, RGB(r, g, b));
-#else
- XPutPixel(bgImg, x, y, RGBA(r, g, b, alpha));
-#endif
}
}
}
#undef ALPHA_BLEND
}
+#endif /* MAC_OSX_TK */
/*
*----------------------------------------------------------------------
@@ -651,6 +620,24 @@ TkImgPhotoDisplay(
return;
}
+#ifdef MAC_OSX_TK
+ /*
+ * The Mac version of TkPutImage handles RGBA images directly. There is
+ * no need to call XGetImage or to do the Porter-Duff compositing by hand.
+ * We just let the CG graphics library do it, using the graphics hardware.
+ */
+ unsigned char *rgbaPixels = instancePtr->masterPtr->pix32;
+
+ XImage *photo = XCreateImage(display, NULL, 32, ZPixmap, 0, (char*)rgbaPixels,
+ (unsigned int)instancePtr->width,
+ (unsigned int)instancePtr->height,
+ 0, (unsigned int)(4 * instancePtr->width));
+ TkPutImage(NULL, 0, display, drawable, instancePtr->gc,
+ photo, imageX, imageY, drawableX, drawableY,
+ (unsigned int) width, (unsigned int) height);
+ photo->data = NULL;
+ XDestroyImage(photo);
+#else
if ((instancePtr->masterPtr->flags & COMPLEX_ALPHA)
&& visInfo.depth >= 15
&& (visInfo.class == DirectColor || visInfo.class == TrueColor)) {
@@ -709,6 +696,7 @@ TkImgPhotoDisplay(
XSetClipOrigin(display, instancePtr->gc, 0, 0);
}
XFlush(display);
+#endif
}
/*
diff --git a/generic/tkOption.c b/generic/tkOption.c
index 24e7fb336..545a9b9b5 100644
--- a/generic/tkOption.c
+++ b/generic/tkOption.c
@@ -996,6 +996,9 @@ AddFromString(
while ((*src == ' ') || (*src == '\t')) {
src++;
}
+ if (*src == '\\' && (src[1] == '\t' || src[1] == ' ')) {
+ src++;
+ }
if (*src == '\0') {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"missing value on line %d", lineNum));
@@ -1025,7 +1028,7 @@ AddFromString(
src += 2;
*dst++ = '\n';
continue;
- } else if (src[1] == '\t' || src[1] == ' ' || src[1] == '\\') {
+ } else if (src[1] == '\\') {
++src;
} else if (src[1] >= '0' && src[1] <= '3' && src[2] >= '0' &&
src[2] <= '9' && src[3] >= '0' && src[3] <= '9') {
diff --git a/generic/tkTest.c b/generic/tkTest.c
index 2dbd87724..560939130 100644
--- a/generic/tkTest.c
+++ b/generic/tkTest.c
@@ -31,6 +31,9 @@
#if defined(MAC_OSX_TK)
#include "tkMacOSXInt.h"
#include "tkScrollbar.h"
+#define SIMULATE_DRAWING TkTestSimulateDrawing(true);
+#else
+#define SIMULATE_DRAWING
#endif
#ifdef __UNIX__
@@ -1550,16 +1553,35 @@ ImageDisplay(
TImageInstance *instPtr = (TImageInstance *) clientData;
char buffer[200 + TCL_INTEGER_SPACE * 6];
+ /*
+ * The purpose of the test image type is to track the calls to an image
+ * display proc and record the parameters passed in each call. On macOS
+ * these tests will fail because of the asynchronous drawing. The low
+ * level graphics calls below which are supposed to draw a rectangle will
+ * not draw anything to the screen because the idle task will not be
+ * processed inside of the drawRect method and hence will not be able to
+ * obtain a valid graphics context. Instead, the window will be marked as
+ * needing display, and will be redrawn during a future asynchronous call
+ * to drawRect. This will generate an other call to this display proc,
+ * and the recorded data will show extra calls, causing the test to fail.
+ * To avoid this, we can set the [NSApp simulateDrawing] flag, which will
+ * cause all low level drawing routines to return immediately and not
+ * schedule the window for drawing later. This flag is cleared by the
+ * next call to XSync, which is called by the update command.
+ */
+
sprintf(buffer, "%s display %d %d %d %d",
instPtr->masterPtr->imageName, imageX, imageY, width, height);
Tcl_SetVar2(instPtr->masterPtr->interp, instPtr->masterPtr->varName, NULL,
- buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
+ buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
if (width > (instPtr->masterPtr->width - imageX)) {
width = instPtr->masterPtr->width - imageX;
}
if (height > (instPtr->masterPtr->height - imageY)) {
height = instPtr->masterPtr->height - imageY;
}
+
+ SIMULATE_DRAWING
XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
(unsigned) (width-1), (unsigned) (height-1));
XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,
diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c
index 14b8872d3..ea78d435d 100644
--- a/macosx/tkMacOSXButton.c
+++ b/macosx/tkMacOSXButton.c
@@ -1201,3 +1201,11 @@ PulseDefaultButtonProc(ClientData clientData)
PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData);
}
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/macosx/tkMacOSXConfig.c b/macosx/tkMacOSXConfig.c
index bdfcb6ec0..841fc54ed 100644
--- a/macosx/tkMacOSXConfig.c
+++ b/macosx/tkMacOSXConfig.c
@@ -41,3 +41,12 @@ TkpGetSystemDefault(
{
return NULL;
}
+
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/macosx/tkMacOSXConstants.h b/macosx/tkMacOSXConstants.h
index b160083ed..0badf1a8f 100644
--- a/macosx/tkMacOSXConstants.h
+++ b/macosx/tkMacOSXConstants.h
@@ -40,6 +40,7 @@
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
#define NSAppKitDefined NSEventTypeAppKitDefined
+#define NSApplicationDefined NSEventTypeApplicationDefined
#define NSApplicationActivatedEventType NSEventSubtypeApplicationActivated
#define NSApplicationDeactivatedEventType NSEventSubtypeApplicationDeactivated
#define NSWindowExposedEventType NSEventSubtypeWindowExposed
@@ -92,6 +93,7 @@
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
#define NSShiftKeyMask NSEventModifierFlagShift
#define NSAnyEventMask NSEventMaskAny
+#define NSApplicationDefinedMask NSEventMaskApplicationDefined
#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground
#define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow
#define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel
diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c
index 8d20d4e90..f8453c77b 100644
--- a/macosx/tkMacOSXDialog.c
+++ b/macosx/tkMacOSXDialog.c
@@ -1198,36 +1198,42 @@ TkAboutDlg(void)
NSString *year = [dateFormatter stringFromDate:[NSDate date]];
[dateFormatter release];
-
- NSMutableParagraphStyle *style =
- [[[NSParagraphStyle defaultParagraphStyle] mutableCopy]
- autorelease];
-
- [style setAlignment:NSCenterTextAlignment];
-
- NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
- @"Tcl & Tk", @"ApplicationName",
- @"Tcl " TCL_VERSION " & Tk " TK_VERSION, @"ApplicationVersion",
- @TK_PATCH_LEVEL, @"Version",
- image, @"ApplicationIcon",
- [NSString stringWithFormat:@"Copyright %1$C 1987-%2$@.", 0xA9,
- year], @"Copyright",
- [[[NSAttributedString alloc] initWithString:
- [NSString stringWithFormat:
- @"%1$C 1987-%2$@ Tcl Core Team." "\n\n"
- "%1$C 1989-%2$@ Contributors." "\n\n"
- "%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC." "\n\n"
- "%1$C 2014-%2$@ Marc Culler." "\n\n"
- "%1$C 2002-%2$@ Daniel A. Steffen." "\n\n"
- "%1$C 2001-2009 Apple Inc." "\n\n"
- "%1$C 2001-2002 Jim Ingham & Ian Reid" "\n\n"
- "%1$C 1998-2000 Jim Ingham & Ray Johnson" "\n\n"
- "%1$C 1998-2000 Scriptics Inc." "\n\n"
- "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] attributes:
- [NSDictionary dictionaryWithObject:style
- forKey:NSParagraphStyleAttributeName]] autorelease], @"Credits",
- nil];
- [NSApp orderFrontStandardAboutPanelWithOptions:options];
+
+ /*
+ * This replaces the old about dialog with a standard alert that displays
+ * correctly on 10.14.
+ */
+
+ NSString *version = @"Tcl " TCL_PATCH_LEVEL " & Tk " TCL_PATCH_LEVEL;
+ NSString *url = @"www.tcl-lang.org";
+ NSTextView *credits = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,300,300)];
+ NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
+ NSDictionary *textAttributes = [NSDictionary dictionaryWithObject:font
+ forKey:NSFontAttributeName];
+ [credits insertText: [[NSAttributedString alloc]
+ initWithString:[NSString stringWithFormat: @"\n"
+ "Tcl and Tk are distributed under a modified BSD license: "
+ "www.tcl.tk/software/tcltk/license.html\n\n"
+ "%1$C 1987-%2$@ Tcl Core Team and Contributers.\n\n"
+ "%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC.\n\n"
+ "%1$C 2014-%2$@ Marc Culler.\n\n"
+ "%1$C 2002-2012 Daniel A. Steffen.\n\n"
+ "%1$C 2001-2009 Apple Inc.\n\n"
+ "%1$C 2001-2002 Jim Ingham & Ian Reid\n\n"
+ "%1$C 1998-2000 Jim Ingham & Ray Johnson\n\n"
+ "%1$C 1998-2000 Scriptics Inc.\n\n"
+ "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year]
+ attributes:textAttributes]
+ replacementRange:NSMakeRange(0,0)];
+ [credits setDrawsBackground:NO];
+ [credits setEditable:NO];
+ NSAlert *about = [[NSAlert alloc] init];
+ [[about window] setTitle:@"About Tcl & Tk"];
+ [about setMessageText: version];
+ [about setInformativeText:url];
+ about.accessoryView = credits;
+ [about runModal];
+ [about release];
}
/*
@@ -1257,7 +1263,7 @@ TkMacOSXStandardAboutPanelObjCmd(
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
- [NSApp orderFrontStandardAboutPanelWithOptions:[NSDictionary dictionary]];
+ TkAboutDlg();
return TCL_OK;
}
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index ce53a177e..984e2e57b 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -111,6 +111,25 @@ TkMacOSXInitCGDrawing(
*
* Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep.
*
+ * This is only used by XGetImage, which is never called. And this
+ * implementation does not work correctly. Originally it relied on
+ * [NSBitmapImageRep initWithFocusedViewRect:view_rect] which was
+ * deprecated by Apple in OSX 10.14 and also required the use of other
+ * deprecated functions such as [NSView lockFocus]. Apple's suggested
+ * replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that
+ * is what is being used here. However, that method only works when the
+ * view has a valid CGContext, and a view is only guaranteed to have a
+ * valid context during a call to [NSView drawRect]. To further
+ * complicate matters, cacheDisplayInRect calls [NSView drawRect].
+ * Essentially it is asking the view to draw a subrectangle of itself into
+ * a special graphics context which is linked to the BitmapImageRep. But
+ * our implementation of [NSView drawRect] does not allow recursive calls.
+ * If called recursively it returns immediately without doing any drawing.
+ * So the bottom line is that this function either returns a NULL pointer
+ * or a black image. To make it useful would require a significant amount
+ * of rewriting of the drawRect method. Perhaps the next release of OSX
+ * will include some more helpful ways of doing this.
+ *
* Results:
* Returns an NSBitmapRep representing the image of the given
* rectangle of the given drawable. This object is retained.
@@ -134,15 +153,16 @@ TkMacOSXBitmapRepFromDrawableRect(
unsigned int height)
{
MacDrawable *mac_drawable = (MacDrawable *) drawable;
- CGContextRef cg_context=NULL;
- CGImageRef cg_image=NULL, sub_cg_image=NULL;
- NSBitmapImageRep *bitmap_rep=NULL;
+ CGContextRef cg_context = NULL;
+ CGImageRef cg_image=NULL, sub_cg_image = NULL;
+ NSBitmapImageRep *bitmap_rep = NULL;
NSView *view=NULL;
if ( mac_drawable->flags & TK_IS_PIXMAP ) {
+
/*
- * This means that the MacDrawable is functioning as a
- * Tk Pixmap, so its view field is NULL.
- */
+ * This MacDrawable is a bitmap, so its view is NULL.
+ */
+
cg_context = TkMacOSXGetCGContextForDrawable(drawable);
CGRect image_rect = CGRectMake(x, y, width, height);
cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context);
@@ -155,22 +175,32 @@ TkMacOSXBitmapRepFromDrawableRect(
CGImageRelease(cg_image);
}
} else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) {
+
/*
* 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);
- if ( [view lockFocusIfCanDraw] ) {
- bitmap_rep = [NSBitmapImageRep alloc];
- bitmap_rep = [bitmap_rep initWithFocusedViewRect:view_rect];
- [view unlockFocus];
+ /*
+ * 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 mark the view as needing
+ * display and return NULL.
+ */
+
+ if (view == [NSView focusView]) {
+ bitmap_rep = [view bitmapImageRepForCachingDisplayInRect: view_rect];
+ [bitmap_rep retain];
+ [view cacheDisplayInRect:view_rect toBitmapImageRep:bitmap_rep];
} else {
- TkMacOSXDbgMsg("Could not lock focus on view.");
+ TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap.");
+ [view setNeedsDisplay:YES];
+ return NULL;
}
-
} else {
TkMacOSXDbgMsg("Invalid source drawable");
}
@@ -211,26 +241,24 @@ XCopyArea(
MacDrawable *srcDraw = (MacDrawable *) src;
NSBitmapImageRep *bitmap_rep = NULL;
CGImageRef img = NULL;
+ CGRect bounds, srcRect, dstRect;
display->request++;
-
if (!width || !height) {
- /* This happens all the time.
- TkMacOSXDbgMsg("Drawing of empty area requested");
- */
return;
}
if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
return;
- /*TkMacOSXDbgMsg("Failed to setup drawing context.");*/
+ TkMacOSXDbgMsg("Failed to setup drawing context.");
}
if ( dc.context ) {
if (srcDraw->flags & TK_IS_PIXMAP) {
img = TkMacOSXCreateCGImageWithDrawable(src);
}else if (TkMacOSXDrawableWindow(src)) {
- bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src, src_x, src_y, width, height);
+ bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src,
+ src_x, src_y, width, height);
if ( bitmap_rep ) {
img = [bitmap_rep CGImage];
}
@@ -239,13 +267,12 @@ XCopyArea(
}
if (img) {
- TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, gc->background,
- CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
- CGRectMake(src_x, src_y, width, height),
- CGRectMake(dest_x, dest_y, width, height));
+ bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
+ srcRect = CGRectMake(src_x, src_y, width, height);
+ dstRect = CGRectMake(dest_x, dest_y, width, height);
+ TkMacOSXDrawCGImage(dst, gc, dc.context, img,
+ gc->foreground, gc->background, bounds, srcRect, dstRect);
CFRelease(img);
-
-
} else {
TkMacOSXDbgMsg("Failed to construct CGImage.");
}
@@ -294,7 +321,7 @@ XCopyPlane(
TkMacOSXDrawingContext dc;
MacDrawable *srcDraw = (MacDrawable *) src;
MacDrawable *dstDraw = (MacDrawable *) dst;
-
+ CGRect bounds, srcRect, dstRect;
display->request++;
if (!width || !height) {
/* TkMacOSXDbgMsg("Drawing of empty area requested"); */
@@ -314,7 +341,7 @@ XCopyPlane(
TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
unsigned long imageBackground = gc->background;
if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP){
- CGRect srcRect = CGRectMake(src_x, src_y, width, height);
+ srcRect = CGRectMake(src_x, src_y, width, height);
CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(clipPtr->value.pixmap);
CGImageRef submask = CGImageCreateWithImageInRect(img, srcRect);
CGRect rect = CGRectMake(dest_x, dest_y, width, height);
@@ -339,10 +366,11 @@ XCopyPlane(
CGImageRelease(submask);
CGImageRelease(subimage);
} else {
- TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, imageBackground,
- CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
- CGRectMake(src_x, src_y, width, height),
- CGRectMake(dest_x, dest_y, width, height));
+ bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
+ srcRect = CGRectMake(src_x, src_y, width, height);
+ dstRect = CGRectMake(dest_x, dest_y, width, height);
+ TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground,
+ imageBackground, bounds, srcRect, dstRect);
CGImageRelease(img);
}
} else { /* no image */
@@ -446,10 +474,8 @@ TkMacOSXGetNSImageWithTkImage(
int height)
{
Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);
- MacDrawable *macDraw = (MacDrawable *) pixmap;
NSImage *nsImage;
- macDraw->flags |= TK_USE_XIMAGE_ALPHA;
Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);
nsImage = CreateNSImageWithPixmap(pixmap, width, height);
Tk_FreePixmap(display, pixmap);
@@ -602,11 +628,13 @@ TkMacOSXDrawCGImage(
}
}
dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff);
-
if (CGImageIsMask(image)) {
- /*CGContextSaveGState(context);*/
if (macDraw->flags & TK_IS_BW_PIXMAP) {
- /* Set fill color to black, background comes from the context, or is transparent. */
+
+ /* Set fill color to black; background comes from the context,
+ * or is transparent.
+ */
+
if (imageBackground != TRANSPARENT_PIXEL << 24) {
CGContextClearRect(context, dstBounds);
}
@@ -1454,7 +1482,7 @@ TkMacOSXSetUpGraphicsPort(
*----------------------------------------------------------------------
*/
-int
+Bool
TkMacOSXSetupDrawingContext(
Drawable d,
GC gc,
@@ -1462,38 +1490,69 @@ TkMacOSXSetupDrawingContext(
TkMacOSXDrawingContext *dcPtr)
{
MacDrawable *macDraw = ((MacDrawable*)d);
- int dontDraw = 0, isWin = 0;
+ Bool canDraw = true;
+ NSWindow *win = NULL;
TkMacOSXDrawingContext dc = {};
CGRect clipBounds;
- dc.clipRgn = TkMacOSXGetClipRgn(d);
- if (!dontDraw) {
- ClipToGC(d, gc, &dc.clipRgn);
- dontDraw = dc.clipRgn ? HIShapeIsEmpty(dc.clipRgn) : 0;
- }
- if (dontDraw) {
- goto end;
+ /*
+ * If we are simulating drawing for tests, just return false.
+ */
+
+ if ([NSApp simulateDrawing]) {
+ return false;
}
- if (useCG) {
- dc.context = TkMacOSXGetCGContextForDrawable(d);
+
+ /*
+ * If the drawable is not a pixmap and it has an associated
+ * NSWindow then we know we are drawing to a window.
+ */
+
+ if (!(macDraw->flags & TK_IS_PIXMAP)) {
+ win = TkMacOSXDrawableWindow(d);
}
- if (!dc.context || !(macDraw->flags & TK_IS_PIXMAP)) {
- isWin = (TkMacOSXDrawableWindow(d) != nil);
+
+ /*
+ * Check that we have a non-empty clipping region.
+ */
+
+ dc.clipRgn = TkMacOSXGetClipRgn(d);
+ ClipToGC(d, gc, &dc.clipRgn);
+ if (dc.clipRgn && HIShapeIsEmpty(dc.clipRgn)) {
+ canDraw = false;
+ goto end;
}
+
+ /*
+ * If we already have a CGContext, use it. Otherwise, if we
+ * are drawing to a window then we can get one from the
+ * window.
+ */
+
+ dc.context = TkMacOSXGetCGContextForDrawable(d);
if (dc.context) {
dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
- } else if (isWin) {
+ } else if (win) {
NSView *view = TkMacOSXDrawableView(macDraw);
if (view) {
- if (view != [NSView focusView]) {
- dc.focusLocked = [view lockFocusIfCanDraw];
- dontDraw = !dc.focusLocked;
- } else {
- dontDraw = ![view canDraw];
- }
- if (dontDraw) {
- goto end;
- }
+
+ /*
+ * We can only draw into the view when the current CGContext is
+ * valid and belongs to the view. Validity can only be guaranteed
+ * inside of a view's drawRect or setFrame methods. The isDrawing
+ * attribute tells us whether we are being called from one of those
+ * methods.
+ *
+ * If the CGContext is not valid, or belongs to a different View,
+ * then we mark our view as needing display and return failure.
+ * It should get drawn in a later call to drawRect.
+ */
+
+ if (view != [NSView focusView]) {
+ [view setNeedsDisplay:YES];
+ canDraw = false;
+ goto end;
+ }
dc.view = view;
dc.context = GET_CGCONTEXT;
dc.portBounds = NSRectToCGRect([view bounds]);
@@ -1508,14 +1567,17 @@ TkMacOSXSetupDrawingContext(
Tcl_Panic("TkMacOSXSetupDrawingContext(): "
"no context to draw into !");
}
+
+ /*
+ * Configure the drawing context.
+ */
+
if (dc.context) {
CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
.ty = dc.portBounds.size.height};
dc.portBounds.origin.x += macDraw->xOff;
dc.portBounds.origin.y += macDraw->yOff;
- if (!dc.focusLocked) {
- CGContextSaveGState(dc.context);
- }
+ CGContextSaveGState(dc.context);
CGContextSetTextDrawingMode(dc.context, kCGTextFill);
CGContextConcatCTM(dc.context, t);
if (dc.clipRgn) {
@@ -1550,7 +1612,7 @@ TkMacOSXSetupDrawingContext(
double w = gc->line_width;
TkMacOSXSetColorInContext(gc, gc->foreground, dc.context);
- if (isWin) {
+ if (win) {
CGContextSetPatternPhase(dc.context, CGSizeMake(
dc.portBounds.size.width, dc.portBounds.size.height));
}
@@ -1588,13 +1650,21 @@ TkMacOSXSetupDrawingContext(
}
}
}
+
end:
- if (dontDraw && dc.clipRgn) {
+#ifdef TK_MAC_DEBUG_DRAWING
+ if (!canDraw && win != NULL) {
+ TkWindow *winPtr = TkMacOSXGetTkWindow(win);
+ if (winPtr) fprintf(stderr, "Cannot draw in %s - postponing.\n",
+ Tk_PathName(winPtr));
+ }
+#endif
+ if (!canDraw && dc.clipRgn) {
CFRelease(dc.clipRgn);
dc.clipRgn = NULL;
}
*dcPtr = dc;
- return !dontDraw;
+ return canDraw;
}
/*
@@ -1619,12 +1689,7 @@ TkMacOSXRestoreDrawingContext(
{
if (dcPtr->context) {
CGContextSynchronize(dcPtr->context);
- [[dcPtr->view window] setViewsNeedDisplay:YES];
- if (dcPtr->focusLocked) {
- [dcPtr->view unlockFocus];
- } else {
- CGContextRestoreGState(dcPtr->context);
- }
+ CGContextRestoreGState(dcPtr->context);
}
if (dcPtr->clipRgn) {
CFRelease(dcPtr->clipRgn);
@@ -1663,17 +1728,13 @@ TkMacOSXGetClipRgn(
#ifdef TK_MAC_DEBUG_DRAWING
TkMacOSXDbgMsg("%s", macDraw->winPtr->pathName);
NSView *view = TkMacOSXDrawableView(macDraw);
- if ([view lockFocusIfCanDraw]) {
- CGContextRef context = GET_CGCONTEXT;
- CGContextSaveGState(context);
- CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0,
- -1.0, 0.0, [view bounds].size.height));
- ChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context);
- CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1);
- CGContextEOFillPath(context);
- CGContextRestoreGState(context);
- [view unlockFocus];
- }
+ CGContextSaveGState(context);
+ CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0,
+ -1.0, 0.0, [view bounds].size.height));
+ ChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context);
+ CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1);
+ CGContextEOFillPath(context);
+ CGContextRestoreGState(context);
#endif /* TK_MAC_DEBUG_DRAWING */
}
@@ -1733,13 +1794,11 @@ TkpClipDrawableToRect(
int width, int height)
{
MacDrawable *macDraw = (MacDrawable *) d;
- NSView *view = TkMacOSXDrawableView(macDraw);
if (macDraw->drawRgn) {
CFRelease(macDraw->drawRgn);
macDraw->drawRgn = NULL;
}
-
if (width >= 0 && height >= 0) {
CGRect clipRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff,
width, height);
@@ -1755,17 +1814,6 @@ TkpClipDrawableToRect(
} else {
macDraw->drawRgn = drawRgn;
}
- if (view && view != [NSView focusView] && [view lockFocusIfCanDraw]) {
- clipRect.origin.y = [view bounds].size.height -
- (clipRect.origin.y + clipRect.size.height);
- NSRectClip(NSRectFromCGRect(clipRect));
- macDraw->flags |= TK_FOCUSED_VIEW;
- }
- } else {
- if (view && (macDraw->flags & TK_FOCUSED_VIEW)) {
- [view unlockFocus];
- macDraw->flags &= ~TK_FOCUSED_VIEW;
- }
}
}
diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c
index 25c0bea36..798c73ca0 100644
--- a/macosx/tkMacOSXEvent.c
+++ b/macosx/tkMacOSXEvent.c
@@ -112,11 +112,16 @@ enum {
*
* TkMacOSXFlushWindows --
*
- * This routine is a stub called by XSync, which is called during
- * the Tk update command. It calls displayIfNeeded on all visible
- * windows. This is necessary in order to insure that update will
- * run all of the display procedures which have been registered as
- * idle tasks. The test suite assumes that this is the case.
+ * This routine is a stub called by XSync, which is called during the Tk
+ * update command. The language specification does not require that the
+ * update command be synchronous but many of the tests assume that is the
+ * case. It is not naturally the case on macOS since many idle tasks are
+ * run inside of the drawRect method of a window's contentView, and that
+ * method will not be called until after this function returns. To make
+ * the tests work, we attempt to force this to be synchronous by waiting
+ * until drawRect has been called for each window. The mechanism we use
+ * for this is to have drawRect post an ApplicationDefined NSEvent on the
+ * AppKit event queue when it finishes drawing, and wait for it here.
*
* Results:
* None.
@@ -132,13 +137,15 @@ MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
NSArray *macWindows = [NSApp orderedWindows];
-
+ if ([NSApp simulateDrawing]) {
+ [NSApp setSimulateDrawing:NO];
+ return;
+ }
for (NSWindow *w in macWindows) {
- if (TkMacOSXGetXWindow(w)) {
- [w displayIfNeeded];
- }
+ if (TkMacOSXGetXWindow(w)) {
+ [w displayIfNeeded];
+ }
}
-
}
diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c
index 096faac71..a5c870adb 100644
--- a/macosx/tkMacOSXImage.c
+++ b/macosx/tkMacOSXImage.c
@@ -6,7 +6,7 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2005-2009 Daniel A. Steffen <[email protected]>
- * Copyright 2017 Marc Culler.
+ * Copyright 2017-2018 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -29,7 +29,8 @@ _XInitImageFuncPtrs(
*
* TkMacOSXCreateCGImageWithXImage --
*
- * Create CGImage from XImage, copying the image data.
+ * Create CGImage from XImage, copying the image data. Called
+ * in Tk_PutImage and (currently) nowhere else.
*
* Results:
* CGImage, release after use.
@@ -46,8 +47,7 @@ static void ReleaseData(void *info, const void *data, size_t size) {
CGImageRef
TkMacOSXCreateCGImageWithXImage(
- XImage *image,
- int use_ximage_alpha)
+ XImage *image)
{
CGImageRef img = NULL;
size_t bitsPerComponent, bitsPerPixel;
@@ -88,21 +88,17 @@ TkMacOSXCreateCGImageWithXImage(
bitsPerPixel, image->bytes_per_line, provider, decode, 0);
}
} else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
+
/*
* Color image
*/
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
-
bitsPerComponent = 8;
bitsPerPixel = 32;
bitmapInfo = (image->byte_order == MSBFirst ?
- kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little);
- if (use_ximage_alpha) {
- bitmapInfo |= kCGImageAlphaPremultipliedFirst;
- } else {
- bitmapInfo |= kCGImageAlphaNoneSkipFirst;
- }
+ kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big);
+ bitmapInfo |= kCGImageAlphaLast;
data = memcpy(ckalloc(len), image->data + image->xoffset, len);
if (data) {
provider = CGDataProviderCreateWithData(data, data, len, releaseData);
@@ -128,7 +124,12 @@ TkMacOSXCreateCGImageWithXImage(
*
* XGetImage --
*
- * This function copies data from a pixmap or window into an XImage.
+ * This function copies data from a pixmap or window into an XImage. It
+ * is essentially never used. At one time it was called by
+ * pTkImgPhotoDisplay, but that is no longer the case. Currently it is
+ * called two places, one of which is requesting an XY image which we do
+ * not support. It probably does not work correctly -- see the comments
+ * for TkMacOSXBitmapRepFromDrawableRect.
*
* Results:
* Returns a newly allocated XImage containing the data from the given
@@ -165,7 +166,6 @@ XGetImage(
unsigned int bytes_per_row, size, row, n, m;
unsigned int scalefactor=1, scaled_height=height, scaled_width=width;
NSWindow *win = TkMacOSXDrawableWindow(drawable);
- MacDrawable *macDraw = ((MacDrawable*)drawable);
static enum {unknown, no, yes} has_retina = unknown;
if (win && has_retina == unknown) {
@@ -178,9 +178,11 @@ XGetImage(
}
if (has_retina == yes) {
+
/*
* We only allow scale factors 1 or 2, as Apple currently does.
*/
+
#ifdef __clang__
scalefactor = [win backingScaleFactor] == 2.0 ? 2 : 1;
#endif
@@ -192,8 +194,9 @@ XGetImage(
if (width == 0 || height == 0) {
return NULL;
}
+
bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable,
- x, y, width, height);
+ x, y, width, height);
if (!bitmap_rep) {
TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
return NULL;
@@ -206,39 +209,24 @@ XGetImage(
(bitmap_fmt != 0 && bitmap_fmt != 1) ||
[bitmap_rep samplesPerPixel] != 4 ||
[bitmap_rep isPlanar] != 0 ||
- bytes_per_row != 4 * scaled_width ||
+ bytes_per_row < 4 * scaled_width ||
size != bytes_per_row*scaled_height ) {
TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
CFRelease(bitmap_rep);
return NULL;
}
-
- if (macDraw->flags & TK_USE_XIMAGE_ALPHA) {
- /*
- * When called by TkImgPhotoDisplay we are being asked to return a
- * background image to be blended with the photoimage using its
- * alpha channel, if it has one. Returning a black pixmap here
- * makes TkImgPhotoDisplay create an XImage with a premultiplied
- * alpha channel, as favored by Apple. When TkImgPhotoDisplay
- * passes this XImage to TkPutImage, targeting a pixmap, it creates
- * an image with correct transparency. This is used, for example,
- * when creating an iconphoto or a menu image from a PNG
- * photoimage.
- */
- bzero(bitmap, size);
- } else {
- memcpy(bitmap, (char *)[bitmap_rep bitmapData], size);
- }
+ memcpy(bitmap, (char *)[bitmap_rep bitmapData], size);
CFRelease(bitmap_rep);
/*
* When Apple extracts a bitmap from an NSView, it may be in
* either BGRA or ABGR format. For an XImage we need RGBA.
*/
+
struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr;
- for (row=0, n=0; row<scaled_height; row++, n+=bytes_per_row) {
- for (m=n; m<n+bytes_per_row; m+=4) {
+ for (row = 0, n = 0; row < scaled_height; row++, n += bytes_per_row) {
+ for (m = n; m < n + 4*scaled_width; m += 4) {
R = *(bitmap + m + pixel.r);
G = *(bitmap + m + pixel.g);
B = *(bitmap + m + pixel.b);
@@ -514,8 +502,9 @@ XCreateImage(
*
* TkPutImage --
*
- * Copies a subimage from an in-memory image to a rectangle of
- * of the specified drawable.
+ * Copies a rectangular subimage of an XImage into a drawable.
+ * Currently this is only called by TkImgPhotoDisplay, using
+ * a Window as the drawable.
*
* Results:
* None.
@@ -542,23 +531,38 @@ TkPutImage(
unsigned int height) /* distination and source. */
{
TkMacOSXDrawingContext dc;
- MacDrawable *macDraw = ((MacDrawable*)drawable);
+ MacDrawable *macDraw = (MacDrawable *) drawable;
display->request++;
if (!TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc)) {
return BadDrawable;
}
if (dc.context) {
- CGImageRef img = TkMacOSXCreateCGImageWithXImage(image,
- macDraw->flags & TK_USE_XIMAGE_ALPHA);
+ CGRect bounds, srcRect, dstRect;
+ CGImageRef img = TkMacOSXCreateCGImageWithXImage(image);
+
+ /*
+ * The CGContext for a pixmap is RGB only, with A = 0.
+ */
+
+ if (!(macDraw->flags & TK_IS_PIXMAP)) {
+ CGContextSetBlendMode(dc.context, kCGBlendModeSourceAtop);
+ }
if (img) {
- /* If the XImage has big pixels, rescale the source dimensions.*/
+
+ /* If the XImage has big pixels, the source is rescaled to reflect
+ * the actual pixel dimensions. This is not currently used, but
+ * could arise if the image were copied from a retina monitor and
+ * redrawn on an ordinary monitor.
+ */
+
int pp = image->pixelpower;
+ bounds = CGRectMake(0, 0, image->width, image->height);
+ srcRect = CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp);
+ dstRect = CGRectMake(dest_x, dest_y, width, height);
TkMacOSXDrawCGImage(drawable, gc, dc.context,
- img, gc->foreground, gc->background,
- CGRectMake(0, 0, image->width<<pp, image->height<<pp),
- CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp),
- CGRectMake(dest_x, dest_y, width, height));
+ img, gc->foreground, gc->background,
+ bounds, srcRect, dstRect);
CFRelease(img);
} else {
TkMacOSXDbgMsg("Invalid source drawable");
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index 10ef87efc..8e9c60010 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -47,6 +47,7 @@ static char scriptPath[PATH_MAX + 1] = "";
@synthesize poolLock = _poolLock;
@synthesize macMinorVersion = _macMinorVersion;
@synthesize isDrawing = _isDrawing;
+@synthesize simulateDrawing = _simulateDrawing;
@end
/*
@@ -162,13 +163,14 @@ static char scriptPath[PATH_MAX + 1] = "";
systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
minorVersion = systemVersion.minorVersion;
#endif
- [NSApp setMacMinorVersion: minorVersion];
+ [NSApp setMacMinorVersion: minorVersion];
/*
* We are not drawing yet.
*/
- [NSApp setIsDrawing: NO];
+ [NSApp setIsDrawing:NO];
+ [NSApp setSimulateDrawing:NO];
/*
* Be our own delegate.
@@ -178,6 +180,7 @@ static char scriptPath[PATH_MAX + 1] = "";
/*
* Make sure we are allowed to open windows.
*/
+
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
/*
diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h
index f4859ff88..4e1e689b6 100644
--- a/macosx/tkMacOSXInt.h
+++ b/macosx/tkMacOSXInt.h
@@ -83,11 +83,10 @@ typedef struct TkWindowPrivate MacDrawable;
#define TK_CLIP_INVALID 0x02
#define TK_HOST_EXISTS 0x04
#define TK_DRAWN_UNDER_MENU 0x08
-#define TK_FOCUSED_VIEW 0x10
-#define TK_IS_PIXMAP 0x20
-#define TK_IS_BW_PIXMAP 0x40
-#define TK_DO_NOT_DRAW 0x80
-#define TK_USE_XIMAGE_ALPHA 0x100
+#define TK_IS_PIXMAP 0x10
+#define TK_IS_BW_PIXMAP 0x20
+#define TK_DO_NOT_DRAW 0x40
+
/*
* I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags
* This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the
@@ -201,6 +200,7 @@ MODULE_SCOPE void TkpReleaseRegion(TkRegion r);
MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
MODULE_SCOPE Bool TkpAppIsDrawing(void);
MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin);
+MODULE_SCOPE void TkTestSimulateDrawing(Bool);
/*
* Include the stubbed internal platform-specific API.
diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c
index f79185e85..31fffa15a 100644
--- a/macosx/tkMacOSXKeyEvent.c
+++ b/macosx/tkMacOSXKeyEvent.c
@@ -68,15 +68,19 @@ unsigned short releaseCode;
processingCompose = NO;
}
+ w = [theEvent window];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(w);
+ Tk_Window tkwin = (Tk_Window) winPtr;
+ XEvent xEvent;
+
+ if (!winPtr) {
+ return theEvent;
+ }
+
switch (type) {
case NSKeyUp:
-
/*Fix for bug #1ba71a86bb: key release firing on key press.*/
- w = [theEvent window];
- XEvent xEvent;
setupXEvent(&xEvent, w, 0);
- TkWindow *winPtr = TkMacOSXGetTkWindow(w);
- Tk_Window tkwin = (Tk_Window) winPtr;
xEvent.xany.type = KeyRelease;
xEvent.xkey.keycode = releaseCode;
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
@@ -88,8 +92,7 @@ unsigned short releaseCode;
case NSFlagsChanged:
modifiers = [theEvent modifierFlags];
keyCode = [theEvent keyCode];
- // w = [self windowWithWindowNumber:[theEvent windowNumber]];
- w = [theEvent window];
+
#if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1
TKLog(@"-[%@(%p) %s] r=%d mods=%u '%@' '%@' code=%u c=%d %@ %d", [self class], self, _cmd, repeat, modifiers, characters, charactersIgnoringModifiers, keyCode,([charactersIgnoringModifiers length] == 0) ? 0 : [charactersIgnoringModifiers characterAtIndex: 0], w, type);
#endif
@@ -431,6 +434,9 @@ setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
{
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
+ if (!winPtr) {
+ return;
+ }
memset(xEvent, 0, sizeof(XEvent));
xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c
index a85e57273..1acefe51a 100644
--- a/macosx/tkMacOSXMenubutton.c
+++ b/macosx/tkMacOSXMenubutton.c
@@ -843,3 +843,11 @@ TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr)
return 1;
}
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/macosx/tkMacOSXMenus.c b/macosx/tkMacOSXMenus.c
index f8f00a62b..15dbad4f3 100644
--- a/macosx/tkMacOSXMenus.c
+++ b/macosx/tkMacOSXMenus.c
@@ -379,13 +379,13 @@ GenerateEditEvent(
XVirtualEvent event;
int x, y;
TkWindow *winPtr = TkMacOSXGetTkWindow([NSApp keyWindow]);
- Tk_Window tkwin = (Tk_Window) winPtr;
+ Tk_Window tkwin;
- if (tkwin == NULL) {
+ if (!winPtr) {
return;
}
tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
- if (tkwin == NULL) {
+ if (!tkwin) {
return;
}
bzero(&event, sizeof(XVirtualEvent));
diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c
index e2769269d..7cbd24830 100644
--- a/macosx/tkMacOSXNotify.c
+++ b/macosx/tkMacOSXNotify.c
@@ -169,7 +169,7 @@ void DebugPrintQueue(void)
*----------------------------------------------------------------------
*/
-static NSString *
+NSString *
GetRunLoopMode(NSModalSession modalSession)
{
NSString *runLoopMode = nil;
diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h
index 197879f1b..d804ca063 100644
--- a/macosx/tkMacOSXPrivate.h
+++ b/macosx/tkMacOSXPrivate.h
@@ -131,7 +131,6 @@ typedef struct TkMacOSXDrawingContext {
NSView *view;
HIShapeRef clipRgn;
CGRect portBounds;
- int focusLocked;
} TkMacOSXDrawingContext;
/*
@@ -190,8 +189,7 @@ MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window);
MODULE_SCOPE EventModifiers TkMacOSXModifierState(void);
MODULE_SCOPE NSBitmapImageRep* TkMacOSXBitmapRepFromDrawableRect(Drawable drawable,
int x, int y, unsigned int width, unsigned int height);
-MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image,
- int use_ximage_alpha);
+MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image);
MODULE_SCOPE void TkMacOSXDrawCGImage(Drawable d, GC gc, CGContextRef context,
CGImageRef image, unsigned long imageForeground,
unsigned long imageBackground, CGRect imageBounds,
@@ -267,11 +265,13 @@ VISIBILITY_HIDDEN
int _poolLock;
int _macMinorVersion;
Bool _isDrawing;
+ Bool _simulateDrawing;
#endif
}
@property int poolLock;
@property int macMinorVersion;
@property Bool isDrawing;
+@property Bool simulateDrawing;
@end
@interface TKApplication(TKInit)
@@ -333,9 +333,7 @@ VISIBILITY_HIDDEN
@interface TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect;
-- (void) generateExposeEvents: (HIShapeRef) shape;
-- (void) viewDidChangeEffectiveAppearance;
-- (void) updateAppearanceEvent;
+- (void) generateExposeEvents: (HIShapeRef) shape;
- (void) tkToolbarButton: (id) sender;
- (BOOL) isOpaque;
- (BOOL) wantsDefaultClipping;
diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c
index 1882ce62e..5576c44af 100644
--- a/macosx/tkMacOSXTest.c
+++ b/macosx/tkMacOSXTest.c
@@ -79,6 +79,35 @@ DebuggerObjCmd(
return TCL_OK;
}
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkTestSimulateDrawing --
+ *
+ * A test widget display procedure which records calls can use this to
+ * avoid duplicate calls which would occur due to fact that no valid
+ * graphics context is available to the idle task which is running the
+ * display proc. Note that no actual drawing to the screen will take
+ * place when this flag is set. This is just a wrapper for the NSApp
+ * property.
+ *
+ *
+ * Results:
+ * Calls to low level drawing routines will return without actually
+ * drawing anything to the screen.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+MODULE_SCOPE void
+TkTestSimulateDrawing(Bool yesno) {
+ [NSApp setSimulateDrawing:yesno];
+}
+
+
+
/*
* Local Variables:
* mode: objc
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index 3e2231160..5bb42ae50 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -832,13 +832,20 @@ ConfigureRestrictProc(
Tk_PathName(winPtr));
#endif
+ if ([NSApp simulateDrawing]) {
+ return;
+ }
+
/*
- * We do not allow recursive calls to drawRect.
+ * We do not allow recursive calls to drawRect, but we only log
+ * them on OSX > 10.13, where they should never happen.
*/
- if ([NSApp isDrawing]) {
+
+ if ([NSApp isDrawing] && [NSApp macMinorVersion] > 13) {
TKLog(@"WARNING: a recursive call to drawRect was aborted.");
return;
}
+
[NSApp setIsDrawing: YES];
[self getRectsBeingDrawn:&rectsBeingDrawn count:&rectsBeingDrawnCount];
@@ -863,7 +870,6 @@ ConfigureRestrictProc(
#ifdef TK_MAC_DEBUG_DRAWING
fprintf(stderr, "drawRect: done.\n");
#endif
-
}
-(void) setFrameSize: (NSSize)newsize
@@ -873,6 +879,12 @@ ConfigureRestrictProc(
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
if (winPtr) {
+ /* On OSX versions below 10.14 setFrame calls drawRect.
+ * On 10.14 it does its own drawing.
+ */
+ if ([NSApp macMinorVersion] > 13) {
+ [NSApp setIsDrawing:YES];
+ }
unsigned int width = (unsigned int)newsize.width;
unsigned int height=(unsigned int)newsize.height;
ClientData oldArg;
@@ -910,13 +922,18 @@ ConfigureRestrictProc(
TkMacOSXUpdateClipRgn(winPtr);
/*
- * Finally, generate and process expose events to redraw the window.
+ * Generate and process expose events to redraw the window.
*/
HIRect bounds = NSRectToCGRect([self bounds]);
HIShapeRef shape = HIShapeCreateWithRect(&bounds);
[self generateExposeEvents: shape];
[w displayIfNeeded];
+
+ /*
+ * Finally, unlock the main autoreleasePool.
+ */
+
[NSApp _unlockAutoreleasePool];
}
}
@@ -973,34 +990,30 @@ ConfigureRestrictProc(
*
* Fortunately, Tk schedules all drawing to be done while Tcl is idle.
* So we can do the drawing by processing all of the idle events that
- * were created when the expose events were processed. Unfortunately
- * this does not work in macOS 10.13.
+ * were created when the expose events were processed.
*/
- if ([NSApp macMinorVersion] > 13 || [self inLiveResize]) {
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
- }
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
}
}
-
/*
- * These two methods allow Tk to register a virtual event which fires when the
- * appearance changes on 10.14.
+ * This method is called when a user changes between light and dark mode.
+ * The implementation here generates a Tk virtual event which can be bound
+ * to a function that redraws the window in an appropriate style.
*/
- (void) viewDidChangeEffectiveAppearance
{
- [self updateAppearanceEvent];
-}
-
-- (void) updateAppearanceEvent
-{
+ XVirtualEvent event;
+ int x, y;
NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
NSWindow *w = [self window];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
- XVirtualEvent event;
- int x, y;
Tk_Window tkwin = (Tk_Window) winPtr;
+
+ if (!winPtr) {
+ return;
+ }
bzero(&event, sizeof(XVirtualEvent));
event.type = VirtualEvent;
event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
@@ -1040,6 +1053,9 @@ ConfigureRestrictProc(
int x, y;
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
Tk_Window tkwin = (Tk_Window) winPtr;
+ if (!winPtr){
+ return;
+ }
bzero(&event, sizeof(XVirtualEvent));
event.type = VirtualEvent;
event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index 5dcc07586..9e45996cc 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.c
@@ -403,6 +403,9 @@ NSStatusItem *exitFullScreen;
- (void)toggleFullScreen:(id)sender
{
TkWindow *winPtr = TkMacOSXGetTkWindow(self);
+ if (!winPtr) {
+ return;
+ }
Tcl_Interp *interp = Tk_Interp((Tk_Window)winPtr);
if ([NSApp macMinorVersion] > 12) {
if (([self styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask) {
@@ -415,13 +418,15 @@ NSStatusItem *exitFullScreen;
}
}
--(void)restoreOldScreen:(id)sender {
-
- TkWindow *winPtr = TkMacOSXGetTkWindow(self);
- Tcl_Interp *interp = Tk_Interp((Tk_Window)winPtr);
-
- TkMacOSXMakeFullscreen(winPtr, self, 0, interp);
- [[NSStatusBar systemStatusBar] removeStatusItem: exitFullScreen];
+-(void)restoreOldScreen:(id)sender
+{
+ TkWindow *winPtr = TkMacOSXGetTkWindow(self);
+ if (!winPtr) {
+ return;
+ }
+ Tcl_Interp *interp = Tk_Interp((Tk_Window)winPtr);
+ TkMacOSXMakeFullscreen(winPtr, self, 0, interp);
+ [[NSStatusBar systemStatusBar] removeStatusItem: exitFullScreen];
}
@end
@@ -431,14 +436,15 @@ NSStatusItem *exitFullScreen;
- (BOOL) canBecomeKeyWindow
{
TkWindow *winPtr = TkMacOSXGetTkWindow(self);
-
- return (winPtr && winPtr->wmInfoPtr && (winPtr->wmInfoPtr->macClass ==
- kHelpWindowClass || winPtr->wmInfoPtr->attributes &
- kWindowNoActivatesAttribute)) ? NO : YES;
+ if (!winPtr) {
+ return NO;
+ }
+ return (winPtr->wmInfoPtr &&
+ (winPtr->wmInfoPtr->macClass == kHelpWindowClass ||
+ winPtr->wmInfoPtr->attributes & kWindowNoActivatesAttribute)
+ ) ? NO : YES;
}
-
-
#if DEBUG_ZOMBIES
- (id) retain
{
@@ -462,7 +468,8 @@ NSStatusItem *exitFullScreen;
title = "unnamed window";
}
if (DEBUG_ZOMBIES > 1){
- printf("Autoreleased <%s>. Count is %lu\n", title, [self retainCount]);
+ fprintf(stderr, "Autoreleased <%s>. Count is %lu\n",
+ title, [self retainCount]);
}
return result;
}
@@ -473,7 +480,8 @@ NSStatusItem *exitFullScreen;
title = "unnamed window";
}
if (DEBUG_ZOMBIES > 1){
- printf("Releasing <%s>. Count is %lu\n", title, [self retainCount]);
+ fprintf(stderr, "Releasing <%s>. Count is %lu\n",
+ title, [self retainCount]);
}
[super release];
}
@@ -484,7 +492,8 @@ NSStatusItem *exitFullScreen;
title = "unnamed window";
}
if (DEBUG_ZOMBIES > 0){
- printf(">>>> Freeing <%s>. Count is %lu\n", title, [self retainCount]);
+ fprintf(stderr, ">>>> Freeing <%s>. Count is %lu\n",
+ title, [self retainCount]);
}
[super dealloc];
}
@@ -605,15 +614,15 @@ FrontWindowAtPoint(
{
NSPoint p = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
NSArray *windows = [NSApp orderedWindows];
- TkWindow *front = NULL;
+ TkWindow *winPtr = NULL;
for (NSWindow *w in windows) {
- if (w && NSMouseInRect(p, [w frame], NO)) {
- front = TkMacOSXGetTkWindow(w);
- break;
- }
+ winPtr = TkMacOSXGetTkWindow(w);
+ if (winPtr && NSMouseInRect(p, [w frame], NO)) {
+ break;
}
- return front;
+ }
+ return winPtr;
}
/*
@@ -741,7 +750,6 @@ TkWmMapWindow(
* mapped. */
{
WmInfo *wmPtr = winPtr->wmInfoPtr;
-
if (wmPtr->flags & WM_NEVER_MAPPED) {
/*
* Create the underlying Mac window for this Tk window.
@@ -5677,7 +5685,7 @@ TkMacOSXMakeRealWindowExist(
geometry.size.height += structureRect.size.height;
geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y +
geometry.size.height);
- [window setFrame:geometry display:NO];
+ [window setFrame:geometry display:YES];
TkMacOSXRegisterOffScreenWindow((Window) macWin, window);
macWin->flags |= TK_HOST_EXISTS;
}
diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c
index 17cbc46b6..cc98e84a8 100644
--- a/macosx/tkMacOSXXStubs.c
+++ b/macosx/tkMacOSXXStubs.c
@@ -3,7 +3,7 @@
*
* This file contains most of the X calls called by Tk. Many of these
* calls are just stubs and either don't make sense on the Macintosh or
- * their implamentation just doesn't do anything. Other calls will
+ * their implementation just doesn't do anything. Other calls will
* eventually be moved into other files.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
@@ -203,7 +203,6 @@ TkpOpenDisplay(
screen->root_visual = ckalloc(sizeof(Visual));
screen->root_visual->visualid = 0;
screen->root_visual->class = TrueColor;
- screen->root_visual->alpha_mask = 0xFF000000;
screen->root_visual->red_mask = 0x00FF0000;
screen->root_visual->green_mask = 0x0000FF00;
screen->root_visual->blue_mask = 0x000000FF;
diff --git a/tests/option.test b/tests/option.test
index ea5b5d115..c8e29da61 100644
--- a/tests/option.test
+++ b/tests/option.test
@@ -386,7 +386,7 @@ test option-15.6 {database files} -body {
test option-15.7 {database files} -body {
option read $option1
option get . x9 color
-} -result " \t\\A\n"
+} -result " \\\t\\A\n"
test option-15.8 {database files} -body {
option read $option1 widget foo
} -returnCodes error -result {wrong # args: should be "option readfile fileName ?priority?"}
@@ -415,6 +415,22 @@ test option-16.1 {ReadOptionFile} -body {
removeFile $option4
} -result {true false}
+set opt162val {label {
+ foo bar
+}
+}
+set opt162list [split $opt162val \n]
+
+test option-16.2 {ticket 766ef52f3} {
+ set option5 [makeFile {} option.file4]
+ set file [open $option5 w]
+ fconfigure $file -translation crlf
+ puts $file "*notok: $opt162list"
+ close $file
+ option read $option5 userDefault
+ option get . notok notok
+} $opt162list
+
deleteWindows
# cleanup
diff --git a/xlib/X11/Xlib.h b/xlib/X11/Xlib.h
index b027e286c..8d8ec686b 100644
--- a/xlib/X11/Xlib.h
+++ b/xlib/X11/Xlib.h
@@ -203,9 +203,6 @@ typedef struct {
int class; /* class of screen (monochrome, etc.) */
#endif
unsigned long red_mask, green_mask, blue_mask; /* mask values */
-#if defined(MAC_OSX_TK)
- unsigned long alpha_mask;
-#endif
int bits_per_rgb; /* log base 2 of distinct color values */
int map_entries; /* color map entries */
} Visual;
@@ -335,7 +332,6 @@ typedef struct _XImage {
XPointer obdata; /* hook for the object routines to hang on */
#if defined(MAC_OSX_TK)
int pixelpower; /* n such that pixels are 2^n x 2^n blocks*/
- unsigned long alpha_mask;
#endif
struct funcs { /* image manipulation routines */
struct _XImage *(*create_image)();