diff options
-rw-r--r-- | generic/tkFont.c | 15 | ||||
-rw-r--r-- | library/demos/unicodeout.tcl | 4 | ||||
-rw-r--r-- | macosx/tkMacOSXClipboard.c | 33 | ||||
-rw-r--r-- | macosx/tkMacOSXDraw.c | 7 | ||||
-rw-r--r-- | macosx/tkMacOSXFont.c | 172 | ||||
-rw-r--r-- | macosx/tkMacOSXKeyEvent.c | 56 | ||||
-rw-r--r-- | macosx/tkMacOSXPrivate.h | 4 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.c | 88 | ||||
-rw-r--r-- | macosx/ttkMacOSXTheme.c | 17 | ||||
-rw-r--r-- | tests/wm.test | 20 | ||||
-rw-r--r-- | unix/tkUnixWm.c | 9 | ||||
-rw-r--r-- | win/tkWinWm.c | 28 |
12 files changed, 293 insertions, 160 deletions
diff --git a/generic/tkFont.c b/generic/tkFont.c index 86fdd87..156ebf3 100644 --- a/generic/tkFont.c +++ b/generic/tkFont.c @@ -13,7 +13,9 @@ #include "tkInt.h" #include "tkFont.h" - +#if defined(MAC_OSX_TK) +#include "tkMacOSXInt.h" +#endif /* * The following structure is used to keep track of all the fonts that exist * in the current application. It must be stored in the TkMainInfo for the @@ -872,7 +874,18 @@ TheWorldHasChanged( ClientData clientData) /* Info about application's fonts. */ { TkFontInfo *fiPtr = clientData; +#if defined(MAC_OSX_TK) + /* + * On macOS it is catastrophic to recompute all widgets while the + * [NSView drawRect] method is drawing. The best that we can do in + * that situation is to abort the recomputation and hope for the best. + */ + + if (TkpAppIsDrawing()) { + return; + } +#endif fiPtr->updatePending = 0; RecomputeWidgets(fiPtr->mainPtr->winPtr); } diff --git a/library/demos/unicodeout.tcl b/library/demos/unicodeout.tcl index faa9f90..811d210 100644 --- a/library/demos/unicodeout.tcl +++ b/library/demos/unicodeout.tcl @@ -131,6 +131,10 @@ addSample $w Japanese \ addSample $w Korean "\uB300\uD55C\uBBFC\uAD6D\uC758 \uD55C\uAE00" addSample $w Russian \ "\u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u043A" +if {[tk windowingsystem] ne "x11"} { + addSample $w Emoji \ + "\uD83D\uDE00\uD83D\uDCA9\uD83D\uDC4D\uD83C\uDDF3\uD83C\uDDF1" +} ## We're done processing, so change things back to normal running... destroy $w.wait diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c index 696b70e..db45428 100644 --- a/macosx/tkMacOSXClipboard.c +++ b/macosx/tkMacOSXClipboard.c @@ -35,10 +35,7 @@ static Tk_Window clipboardOwner = NULL; targetPtr->type == dispPtr->utf8Atom) { for (TkClipboardBuffer *cbPtr = targetPtr->firstBufferPtr; cbPtr; cbPtr = cbPtr->nextPtr) { - NSString *s = [[NSString alloc] initWithBytesNoCopy: - cbPtr->buffer length:cbPtr->length - encoding:NSUTF8StringEncoding freeWhenDone:NO]; - + NSString *s = TclUniToNSString(cbPtr->buffer, cbPtr->length); [string appendString:s]; [s release]; } @@ -130,7 +127,6 @@ TkSelGetSelection( && selection == dispPtr->clipboardAtom && (target == XA_STRING || target == dispPtr->utf8Atom)) { NSString *string = nil; - NSString *clean; NSPasteboard *pb = [NSPasteboard generalPasteboard]; NSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject: NSStringPboardType]]; @@ -139,25 +135,20 @@ TkSelGetSelection( string = [pb stringForType:type]; } if (string) { + /* - * Replace all non-BMP characters by the replacement character 0xfffd. - * This is a workaround until Tcl supports TCL_UTF_MAX > 3. + * Encode the string using the encoding which is used in Tcl + * when TCL_UTF_MAX = 3. This replaces each UTF-16 surrogate with + * a 3-byte sequence generated using the UTF-8 algorithm. (Even + * though UTF-8 does not allow encoding surrogates, the algorithm + * does produce a 3-byte sequence.) */ - int i, j, len = [string length]; - CFRange all = CFRangeMake(0, len); - UniChar *buffer = ckalloc(len*sizeof(UniChar)); - CFStringGetCharacters((CFStringRef) string, all, buffer); - for (i = 0, j = 0 ; j < len ; i++, j++) { - if (CFStringIsSurrogateHighCharacter(buffer[j])) { - buffer[i] = 0xfffd; - j++; - } else { - buffer[i] = buffer[j]; - } + + char *bytes = NSStringToTclUni(string, NULL); + result = proc(clientData, interp, bytes); + if (bytes) { + ckfree(bytes); } - clean = (NSString *)CFStringCreateWithCharacters(NULL, buffer, i); - ckfree(buffer); - result = proc(clientData, interp, [clean UTF8String]); } } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index f4c0107..1bf2572 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -501,9 +501,12 @@ TkMacOSXGetNSImageWithTkImage( int width, int height) { - Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0); + Pixmap pixmap; NSImage *nsImage; - + if (width == 0 || height == 0) { + return nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0,0)]; + } + pixmap = Tk_GetPixmap(display, None, width, height, 0); Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0); nsImage = CreateNSImageWithPixmap(pixmap, width, height); Tk_FreePixmap(display, pixmap); diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index 153ce3b..9b2d11c 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -101,6 +101,148 @@ static void DrawCharsInContext(Display *display, Drawable drawable, #pragma mark - #pragma mark Font Helpers: +/* + *--------------------------------------------------------------------------- + * + * TclUniToNSString -- + * + * When Tcl is compiled with TCL_UTF_MAX = 3 (the default for 8.6) it cannot + * deal directly with UTF-8 encoded non-BMP characters, since their UTF-8 + * encoding requires 4 bytes. + * + * As a workaround, these versions of Tcl encode non-BMP characters as a string + * of length 6 in which the high and low UTF-16 surrogates have been encoded + * using the UTF-8 algorithm. The UTF-8 encoding does not allow encoding + * surrogates, so these 6-byte strings are not valid UTF-8, and hence Apple's + * NString class will refuse to instantiate an NSString from the 6-byte + * encoding. This function allows creating an NSString from a C-string which + * has been encoded using this scheme. + * + * Results: + * An NSString, which may be nil. + * + * Side effects: + * None. + *--------------------------------------------------------------------------- + */ + +MODULE_SCOPE NSString* +TclUniToNSString( + const char *source, + int numBytes) +{ + NSString *string = [[NSString alloc] initWithBytesNoCopy:(void *)source + length:numBytes + encoding:NSUTF8StringEncoding + freeWhenDone:NO]; + if (!string) { + const unichar *characters = ckalloc(numBytes*sizeof(unichar)); + const char *in = source; + unichar *out = (unichar *) characters; + while (in < source + numBytes) { + in += Tcl_UtfToUniChar(in, out++); + } + string = [[NSString alloc] initWithCharacters:characters + length:(out - characters)]; + ckfree(characters); + } + return string; +} + +/* + *--------------------------------------------------------------------------- + * + * TclUniAtIndex -- + * + * Write a sequence of bytes up to length 6 which is an encoding of a UTF-16 + * character in an NSString. Also record the unicode code point of the character. + * this may be a non-BMP character constructed by reading two surrogates from + * the NSString. + * + * Results: + * Returns the number of bytes written. + * + * Side effects: + * Bytes are written to the char array referenced by the pointer uni and + * the unicode code point is written to the integer referenced by the + * pointer code. + * + */ + +MODULE_SCOPE int +TclUniAtIndex( + NSString *string, + int index, + char *uni, + unsigned int *code) +{ + char *ptr = uni; + UniChar uniChar = [string characterAtIndex: index]; + if (CFStringIsSurrogateHighCharacter(uniChar)) { + UniChar lowChar = [string characterAtIndex: ++index]; + *code = CFStringGetLongCharacterForSurrogatePair( + uniChar, lowChar); + ptr += Tcl_UniCharToUtf(uniChar, ptr); + ptr += Tcl_UniCharToUtf(lowChar, ptr); + return ptr - uni; + } else { + *code = (int) uniChar; + [[string substringWithRange: NSMakeRange(index, 1)] + getCString: uni + maxLength: XMaxTransChars + encoding: NSUTF8StringEncoding]; + return strlen(uni); + } +} + +/* + *--------------------------------------------------------------------------- + * + * NSStringToTclUni -- + * + * Encodes the unicode string represented by an NSString object with the + * internal encoding that Tcl uses when TCL_UTF_MAX = 3. This encoding + * is similar to UTF-8 except that non-BMP characters are encoded as two + * successive 3-byte sequences which are constructed from UTF-16 surrogates + * by applying the UTF-8 algorithm. Even though the UTF-8 encoding does not + * allow encoding surrogates, the algorithm does produce a well-defined + * 3-byte sequence. + * + * Results: + * Returns a pointer to a null-terminated byte array which encodes the + * NSString. + * + * Side effects: + * Memory is allocated to hold the byte array, which must be freed with + * ckalloc. If the pointer numBytes is not NULL the number of non-null + * bytes written to the array is stored in the integer it references. + */ + +MODULE_SCOPE char* +NSStringToTclUni( + NSString *string, + int *numBytes) +{ + unsigned int code; + int i; + char *ptr, *bytes = ckalloc(6*[string length] + 1); + + ptr = bytes; + if (ptr) { + for (i = 0; i < [string length]; i++) { + ptr += TclUniAtIndex(string, i, ptr, &code); + if (code > 0xffff){ + i++; + } + } + *ptr = '\0'; + } + if (numBytes) { + *numBytes = ptr - bytes; + } + return bytes; +} + #define GetNSFontTraitsFromTkFontAttributes(faPtr) \ ((faPtr)->weight == TK_FW_BOLD ? NSBoldFontMask : NSUnboldFontMask) | \ ((faPtr)->slant == TK_FS_ITALIC ? NSItalicFontMask : NSUnitalicFontMask) @@ -176,6 +318,18 @@ FindNSFont( size = [defaultFont pointSize]; } nsFont = [fm fontWithFamily:family traits:traits weight:weight size:size]; + + /* + * A second bug in NSFontManager that Apple created for the Catalina OS + * causes requests as above to sometimes return fonts with additional + * traits that were not requested, even though fonts without those unwanted + * traits exist on the system. See bug [90d555e088]. As a workaround + * we ask the font manager to remove any unrequested traits. + */ + + if (nsFont) { + nsFont = [fm convertFont:nsFont toNotHaveTrait:~traits]; + } if (!nsFont) { NSArray *availableFamilies = [fm availableFontFamilies]; NSString *caseFamily = nil; @@ -395,12 +549,15 @@ TkpFontPkgInit( } TkInitFontAttributes(&fa); #if 0 + /* - * In macOS 10.15.1 Apple introduced a bug which caused the call below to - * return a font with the invalid familyName ".SF NSMono" instead of the - * valid familyName "NSMono". Calling [NSFont userFixedPitchFontOfSize:11] - * returns a font in the "Menlo" family which has a valid familyName. + * In macOS 10.15.1 Apple introduced a bug in NSFontManager which caused + * it to not recognize the familyName ".SF NSMono" which is the familyName + * of the default fixed pitch system fault on that system. See bug [855049e799]. + * As a workaround we call [NSFont userFixedPitchFontOfSize:11] instead. + * This returns a user font in the "Menlo" family. */ + nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL); #else nsFont = [NSFont userFixedPitchFontOfSize:11]; @@ -829,8 +986,7 @@ TkpMeasureCharsInContext( if (maxLength > 32767) { maxLength = 32767; } - string = [[NSString alloc] initWithBytesNoCopy:(void*)source - length:numBytes encoding:NSUTF8StringEncoding freeWhenDone:NO]; + string = TclUniToNSString((const char *)source, numBytes); if (!string) { length = 0; fit = rangeLength; @@ -1109,12 +1265,10 @@ DrawCharsInContext( !TkMacOSXSetupDrawingContext(drawable, gc, 1, &drawingContext)) { return; } - string = [[NSString alloc] initWithBytesNoCopy:(void*)source - length:numBytes encoding:NSUTF8StringEncoding freeWhenDone:NO]; + string = TclUniToNSString((const char *)source, numBytes); if (!string) { return; } - context = drawingContext.context; fg = TkMacOSXCreateCGColor(gc, gc->foreground); attributes = [fontPtr->nsAttributes mutableCopy]; diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 677f77e..7ea085b 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -14,7 +14,7 @@ */ #include "tkMacOSXPrivate.h" -#include "tkMacOSXEvent.h" +#include "tkMacOSXInt.h" #include "tkMacOSXConstants.h" /* @@ -293,7 +293,7 @@ static unsigned isFunctionKey(unsigned int code); NSString *str; str = ([aString isKindOfClass: [NSAttributedString class]]) ? - str = [aString string] : aString; + [aString string] : aString; len = [str length]; if (NS_KEYLOG) { @@ -331,42 +331,30 @@ static unsigned isFunctionKey(unsigned int code); } /* - * NSString represents a non-BMP character as a string of length 2 where - * the first character is the high surrogate and the second character is - * the low surrogate. We could record this in the XEvent by setting the - * keycode to the unicode code point and setting the trans_chars to the - * 4-byte UTF-8 string. However, that will not help as long as TCL_UTF_MAX - * is set to 3. Until that changes, we just replace non-BMP characters by - * the "replacement character" U+FFFD. + * Next we generate an XEvent for each unicode character in our string. + * + * NSString uses UTF-16 internally, which means that a non-BMP character is + * represented by a sequence of two 16-bit "surrogates". In principle we + * could record this in the XEvent by setting the keycode to the 32-bit + * unicode code point and setting the trans_chars string to the 4-byte + * UTF-8 string for the non-BMP character. However, that will not work + * when TCL_UTF_MAX is set to 3, as is the case for Tcl 8.6. A workaround + * used internally by Tcl 8.6 is to encode each surrogate as a 3-byte + * sequence using the UTF-8 algorithm (ignoring the fact that the UTF-8 + * encoding specification does not allow encoding UTF-16 surrogates). + * This gives a 6-byte encoding of the non-BMP character which we write into + * the trans_chars field of the XEvent. */ for (i = 0; i < len; i++) { - UniChar nextChar = [str characterAtIndex: i]; - if (CFStringIsSurrogateHighCharacter(nextChar)) { -#if 0 - UniChar lowChar = [str characterAtIndex: ++i]; - xEvent.xkey.keycode = CFStringGetLongCharacterForSurrogatePair( - nextChar, lowChar); - xEvent.xkey.nbytes = TkUniCharToUtf(xEvent.xkey.keycode, - &xEvent.xkey.trans_chars); -#else + xEvent.xkey.nbytes = TclUniAtIndex(str, i, xEvent.xkey.trans_chars, + &xEvent.xkey.keycode); + if (xEvent.xkey.keycode > 0xffff){ i++; - xEvent.xkey.keycode = 0xfffd; - strcpy(xEvent.xkey.trans_chars, "\xef\xbf\xbd"); - xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars); -#endif - } else { - xEvent.xkey.keycode = (int) nextChar; - [[str substringWithRange: NSMakeRange(i,1)] - getCString: xEvent.xkey.trans_chars - maxLength: XMaxTransChars encoding: NSUTF8StringEncoding]; - xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars); } - xEvent.xany.type = KeyPress; - releaseCode = (UInt16) nextChar; - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + xEvent.xany.type = KeyPress; + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); } - releaseCode = (UInt16) [str characterAtIndex: 0]; } @@ -396,7 +384,7 @@ static unsigned isFunctionKey(unsigned int code); NSString *str; str = ([aString isKindOfClass: [NSAttributedString class]]) ? - str = [aString string] : aString; + [aString string] : aString; if (focusWin) { @@ -642,7 +630,7 @@ XGrabKeyboard( Time time) { keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window); - TkWindow *captureWinPtr = (TkWindow *) TkMacOSXGetCapture(); + TkWindow *captureWinPtr = (TkWindow *) TkpGetCapture(); if (keyboardGrabWinPtr && captureWinPtr) { NSWindow *w = TkMacOSXDrawableWindow(grab_window); diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 68bad41..9417b62 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -239,6 +239,10 @@ MODULE_SCOPE int TkMacOSXServices_Init(Tcl_Interp *interp); MODULE_SCOPE int TkMacOSXRegisterServiceWidgetObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE NSString* TclUniToNSString(const char *source, int numBytes); +MODULE_SCOPE int TclUniAtIndex(NSString *string, int index, char *uni, + unsigned int *code); +MODULE_SCOPE char* NSStringToTclUni(NSString *string, int *numBytes); #pragma mark Private Objective-C Classes diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index c2b67f6..ceb3f3f 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -2518,6 +2518,7 @@ WmIconphotoCmd( { Tk_Image tk_icon; int width, height, isDefault = 0; + NSImage *newIcon = NULL; if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, @@ -2563,12 +2564,16 @@ WmIconphotoCmd( return TCL_ERROR; } - NSImage *newIcon; Tk_SizeOfImage(tk_icon, &width, &height); - newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon, - width, height); + if (width != 0 && height != 0) { + newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon, + width, height); + } Tk_FreeImage(tk_icon); if (newIcon == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "failed to create an iconphoto with image \"%s\"", icon)); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL); return TCL_ERROR; } [NSApp setApplicationIconImage: newIcon]; @@ -3309,18 +3314,18 @@ WmStackorderCmd( if (objc == 3) { windows = TkWmStackorderToplevel(winPtr); - if (windows == NULL) { - Tcl_Panic("TkWmStackorderToplevel failed"); - } - - resultObj = Tcl_NewObj(); - for (windowPtr = windows; *windowPtr ; windowPtr++) { - Tcl_ListObjAppendElement(NULL, resultObj, + if (windows != NULL) { + resultObj = Tcl_NewObj(); + for (windowPtr = windows; *windowPtr ; windowPtr++) { + Tcl_ListObjAppendElement(NULL, resultObj, TkNewWindowObj((Tk_Window) *windowPtr)); + } + Tcl_SetObjResult(interp, resultObj); + ckfree(windows); + return TCL_OK; + } else { + return TCL_ERROR; } - Tcl_SetObjResult(interp, resultObj); - ckfree(windows); - return TCL_OK; } else { TkWindow *winPtr2; int index1 = -1, index2 = -1, result; @@ -6621,7 +6626,7 @@ WmStackorderToplevelWrapperMap( Tcl_HashEntry *hPtr; int newEntry; - if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) + if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr) && (winPtr->display == display)) { hPtr = Tcl_CreateHashEntry(table, (char*) TkMacOSXDrawableWindow(winPtr->window), &newEntry); @@ -6642,8 +6647,8 @@ WmStackorderToplevelWrapperMap( * This procedure returns the stack order of toplevel windows. * * Results: - * An array of pointers to tk window objects in stacking order or else - * NULL if there was an error. + * A NULL terminated array of pointers to tk window objects in stacking + * order or else NULL if there was an error. * * Side effects: * None. @@ -6658,57 +6663,24 @@ TkWmStackorderToplevel( TkWindow *childWinPtr, **windows, **windowPtr; Tcl_HashTable table; Tcl_HashEntry *hPtr; - Tcl_HashSearch search; - - /* - * Map mac windows to a TkWindow of the wrapped toplevel. - */ - - Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); - WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); - - windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *)); - - /* - * Special cases: If zero or one toplevels were mapped there is no need to - * enumerate Windows. - */ - - switch (table.numEntries) { - case 0: - windows[0] = NULL; - goto done; - case 1: - hPtr = Tcl_FirstHashEntry(&table, &search); - windows[0] = Tcl_GetHashValue(hPtr); - windows[1] = NULL; - goto done; - } - NSArray *macWindows = [NSApp orderedWindows]; + NSArray* backToFront = [[macWindows reverseObjectEnumerator] allObjects]; NSInteger windowCount = [macWindows count]; - if (!windowCount) { - ckfree(windows); - windows = NULL; - } else { - windowPtr = windows + table.numEntries; - *windowPtr-- = NULL; - for (NSWindow *w in macWindows) { + windows = windowPtr = ckalloc((windowCount + 1) * sizeof(TkWindow *)); + if (windows != NULL) { + Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); + WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); + for (NSWindow *w in backToFront) { hPtr = Tcl_FindHashEntry(&table, (char*) w); if (hPtr != NULL) { childWinPtr = Tcl_GetHashValue(hPtr); - *windowPtr-- = childWinPtr; + *windowPtr++ = childWinPtr; } } - if (windowPtr != windows-1) { - Tcl_Panic("num matched toplevel windows does not equal num " - "children"); - } + *windowPtr = NULL; + Tcl_DeleteHashTable(&table); } - - done: - Tcl_DeleteHashTable(&table); return windows; } diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index 952aa20..7e8377e 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -1409,8 +1409,10 @@ static void ButtonElementDraw( } else if (info.kind == kThemePushButton && (state & TTK_STATE_PRESSED)) { bounds.size.height += 2; - GradientFillRoundedRectangle(dc.context, bounds, 4, - pressedPushButtonGradient, 2); + if ([NSApp macMinorVersion] > 8) { + GradientFillRoundedRectangle(dc.context, bounds, 4, + pressedPushButtonGradient, 2); + } } else { /* @@ -1859,18 +1861,17 @@ static void ComboboxElementDraw( BEGIN_DRAWING(d) bounds.origin.y += 1; if (TkMacOSXInDarkMode(tkwin)) { - bounds.size.height += 1; + bounds.size.height += 1; DrawDarkButton(bounds, info.kind, state, dc.context); - } else if ([NSApp macMinorVersion] > 8) { - if ((state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED)) { + } else if ([NSApp macMinorVersion] > 8) { + if ((state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED)) { NSColor *background = [NSColor textBackgroundColor]; CGRect innerBounds = CGRectInset(bounds, 1, 2); SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); } - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, - NULL); } + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); END_DRAWING } diff --git a/tests/wm.test b/tests/wm.test index c2bc385..4d0d73b 100644 --- a/tests/wm.test +++ b/tests/wm.test @@ -873,6 +873,12 @@ test wm-iconphoto-1.4 {usage} -returnCodes error -body { # we currently have no return info wm iconphoto . -default } -result {wrong # args: should be "wm iconphoto window ?-default? image1 ?image2 ...?"} +test wm-iconphoto-1.5.1 {usage} -constraints aquaOrWin32 -returnCodes error -body { + wm iconphoto . -default [image create photo -file {}] +} -match {glob} -result {failed to create an iconphoto with image *} +test wm-iconphoto-1.5.2 {usage} -constraints x11 -body { + wm iconphoto . -default [image create photo -file {}] +} -result {} # All other iconphoto tests are platform specific @@ -1553,8 +1559,8 @@ test wm-stackorder-5.3 {An overrideredirect window\ destroy .t } -result 1 -test wm-stackorder-6.1 {An embedded toplevel does not\ - appear in the stacking order on unix or win} -constraints notAqua -body { +test wm-stackorder-6.1 {An embedded toplevel does not appear in the \ + stacking order} -body { toplevel .real -container 1 toplevel .embd -bg blue -use [winfo id .real] update @@ -1562,16 +1568,6 @@ test wm-stackorder-6.1 {An embedded toplevel does not\ } -cleanup { deleteWindows } -result {. .real} -test wm-stackorder-6.1.1 {An embedded toplevel does\ - appear in the stacking order on macOS} -constraints aqua -body { - toplevel .real -container 1 - toplevel .embd -bg blue -use [winfo id .real] - update - wm stackorder . -} -cleanup { - deleteWindows -} -result {. .embd} - stdWindow diff --git a/unix/tkUnixWm.c b/unix/tkUnixWm.c index bc7f1cb..2c9e9dd 100644 --- a/unix/tkUnixWm.c +++ b/unix/tkUnixWm.c @@ -2447,6 +2447,10 @@ WmIconphotoCmd( photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i])); if (photo == NULL) { ckfree((char *) iconPropertyData); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "failed to create an iconphoto with image \"%s\"", + Tcl_GetString(objv[i]))); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL); return TCL_ERROR; } Tk_PhotoGetSize(photo, &width, &height); @@ -3268,6 +3272,8 @@ WmStackorderCmd( ckfree(windows); Tcl_SetObjResult(interp, resultObj); return TCL_OK; + } else { + return TCL_ERROR; } } else { Tk_Window relWin; @@ -6432,6 +6438,9 @@ TkWmStackorderToplevel( TkWmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); window_ptr = windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *)); + if (windows == NULL) { + return NULL; + } /* * Special cases: If zero or one toplevels were mapped there is no need to diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 117b539..bddbe05 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -4384,9 +4384,9 @@ WmIconphotoCmd( if (!iconInfo.hbmColor) { ckfree(lpIR); Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "failed to create color bitmap for \"%s\"", + "failed to create an iconphoto with image \"%s\"", Tcl_GetString(objv[i]))); - Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "BITMAP", NULL); + Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL); return TCL_ERROR; } @@ -5195,18 +5195,18 @@ WmStackorderCmd( if (objc == 3) { windows = TkWmStackorderToplevel(winPtr); - if (windows == NULL) { - Tcl_Panic("TkWmStackorderToplevel failed"); - } - - resultObj = Tcl_NewObj(); - for (windowPtr = windows; *windowPtr ; windowPtr++) { - Tcl_ListObjAppendElement(NULL, resultObj, - TkNewWindowObj((Tk_Window) *windowPtr)); + if (windows != NULL) { + resultObj = Tcl_NewObj(); + for (windowPtr = windows; *windowPtr ; windowPtr++) { + Tcl_ListObjAppendElement(NULL, resultObj, + TkNewWindowObj((Tk_Window) *windowPtr)); + } + Tcl_SetObjResult(interp, resultObj); + ckfree(windows); + return TCL_OK; + } else { + return TCL_ERROR; } - Tcl_SetObjResult(interp, resultObj); - ckfree(windows); - return TCL_OK; } else { TkWindow *winPtr2, **winPtr2Ptr = &winPtr2; int index1 = -1, index2 = -1, result; @@ -6812,8 +6812,6 @@ TkWmStackorderToplevel( (LPARAM) &pair) == 0) { ckfree(windows); windows = NULL; - } else if (pair.windowPtr != (windows-1)) { - Tcl_Panic("num matched toplevel windows does not equal num children"); } done: |