From 2e183c2f17ff52102f5f752ef11c47d624f08c19 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 4 Nov 2024 23:51:57 +0000 Subject: [PATCH 1/3] Backport to 8.7 --- generic/tkCanvas.c | 17 -- generic/tkFont.c | 11 -- generic/tkImage.c | 6 +- generic/tkStubInit.c | 3 + generic/tkTextDisp.c | 43 +---- generic/tkWindow.c | 53 +++++- library/demos/mac_styles.tcl | 12 +- library/palette.tcl | 27 +-- macosx/README | 26 ++- macosx/tkMacOSXClipboard.c | 4 +- macosx/tkMacOSXColor.c | 67 +++++--- macosx/tkMacOSXColor.h | 15 -- macosx/tkMacOSXDefault.h | 6 +- macosx/tkMacOSXDraw.c | 168 +++++++++--------- macosx/tkMacOSXEmbed.c | 13 +- macosx/tkMacOSXEvent.c | 16 +- macosx/tkMacOSXFileTypes.c | 6 +- macosx/tkMacOSXFont.c | 38 +++- macosx/tkMacOSXHLEvents.c | 90 +++++----- macosx/tkMacOSXImage.c | 123 ++++++++----- macosx/tkMacOSXInit.c | 81 +++++---- macosx/tkMacOSXInt.h | 1 - macosx/tkMacOSXKeyEvent.c | 24 ++- macosx/tkMacOSXKeyboard.c | 6 +- macosx/tkMacOSXMenu.c | 7 +- macosx/tkMacOSXMouseEvent.c | 9 +- macosx/tkMacOSXNotify.c | 134 +-------------- macosx/tkMacOSXPrint.c | 208 +++++++++++----------- macosx/tkMacOSXPrivate.h | 41 ++--- macosx/tkMacOSXScrlbr.c | 15 +- macosx/tkMacOSXSubwindows.c | 193 +++++++++------------ macosx/tkMacOSXSysTray.c | 30 ++-- macosx/tkMacOSXTest.c | 19 +- macosx/tkMacOSXWindowEvent.c | 324 ++++++++++++++++------------------- macosx/tkMacOSXWm.c | 217 +++++++++++++++-------- macosx/tkMacOSXXStubs.c | 8 + macosx/ttkMacOSXTheme.h | 2 +- tests/button.test | 18 +- tests/canvImg.test | 4 +- tests/event.test | 308 +++++++++++++++++++++++++++++++++ tests/font.test | 1 + tests/frame.test | 4 +- tests/image.test | 26 ++- tests/menu.test | 12 +- tests/menubut.test | 2 +- tests/pack.test | 14 +- tests/raise.test | 1 + tests/systray.test | 2 +- tests/textDisp.test | 12 +- tests/ttk/image.test | 2 +- tests/ttk/ttk.test | 11 +- tests/unixWm.test | 60 +++---- tests/window.test | 3 +- tests/winfo.test | 2 + tests/xmfbox.test | 7 + 55 files changed, 1411 insertions(+), 1141 deletions(-) diff --git a/generic/tkCanvas.c b/generic/tkCanvas.c index db9a3fd087..f6be8e92cd 100644 --- a/generic/tkCanvas.c +++ b/generic/tkCanvas.c @@ -3081,10 +3081,6 @@ DisplayCanvas( Tk_Item *itemPtr; Pixmap pixmap; int screenX1, screenX2, screenY1, screenY2, width, height; -#ifdef MAC_OSX_TK - TkWindow *winPtr; - MacDrawable *macWin; -#endif if (canvasPtr->tkwin == NULL) { return; @@ -3094,19 +3090,6 @@ DisplayCanvas( goto done; } -#ifdef MAC_OSX_TK - /* - * If drawing is disabled, all we need to do is - * clear the REDRAW_PENDING flag. - */ - winPtr = (TkWindow *)(canvasPtr->tkwin); - macWin = winPtr->privatePtr; - if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){ - canvasPtr->flags &= ~REDRAW_PENDING; - return; - } -#endif - /* * Choose a new current item if that is needed (this could cause event * handlers to be invoked). diff --git a/generic/tkFont.c b/generic/tkFont.c index ecad7700df..3ae02b7859 100644 --- a/generic/tkFont.c +++ b/generic/tkFont.c @@ -887,17 +887,6 @@ TheWorldHasChanged( { TkFontInfo *fiPtr = (TkFontInfo *)clientData; - /* - * 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. - * This is ignored on other platforms. - */ - - if (TkpWillDrawWidget(NULL)) { - return; - } - fiPtr->updatePending = 0; RecomputeWidgets(fiPtr->mainPtr->winPtr); } diff --git a/generic/tkImage.c b/generic/tkImage.c index 701c7658ac..7da3044158 100644 --- a/generic/tkImage.c +++ b/generic/tkImage.c @@ -279,7 +279,7 @@ Tk_ImageObjCmd( } if (typePtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "image type \"%s\" doesn't exist", arg)); + "image type \"%s\" does not exist", arg)); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE_TYPE", arg, (char *)NULL); return TCL_ERROR; } @@ -510,7 +510,7 @@ Tk_ImageObjCmd( return TCL_OK; alreadyDeleted: - Tcl_SetObjResult(interp, Tcl_ObjPrintf("image \"%s\" doesn't exist",arg)); + Tcl_SetObjResult(interp, Tcl_ObjPrintf("image \"%s\" does not exist",arg)); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE", arg, (char *)NULL); return TCL_ERROR; } @@ -656,7 +656,7 @@ Tk_GetImage( noSuchImage: if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "image \"%s\" doesn't exist", name)); + "image \"%s\" does not exist", name)); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "IMAGE", name, (char *)NULL); } return NULL; diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index ac0af8e2bc..01bf19a533 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -49,6 +49,9 @@ MODULE_SCOPE const TkStubs tkStubs; #define TkMacOSXSetUpClippingRgn (void (*)(Drawable))(void *)doNothing #undef TkMacOSXIsCharacterMissing #define TkMacOSXIsCharacterMissing (int (*)(Tk_Font, unsigned int))(void *)doNothing +#undef TkMacOSXSetDrawingEnabled +#define TkMacOSXSetDrawingEnabled (void (*)(TkWindow *, int))(void *)doNothing + #if defined(_WIN32) && !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 # define Tk_TranslateWinEvent TkTranslateWinEvent diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 1efc87ae1c..c09e2d295f 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -24,8 +24,6 @@ #include "tkMacOSXInt.h" #endif -#define OK_TO_LOG (!TkpWillDrawWidget(textPtr->tkwin)) - /* * "Calculations of line pixel heights and the size of the vertical * scrollbar." @@ -205,20 +203,13 @@ typedef struct TextStyle { /* * Macros to make debugging/testing logging a little easier. - * - * On OSX 10.14 Drawing procedures are sometimes run because the system has - * decided to redraw the window. This can corrupt the data that a test is - * trying to collect. So we don't write to the logging variables when the - * drawing procedure is being run that way. Other systems can always log. */ #define LOG(toVar,what) \ - if (OK_TO_LOG) \ - Tcl_SetVar2(textPtr->interp, toVar, NULL, (what), \ - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT) + Tcl_SetVar2(textPtr->interp, toVar, NULL, (what), \ + TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT) #define CLEAR(var) \ - if (OK_TO_LOG) \ - Tcl_SetVar2(interp, var, NULL, "", TCL_GLOBAL_ONLY) + Tcl_SetVar2(interp, var, NULL, "", TCL_GLOBAL_ONLY) /* * The following structure describes one line of the display, which may be @@ -4192,22 +4183,6 @@ DisplayText( return; } -#ifdef MAC_OSX_TK - /* - * If the toplevel is being resized it would be dangerous to try redrawing - * the widget. But we can just clear the REDRAW_PENDING flag and return. - * This display proc will be called again after the widget has been - * reconfigured. - */ - - TkWindow *winPtr = (TkWindow *)(textPtr->tkwin); - MacDrawable *macWin = winPtr->privatePtr; - if (macWin && (macWin->flags & TK_DO_NOT_DRAW)) { - dInfoPtr->flags &= ~REDRAW_PENDING; - return; - } -#endif - interp = textPtr->interp; Tcl_Preserve(interp); @@ -4411,8 +4386,8 @@ DisplayText( Tk_Draw3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin), textPtr->border, textPtr->highlightWidth, textPtr->highlightWidth, - Tk_Width(textPtr->tkwin) - 2*textPtr->highlightWidth, - Tk_Height(textPtr->tkwin) - 2*textPtr->highlightWidth, + Tk_Width(textPtr->tkwin) - 2 * textPtr->highlightWidth, + Tk_Height(textPtr->tkwin) - 2 * textPtr->highlightWidth, textPtr->borderWidth, textPtr->relief); if (textPtr->highlightWidth > 0) { GC fgGC, bgGC; @@ -4433,25 +4408,25 @@ DisplayText( if (textPtr->padY > 0) { Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin), textPtr->border, borders, borders, - Tk_Width(textPtr->tkwin) - 2*borders, textPtr->padY, + Tk_Width(textPtr->tkwin) - 2 * borders, textPtr->padY, 0, TK_RELIEF_FLAT); Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin), textPtr->border, borders, Tk_Height(textPtr->tkwin) - borders - textPtr->padY, - Tk_Width(textPtr->tkwin) - 2*borders, + Tk_Width(textPtr->tkwin) - 2 * borders, textPtr->padY, 0, TK_RELIEF_FLAT); } if (textPtr->padX > 0) { Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin), textPtr->border, borders, borders + textPtr->padY, textPtr->padX, - Tk_Height(textPtr->tkwin) - 2*borders -2*textPtr->padY, + Tk_Height(textPtr->tkwin) - 2 * borders -2 * textPtr->padY, 0, TK_RELIEF_FLAT); Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin), textPtr->border, Tk_Width(textPtr->tkwin) - borders - textPtr->padX, borders + textPtr->padY, textPtr->padX, - Tk_Height(textPtr->tkwin) - 2*borders -2*textPtr->padY, + Tk_Height(textPtr->tkwin) - 2 * borders -2 * textPtr->padY, 0, TK_RELIEF_FLAT); } dInfoPtr->flags &= ~REDRAW_BORDERS; diff --git a/generic/tkWindow.c b/generic/tkWindow.c index ee0e1b8c03..bba87d080e 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -215,6 +215,17 @@ static int Initialize(Tcl_Interp *interp); static int NameWindow(Tcl_Interp *interp, TkWindow *winPtr, TkWindow *parentPtr, const char *name); static void UnlinkWindow(TkWindow *winPtr); + +/* + * This static variable only makes sense for macOS and Windows, which never + * have more than one display. It is set by TkCloseDisplay, and when set + * prevents sending Enter and Leave events when all of the windows in the + * display are being destroyed. Tk does not send those events on X11; that + * job is handled by the X server. + */ + +static int displayBeingClosed = 0; + /* *---------------------------------------------------------------------- @@ -239,6 +250,7 @@ static void TkCloseDisplay( TkDisplay *dispPtr) { + displayBeingClosed = 1; TkClipCleanup(dispPtr); if (dispPtr->name != NULL) { @@ -1334,6 +1346,39 @@ Tk_CreateWindowFromPath( *-------------------------------------------------------------- */ +#if defined(MAC_OSX_TK) || defined(_WIN32) +static void SendEnterLeaveForDestroy( + Tk_Window tkwin) +{ + int x, y; + unsigned int state; + Tk_Window pointerWin; + TkWindow *containerPtr; + + if (displayBeingClosed) { + return; + } + XQueryPointer(Tk_Display(tkwin), None, NULL, NULL, &x, &y, + NULL, NULL, &state); + pointerWin = Tk_CoordsToWindow(x, y, tkwin); + if (pointerWin == tkwin) { + if (!Tk_IsTopLevel(tkwin)) { + containerPtr = TkGetContainer((TkWindow *)pointerWin); + Tk_UpdatePointer((Tk_Window) containerPtr, x, y, state); + } + } + + if (pointerWin && (tkwin == Tk_Parent(pointerWin))) { + Tk_UpdatePointer(Tk_Parent(tkwin), x, y, state); + } +} +#else +static void SendEnterLeaveForDestroy( + TCL_UNUSED(Tk_Window)) +{ +} +#endif + void Tk_DestroyWindow( Tk_Window tkwin) /* Window to destroy. */ @@ -1353,6 +1398,10 @@ Tk_DestroyWindow( return; } + if ((winPtr->flags & TK_DONT_DESTROY_WINDOW) == 0) { + SendEnterLeaveForDestroy(tkwin); + } + winPtr->flags |= TK_ALREADY_DEAD; /* @@ -1523,7 +1572,7 @@ Tk_DestroyWindow( * Cleanup the data structures associated with this window. */ - if (winPtr->flags & TK_WIN_MANAGED) { + if (winPtr->wmInfoPtr && (winPtr->flags & TK_WIN_MANAGED)) { TkWmDeadWindow(winPtr); } else if (winPtr->flags & TK_WM_COLORMAP_WINDOW) { TkWmRemoveFromColormapWindows(winPtr); @@ -2612,7 +2661,7 @@ Tk_RestackWindow( TkWindow *otherPtr = (TkWindow *) other; /* - * Special case: if winPtr is a top-level window then just find the + * Special case: if winPtr is a toplevel window then just find the * top-level ancestor of otherPtr and restack winPtr above otherPtr * without changing any of Tk's childLists. */ diff --git a/library/demos/mac_styles.tcl b/library/demos/mac_styles.tcl index 2c3a224a22..9675356e56 100644 --- a/library/demos/mac_styles.tcl +++ b/library/demos/mac_styles.tcl @@ -247,16 +247,16 @@ if { [wm attributes $w -isdark] } { } proc beLight {f w} { wm attributes $w -appearance aqua - $f.dark state !selected - $f.light state selected - after 10 $f.light state !hover + # A small delay is needed for the appearance change to complete. + after 10 [list $f.dark state !selected] + after 10 [list $f.light state selected] } proc beDark {f w} { wm attributes $w -appearance darkaqua - $f.light state !selected - $f.dark state selected - after 10 $f.dark state !hover + # A small delay is needed for the appearance change to complete. + after 10 [list $f.light state !selected] + after 10 [list $f.dark state selected] } $w.notebook add $appearanceFrame -text "Appearance" diff --git a/library/palette.tcl b/library/palette.tcl index d5d88600d6..43dccc5603 100644 --- a/library/palette.tcl +++ b/library/palette.tcl @@ -189,6 +189,9 @@ proc ::tk_setPalette {args} { # which contains color information. Each element # is named after a widget configuration option, and # each value is the value for that option. +# Return Value: +# A list of commands which can be run to update +# the defaults database when exec'ed. proc ::tk::RecolorTree {w colors} { upvar $colors c @@ -200,11 +203,14 @@ proc ::tk::RecolorTree {w colors} { foreach dbOption [array names c] { set option -[string tolower $dbOption] set class [string replace $dbOption 0 0 [string toupper \ - [string index $dbOption 0]]] + [string index $dbOption 0]]] + # Make sure this option is valid for this window. if {![catch {$w configure $option} value]} { - # if the option database has a preference for this - # dbOption, then use it, otherwise use the defaults - # for the widget. + # Update the option for this window. + $w configure $option $c($dbOption) + # Retrieve a default value for this option. First check + # the option database. If it is not in the database use + # the value for the temporary prototype widget. set defaultcolor [option get $w $dbOption $class] if {$defaultcolor eq "" || \ ([info exists prototype] && \ @@ -214,16 +220,15 @@ proc ::tk::RecolorTree {w colors} { if {$defaultcolor ne ""} { set defaultcolor [winfo rgb . $defaultcolor] } - set chosencolor [lindex $value 4] - if {$chosencolor ne ""} { - set chosencolor [winfo rgb . $chosencolor] + # If the color requested for this option differs from + # the default, append a command to update the default. + set requestcolor [lindex $value 4] + if {$requestcolor ne ""} { + set requestcolor [winfo rgb . $requestcolor] } - if {[string match $defaultcolor $chosencolor]} { - # Change the option database so that future windows will get - # the same colors. + if {![string match $defaultcolor $requestcolor]} { append result ";\noption add [list \ *[winfo class $w].$dbOption $c($dbOption) 60]" - $w configure $option $c($dbOption) } } } diff --git a/macosx/README b/macosx/README index 26ccf7e800..85d8f6e9e7 100644 --- a/macosx/README +++ b/macosx/README @@ -183,6 +183,15 @@ environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will cause us to force closing stdin & stdout. Otherwise, given how Xcode launches Wish remotely, they will be left open and then Wish & gdb will fight for stdin. +- The Aqua port also supports the environment variable TK_NO_STDERR which, if set +to a non-empty value, causes stderr to be redirected to /dev/null. This is +convenient because Apple sometimes releases a new OS without removing all of +their commands which log debugging information. Log messages are written to +stderr, and hence printed in the terminal, when wish or tclsh is started from +the terminal, or when running the tests. The messages are not only annoying, +they can also cause tests to fail if a debugging message is written to stderr +while a test is running tktest as a subprocess with exec or open. + 3. FullScreen, Split View and Tabbed Windows -------------------------------------------- @@ -470,9 +479,9 @@ https://developer.apple.com/library/mac/documentation/Cocoa/\ Reference/ApplicationKit/Classes/NSApplication_Class) void NSApplicationMain(int argc, char *argv[]) { - [NSApplication sharedApplication]; - [NSBundle loadNibNamed:@"myMain" owner:NSApp]; - [NSApp run]; + [NSApplication sharedApplication]; + [NSBundle loadNibNamed:@"myMain" owner:NSApp]; + [NSApp run]; } Here NSApp is a standard global variable, initialized by the OS, which points to an object in a subclass of NSApplication (called @@ -510,17 +519,6 @@ specific SetupProc and then a platform specific CheckProc. In the macOS port, these are named TkMacOSXEventsSetupProc and TkMacOSXEventsCheckProc. -It is important to understand that the Apple window manager does not -have the concept of an expose event. Their replacement for an expose -event is to have the window manager call the [NSView drawRect] method -in any situation where an expose event for that NSView would be -generated in X11. The [NSView drawRect] method is a no-op which is -expected to be overridden by any application. In the case of Tcl, the -replacement [NSView drawRect] method creates a Tcl expose event -for each dirty rectangle of the NSView, and then adds the expose -event to the Tcl queue. - - 5.2 Autorelease pools ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c index f16ab0df50..8d5f727ea3 100644 --- a/macosx/tkMacOSXClipboard.c +++ b/macosx/tkMacOSXClipboard.c @@ -126,8 +126,8 @@ TkSelGetSelection( ([[NSPasteboard generalPasteboard] changeCount] != changeCount); if (dispPtr && (haveExternalClip || dispPtr->clipboardActive) - && selection == dispPtr->clipboardAtom - && (target == XA_STRING || target == dispPtr->utf8Atom)) { + && selection == dispPtr->clipboardAtom + && (target == XA_STRING || target == dispPtr->utf8Atom)) { NSString *string = nil; NSPasteboard *pb = [NSPasteboard generalPasteboard]; NSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject: diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 978b9d6de7..29bd240dfd 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -52,7 +52,7 @@ static void initColorTable() #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 if (@available(macOS 10.14, *)) { darkAqua = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; - lightAqua = [NSAppearance appearanceNamed:NSAppearanceNameAqua]; + lightAqua = [NSAppearance appearanceNamed:NSAppearanceNameAqua]; } #endif @@ -103,7 +103,7 @@ static void initColorTable() name = (char *)ckalloc(length + 1); strcpy(name, key.UTF8String); name[0] = (char)toupper(UCHAR(name[0])); - if (!strcmp(name, "WindowBackgroundColor")) { + if (!strcmp(name, "WindowBackgroundColor")) { /* * Avoid black windows on old systems. @@ -192,8 +192,8 @@ TkMacOSXRGBPixel( MacPixel p = {0}; p.pixel.colortype = rgbColor; p.pixel.value = (unsigned int)(((red & 0xff) << 16) | - ((green & 0xff) << 8) | - (blue & 0xff)); + ((green & 0xff) << 8) | + (blue & 0xff)); return p.ulong; } @@ -436,7 +436,7 @@ TkMacOSXInDarkMode(Tk_Window tkwin) #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 if (@available(macOS 10.14, *)) { - TkWindow *winPtr = (TkWindow*) tkwin; + TkWindow *winPtr = (TkWindow*) tkwin; NSAppearanceName name; NSView *view = nil; if (winPtr && winPtr->privatePtr) { @@ -583,10 +583,7 @@ TkMacOSXSetColorInContext( * TkpGetColor -- * * Create a new TkColor for the color with the given name, for use in the - * specified window. The colormap field is set to lightColormap if the - * window has a LightAqua appearance, or darkColormap if the window has a - * DarkAqua appearance. TkColors with different colormaps are managed - * separately in the per-display table of TkColors maintained by Tk. + * specified window. * * This function is called by Tk_GetColor. * @@ -609,8 +606,9 @@ TkpGetColor( Display *display = NULL; TkColor *tkColPtr; XColor color; - Colormap colormap = tkwin ? Tk_Colormap(tkwin) : noColormap; + Colormap colormap = TK_DYNAMIC_COLORMAP; NSView *view = nil; + Bool haveValidXColor = False; static Bool initialized = NO; if (!initialized) { @@ -638,27 +636,43 @@ TkpGetColor( p.pixel.colortype = entry->type; p.pixel.value = (unsigned int)entry->index; color.pixel = p.ulong; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + NSAppearance *windowAppearance; + /* See comments in tkMacOSXDraw.c */ + if (@available(macOS 12.0, *)) { +#if MAC_OS_X_VERSION_MAX_ALLOWED > 120000 + NSAppearance *current = NSAppearance.currentDrawingAppearance; + NSAppearance *effective = view.effectiveAppearance; + if( current != effective) { + // printf("Appearances are out of sync!\n"); + // Deprecations be damned! + NSAppearance.currentAppearance = effective; + } +#endif + } + if (@available(macOS 10.14, *)) { + if (view) { + windowAppearance = [view effectiveAppearance]; + } else { + windowAppearance = [NSApp effectiveAppearance]; + } + } +#endif + if (entry->type == semantic) { CGFloat rgba[4]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 if (@available(macOS 10.14, *)) { - NSAppearance *windowAppearance; - if (view) { - windowAppearance = [view effectiveAppearance]; - } else { - windowAppearance = [NSApp effectiveAppearance]; - } - if ([windowAppearance name] == NSAppearanceNameDarkAqua) { - colormap = darkColormap; - } else { - colormap = lightColormap; - } if (@available(macOS 11.0, *)) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000 CGFloat *rgbaPtr = rgba; [windowAppearance performAsCurrentDrawingAppearance:^{ GetRGBA(entry, p.ulong, rgbaPtr); }]; + color.red = (unsigned short)(rgba[0] * 65535.0); + color.green = (unsigned short)(rgba[1] * 65535.0); + color.blue = (unsigned short)(rgba[2] * 65535.0); #endif } else { #if MAC_OS_X_VERSION_MIN_REQUIRED < 110000 @@ -671,13 +685,13 @@ TkpGetColor( } else { GetRGBA(entry, p.ulong, rgba); } -#else +#else //MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 GetRGBA(entry, p.ulong, rgba); -#endif color.red = (unsigned short)(rgba[0] * 65535.0); color.green = (unsigned short)(rgba[1] * 65535.0); color.blue = (unsigned short)(rgba[2] * 65535.0); - goto validXColor; +#endif //MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + haveValidXColor = True; } else if (SetCGColorComponents(entry, 0, &c)) { const size_t n = CGColorGetNumberOfComponents(c); const CGFloat *rgba = CGColorGetComponents(c); @@ -695,15 +709,14 @@ TkpGetColor( Tcl_Panic("CGColor with %d components", (int) n); } CGColorRelease(c); - goto validXColor; + haveValidXColor = True; } } } - if (TkParseColor(display, colormap, name, &color) == 0) { + if (!haveValidXColor && TkParseColor(display, colormap, name, &color) == 0) { return NULL; } -validXColor: tkColPtr = (TkColor *)ckalloc(sizeof(TkColor)); tkColPtr->colormap = colormap; tkColPtr->color = color; diff --git a/macosx/tkMacOSXColor.h b/macosx/tkMacOSXColor.h index fd4881cf03..54077f80ce 100644 --- a/macosx/tkMacOSXColor.h +++ b/macosx/tkMacOSXColor.h @@ -38,10 +38,6 @@ enum colorType { rgbColor, /* The 24 bit value is an rgb color. */ clearColor, /* The unique rgba color with all channels 0. */ HIBrush, /* A HITheme brush color.*/ -#if TCL_MAJOR_VERSION < 9 - HIText, /* A HITheme text color (32-bit only). */ - HIBackground, /* A HITheme background color (32-bit only). */ -#endif ttkBackground, /* A background color which indicates nesting level.*/ semantic, /* A semantic NSColor.*/ }; @@ -56,17 +52,6 @@ typedef union MacPixel_t { xpixel pixel; } MacPixel; -/* - * We maintain two colormaps, one for the LightAqua appearance and one for the - * DarkAqua appearance. - */ - -enum macColormap { - noColormap, - lightColormap, - darkColormap, -}; - /* * In TkMacOSXColor.c a Tk hash table is constructed from the static data * below to map system color names to CGColors. diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h index 0bfbc71a8b..ca4db03f63 100644 --- a/macosx/tkMacOSXDefault.h +++ b/macosx/tkMacOSXDefault.h @@ -379,8 +379,8 @@ #define DEF_MESSAGE_HIGHLIGHT NORMAL_FG #define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" #define DEF_MESSAGE_JUSTIFY "left" -#define DEF_MESSAGE_PADX "-1" -#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_PADX NULL +#define DEF_MESSAGE_PADY NULL #define DEF_MESSAGE_RELIEF "flat" #define DEF_MESSAGE_TAKE_FOCUS "0" #define DEF_MESSAGE_TEXT "" @@ -475,7 +475,7 @@ #define DEF_SCROLLBAR_BORDER_WIDTH "0" #define DEF_SCROLLBAR_COMMAND "" #define DEF_SCROLLBAR_CURSOR "" -#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH NULL #define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG #define DEF_SCROLLBAR_HIGHLIGHT NORMAL_FG #define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 7ce630b3bd..e93f9cf33e 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -86,7 +86,7 @@ TkMacOSXInitCGDrawing( } if (Tcl_LinkVar(interp, "::tk::mac::CGAntialiasLimit", - (char *)&cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) { + &cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) { Tcl_ResetResult(interp); } cgAntiAliasLimit = limit; @@ -96,11 +96,11 @@ TkMacOSXInitCGDrawing( */ if (Tcl_LinkVar(interp, "::tk::mac::useThemedToplevel", - (char *)&useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) { + &useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); } if (Tcl_LinkVar(interp, "::tk::mac::useThemedFrame", - (char *)&useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) { + &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); } transparentColor = TkMacOSXClearPixel(); @@ -283,7 +283,8 @@ Tk_MacOSXGetCGContextForDrawable( * * TkMacOSXDrawCGImage -- * - * Draw CG image into drawable. + * Draw CG image into drawable. The entire image is used, and will + * be rescaled if its dimensions do not equal dstBounds.size. * * Results: * None. @@ -302,25 +303,11 @@ TkMacOSXDrawCGImage( CGImageRef image, unsigned long imageForeground, unsigned long imageBackground, - CGRect imageBounds, - CGRect srcBounds, CGRect dstBounds) { MacDrawable *macDraw = (MacDrawable *)d; if (macDraw && context && image) { - CGImageRef subImage = NULL; - - if (!CGRectEqualToRect(imageBounds, srcBounds)) { - if (!CGRectContainsRect(imageBounds, srcBounds)) { - TkMacOSXDbgMsg("Mismatch of sub CGImage bounds"); - } - subImage = CGImageCreateWithImageInRect(image, CGRectOffset( - srcBounds, -imageBounds.origin.x, -imageBounds.origin.y)); - if (subImage) { - image = subImage; - } - } dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff); if (CGImageIsMask(image)) { if (macDraw->flags & TK_IS_BW_PIXMAP) { @@ -369,9 +356,6 @@ TkMacOSXDrawCGImage( CGContextDrawImage(context, dstBounds, image); CGContextRestoreGState(context); #endif /* TK_MAC_DEBUG_IMAGE_DRAWING */ - if (subImage) { - CFRelease(subImage); - } } else { TkMacOSXDbgMsg("Drawing of empty CGImage requested"); } @@ -1093,6 +1077,23 @@ XFillArcs( * Results: * Returns 0 if the scroll generated no additional damage. Otherwise, sets * the region that needs to be repainted after scrolling and returns 1. + * When drawRect was in use, this function used the now deprecated + * scrollRect method of NSView. With the current updateLayer + * implementation, using a CGImage as the view's backing layer, we are + * able to use XCopyArea. But both implementations are incomplete. + * They return a damage area which is just the source rectangle minus + * destination rectangle. Other platforms, e.g. Windows, where + * this function is essentially provided by the windowing system, + * are able to add to the damage region the bounding rectangles of + * all subwindows which meet the source rectangle, even if they are + * contained in the destination rectangle. The information needed + * to do that is not available in this module, as far as I know. + * + * In fact, the Text widget is the only one which calls this + * function, and textDisp.c compensates for this defect by using + * macOS-specific code. This is possible because access to the + * list of all embedded windows in a Text widget is available in + * that module. * * Side effects: * Scrolls the bits in the window. @@ -1103,36 +1104,21 @@ XFillArcs( int TkScrollWindow( Tk_Window tkwin, /* The window to be scrolled. */ - TCL_UNUSED(GC), /* GC for window to be scrolled. */ + GC gc, /* GC for window to be scrolled. */ int x, int y, /* Position rectangle to be scrolled. */ int width, int height, int dx, int dy, /* Distance rectangle should be moved. */ Region damageRgn) /* Region to accumulate damage in. */ { Drawable drawable = Tk_WindowId(tkwin); - MacDrawable *macDraw = (MacDrawable *)drawable; - TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(macDraw); HIShapeRef srcRgn, dstRgn; HIMutableShapeRef dmgRgn = HIShapeCreateMutable(); - NSRect bounds, viewSrcRect, srcRect, dstRect; + NSRect srcRect, dstRect; int result = 0; - if (view) { - - /* - * Get the scroll area in NSView coordinates (origin at bottom left). - */ - - bounds = [view bounds]; - viewSrcRect = NSMakeRect(macDraw->xOff + x, - bounds.size.height - height - (macDraw->yOff + y), - width, height); - - /* - * Scroll the rectangle. - */ - - [view scrollRect:viewSrcRect by:NSMakeSize(dx, -dy)]; + // Should behave more like TkScrollWindow on other platforms + if (XCopyArea(Tk_Display(tkwin), drawable, drawable, gc, x, y, + (unsigned)width, (unsigned)height, x+dx, y+dy) == Success) { /* * Compute the damage region, using Tk coordinates (origin at top left). @@ -1237,14 +1223,19 @@ TkMacOSXSetupDrawingContext( * Intersect the drawable's clipping region with the region stored in the * X GC. If the resulting region is empty, don't do any drawing. */ - +//#if 0 // disable clipping (almost works, but windows can open up blank) dc.clipRgn = TkMacOSXGetClipRgn(d); ClipToGC(d, gc, &dc.clipRgn); if (dc.clipRgn && HIShapeIsEmpty(dc.clipRgn)) { + /* + * Things are probably not set up for drawing yet. Request a call to + * updateLayer and return failure. + */ canDraw = false; + [view setNeedsDisplay:YES]; goto end; } - +//#endif //disable clipping /* * If the drawable already has a CGContext, use it. Otherwise, we must be * drawing to a window and we use the current context of its ContentView. @@ -1252,53 +1243,62 @@ TkMacOSXSetupDrawingContext( dc.context = TkMacOSXGetCGContextForDrawable(d); if (!dc.context) { - NSRect drawingBounds, currentBounds; dc.view = view; - dc.context = GET_CGCONTEXT; + dc.context = view.tkLayerBitmapContext; if (dc.clipRgn) { CGRect clipBounds; CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, .ty = [view bounds].size.height}; HIShapeGetBounds(dc.clipRgn, &clipBounds); clipBounds = CGRectApplyAffineTransform(clipBounds, t); - drawingBounds = NSRectFromCGRect(clipBounds); - } else { - drawingBounds = [view bounds]; } /* - * We can only draw into the NSView which is the current focusView. - * When the current [NSView focusView] is nil, the CGContext for - * [NSGraphicsContext currentContext] is nil. Otherwise the current - * CGContext draws into the current focusView. An NSView is guaranteed - * to be the focusView when its drawRect or setFrame methods are - * running. Prior to OSX 10.14 it was also possible to call the - * lockFocus method to force an NSView to become the current focusView. - * But that method was deprecated in 10.14 and so is no longer used by - * Tk. Instead, if the view is not the current focusView then we add - * the drawing bounds to its dirty rectangle and return false. The - * part of the view inside the drawing bounds will get redrawn during - * the next call to its drawRect method. + * Workaround for an Apple bug. + * + * Without the block below, ttk frames, labelframes and labels do not + * get the correct background color on macOS 12.5 after the appearance + * changes. This function is only called when drawing, so we know that + * our view is the focus view. Even though the effective appearance of + * the view has been changed, the currentAppearance, i.e. the + * appearance that will be used for drawing, may not have been changed + * to match. + * + * Prior to macOS 12.0 the currentAppearance property of NSAppearance + * was settable. In macOS 12.0 currentAppearance was deprecated and + * replaced by the read-only property currentDrawingAppearance. The + * ttk color issues are fixed by setting the currentAppearance to + * the effectiveAppearance of the view. So we are forced to use this + * deprecated function until Apple fixes this. + * + * It is a mystery why this only affects the ttk widgets. A possible + * clue is that when drawing a ttk widget this function is called with + * a NULL gc, whereas the gc is non-null when it is called for drawing + * a Tk widget. This means that the CGContext setup below is not done + * for ttk widgets. Perhaps that setup triggers an update of the + * currentAppearance property, but that has not been verified. */ - if (view != [NSView focusView]) { - [view addTkDirtyRect:drawingBounds]; - canDraw = false; - goto end; - } - - /* - * Drawing will also fail when the view is the current focusView but - * the clipping rectangle set by drawRect does not contain the clipping - * region of our drawing context. (See bug [2a61eca3a8].) If part of - * the drawing bounds will be clipped then we draw whatever we can, but - * we also add the drawing bounds to the view's dirty rectangle so it - * will get redrawn in the next call to its drawRect method. - */ + if (@available(macOS 12.0, *)) { +#if MAC_OS_X_VERSION_MAX_ALLOWED > 120000 + NSAppearance *current = NSAppearance.currentDrawingAppearance; + NSAppearance *effective = view.effectiveAppearance; + if( current != effective) { + // printf("Appearances are out of sync!\n"); + // Deprecations be damned! + NSAppearance.currentAppearance = effective; + } +#endif + } else { + /* + *It is not clear if this is a problem before macos 12.0, but + * we might as well do the update anyway. + */ - currentBounds = NSRectFromCGRect(CGContextGetClipBoundingBox(dc.context)); - if (!NSContainsRect(currentBounds, drawingBounds)) { - [view addTkDirtyRect:drawingBounds]; +#if MAC_OS_X_VERSION_MIN_REQUIRED < 120000 +/* currentAppearance is not deprecated. */ + NSAppearance.currentAppearance = view.effectiveAppearance; +#endif } } @@ -1324,6 +1324,7 @@ TkMacOSXSetupDrawingContext( }; CGContextConcatCTM(dc.context, t); } +//#if 0 // disable clipping if (dc.clipRgn) { #ifdef TK_MAC_DEBUG_DRAWING @@ -1369,6 +1370,8 @@ TkMacOSXSetupDrawingContext( CGContextClipToRect(dc.context, r); } } +//#endif //disable clipping + if (gc) { static const CGLineCap cgCap[] = { [CapNotLast] = kCGLineCapButt, @@ -1475,6 +1478,13 @@ TkMacOSXRestoreDrawingContext( dcPtr->clipRgn = NULL; } + /* + * Mark the view as needing to be redisplayed, since we have drawn on its + * backing layer. + */ + + [dcPtr->view setNeedsDisplay:YES]; + #ifdef TK_MAC_DEBUG bzero(dcPtr, sizeof(TkMacOSXDrawingContext)); #endif @@ -1541,8 +1551,8 @@ TkMacOSXGetClipRgn( * * Clip all drawing into the drawable d to the given rectangle. If width * or height are negative, reset to no clipping. This is called by the - * Text widget to display each DLine, and by the Canvas widget when it - * is updating a sub rectangle in the canvas. + * Text widget to display each DLine, and by the Canvas widget when it + * is updating a sub rectangle in the canvas. * * Results: * None. diff --git a/macosx/tkMacOSXEmbed.c b/macosx/tkMacOSXEmbed.c index ef4f44dfc7..8b556ba96c 100644 --- a/macosx/tkMacOSXEmbed.c +++ b/macosx/tkMacOSXEmbed.c @@ -850,12 +850,12 @@ EmbedStructureProc( if (eventPtr->type == ConfigureNotify) { /* - * Send a ConfigureNotify to the embedded application. - */ + * Send a ConfigureNotify to the embedded application. + */ - if (containerPtr->embeddedPtr != NULL) { - TkDoConfigureNotify(containerPtr->embeddedPtr); - } + if (containerPtr->embeddedPtr != NULL) { + TkDoConfigureNotify(containerPtr->embeddedPtr); + } if (containerPtr->embedded != None) { /* * Ignore errors, since the embedded application could have @@ -1011,9 +1011,8 @@ EmbedGeometryRequest( */ Tk_GeometryRequest((Tk_Window)winPtr, width, height); - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_TIMER_EVENTS|TCL_DONT_WAIT)) {} if ((winPtr->changes.width != width) - || (winPtr->changes.height != height)) { + || (winPtr->changes.height != height)) { EmbedSendConfigure(containerPtr); } } diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c index 4f36915ffc..63493bcc79 100644 --- a/macosx/tkMacOSXEvent.c +++ b/macosx/tkMacOSXEvent.c @@ -35,7 +35,7 @@ enum { switch ((NSInteger)type) { case NSAppKitDefined: - subtype = [theEvent subtype]; + subtype = [theEvent subtype]; switch (subtype) { /* Ignored at the moment. */ @@ -49,11 +49,11 @@ enum { break; case NSWindowMovedEventType: break; - case NSWindowWillMoveEventType: - break; + case NSWindowWillMoveEventType: + break; - default: - break; + default: + break; } break; /* AppkitEvent. Return theEvent */ case NSKeyUp: @@ -80,7 +80,7 @@ enum { break; /* Mouse event. Return the processed event. */ #if 0 case NSSystemDefined: - subtype = [theEvent subtype]; + subtype = [theEvent subtype]; break; case NSApplicationDefined: { id win; @@ -88,14 +88,14 @@ enum { break; } case NSCursorUpdate: - break; + break; case NSEventTypeGesture: case NSEventTypeMagnify: case NSEventTypeRotate: case NSEventTypeSwipe: case NSEventTypeBeginGesture: case NSEventTypeEndGesture: - break; + break; #endif default: diff --git a/macosx/tkMacOSXFileTypes.c b/macosx/tkMacOSXFileTypes.c index 5df7dddc93..acf2da9eac 100644 --- a/macosx/tkMacOSXFileTypes.c +++ b/macosx/tkMacOSXFileTypes.c @@ -26,9 +26,9 @@ without generating deprecation warnings. #include "tkMacOSXPrivate.h" #define CHARS_TO_OSTYPE(string) (OSType) string[0] << 24 | \ - (OSType) string[1] << 16 | \ - (OSType) string[2] << 8 | \ - (OSType) string[3] + (OSType) string[1] << 16 | \ + (OSType) string[2] << 8 | \ + (OSType) string[3] MODULE_SCOPE NSString *TkMacOSXOSTypeToUTI(OSType ostype) { char string[5]; diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index b6dedd4f75..ec8671be95 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -24,6 +24,26 @@ #endif */ +/* + * TclNumUtfChars() is the same as Tcl_NumUtfChars(), but counting + * in UTF-16 in stead of UTF-32. For Tcl 8.7 it's a little bit + * tricky to get this function, because we are compiling with + * TCL_UTF_MAX=4. Same for TclUtfAtIndex() + */ +#if TCL_MAJOR_VERSION < 9 +# undef TclNumUtfChars +# undef TclUtfAtIndex +# ifdef USE_TCL_STUBS +# define TclNumUtfChars \ + (tclStubsPtr->tcl_NumUtfChars) /* 312 */ +# define TclUtfAtIndex \ + (tclStubsPtr->tcl_UtfAtIndex) /* 325 */ +# else +# define TclNumUtfChars Tcl_NumUtfChars +# define TclUtfAtIndex Tcl_UtfAtIndex +# endif +#endif + /* * The following structure represents our Macintosh-specific implementation * of a font object. @@ -456,7 +476,7 @@ startOfClusterObjCmd( if (stringArg == NULL) { return TCL_ERROR; } - Tcl_Size ulen = TkGetCharLength(objv[1]); + Tcl_Size ulen = Tcl_GetCharLength(objv[1]); S = [[TKNSString alloc] initWithTclUtfBytes:stringArg length:len]; len = [S length]; if (TkGetIntForIndex(objv[2], ulen - 1, 0, &idx) != TCL_OK) { @@ -470,7 +490,7 @@ startOfClusterObjCmd( /* The string contains codepoints > \uFFFF. Determine UTF-16 index */ Tcl_Size newIdx = 0; for (Tcl_Size i = 0; i < idx; i++) { - newIdx += 1 + (((newIdx < (Tcl_Size)len-1) && ([S characterAtIndex:newIdx]&0xFC00) == 0xD800) && (([S characterAtIndex:newIdx+1]&0xFC00) == 0xDC00)); + newIdx += 1 + (((newIdx < len-1) && ([S characterAtIndex:newIdx]&0xFC00) == 0xD800) && (([S characterAtIndex:newIdx+1]&0xFC00) == 0xDC00)); } idx = newIdx; } @@ -513,7 +533,7 @@ endOfClusterObjCmd( if (stringArg == NULL) { return TCL_ERROR; } - Tcl_Size ulen = TkGetCharLength(objv[1]); + Tcl_Size ulen = Tcl_GetCharLength(objv[1]); S = [[TKNSString alloc] initWithTclUtfBytes:stringArg length:len]; len = [S length]; if (TkGetIntForIndex(objv[2], ulen - 1, 0, &idx) != TCL_OK) { @@ -1062,8 +1082,8 @@ TkpMeasureCharsInContext( attributes:fontPtr->nsAttributes]; typesetter = CTTypesetterCreateWithAttributedString( (CFAttributedStringRef)attributedString); - start = Tcl_NumUtfChars(source, rangeStart); - len = Tcl_NumUtfChars(source + rangeStart, rangeLength); + start = TclNumUtfChars(source, rangeStart); + len = TclNumUtfChars(source + rangeStart, rangeLength); if (start > 0) { range.length = start; line = CTTypesetterCreateLine(typesetter, range); @@ -1164,7 +1184,7 @@ TkpMeasureCharsInContext( [attributedString release]; [string release]; length = ceil(width - offset); - fit = (Tcl_UtfAtIndex(source, index) - source) - rangeStart; + fit = (TclUtfAtIndex(source, index) - source) - rangeStart; done: #ifdef TK_MAC_DEBUG_FONTS TkMacOSXDbgMsg("measure: source=\"%s\" range=\"%.*s\" maxLength=%d " @@ -1363,8 +1383,8 @@ TkpDrawAngledCharsInContext( -textX, -textY); } CGContextConcatCTM(context, t); - start = Tcl_NumUtfChars(source, rangeStart); - length = Tcl_NumUtfChars(source, rangeStart + rangeLength) - start; + start = TclNumUtfChars(source, rangeStart); + length = TclNumUtfChars(source, rangeStart + rangeLength) - start; line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, length)); if (start > 0) { @@ -1532,7 +1552,7 @@ TkMacOSXUseAntialiasedText( Tcl_ResetResult(interp); } if (Tcl_LinkVar(interp, "::tk::mac::antialiasedtext", - (char *) &antialiasedTextEnabled, + &antialiasedTextEnabled, TCL_LINK_INT) != TCL_OK) { Tcl_ResetResult(interp); } diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c index 8e1fff5836..0d07fdf431 100644 --- a/macosx/tkMacOSXHLEvents.c +++ b/macosx/tkMacOSXHLEvents.c @@ -307,34 +307,34 @@ static const char getSdefProc[] = "::tk::mac::GetDynamicSdef"; /* * This descriptor can be coerced to a file url. Construct a Tcl * expression which passes the file path as a string argument to - * ::tk::mac::DoScriptFile. + * ::tk::mac::DoScriptFile. */ if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type, - (Ptr) URLBuffer, URL_MAX_LENGTH, &actual)) { - if (actual > 0) { - URLBuffer[actual] = '\0'; - NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer]; - NSURL *fileURL = [NSURL URLWithString:urlString]; - AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo)); - Tcl_DString *scriptFileCommand = &AEInfo->command; - Tcl_DStringInit(scriptFileCommand); - Tcl_DStringAppend(scriptFileCommand, scriptFileProc, TCL_INDEX_NONE); - Tcl_DStringAppendElement(scriptFileCommand, [[fileURL path] UTF8String]); - AEInfo->interp = _eventInterp; - AEInfo->procedure = scriptFileProc; - AEInfo->replyEvent = nil; + (Ptr) URLBuffer, URL_MAX_LENGTH, &actual)) { + if (actual > 0) { + URLBuffer[actual] = '\0'; + NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer]; + NSURL *fileURL = [NSURL URLWithString:urlString]; + AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo)); + Tcl_DString *scriptFileCommand = &AEInfo->command; + Tcl_DStringInit(scriptFileCommand); + Tcl_DStringAppend(scriptFileCommand, scriptFileProc, TCL_INDEX_NONE); + Tcl_DStringAppendElement(scriptFileCommand, [[fileURL path] UTF8String]); + AEInfo->interp = _eventInterp; + AEInfo->procedure = scriptFileProc; + AEInfo->replyEvent = nil; AEInfo->retryCount = 0; - ProcessAppleEvent((void *)AEInfo); - } - } + ProcessAppleEvent((void *)AEInfo); + } + } } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type, NULL, 0, &actual)) { - /* - * The descriptor cannot be coerced to a file URL but can be coerced to - * text. Construct a Tcl expression which passes the text as a string - * argument to ::tk::mac::DoScriptText. - */ + /* + * The descriptor cannot be coerced to a file URL but can be coerced to + * text. Construct a Tcl expression which passes the text as a string + * argument to ::tk::mac::DoScriptText. + */ if (actual > 0) { char *data = (char *)ckalloc(actual + 1); @@ -350,23 +350,23 @@ static const char getSdefProc[] = "::tk::mac::GetDynamicSdef"; AEInfo->interp = _eventInterp; AEInfo->procedure = scriptTextProc; AEInfo->retryCount = 0; - if (Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) { - AEInfo->replyEvent = replyEvent; - ProcessAppleEvent(AEInfo); - } else { - AEInfo->replyEvent = nil; - ProcessAppleEvent(AEInfo); - } + if (Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) { + AEInfo->replyEvent = replyEvent; + ProcessAppleEvent(AEInfo); + } else { + AEInfo->replyEvent = nil; + ProcessAppleEvent(AEInfo); + } } } } } - (void)handleURLEvent:(NSAppleEventDescriptor*)event - withReplyEvent:(NSAppleEventDescriptor*)replyEvent + withReplyEvent:(NSAppleEventDescriptor*)replyEvent { NSString* url = [[event paramDescriptorForKeyword:keyDirectObject] - stringValue]; + stringValue]; const char *cURL=[url UTF8String]; AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo)); Tcl_DString *launchCommand = &AEInfo->command; @@ -456,18 +456,18 @@ static void ProcessAppleEvent( Tcl_DStringLength(&AEInfo->command), TCL_EVAL_GLOBAL); if (AEInfo->replyEvent && code >= 0) { - Tcl_Size reslen; - const char *result = Tcl_GetStringFromObj(Tcl_GetObjResult(AEInfo->interp), - &reslen); - if (code == TCL_OK) { - AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc], - keyDirectObject, typeChar, result, reslen); - } else { - AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc], - keyErrorString, typeChar, result, reslen); - AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc], - keyErrorNumber, typeSInt32, (Ptr) &code, sizeof(int)); - } + Tcl_Size reslen; + const char *result = Tcl_GetStringFromObj(Tcl_GetObjResult(AEInfo->interp), + &reslen); + if (code == TCL_OK) { + AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc], + keyDirectObject, typeChar, result, reslen); + } else { + AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc], + keyErrorString, typeChar, result, reslen); + AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc], + keyErrorNumber, typeSInt32, (Ptr) &code, sizeof(int)); + } } else if (code != TCL_OK) { Tcl_BackgroundException(AEInfo->interp, code); } @@ -537,8 +537,8 @@ TkMacOSXInitAppleEvents( /* * We do not load our sdef dynamically but this event handler - * is required to silence error messages from inline execution - * of AppleScript at the Objective-C level. + * is required to silence error messages from inline execution + * of AppleScript at the Objective-C level. */ [aeManager setEventHandler:NSApp andSelector:@selector(handleGetSDEFEvent:withReplyEvent:) diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index 11421ccc23..efd4d0a881 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -19,6 +19,10 @@ #include "tkColor.h" #include "xbytes.h" +static CGImageRef CreateCGImageFromPixmap(Drawable pixmap); +static CGImageRef CreateCGImageFromDrawableRect( Drawable drawable, int force_1x_scale, + int x, int y, unsigned int width, unsigned int height); + /* Pixel formats * * Tk uses the XImage structure defined in Xlib.h for storing images. The @@ -510,8 +514,16 @@ TkMacOSXPutImage( return BadDrawable; } if (dc.context) { - CGRect bounds, srcRect, dstRect; + CGRect dstRect, srcRect = CGRectMake(src_x, src_y, width, height); + /* + * Whole image is copied before cropping. For performance, + * consider revising TkMacOSXCreateCGImageWithXImage() to accept + * source x/y/w/h and copy only the needed portion instead. + */ CGImageRef img = TkMacOSXCreateCGImageWithXImage(image, pixelFormat); + CGImageRef cropped = CGImageCreateWithImageInRect(img, srcRect); + CGImageRelease(img); + img = cropped; /* * The CGContext for a pixmap is RGB only, with A = 0. @@ -521,11 +533,9 @@ TkMacOSXPutImage( CGContextSetBlendMode(dc.context, kCGBlendModeSourceAtop); } if (img) { - bounds = CGRectMake(0, 0, image->width, image->height); - srcRect = CGRectMake(src_x, src_y, width, height); dstRect = CGRectMake(dest_x, dest_y, width, height); TkMacOSXDrawCGImage(drawable, gc, dc.context, img, - gc->foreground, gc->background, bounds, srcRect, dstRect); + gc->foreground, gc->background, dstRect); CFRelease(img); } else { TkMacOSXDbgMsg("Invalid source drawable"); @@ -619,6 +629,11 @@ int TkpPutRGBAImage( * with origin at the top left, as used by XImage and CGImage, not bottom * left as used by NSView. * + * If force_1x_scale is true, then the returned CGImage will be downscaled + * if necessary to have the requested width and height. Othewise, for + * windows on Retina displays, the width and height of the returned CGImage + * will be twice the requested width and height. + * * Side effects: * None * @@ -628,6 +643,7 @@ int TkpPutRGBAImage( static CGImageRef CreateCGImageFromDrawableRect( Drawable drawable, + int force_1x_scale, int x, int y, unsigned int width, @@ -636,6 +652,7 @@ CreateCGImageFromDrawableRect( MacDrawable *mac_drawable = (MacDrawable *)drawable; CGContextRef cg_context = NULL; CGImageRef cg_image = NULL, result = NULL; + CGFloat scaleFactor = 1.0; if (mac_drawable->flags & TK_IS_PIXMAP) { cg_context = TkMacOSXGetCGContextForDrawable(drawable); CGContextRetain(cg_context); @@ -645,18 +662,9 @@ CreateCGImageFromDrawableRect( TkMacOSXDbgMsg("Invalid source drawable"); return NULL; } - NSSize size = view.frame.size; - NSUInteger view_width = size.width, view_height = size.height; - NSUInteger bytesPerPixel = 4, - bytesPerRow = bytesPerPixel * view_width, - bitsPerComponent = 8; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - cg_context = CGBitmapContextCreate(NULL, view_width, view_height, - bitsPerComponent, bytesPerRow, colorSpace, - kCGImageAlphaPremultipliedLast | - kCGBitmapByteOrder32Big); - CFRelease(colorSpace); - [view.layer renderInContext:cg_context]; + scaleFactor = view.layer.contentsScale; + cg_context = ((TKContentView *)view).tkLayerBitmapContext; + CGContextRetain(cg_context); } if (cg_context) { cg_image = CGBitmapContextCreateImage(cg_context); @@ -665,7 +673,33 @@ CreateCGImageFromDrawableRect( if (cg_image) { CGRect rect = CGRectMake(x + mac_drawable->xOff, y + mac_drawable->yOff, width, height); - result = CGImageCreateWithImageInRect(cg_image, rect); + rect = CGRectApplyAffineTransform(rect, CGAffineTransformMakeScale(scaleFactor, scaleFactor)); + if (force_1x_scale && (scaleFactor != 1.0)) { + // See https://web.archive.org/web/20200219030756/http://blog.foundry376.com/2008/07/scaling-a-cgimage/#comment-200 + // create context, keeping original image properties + CGColorSpaceRef colorspace = CGImageGetColorSpace(cg_image); + cg_context = CGBitmapContextCreate(NULL, width, height, + CGImageGetBitsPerComponent(cg_image), + //CGImageGetBytesPerRow(cg_image), // wastes space? + CGImageGetBitsPerPixel(cg_image) * width / 8, + colorspace, + CGImageGetAlphaInfo(cg_image)); + CGColorSpaceRelease(colorspace); + if (cg_context) { + // Extract the subimage in the specified rectangle. + CGImageRef subimage = CGImageCreateWithImageInRect(cg_image, rect); + // Draw the subimage in our context (resizing it to fit). + CGContextDrawImage(cg_context, CGRectMake(0, 0, width, height), + subimage); + // We will return the image we just drew. + result = CGBitmapContextCreateImage(cg_context); + CGContextRelease(cg_context); + CGImageRelease(subimage); + } + } else { + // No resizing is needed. Just return the subimage + result = CGImageCreateWithImageInRect(cg_image, rect); + } CGImageRelease(cg_image); } return result; @@ -785,12 +819,13 @@ XGetImage( TCL_UNUSED(unsigned long), /* plane_mask */ int format) { - NSBitmapImageRep* bitmapRep = nil; - NSUInteger bitmap_fmt = 0; XImage* imagePtr = NULL; + NSBitmapImageRep* bitmapRep = nil; + NSBitmapFormat bitmap_fmt = 0; char *bitmap = NULL; int depth = 32, offset = 0, bitmap_pad = 0; - unsigned int bytes_per_row, size, row, n, m; + NSInteger bytes_per_row, samples_per_pixel, size; + unsigned int row, n, m; if (format == ZPixmap) { CGImageRef cgImage; @@ -798,7 +833,8 @@ XGetImage( return NULL; } - cgImage = CreateCGImageFromDrawableRect(drawable, x, y, width, height); + // Request 1x-scale image for compatibility + cgImage = CreateCGImageFromDrawableRect(drawable, 1, x, y, width, height); if (cgImage) { bitmapRep = [NSBitmapImageRep alloc]; [bitmapRep initWithCGImage:cgImage]; @@ -810,10 +846,27 @@ XGetImage( bitmap_fmt = [bitmapRep bitmapFormat]; size = [bitmapRep bytesPerPlane]; bytes_per_row = [bitmapRep bytesPerRow]; + samples_per_pixel = [bitmapRep samplesPerPixel]; +#if 0 + fprintf(stderr, "XGetImage:\n" + " bitmsp_fmt = %ld\n" + " samples_per_pixel = %ld\n" + " width = %u\n" + " height = %u\n" + " bytes_per_row = %ld\n" + " size = %ld\n", + bitmap_fmt, samples_per_pixel, width, height, bytes_per_row, size); +#endif + /* + * Image data with all pixels having alpha value 255 may be reported + * as 3 samples per pixel, even though each row has 4*width pixels and + * the pixels are stored in the default ARGB32 format. + */ + if ((bitmap_fmt != 0 && bitmap_fmt != NSAlphaFirstBitmapFormat) - || [bitmapRep samplesPerPixel] != 4 + || samples_per_pixel < 3 + || samples_per_pixel > 4 || [bitmapRep isPlanar] != 0 - || bytes_per_row < 4 * width || size != bytes_per_row * height) { TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format"); [bitmapRep release]; @@ -890,9 +943,8 @@ XCopyArea( int dest_y) { TkMacOSXDrawingContext dc; - MacDrawable *srcDraw = (MacDrawable *)src; CGImageRef img = NULL; - CGRect bounds, srcRect, dstRect; + CGRect dstRect; LastKnownRequestProcessed(display)++; if (!width || !height) { @@ -909,20 +961,13 @@ XCopyArea( return BadDrawable; } - if (srcDraw->flags & TK_IS_PIXMAP) { - img = CreateCGImageFromPixmap(src); - } else if (TkMacOSXGetNSWindowForDrawable(src)) { - img = CreateCGImageFromDrawableRect(src, src_x, src_y, width, height); - } else { - TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap."); - } + // Use unscaled source (TkMacOSXDrawCGImage() will implicitly downscale) + img = CreateCGImageFromDrawableRect(src, 0, src_x, src_y, width, height); if (img) { - 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); + gc->foreground, gc->background, dstRect); CFRelease(img); } else { TkMacOSXDbgMsg("Failed to construct CGImage."); @@ -967,7 +1012,7 @@ XCopyPlane( TkMacOSXDrawingContext dc; MacDrawable *srcDraw = (MacDrawable *)src; MacDrawable *dstDraw = (MacDrawable *)dst; - CGRect bounds, srcRect, dstRect; + CGRect srcRect, dstRect; LastKnownRequestProcessed(display)++; if (!width || !height) { /* TkMacOSXDbgMsg("Drawing of empty area requested"); */ @@ -1033,13 +1078,9 @@ XCopyPlane( CGImageRelease(submask); CGImageRelease(subimage); } else { - 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); + gc->foreground, imageBackground, dstRect); CGImageRelease(img); } } else { diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index b39a2fcc90..baa1bbe297 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -15,6 +15,7 @@ #include "tkMacOSXPrivate.h" #include "tkMacOSXConstants.h" +#include "tkMacOSXWm.h" #include #include #include @@ -41,9 +42,8 @@ static Tcl_ObjCmdProc TkMacOSVersionObjCmd; @implementation TKApplication @synthesize poolLock = _poolLock; @synthesize macOSVersion = _macOSVersion; -@synthesize isDrawing = _isDrawing; -@synthesize isSigned = _isSigned; @synthesize tkLiveResizeEnded = _tkLiveResizeEnded; +@synthesize tkWillExit = _tkWillExit; @synthesize tkPointerWindow = _tkPointerWindow; - (void) setTkPointerWindow: (TkWindow *)winPtr { @@ -137,6 +137,7 @@ static Tcl_ObjCmdProc TkMacOSVersionObjCmd; - (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app { + (void) app; return YES; } @@ -203,18 +204,7 @@ static Tcl_ObjCmdProc TkMacOSVersionObjCmd; */ Ttk_MacOSXInit(); - - /* - * It is not safe to force activation of the NSApp until this method is - * called. Activating too early can cause the menu bar to be unresponsive. - * The call to activateIgnoringOtherApps was moved here to avoid this. - * However, with the release of macOS 10.15 (Catalina) that was no longer - * sufficient. (See ticket bf93d098d7.) The call to setActivationPolicy - * needed to be moved into this function as well. - */ - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - [NSApp activateIgnoringOtherApps: YES]; /* * Add an event monitor so we continue to receive NSMouseMoved and @@ -229,15 +219,6 @@ static Tcl_ObjCmdProc TkMacOSVersionObjCmd; { return event; }]; - - /* - * Process events to ensure that the root window is fully initialized. See - * ticket 56a1823c73. - */ - - [NSApp _lockAutoreleasePool]; - while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {} - [NSApp _unlockAutoreleasePool]; } - (void) _setup: (Tcl_Interp *) interp @@ -288,12 +269,6 @@ static Tcl_ObjCmdProc TkMacOSVersionObjCmd; } [NSApp setMacOSVersion: 10000*majorVersion + 100*minorVersion]; - /* - * We are not drawing right now. - */ - - [NSApp setIsDrawing:NO]; - /* * Be our own delegate. */ @@ -429,6 +404,21 @@ TCL_NORETURN void TkpExitProc( closePanels(); } + /* + * At this point it is too late to be looking up the Tk window associated + * to any NSWindows, but it can happen. This makes sure the answer is None + * if such a query is attempted. It is also too late to be running any + * event loops, as happens in updateLayer. Set the tkWillExit flag to + * prevent this. + */ + + [NSApp setTkWillExit:YES]; + for (TKWindow *w in [NSApp orderedWindows]) { + if ([w respondsToSelector: @selector (tkWindow)]) { + [w setTkWindow: None]; + } + } + /* * Tcl_Exit does not call Tcl_Finalize if there is an exit proc installed. */ @@ -456,6 +446,26 @@ static void TkMacOSXSignalHandler(TCL_UNUSED(int)) { Tcl_Exit(1); } +/* + * This static function is run as an idle task to order the root window front. + * This is only done if the window is in the normal state. This avoids + * flashing the root window on the screen if it was withdrawn immediately after + * loading Tk. + */ + +static void showRootWindow(void *clientData) { + NSWindow *root = (NSWindow *) clientData; + if ([NSApp tkWillExit]) { + return; + } + TkWindow *winPtr = TkMacOSXGetTkWindow(root); + WmInfo *wmPtr = winPtr->wmInfoPtr; + if (wmPtr->hints.initial_state == NormalState) { + [root makeKeyAndOrderFront:NSApp]; + } + [NSApp activateIgnoringOtherApps: YES]; +} + int TkpInit( Tcl_Interp *interp) @@ -599,6 +609,9 @@ TkpInit( #if defined(USE_CUSTOM_EXIT_PROC) doCleanupFromExit = YES; #endif + } else if (getenv("TK_NO_STDERR") != NULL) { + FILE *null = fopen("/dev/null", "w"); + dup2(fileno(null), STDERR_FILENO); } /* @@ -624,14 +637,22 @@ TkpInit( * The root window has been created and mapped, but XMapWindow deferred its * call to makeKeyAndOrderFront because the first call to XMapWindow * occurs too early in the initialization process for that. Process idle - * tasks now, so the root window is configured, then order it front. + * tasks now, so the root window is configured. */ while(Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}; + for (NSWindow *window in [NSApp windows]) { TkWindow *winPtr = TkMacOSXGetTkWindow(window); if (winPtr && Tk_IsMapped(winPtr)) { - [window makeKeyAndOrderFront:NSApp]; + + /* + * Ordering the root window front in an idle task allows + * checking whether it was immediately withdrawn, and + * therefore does not need to be placed on the screen. + */ + + Tcl_DoWhenIdle(showRootWindow, window); break; } } diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index 29b20f71e9..feb6a32b39 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -88,7 +88,6 @@ typedef struct TkWindowPrivate MacDrawable; #define TK_DRAWN_UNDER_MENU 0x08 #define TK_IS_PIXMAP 0x10 #define TK_IS_BW_PIXMAP 0x20 -#define TK_DO_NOT_DRAW 0x40 #define TTK_HAS_CONTRASTING_BG 0x80 /* diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index a16eb422ef..19c7ba9837 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -64,8 +64,8 @@ static NSUInteger textInputModifiers; static NSMutableArray *nsEvArray = nil; if (nsEvArray == nil) { - nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1]; - processingCompose = NO; + nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1]; + processingCompose = NO; } if (!winPtr) { return theEvent; @@ -80,7 +80,7 @@ static NSUInteger textInputModifiers; if ([theEvent type] == NSKeyDown && [theEvent isARepeat] && [NSEvent keyRepeatDelay] < 0) { - return theEvent; + return theEvent; } /* @@ -288,8 +288,6 @@ static NSUInteger textInputModifiers; @implementation TKContentView -@synthesize tkDirtyRect = _tkDirtyRect; -@synthesize tkNeedsDisplay = _tkNeedsDisplay; /* * Implementation of the NSTextInputClient protocol. @@ -311,7 +309,7 @@ static NSUInteger textInputModifiers; Bool sendingIMEText = NO; str = ([aString isKindOfClass: [NSAttributedString class]]) ? - [aString string] : aString; + [aString string] : aString; len = [str length]; if (NS_KEYLOG) { @@ -426,7 +424,7 @@ static NSUInteger textInputModifiers; (void)selRange; str = ([aString isKindOfClass: [NSAttributedString class]]) ? - [aString string] : aString; + [aString string] : aString; if (focusWin) { /* @@ -636,12 +634,12 @@ setupXEvent(XEvent *xEvent, Tk_Window tkwin, NSUInteger modifiers) display = Tk_Display(tkwin); if (modifiers) { state = (modifiers & NSAlphaShiftKeyMask ? LockMask : 0) | - (modifiers & NSShiftKeyMask ? ShiftMask : 0) | - (modifiers & NSControlKeyMask ? ControlMask : 0) | - (modifiers & NSCommandKeyMask ? Mod1Mask : 0) | - (modifiers & NSAlternateKeyMask ? Mod2Mask : 0) | - (modifiers & NSNumericPadKeyMask ? Mod3Mask : 0) | - (modifiers & NSFunctionKeyMask ? Mod4Mask : 0) ; + (modifiers & NSShiftKeyMask ? ShiftMask : 0) | + (modifiers & NSControlKeyMask ? ControlMask : 0) | + (modifiers & NSCommandKeyMask ? Mod1Mask : 0) | + (modifiers & NSAlternateKeyMask ? Mod2Mask : 0) | + (modifiers & NSNumericPadKeyMask ? Mod3Mask : 0) | + (modifiers & NSFunctionKeyMask ? Mod4Mask : 0) ; } memset(xEvent, 0, sizeof(XEvent)); xEvent->xany.serial = LastKnownRequestProcessed(display); diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c index f02144f4f2..f898496a9d 100644 --- a/macosx/tkMacOSXKeyboard.c +++ b/macosx/tkMacOSXKeyboard.c @@ -268,7 +268,7 @@ UpdateKeymaps() */ for (index = 3; index >= 0; index--) { - for (virt = 0; virt < 128; virt++) { + for (virt = 0; virt < 128; virt++) { MacKeycode macKC; macKC.v = (keycode_v) {.virt = virt, .o_s = index, .keychar = 0}; int modifiers = INDEX2CARBON(index); @@ -288,7 +288,7 @@ UpdateKeymaps() hPtr = Tcl_CreateHashEntry(&unichar2xvirtual, INT2PTR(macKC.x.keychar), &dummy); Tcl_SetHashValue(hPtr, INT2PTR(macKC.x.xvirtual)); - } + } xvirtual2unichar[macKC.x.xvirtual] = macKC.x.keychar; } } @@ -501,7 +501,7 @@ TkpGetString( macKC.uint = eventPtr->xkey.keycode; if (IS_PRINTABLE(macKC.v.keychar)) { - length = TkUniCharToUtf(macKC.v.keychar, utfChars); + length = Tcl_UniCharToUtf(macKC.v.keychar, utfChars); } utfChars[length] = 0; diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index 8bcd657b03..bf41d6654d 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -960,8 +960,6 @@ TkpPostMenu( } realWin = Tk_Parent(realWin); } - NSWindow *win = [realWinView window]; - NSView *view = [win contentView]; NSMenu *menu = (NSMenu *) menuPtr->platformData; NSInteger itemIndex = index; NSInteger numItems = [menu numberOfItems]; @@ -991,8 +989,9 @@ TkpPostMenu( } [menu popUpMenuPositioningItem:item - atLocation:[win tkConvertPointFromScreen:location] - inView:view]; + atLocation:location + inView:nil + appearance:realWinView.effectiveAppearance]; inPostMenu = false; return TCL_OK; } diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 83d2cd2230..062a12596b 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -504,8 +504,9 @@ enum { state |= Tk_GetButtonMask(Button1); } if (eventType == NSMouseEntered) { - Tk_UpdatePointer((Tk_Window) [NSApp tkPointerWindow], - global.x, global.y, state); + Tk_Window new_win = Tk_CoordsToWindow(global.x, global.y, + (Tk_Window) [NSApp tkPointerWindow]); + Tk_UpdatePointer(new_win, global.x, global.y, state); } else if (eventType == NSMouseExited) { if ([NSApp tkDragTarget]) { Tk_UpdatePointer((Tk_Window) [NSApp tkDragTarget], @@ -883,9 +884,9 @@ TkpWarpPointer( CGWarpMouseCursorPosition(pt); if (dispPtr->warpWindow) { - TkGenerateButtonEventForXPointer(Tk_WindowId(dispPtr->warpWindow)); + TkGenerateButtonEventForXPointer(Tk_WindowId(dispPtr->warpWindow)); } else { - TkGenerateButtonEventForXPointer(None); + TkGenerateButtonEventForXPointer(None); } } diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index 0927024b9e..bdb1ef9b26 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -16,34 +16,6 @@ #include "tkMacOSXPrivate.h" #include "tkMacOSXInt.h" #include "tkMacOSXConstants.h" -#if TCL_MAJOR_VERSION < 9 -#undef Tcl_MacOSXNotifierAddRunLoopMode -#ifdef USE_TCL_STUBS -#ifdef __cplusplus -extern "C" { -#endif -/* Little hack to eliminate the need for "tclInt.h" here: - Just copy a small portion of TclIntPlatStubs, just - enough to make it work. See [600b72bfbc] */ -typedef struct TclIntPlatStubs { - int magic; - void *hooks; - void (*dummy[19]) (void); /* dummy entries 0-18, not used */ - void (*tclMacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 19 */ -} TclIntPlatStubs; -extern const TclIntPlatStubs *tclIntPlatStubsPtr; -#ifdef __cplusplus -} -#endif -#define Tcl_MacOSXNotifierAddRunLoopMode \ - (tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */ -#elif TCL_MINOR_VERSION < 7 - extern void TclMacOSXNotifierAddRunLoopMode(const void *runLoopMode); -# define Tcl_MacOSXNotifierAddRunLoopMode TclMacOSXNotifierAddRunLoopMode -#else - extern void Tcl_MacOSXNotifierAddRunLoopMode(const void *runLoopMode); -#endif -#endif #import /* This is not used for anything at the moment. */ @@ -217,7 +189,6 @@ void DebugPrintQueue(void) - (void) _runBackgroundLoop { while(Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_TIMER_EVENTS|TCL_DONT_WAIT)){ - TkMacOSXDrawAllViews(NULL); } } @end @@ -330,88 +301,6 @@ TkMacOSXNotifyExitHandler( tsdPtr->initialized = 0; } -/* - *---------------------------------------------------------------------- - * - * TkMacOSXDrawAllViews -- - * - * This static function is meant to be run as an idle task. It attempts - * to redraw all views which have the tkNeedsDisplay property set to YES. - * This relies on a feature of [NSApp nextEventMatchingMask: ...] which - * is undocumented, namely that it sometimes blocks and calls drawRect - * 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 times when any NSViews have the needsDisplay property set to YES - * are during execution of this function or in the addTkDirtyRect 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 - * drawn. Any idle tasks that might reconfigure them should be higher on - * the idle queue, so they should be run before the display procs are run - * by drawRect. - * - * If this function is called directly with non-NULL clientData parameter - * then the int which it references will be set to the number of windows - * that need display, but the needsDisplay property of those windows will - * not be changed. - * - * Results: - * None. - * - * Side effects: - * Parts of windows may get redrawn. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXDrawAllViews( - void *clientData) -{ - int count = 0, *dirtyCount = (int *)clientData; - - for (NSWindow *window in [NSApp windows]) { - if ([[window contentView] isMemberOfClass:[TKContentView class]]) { - TKContentView *view = [window contentView]; - if ([view tkNeedsDisplay]) { - count++; - if (dirtyCount) { - continue; - } - [[view layer] setNeedsDisplayInRect:[view tkDirtyRect]]; - [view setNeedsDisplay:YES]; - } - } else { - [window displayIfNeeded]; - } - } - if (dirtyCount) { - *dirtyCount = count; - } - [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:GetRunLoopMode(TkMacOSXGetModalSession()) - dequeue:NO]; - for (NSWindow *window in [NSApp windows]) { - if ([[window contentView] isMemberOfClass:[TKContentView class]]) { - TKContentView *view = [window contentView]; - - /* - * If we did not run drawRect, we set needsDisplay back to NO. - * Note that if drawRect did run it may have added to Tk's dirty - * rect, due to attempts to draw outside of drawRect's dirty rect. - */ - - if ([view needsDisplay]) { - [view setNeedsDisplay: NO]; - } - } - } - [NSApp setNeedsToDraw:NO]; -} - /* *---------------------------------------------------------------------- * @@ -476,11 +365,11 @@ TkMacOSXEventsSetupProc( */ NSEvent *currentEvent = - [NSApp nextEventMatchingMask:NSAnyEventMask + [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:GetRunLoopMode(TkMacOSXGetModalSession()) dequeue:NO]; - if ((currentEvent) || [NSApp needsToDraw] ) { + if ((currentEvent)) { Tcl_SetMaxBlockTime(&zeroBlockTime); Tcl_DeleteTimerHandler(ticker); ticker = NULL; @@ -588,25 +477,6 @@ TkMacOSXEventsCheckProc( */ [NSApp _unlockAutoreleasePool]; - - /* - * Add an idle task to the end of the idle queue which will redisplay - * all of our dirty windows. We want this to happen after all other - * idle tasks have run so that all widgets will be configured before - * they are displayed. The drawRect method "borrows" the idle queue - * while drawing views. That is, it sends expose events which cause - * display procs to be posted as idle tasks and then runs an inner - * event loop to processes those idle tasks. We are trying to arrange - * for the idle queue to be empty when it starts that process and empty - * when it finishes. - */ - - int dirtyCount = 0; - TkMacOSXDrawAllViews(&dirtyCount); - if (dirtyCount > 0) { - Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL); - Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL); - } } } diff --git a/macosx/tkMacOSXPrint.c b/macosx/tkMacOSXPrint.c index ee30e1ff9f..ac29714129 100644 --- a/macosx/tkMacOSXPrint.c +++ b/macosx/tkMacOSXPrint.c @@ -92,8 +92,8 @@ StartPrint( /* Check for proper number of arguments. */ if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "file"); - return TCL_ERROR; + Tcl_WrongNumArgs(interp, 1, objv, "file"); + return TCL_ERROR; } fileName = [NSString stringWithUTF8String: Tcl_GetString(objv[1])]; @@ -105,20 +105,20 @@ StartPrint( status = PMCreateSession( & printSession); if (status != noErr) { - NSLog(@ "Error creating print session."); - return TCL_ERROR; + NSLog(@ "Error creating print session."); + return TCL_ERROR; } status = PMCreatePrintSettings( & printSettings); if (status != noErr) { - NSLog(@ "Error creating print settings."); - return TCL_ERROR; + NSLog(@ "Error creating print settings."); + return TCL_ERROR; } status = PMSessionDefaultPrintSettings(printSession, printSettings); if (status != noErr) { - NSLog(@ "Error creating default print settings."); - return TCL_ERROR; + NSLog(@ "Error creating default print settings."); + return TCL_ERROR; } printSession = (PMPrintSession)[printInfo PMPrintSession]; @@ -163,25 +163,25 @@ FinishPrint( * otherwise printing will occur regardless of value. */ if (buttonValue == NSModalResponseCancel) { - return noErr; + return noErr; } status = PMCreateSession( & printSession); if (status != noErr) { - NSLog(@ "Error creating print session."); - return status; + NSLog(@ "Error creating print session."); + return status; } status = PMCreatePrintSettings( & printSettings); if (status != noErr) { - NSLog(@ "Error creating print settings."); - return status; + NSLog(@ "Error creating print settings."); + return status; } status = PMSessionDefaultPrintSettings(printSession, printSettings); if (status != noErr) { - NSLog(@ "Error creating default print settings."); - return status; + NSLog(@ "Error creating default print settings."); + return status; } printSession = (PMPrintSession)[printInfo PMPrintSession]; @@ -191,81 +191,81 @@ FinishPrint( /*Handle print operation.*/ if (buttonValue == NSModalResponseOK) { - if (urlFile == NULL) { - NSLog(@ "Could not get file to print."); - return noErr; - } - - fileName = file; - - CFURLRef printURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, urlFile, kCFURLPOSIXPathStyle, false); - - PMPrinter currentPrinter; - PMDestinationType printDestination; - - /*Get the intended destination.*/ - status = PMSessionGetDestinationType(printSession, printSettings, & printDestination); - - /*Destination is printer. Send file to printer.*/ - if (status == noErr && printDestination == kPMDestinationPrinter) { - - status = PMSessionGetCurrentPrinter(printSession, & currentPrinter); - if (status == noErr) { - CFArrayRef mimeTypes; - status = PMPrinterGetMimeTypes(currentPrinter, printSettings, & mimeTypes); - if (status == noErr && mimeTypes != NULL) { - mimeType = CFSTR("application/pdf"); - if (CFArrayContainsValue(mimeTypes, CFRangeMake(0, CFArrayGetCount(mimeTypes)), mimeType)) { - status = PMPrinterPrintWithFile(currentPrinter, printSettings, pageFormat, mimeType, printURL); - CFRelease(urlFile); - return status; - } - } - } - } - - /* Destination is file. Determine how to handle. */ - if (status == noErr && printDestination == kPMDestinationFile) { - CFURLRef outputLocation = NULL; - - status = PMSessionCopyDestinationLocation(printSession, printSettings, & outputLocation); - if (status == noErr) { - /*Get the source file and target destination, convert to strings.*/ - CFStringRef sourceFile = CFURLCopyFileSystemPath(printURL, kCFURLPOSIXPathStyle); - CFStringRef savePath = CFURLCopyFileSystemPath(outputLocation, kCFURLPOSIXPathStyle); - NSString * sourcePath = (NSString * ) sourceFile; - NSString * finalPath = (NSString * ) savePath; - NSString * pathExtension = [finalPath pathExtension]; - NSFileManager * fileManager = [NSFileManager defaultManager]; + if (urlFile == NULL) { + NSLog(@ "Could not get file to print."); + return noErr; + } + + fileName = file; + + CFURLRef printURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, urlFile, kCFURLPOSIXPathStyle, false); + + PMPrinter currentPrinter; + PMDestinationType printDestination; + + /*Get the intended destination.*/ + status = PMSessionGetDestinationType(printSession, printSettings, & printDestination); + + /*Destination is printer. Send file to printer.*/ + if (status == noErr && printDestination == kPMDestinationPrinter) { + + status = PMSessionGetCurrentPrinter(printSession, & currentPrinter); + if (status == noErr) { + CFArrayRef mimeTypes; + status = PMPrinterGetMimeTypes(currentPrinter, printSettings, & mimeTypes); + if (status == noErr && mimeTypes != NULL) { + mimeType = CFSTR("application/pdf"); + if (CFArrayContainsValue(mimeTypes, CFRangeMake(0, CFArrayGetCount(mimeTypes)), mimeType)) { + status = PMPrinterPrintWithFile(currentPrinter, printSettings, pageFormat, mimeType, printURL); + CFRelease(urlFile); + return status; + } + } + } + } + + /* Destination is file. Determine how to handle. */ + if (status == noErr && printDestination == kPMDestinationFile) { + CFURLRef outputLocation = NULL; + + status = PMSessionCopyDestinationLocation(printSession, printSettings, & outputLocation); + if (status == noErr) { + /*Get the source file and target destination, convert to strings.*/ + CFStringRef sourceFile = CFURLCopyFileSystemPath(printURL, kCFURLPOSIXPathStyle); + CFStringRef savePath = CFURLCopyFileSystemPath(outputLocation, kCFURLPOSIXPathStyle); + NSString * sourcePath = (NSString * ) sourceFile; + NSString * finalPath = (NSString * ) savePath; + NSString * pathExtension = [finalPath pathExtension]; + NSFileManager * fileManager = [NSFileManager defaultManager]; NSError * error = nil; - /* + /* * Is the target file a PDF? If so, copy print file * to output location. */ - if ([pathExtension isEqualToString: @ "pdf"]) { + if ([pathExtension isEqualToString: @ "pdf"]) { /*Make sure no file conflict exists.*/ if ([fileManager fileExistsAtPath: finalPath]) { [fileManager removeItemAtPath: finalPath error: &error]; } - if ([fileManager fileExistsAtPath: sourcePath]) { - error = nil; - [fileManager copyItemAtPath: sourcePath toPath: finalPath error: & error]; - } + if ([fileManager fileExistsAtPath: sourcePath]) { + error = nil; + [fileManager copyItemAtPath: sourcePath toPath: finalPath error: & error]; + } return status; - } - - /* - * Is the target file PostScript? If so, run print file - * through CUPS filter to convert back to PostScript. - */ - - if ([pathExtension isEqualToString: @ "ps"]) { - char source[5012]; - char target[5012]; - [sourcePath getCString: source maxLength: (sizeof source) encoding: NSUTF8StringEncoding]; - [finalPath getCString: target maxLength: (sizeof target) encoding: NSUTF8StringEncoding]; + } + + /* + * Is the target file PostScript? If so, run print file + * through CUPS filter to convert back to PostScript. + */ + + if ([pathExtension isEqualToString: @ "ps"]) { + char source[5012]; + char target[5012]; + [sourcePath getCString: source maxLength: (sizeof source) encoding: NSUTF8StringEncoding]; + [finalPath getCString: target maxLength: (sizeof target) encoding: NSUTF8StringEncoding]; /*Make sure no file conflict exists.*/ if ([fileManager fileExistsAtPath: finalPath]) { [fileManager removeItemAtPath: finalPath error: &error]; @@ -290,39 +290,39 @@ FinishPrint( } } - /* Destination is preview. Open file in default application for PDF. */ - if ((status == noErr) && (printDestination == kPMDestinationPreview)) { - CFStringRef urlpath = CFURLCopyFileSystemPath(printURL, kCFURLPOSIXPathStyle); - NSString * path = (NSString * ) urlpath; - NSURL * url = [NSURL fileURLWithPath: path]; - NSWorkspace * ws = [NSWorkspace sharedWorkspace]; - [ws openURL: url]; - status = noErr; - return status; - } - - /* - * If destination is not printer, file or preview, - * we do not support it. Display alert. - */ + /* Destination is preview. Open file in default application for PDF. */ + if ((status == noErr) && (printDestination == kPMDestinationPreview)) { + CFStringRef urlpath = CFURLCopyFileSystemPath(printURL, kCFURLPOSIXPathStyle); + NSString * path = (NSString * ) urlpath; + NSURL * url = [NSURL fileURLWithPath: path]; + NSWorkspace * ws = [NSWorkspace sharedWorkspace]; + [ws openURL: url]; + status = noErr; + return status; + } + + /* + * If destination is not printer, file or preview, + * we do not support it. Display alert. + */ if (((status == noErr) && (printDestination != kPMDestinationPreview)) || ((status == noErr) && (printDestination != kPMDestinationFile)) || ((status == noErr) && (printDestination != kPMDestinationPrinter))) { - NSAlert * alert = [[[NSAlert alloc] init] autorelease]; - [alert addButtonWithTitle: @ "OK"]; + NSAlert * alert = [[[NSAlert alloc] init] autorelease]; + [alert addButtonWithTitle: @ "OK"]; - [alert setMessageText: @ "Unsupported Printing Operation"]; - [alert setInformativeText: @ "This printing operation is not supported."]; - [alert setAlertStyle: NSAlertStyleInformational]; - [alert runModal]; - return status; - } + [alert setMessageText: @ "Unsupported Printing Operation"]; + [alert setInformativeText: @ "This printing operation is not supported."]; + [alert setAlertStyle: NSAlertStyleInformational]; + [alert runModal]; + return status; + } } /* Return because cancel button was clicked. */ if (buttonValue == NSModalResponseCancel) { - PMRelease(printSession); - return status; + PMRelease(printSession); + return status; } return status; diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index de230da416..c55c8ad5f6 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -166,7 +166,7 @@ typedef union MacKeycode_t { #define ON_KEYPAD(virt) ((virt >= 0x41) && (virt <= 0x5C)) #define IS_PRINTABLE(keychar) ((keychar >= 0x20) && (keychar != 0x7f) && \ - ((keychar < 0xF700) || keychar >= 0xF8FF)) + ((keychar < 0xF700) || keychar >= 0xF8FF)) /* * An "index" is 2-bit bitfield showing the state of the Option and Shift @@ -240,14 +240,14 @@ MODULE_SCOPE int TkMacOSXIsWindowZoomed(TkWindow *winPtr); MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window); MODULE_SCOPE void TkMacOSXDrawCGImage(Drawable d, GC gc, CGContextRef context, CGImageRef image, unsigned long imageForeground, - unsigned long imageBackground, CGRect imageBounds, - CGRect srcBounds, CGRect dstBounds); + unsigned long imageBackground, CGRect dstBounds); MODULE_SCOPE int TkMacOSXSetupDrawingContext(Drawable d, GC gc, TkMacOSXDrawingContext *dcPtr); MODULE_SCOPE void TkMacOSXRestoreDrawingContext( TkMacOSXDrawingContext *dcPtr); MODULE_SCOPE void TkMacOSXSetColorInContext(GC gc, unsigned long pixel, CGContextRef context); +MODULE_SCOPE void TkMacOSXRedrawViewIdleTask(void *clientData); #define TkMacOSXGetTkWindow(window) ((TkWindow *)Tk_MacOSXGetTkWindow(window)) #define TkMacOSXGetNSWindowForDrawable(drawable) ((NSWindow *)Tk_MacOSXGetNSWindowForDrawable(drawable)) #define TkMacOSXGetNSViewForDrawable(macWin) ((NSView *)Tk_MacOSXGetNSViewForDrawable((Drawable)(macWin))) @@ -320,10 +320,8 @@ VISIBILITY_HIDDEN } @property int poolLock; @property int macOSVersion; -@property Bool isDrawing; -@property Bool needsToDraw; -@property Bool isSigned; @property Bool tkLiveResizeEnded; +@property Bool tkWillExit; /* * Persistent state variables used by processMouseEvent. @@ -392,7 +390,7 @@ VISIBILITY_HIDDEN - (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent; - (void)handleURLEvent: (NSAppleEventDescriptor*)event - withReplyEvent: (NSAppleEventDescriptor*)replyEvent; + withReplyEvent: (NSAppleEventDescriptor*)replyEvent; @end VISIBILITY_HIDDEN @@ -405,12 +403,9 @@ VISIBILITY_HIDDEN { @private NSString *privateWorkingText; - Bool _tkNeedsDisplay; - NSRect _tkDirtyRect; NSTrackingArea *trackingArea; } -@property Bool tkNeedsDisplay; -@property NSRect tkDirtyRect; +@property CGContextRef tkLayerBitmapContext; @end @interface TKContentView(TKKeyEvent) @@ -419,10 +414,9 @@ VISIBILITY_HIDDEN @end @interface TKContentView(TKWindowEvent) -- (void) addTkDirtyRect: (NSRect) rect; -- (void) clearTkDirtyRect; - (void) generateExposeEvents: (NSRect) rect; - (void) tkToolbarButton: (id) sender; +- (void) resetTkLayerBitmapContext; @end @interface NSWindow(TKWm) @@ -467,6 +461,14 @@ VISIBILITY_HIDDEN - (NSMenuItem *)itemInSupermenu; @end +// Need undocumented appearance: argument +@interface NSMenu(TKMenu) +- (BOOL)popUpMenuPositioningItem:(NSMenuItem *)item + atLocation:(NSPoint)location + inView:(NSView *)view + appearance:(NSAppearance *)appearance; +@end + @interface NSMenuItem(TKUtils) + (id)itemWithSubmenu:(NSMenu *)submenu; + (id)itemWithTitle:(NSString *)title submenu:(NSMenu *)submenu; @@ -522,18 +524,11 @@ VISIBILITY_HIDDEN * * TKNSString -- * - * 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. Instead, when using these versions of Tcl, Tk - * uses the CESU-8 encoding internally. This encoding is similar to UTF-8 - * except that it allows encoding surrogate characters as 3-byte sequences - * using the same algorithm which UTF-8 uses for non-surrogates. This means - * that a non-BMP character is encoded as a string of length 6. Apple's - * NSString class does not provide a constructor which accepts a CESU-8 encoded + * Tcl uses modified UTF-8 as internal encoding. Apple's NSString class + * does not provide a constructor which accepts a modified UTF-8 encoded * byte sequence as initial data. So we add a new class which does provide * such a constructor. It also has a DString property which is a DString whose - * string pointer is a byte sequence encoding the NSString with the current Tcl - * internal encoding, namely UTF-8 for Tcl8.7+ or CESU-8 otherwise. + * string pointer is a byte sequence encoding the NSString with modified UTF-8. * *--------------------------------------------------------------------------- */ diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index 7335529223..48ebd9e07f 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -183,7 +183,7 @@ static void drawMacScrollbar( if (scrollPtr->vertical) { thumbOrigin.x = troughBounds.origin.x + MIN_GAP; thumbOrigin.y = troughBounds.origin.y + scrollPtr->sliderFirst; - thumbSize.width = troughBounds.size.width - 2*MIN_GAP + 1; + thumbSize.width = troughBounds.size.width - 2 * MIN_GAP + 1; thumbSize.height = scrollPtr->sliderLast - scrollPtr->sliderFirst; inner[0] = troughBounds.origin; inner[1] = CGPointMake(inner[0].x, @@ -195,7 +195,7 @@ static void drawMacScrollbar( thumbOrigin.x = troughBounds.origin.x + scrollPtr->sliderFirst; thumbOrigin.y = troughBounds.origin.y + MIN_GAP; thumbSize.width = scrollPtr->sliderLast - scrollPtr->sliderFirst; - thumbSize.height = troughBounds.size.height - 2*MIN_GAP + 1; + thumbSize.height = troughBounds.size.height - 2 * MIN_GAP + 1; inner[0] = troughBounds.origin; inner[1] = CGPointMake(inner[0].x + troughBounds.size.width, inner[0].y + 1); @@ -259,7 +259,6 @@ TkpDisplayScrollbar( NSView *view = TkMacOSXGetNSViewForDrawable(macWin); if ((view == NULL) - || (macWin->flags & TK_DO_NOT_DRAW) || !TkMacOSXSetupDrawingContext((Drawable)macWin, NULL, &dc)) { return; } @@ -379,7 +378,7 @@ TkpComputeScrollbarGeometry( } fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin) : Tk_Width(scrollPtr->tkwin)) - - 2*(scrollPtr->arrowLength + scrollPtr->inset); + - 2 * (scrollPtr->arrowLength + scrollPtr->inset); if (fieldLength < 0) { fieldLength = 0; } @@ -418,13 +417,13 @@ TkpComputeScrollbarGeometry( if (scrollPtr->vertical) { Tk_GeometryRequest(scrollPtr->tkwin, scrollPtr->width + 2*scrollPtr->inset, - 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + 2 * (scrollPtr->arrowLength + scrollPtr->borderWidth + scrollPtr->inset) + metrics.minThumbHeight); } else { Tk_GeometryRequest(scrollPtr->tkwin, - 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + 2 * (scrollPtr->arrowLength + scrollPtr->borderWidth + scrollPtr->inset) + metrics.minThumbHeight, - scrollPtr->width + 2*scrollPtr->inset); + scrollPtr->width + 2 * scrollPtr->inset); } Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset); } @@ -545,7 +544,7 @@ TkpScrollbarPosition( if (y < scrollPtr->sliderLast) { return SLIDER; } - if (y < length - (2*scrollPtr->arrowLength + inset)) { + if (y < length - (2 * scrollPtr->arrowLength + inset)) { return BOTTOM_GAP; } diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index a4208988ed..2c154452e1 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -56,32 +56,37 @@ XDestroyWindow( Window window) /* Window. */ { MacDrawable *macWin = (MacDrawable *)window; + TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(macWin); + //fprintf(stderr, "XDestroyWindow: %s with parent %s\n", + // Tk_PathName(macWin->winPtr), + // Tk_PathName(macWin->winPtr->parentPtr)); /* * Remove any dangling pointers that may exist if the window we are * deleting is being tracked by the grab code. */ - TkPointerDeadWindow(macWin->winPtr); TkMacOSXSelDeadWindow(macWin->winPtr); + TkPointerDeadWindow(macWin->winPtr); macWin->toplevel->referenceCount--; if (!Tk_IsTopLevel(macWin->winPtr)) { - TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); if (macWin->winPtr->parentPtr != NULL) { TkMacOSXInvalClipRgns((Tk_Window)macWin->winPtr->parentPtr); + Tcl_CancelIdleCall(TkMacOSXRedrawViewIdleTask, (void *) view); + Tcl_DoWhenIdle(TkMacOSXRedrawViewIdleTask, (void *) view); } if (macWin->visRgn) { CFRelease(macWin->visRgn); - macWin->visRgn = NULL; + macWin->visRgn = NULL; } if (macWin->aboveVisRgn) { CFRelease(macWin->aboveVisRgn); - macWin->aboveVisRgn = NULL; + macWin->aboveVisRgn = NULL; } if (macWin->drawRgn) { CFRelease(macWin->drawRgn); - macWin->drawRgn = NULL; + macWin->drawRgn = NULL; } if (macWin->toplevel->referenceCount == 0) { @@ -93,15 +98,15 @@ XDestroyWindow( } if (macWin->visRgn) { CFRelease(macWin->visRgn); - macWin->visRgn = NULL; + macWin->visRgn = NULL; } if (macWin->aboveVisRgn) { CFRelease(macWin->aboveVisRgn); - macWin->aboveVisRgn = NULL; + macWin->aboveVisRgn = NULL; } if (macWin->drawRgn) { CFRelease(macWin->drawRgn); - macWin->drawRgn = NULL; + macWin->drawRgn = NULL; } macWin->view = nil; macWin->winPtr->privatePtr = NULL; @@ -147,11 +152,10 @@ XMapWindow( return BadWindow; } MacDrawable *macWin = (MacDrawable *)window; - TkWindow *winPtr = macWin->winPtr; - NSWindow *win = TkMacOSXGetNSWindowForDrawable(window); static Bool initialized = NO; NSPoint mouse = [NSEvent mouseLocation]; int x = mouse.x, y = TkMacOSXZeroScreenHeight() - mouse.y; + //fprintf(stderr, "XMapWindow: %s\n", Tk_PathName(macWin->winPtr)); /* * Under certain situations it's possible for this function to be called @@ -165,29 +169,44 @@ XMapWindow( TkMacOSXMakeRealWindowExist(macWin->toplevel->winPtr); } + TkWindow *winPtr = macWin->winPtr; + NSWindow *win = TkMacOSXGetNSWindowForDrawable(window); + TKContentView *view = [win contentView]; LastKnownRequestProcessed(display)++; if (Tk_IsTopLevel(winPtr)) { if (!Tk_IsEmbedded(winPtr)) { - TKContentView *view = [win contentView]; /* - * We want to activate Tk when a toplevel is mapped but we must not - * supply YES here. This is because during Tk initialization the - * root window is mapped before applicationDidFinishLaunching - * returns. Forcing the app to activate too early can make the menu - * bar unresponsive. + * We want to activate Tk when a toplevel is mapped but we can't + * always specify activateIgnoringOtherApps to be YES. This is + * because during Tk initialization the root window is mapped + * before applicationDidFinishLaunching returns. Forcing the app to + * activate too early can make the menu bar unresponsive. */ TkMacOSXApplyWindowAttributes(winPtr, win); [win setExcludedFromWindowsMenu:NO]; [NSApp activateIgnoringOtherApps:initialized]; - [view addTkDirtyRect: [view bounds]]; if (initialized) { if ([win canBecomeKeyWindow]) { [win makeKeyAndOrderFront:NSApp]; } else { [win orderFrontRegardless]; } + + /* + * Delay for up to 20 milliseconds until the toplevel has + * actually become the highest toplevel. This is to ensure + * that the Visibility event occurs after the toplevel is + * visible. + */ + + for (int try = 0; try < 20; try++) { + if ([[NSApp orderedWindows] firstObject] == win) { + break; + } + [NSThread sleepForTimeInterval:.001]; + } } /* @@ -208,9 +227,7 @@ XMapWindow( */ TkMacOSXInvalClipRgns(contWinPtr); - TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); } - TkMacOSXInvalClipRgns((Tk_Window)winPtr); } else { /* @@ -222,14 +239,13 @@ XMapWindow( } /* - * Mark the toplevel as needing to be redrawn, unless the window is being - * mapped while drawing is taking place. + * If a geometry manager is mapping hundreds of windows we + * don't want to redraw the view hundreds of times, so do + * it in an idle task. */ - TKContentView *view = [win contentView]; - if (view != [NSView focusView]) { - [view addTkDirtyRect:[view bounds]]; - } + Tcl_CancelIdleCall(TkMacOSXRedrawViewIdleTask, (void *) view); + Tcl_DoWhenIdle(TkMacOSXRedrawViewIdleTask, (void *) view); /* * Generate VisibilityNotify events for window and all mapped children. @@ -253,7 +269,8 @@ XMapWindow( * * NotifyVisibility -- * - * Recursively called helper proc for XMapWindow(). + * Helper for XMapWindow(). Generates VisibilityNotify events + * for the window and all of its descendants. * * Results: * None. @@ -308,7 +325,6 @@ XUnmapWindow( { MacDrawable *macWin = (MacDrawable *)window; TkWindow *winPtr = macWin->winPtr; - TkWindow *parentPtr = winPtr->parentPtr; NSWindow *win = TkMacOSXGetNSWindowForDrawable(window); if (!window) { @@ -353,22 +369,12 @@ XUnmapWindow( } else { /* - * Rebuild the visRgn clip region for the parent so it will be allowed + * Rebuild the clip regions for the parent so it will be allowed * to draw in the space from which this subwindow was removed and then * redraw the window. */ - if (parentPtr && parentPtr->privatePtr->visRgn) { - TkMacOSXInvalidateViewRegion( - TkMacOSXGetNSViewForDrawable(parentPtr->window), - parentPtr->privatePtr->visRgn); - } - TkMacOSXInvalClipRgns((Tk_Window)parentPtr); - TkMacOSXUpdateClipRgn(parentPtr); - } - TKContentView *view = [win contentView]; - if (view != [NSView focusView]) { - [view addTkDirtyRect:[view bounds]]; + TkMacOSXInvalClipRgns((Tk_Window)winPtr->parentPtr); } return Success; } @@ -408,7 +414,6 @@ XResizeWindow( [(TKWindow *)w tkLayoutChanged]; } else { NSRect r = [w contentRectForFrameRect:[w frame]]; - r.origin.y += r.size.height - height; r.size.width = width; r.size.height = height; @@ -739,77 +744,13 @@ XConfigureWindow( NSView *view = TkMacOSXGetNSViewForDrawable(macWin); if (view) { - TkMacOSXInvalClipRgns((Tk_Window)winPtr->parentPtr); - TkpRedrawWidget((Tk_Window)winPtr); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); } } -#if 0 - TkGenWMMoveRequestEvent(macWin->winPtr, - macWin->winPtr->changes.x, macWin->winPtr->changes.y); -#endif return Success; } -/* - *---------------------------------------------------------------------- - * - * TkMacOSXSetDrawingEnabled -- - * - * This function sets the TK_DO_NOT_DRAW flag for a given window and - * all of its children. - * - * Results: - * None. - * - * Side effects: - * The clipping regions for the window and its children are cleared. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXSetDrawingEnabled( - TkWindow *winPtr, - int flag) -{ - TkWindow *childPtr; - MacDrawable *macWin = winPtr->privatePtr; - - if (macWin) { - if (flag) { - macWin->flags &= ~TK_DO_NOT_DRAW; - } else { - macWin->flags |= TK_DO_NOT_DRAW; - } - } - - /* - * Set the flag for all children & their descendants, excluding Toplevels. - * (??? Do we need to exclude Toplevels?) - */ - - childPtr = winPtr->childList; - while (childPtr) { - if (!Tk_IsTopLevel(childPtr)) { - TkMacOSXSetDrawingEnabled(childPtr, flag); - } - childPtr = childPtr->nextPtr; - } - - /* - * If the window is a container, set the flag for its embedded window. - */ - - if (Tk_IsContainer(winPtr)) { - childPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr); - - if (childPtr) { - TkMacOSXSetDrawingEnabled(childPtr, flag); - } - } -} - /* *---------------------------------------------------------------------- * @@ -964,6 +905,7 @@ TkMacOSXUpdateClipRgn( } } +// Unused and misspelled stub function /* *---------------------------------------------------------------------- * @@ -992,6 +934,10 @@ TkMacOSXVisableClipRgn( return (Region) HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn); } +#if 0 +//This code is not currently used. But it shows how to iterate over the +//rectangles in a region described by an HIShape. + /* *---------------------------------------------------------------------- * @@ -1029,9 +975,9 @@ InvalViewRect( break; case kHIShapeEnumerateRect: dirtyRect = NSRectFromCGRect(CGRectApplyAffineTransform(*rect, t)); - [view addTkDirtyRect:dirtyRect]; break; } + [view generateExposeEvents:[view bounds]]; return noErr; } @@ -1046,22 +992,34 @@ TkMacOSXInvalidateViewRegion( InvalViewRect, view); } } +#endif /* *---------------------------------------------------------------------- * * TkMacOSXInvalidateWindow -- * - * This function invalidates a window and (optionally) its children. + * This stub function redraws the part of the toplevel window + * covered by a given Tk window. (Except currently it redraws + * the entire toplevel.) * * Results: * None. * * Side effects: - * Damage is created. + * The window is redrawn. * *---------------------------------------------------------------------- */ +void +TkMacOSXRedrawViewIdleTask( + void *clientData) +{ + TKContentView *view = (TKContentView *) clientData; + // fprintf(stderr, "idle redraw for %p\n", view); + [view generateExposeEvents:[view bounds]]; + [view setNeedsDisplay:YES]; +} void TkMacOSXInvalidateWindow( @@ -1072,11 +1030,16 @@ TkMacOSXInvalidateWindow( #ifdef TK_MAC_DEBUG_CLIP_REGIONS TkMacOSXDbgMsg("%s", macWin->winPtr->pathName); #endif - if (macWin->flags & TK_CLIP_INVALID) { - TkMacOSXUpdateClipRgn(macWin->winPtr); + TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(macWin); + TkWindow *winPtr = macWin->winPtr; + Tk_Window tkwin = (Tk_Window) winPtr; + Tk_Window parent = (Tk_Window) winPtr->parentPtr; + TkMacOSXInvalClipRgns(tkwin); + if ((flag == TK_PARENT_WINDOW) && parent){ + TkMacOSXInvalClipRgns(parent); } - TkMacOSXInvalidateViewRegion(TkMacOSXGetNSViewForDrawable(macWin), - (flag == TK_WINDOW_ONLY) ? macWin->visRgn : macWin->aboveVisRgn); + [view generateExposeEvents:[view bounds]]; + [view setNeedsDisplay:YES]; } /* @@ -1105,17 +1068,19 @@ Tk_MacOSXGetNSWindowForDrawable( if (!macWin || macWin->flags & TK_IS_PIXMAP) { result = nil; + } else if (macWin->toplevel && macWin->toplevel->winPtr && macWin->toplevel->winPtr->wmInfoPtr && macWin->toplevel->winPtr->wmInfoPtr->window) { result = macWin->toplevel->winPtr->wmInfoPtr->window; + } else if (macWin->winPtr && macWin->winPtr->wmInfoPtr && macWin->winPtr->wmInfoPtr->window) { result = macWin->winPtr->wmInfoPtr->window; + } else if (macWin->toplevel && (macWin->toplevel->flags & TK_EMBEDDED)) { TkWindow *contWinPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)macWin->toplevel->winPtr); - - if (contWinPtr) { + if (contWinPtr && contWinPtr->privatePtr) { result = TkMacOSXGetNSWindowForDrawable((Drawable)contWinPtr->privatePtr); } } diff --git a/macosx/tkMacOSXSysTray.c b/macosx/tkMacOSXSysTray.c index 76186cc688..99ffc9b274 100644 --- a/macosx/tkMacOSXSysTray.c +++ b/macosx/tkMacOSXSysTray.c @@ -205,7 +205,7 @@ MacSystrayObjCmd( static const char *modifyOptions[] = {"image", "text", "b1_callback", "b3_callback", NULL}; typedef enum {TRAY_IMAGE, TRAY_TEXT, TRAY_B1_CALLBACK, TRAY_B3_CALLBACK - } modifyOptionsEnum; + } modifyOptionsEnum; if ([NSApp macOSVersion] < 101000) { Tcl_AppendResult(interp, @@ -329,9 +329,9 @@ MacSystrayObjCmd( break; } - /* - * Modify the text for the tooltip. - */ + /* + * Modify the text for the tooltip. + */ case TRAY_TEXT: { NSString *tooltip = [NSString stringWithUTF8String:Tcl_GetString(objv[3])]; @@ -345,9 +345,9 @@ MacSystrayObjCmd( break; } - /* - * Modify the proc for the callback. - */ + /* + * Modify the proc for the callback. + */ case TRAY_B1_CALLBACK: { [statusItem setB1Callback : objv[3]]; @@ -365,14 +365,14 @@ MacSystrayObjCmd( /* * Set all properties to nil, and release statusItem. */ - [statusItem setImagewithImage: nil]; - [statusItem setTextwithString: nil]; - [statusItem setB1Callback : NULL]; - [statusItem setB3Callback : NULL]; - [statusItem release]; - *info = NULL; - statusItem = NULL; - break; + [statusItem setImagewithImage: nil]; + [statusItem setTextwithString: nil]; + [statusItem setB1Callback : NULL]; + [statusItem setB3Callback : NULL]; + [statusItem release]; + *info = NULL; + statusItem = NULL; + break; } } diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c index f13b7718b1..778ccd4a80 100644 --- a/macosx/tkMacOSXTest.c +++ b/macosx/tkMacOSXTest.c @@ -104,6 +104,8 @@ MenuBarHeightObjCmd( * Returns true if and only if the NSView of the drawable is the * current focusView, which on 10.14 and newer systems can only be the * case when within [NSView drawRect]. + * NOTE: This is no longer needed when we use updateLayer instead + * of drawRect. Now it always returns True. * * Side effects: * None @@ -115,21 +117,8 @@ MODULE_SCOPE Bool TkTestLogDisplay( Drawable drawable) { - MacDrawable *macWin = (MacDrawable *)drawable; - NSWindow *win = nil; - if (macWin->toplevel && macWin->toplevel->winPtr && - macWin->toplevel->winPtr->wmInfoPtr && - macWin->toplevel->winPtr->wmInfoPtr->window) { - win = macWin->toplevel->winPtr->wmInfoPtr->window; - } else if (macWin->winPtr && macWin->winPtr->wmInfoPtr && - macWin->winPtr->wmInfoPtr->window) { - win = macWin->winPtr->wmInfoPtr->window; - } - if (win) { - return ([win contentView] == [NSView focusView]); - } else { - return True; - } + (void) drawable; + return True; } /* diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index 0cc91a53e0..13dc916584 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -133,13 +133,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification; TkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState; Tk_MapWindow((Tk_Window)winPtr); - /* - * Process all Tk events generated by Tk_MapWindow(). - */ - - while (Tcl_ServiceEvent(0)) {} - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} - /* * NSWindowDidDeminiaturizeNotification is received after * NSWindowDidBecomeKeyNotification, so activate manually @@ -238,15 +231,14 @@ extern NSString *NSWindowDidOrderOffScreenNotification; TkWindow *winPtr = TkMacOSXGetTkWindow(window); if (winPtr) { TKContentView *view = [window contentView]; + // fprintf(stderr, "Window %s became visible.\n", Tk_PathName(winPtr)); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 if (@available(macOS 10.14, *)) { [view viewDidChangeEffectiveAppearance]; } #endif - [view addTkDirtyRect:[view bounds]]; - Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL); - Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL); + [view setNeedsDisplay:YES]; } } @@ -256,7 +248,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification; TkWindow *winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} + // fprintf(stderr, "Window %s was ordered on screen.\n", Tk_PathName(winPtr)); } } @@ -264,10 +256,10 @@ extern NSString *NSWindowDidOrderOffScreenNotification; { NSString *name = [notification name]; if ([name isEqualToString:NSWindowWillStartLiveResizeNotification]) { - // printf("Starting live resize.\n"); + // fprintf(stderr, "Starting live resize.\n"); } else if ([name isEqualToString:NSWindowDidEndLiveResizeNotification]) { [self setTkLiveResizeEnded:YES]; - // printf("Ending live resize\n"); + // fprintf(stderr, "Ending live resize\n"); } } @@ -284,9 +276,11 @@ extern NSString *NSWindowDidOrderOffScreenNotification; NSWindow *w = [notification object]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); +#if 0 if (winPtr) { - //Tk_UnmapWindow((Tk_Window)winPtr); + Tk_UnmapWindow((Tk_Window)winPtr); } +#endif } #endif /* TK_MAC_DEBUG_NOTIFICATIONS */ @@ -444,7 +438,7 @@ static void RefocusGrabWindow(void *data) { @end #pragma mark - - + /* *---------------------------------------------------------------------- * @@ -470,33 +464,13 @@ static void RefocusGrabWindow(void *data) { * *---------------------------------------------------------------------- */ - +// This stub is no longer used, but is expected by the stub mechanism. int TkpWillDrawWidget(Tk_Window tkwin) { - int result; - if (tkwin) { - TkWindow *winPtr = (TkWindow *)tkwin; - TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable( - (Drawable)winPtr->privatePtr); - result = ([NSApp isDrawing] && view == [NSView focusView]); -#if 0 - printf("TkpWillDrawWidget: %s %d %d \n", Tk_PathName(tkwin), - [NSApp isDrawing], (view == [NSView focusView])); - if (!result) { - NSRect dirtyRect; - TkMacOSXWinNSBounds(winPtr, view, &dirtyRect); - printf("TkpAppCanDraw: dirtyRect for %s is %s\n", - Tk_PathName(tkwin), - NSStringFromRect(dirtyRect).UTF8String); - [view addTkDirtyRect:dirtyRect]; - } -#endif - } else { - result = [NSApp isDrawing]; - } - return result; + (void) tkwin; + return false; } - + /* *---------------------------------------------------------------------- * @@ -524,11 +498,14 @@ GenerateUpdates( TkWindow *childPtr; XEvent event; CGRect bounds, damageBounds; + NSView *view = TkMacOSXGetNSViewForDrawable((Drawable)winPtr->privatePtr); TkMacOSXWinCGBounds(winPtr, &bounds); +#if 0 if (!CGRectIntersectsRect(bounds, *updateBounds)) { return 0; } +#endif /* * Compute the bounding box of the area that the damage occurred in. @@ -545,7 +522,11 @@ GenerateUpdates( event.xexpose.width = damageBounds.size.width; event.xexpose.height = damageBounds.size.height; event.xexpose.count = 0; - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + if ([view inLiveResize]) { + Tk_HandleEvent(&event); + } else { + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + } #ifdef TK_MAC_DEBUG_DRAWING TKLog(@"Exposed %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x, @@ -949,40 +930,16 @@ ExposeRestrictProc( ? TK_PROCESS_EVENT : TK_DEFER_EVENT); } -/* - * Restrict event processing to ConfigureNotify events. - */ - -static Tk_RestrictAction -ConfigureRestrictProc( - TCL_UNUSED(void *), - XEvent *eventPtr) -{ - return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT); -} - @implementation TKContentView(TKWindowEvent) - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; if (self) { - /* - * The layer must exist before we set wantsLayer to YES. - */ - - self.layer = [CALayer layer]; self.wantsLayer = YES; self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; self.layer.contentsGravity = self.layer.contentsAreFlipped ? kCAGravityTopLeft : kCAGravityBottomLeft; - - /* - * Nothing gets drawn at all if the layer does not have a delegate. - * Currently, we do not implement any methods of the delegate, however. - */ - - self.layer.delegate = (id) self; trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:(NSTrackingMouseEnteredAndExited | @@ -997,13 +954,33 @@ ConfigureRestrictProc( return self; } -/* - * We will just use drawRect. - */ - - (BOOL) wantsUpdateLayer { - return NO; + return YES; +} +- (void) updateLayer { + CGContextRef context = self.tkLayerBitmapContext; + if (context && ![NSApp tkWillExit]) { + /* + * Create a CGImage by copying (probably using copy-on-write) the + * bitmap data of the CGBitmapContext that we have been using for + * drawing. Then render that CGImage into the CALayer of this view by + * assigning a reference to the CGImage to the contents property of the + * layer. This will cause all drawing done since the last call to this + * function to become visible. + */ + + CGImageRef newImg = CGBitmapContextCreateImage(context); + self.layer.contents = (__bridge id) newImg; + CGImageRelease(newImg); // will quickly leak memory if this is missing + + /* + * Run any pending widget display procs as part of the update. + * Without this there are black flashes when a window opens. + */ + + while(Tcl_DoOneEvent(TCL_IDLE_EVENTS)){} + } } - (void) viewDidChangeBackingProperties @@ -1017,115 +994,62 @@ ConfigureRestrictProc( */ self.layer.contentsScale = self.window.screen.backingScaleFactor; -} - -- (void) addTkDirtyRect: (NSRect) rect -{ - _tkNeedsDisplay = YES; - _tkDirtyRect = NSUnionRect(_tkDirtyRect, rect); - [NSApp setNeedsToDraw:YES]; - [self setNeedsDisplay:YES]; - [[self layer] setNeedsDisplay]; -} - -- (void) clearTkDirtyRect -{ - _tkNeedsDisplay = NO; - _tkDirtyRect = NSZeroRect; - [NSApp setNeedsToDraw:NO]; -} - -- (void) drawRect: (NSRect) rect -{ - (void)rect; - -#ifdef TK_MAC_DEBUG_DRAWING - TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); - if (winPtr) { - fprintf(stderr, "drawRect: drawing %s in %s\n", - Tk_PathName(winPtr), NSStringFromRect(rect).UTF8String); - } -#endif - - /* - * 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 macOSVersion] > 101300) { - TKLog(@"WARNING: a recursive call to drawRect was aborted."); - } - return; - } - - [NSApp setIsDrawing: YES]; - [self clearTkDirtyRect]; - [self generateExposeEvents:rect]; - [NSApp setIsDrawing:NO]; - -#ifdef TK_MAC_DEBUG_DRAWING - fprintf(stderr, "drawRect: done.\n"); -#endif + [self resetTkLayerBitmapContext]; + // need to redraw + [self generateExposeEvents: self.bounds]; } -(void) setFrameSize: (NSSize)newsize { + NSSize oldsize = self.bounds.size; [super setFrameSize: newsize]; + if ((newsize.width == 1 && newsize.height == 1) || + (oldsize.width == 0 && oldsize.height == 0)) { + return; + } NSWindow *w = [self window]; TkWindow *winPtr = TkMacOSXGetTkWindow(w); Tk_Window tkwin = (Tk_Window)winPtr; - if (![self inLiveResize] && - [w respondsToSelector: @selector (tkLayoutChanged)]) { - [(TKWindow *)w tkLayoutChanged]; - } - if (winPtr) { - unsigned int width = (unsigned int)newsize.width; - unsigned int height=(unsigned int)newsize.height; - void *oldArg; - Tk_RestrictProc *oldProc; + unsigned int width = (unsigned int) newsize.width; + unsigned int height= (unsigned int) newsize.height; /* - * This can be called from outside the Tk event loop. Since it calls - * Tcl_DoOneEvent, we need to make sure we don't clobber the - * AutoreleasePool set up by the caller. + * This function can be re-entered, so we need to make sure we don't + * clobber any AutoreleasePool set up by the caller. */ [NSApp _lockAutoreleasePool]; - /* - * Disable Tk drawing until the window has been completely configured. - */ - - TkMacOSXSetDrawingEnabled(winPtr, 0); - /* * Generate and handle a ConfigureNotify event for the new size. */ TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height, TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY); - oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg); - Tk_RestrictEvents(oldProc, oldArg, &oldArg); /* - * Now that Tk has configured all subwindows, create the clip regions. + * Update Tk's window data for the new size. */ - TkMacOSXSetDrawingEnabled(winPtr, 1); - TkMacOSXInvalClipRgns(tkwin); - TkMacOSXUpdateClipRgn(winPtr); + if ([w respondsToSelector: @selector (tkLayoutChanged)]) { + [(TKWindow *)w tkLayoutChanged]; + } - /* - * Generate and process expose events to redraw the window. To avoid - * crashes, only do this if we are being called from drawRect. See - * ticket [1fa8c3ed8d]. - */ + /* + * Reset the cgimage layer and redraw the entire content view. + */ + + [self viewDidChangeBackingProperties]; + + /* + * In live resize we seem to need to draw a second time to + * avoid artifacts. + */ - if([NSApp isDrawing] || [self inLiveResize]) { - [self generateExposeEvents: [self bounds]]; + if ([self inLiveResize]) { + [self generateExposeEvents:self.bounds]; } /* @@ -1133,7 +1057,14 @@ ConfigureRestrictProc( */ [NSApp _unlockAutoreleasePool]; + } + + /* + * Request a call to updateLayer. + */ + + [self setNeedsDisplay:YES]; } /* @@ -1145,53 +1076,62 @@ ConfigureRestrictProc( - (void) generateExposeEvents: (NSRect) rect { - unsigned long serial; - int updatesNeeded; CGRect updateBounds; TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); void *oldArg; Tk_RestrictProc *oldProc; - if (!winPtr) { + static int reentered = 0; + + if (!winPtr || + (winPtr->flags & (TK_ALREADY_DEAD)) || + !Tk_IsMapped(winPtr)) { + return; + } + + if (reentered) { + /* + * When in liveResize an event loop gets run below to + * immediately process displayProcs while the resize is being + * done. Those can cause calls to this function, leading to + * crashes or very poor performance. The reentered flag is + * used to detect this. + */ + // fprintf(stderr, "Recursive call to generateExposeEvents\n"); return; } + reentered = 1; /* * Generate Tk Expose events. All of these events will share the same * serial number. */ - - updateBounds = NSRectToCGRect(rect); + if ([self inLiveResize]) { + updateBounds = [self bounds]; + } else { + updateBounds = NSRectToCGRect(rect); + } updateBounds.origin.y = ([self bounds].size.height - updateBounds.origin.y - updateBounds.size.height); - updatesNeeded = GenerateUpdates(&updateBounds, winPtr); - if (updatesNeeded) { - - serial = LastKnownRequestProcessed(Tk_Display(winPtr)); - + if ( GenerateUpdates(&updateBounds, winPtr)) { /* - * Use the ExposeRestrictProc to process only the expose events. This - * will create idle drawing tasks, which we handle before we return. + * Use the ExposeRestrictProc to process the expose events we just + * generated. This will create idle drawing tasks, which we handle + * before we return in the case of a live resize. */ - - oldProc = Tk_RestrictEvents(ExposeRestrictProc, UINT2PTR(serial), &oldArg); - while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}; - Tk_RestrictEvents(oldProc, oldArg, &oldArg); + unsigned int serial = LastKnownRequestProcessed(Tk_Display(winPtr)); + oldProc = Tk_RestrictEvents(ExposeRestrictProc, UINT2PTR(serial), &oldArg); + while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}; + Tk_RestrictEvents(oldProc, NULL, &oldArg); /* - * Starting with OSX 10.14, which uses Core Animation to draw windows, - * all drawing must be done within the drawRect method. (The CGContext - * which draws to the backing CALayer is created by the NSView before - * calling drawRect, and destroyed when drawRect returns. Drawing done - * with the current CGContext outside of the drawRect method has no - * effect.) - * - * Fortunately, Tk schedules all drawing to be done while Tcl is idle. - * So to run any display procs which were scheduled by the expose - * events we process all idle events before returning. + * During a LiveResize we process all idle tasks generated by the + * expose events to redraw the window while it is being resized. */ - - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} + if ([self inLiveResize]) { + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {} + } } + reentered = 0; } /* @@ -1246,6 +1186,8 @@ static const char *const accentNames[] = { effectiveAppearanceName.UTF8String, accentName, highlightName); Tk_SendVirtualEvent(tkwin, "AppearanceChanged", Tcl_NewStringObj(data, TCL_INDEX_NONE)); + // Force a redraw of the view. + [self setFrameSize:self.frame.size]; } - (void)observeValueForKeyPath:(NSString *)keyPath @@ -1347,6 +1289,32 @@ static const char *const accentNames[] = { return [super validRequestorForSendType:sendType returnType:returnType]; } +-(void) resetTkLayerBitmapContext { + static CGColorSpaceRef colorspace = NULL; + if (colorspace == NULL) { + colorspace = CGColorSpaceCreateDeviceRGB(); + CGColorSpaceRetain(colorspace); + } + CGContextRef newCtx = CGBitmapContextCreate( + NULL, self.layer.contentsScale * self.frame.size.width, + self.layer.contentsScale * self.frame.size.height, 8, 0, colorspace, + kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast // will also need to specify this when capturing + ); + CGContextScaleCTM(newCtx, self.layer.contentsScale, self.layer.contentsScale); +#if 0 + fprintf(stderr, "rTkLBC %.1f %s %p %p %ld\n", (float)self.layer.contentsScale, + NSStringFromSize(self.frame.size).UTF8String, colorspace, newCtx, + self.tkLayerBitmapContext ? + (long)CFGetRetainCount(self.tkLayerBitmapContext) : INT_MIN); + fprintf(stderr, "rTkLBC %p %ld\n", self.tkLayerBitmapContext, + (long)(self.tkLayerBitmapContext ? + CFGetRetainCount(self.tkLayerBitmapContext) : LONG_MIN)); +#endif + // The context is also released in TkWmDeadWindow. + CGContextRelease(self.tkLayerBitmapContext); + self.tkLayerBitmapContext = newCtx; +} + @end /* diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index eb8a8ee534..debf79b39e 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -291,6 +291,7 @@ static void syncLayout(NSWindow *macWindow) contentRect.size.width; wmPtr->parentHeight = winPtr->changes.height + frameRect.size.height - contentRect.size.height; + TkMacOSXInvalClipRgns((Tk_Window)winPtr); } } #endif @@ -576,6 +577,7 @@ static void placeAsTab(TKWindow *macWindow) { - (void) tkLayoutChanged { syncLayout(self); + [[self contentView] setNeedsDisplay:YES]; } @end @@ -595,6 +597,7 @@ static void placeAsTab(TKWindow *macWindow) { - (void) tkLayoutChanged { syncLayout(self); + [[self contentView] setNeedsDisplay:YES]; } #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 @@ -811,24 +814,25 @@ FrontWindowAtPoint( for (NSWindow *w in [NSApp orderedWindows]) { TkWindow *winPtr = TkMacOSXGetTkWindow(w); if (winPtr) { - WmInfo *wmPtr = winPtr->wmInfoPtr; NSRect windowFrame = [w frame]; - NSRect contentFrame = [w frame]; + NSRect contentFrame = windowFrame; - contentFrame.size.height = [[w contentView] frame].size.height; /* * For consistency with other platforms, points in the * title bar are not considered to be contained in the * window. */ - if ((wmPtr->hints.initial_state == NormalState || - wmPtr->hints.initial_state == ZoomState)) { - if (NSMouseInRect(p, contentFrame, NO)) { - return winPtr; - } else if (NSMouseInRect(p, windowFrame, NO)) { - return NULL; - } + contentFrame.size.height = [[w contentView] frame].size.height; + if (NSMouseInRect(p, contentFrame, NO)) { + return winPtr; + } else if (NSMouseInRect(p, windowFrame, NO)) { + /* + * The pointer is in the title bar of the highest NSWindow + * containing it, and therefore it should not be considered + * to be contained in any Tk window. + */ + return NULL; } } } @@ -1087,12 +1091,15 @@ TkWmUnmapWindow( * * This procedure is invoked when a top-level window is about to be * deleted. It cleans up the wm-related data structures for the window. + * If the dead window contains the pointer, TkUpdatePointer is called + * to tell Tk which window will be the new pointer window. * * Results: * None. * * Side effects: - * The WmInfo structure for winPtr gets freed up. + * The WmInfo structure for winPtr gets freed. Tk's cached pointer + * window may change. * *---------------------------------------------------------------------- */ @@ -1101,13 +1108,15 @@ void TkWmDeadWindow( TkWindow *winPtr) /* Top-level window that's being deleted. */ { + TkWindow *winPtr2; + NSWindow *w; WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; - TKWindow *deadNSWindow; - - if (wmPtr == NULL) { - return; + TKWindow *deadNSWindow = NULL; + if (Tk_WindowId(winPtr) == None) { + fprintf(stderr, "TkWmDeadWindow: no window id\n"); + } else { + deadNSWindow = (TKWindow *)TkMacOSXGetNSWindowForDrawable(Tk_WindowId(winPtr)); } - /* *If the dead window is a transient, remove it from the container's list. */ @@ -1159,11 +1168,10 @@ TkWmDeadWindow( for (Transient *transientPtr = wmPtr->transientPtr; transientPtr != NULL; transientPtr = transientPtr->nextPtr) { - TkWindow *winPtr2 = transientPtr->winPtr; - TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2); - + TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer( + transientPtr->winPtr); if (containerPtr == winPtr) { - wmPtr2 = winPtr2->wmInfoPtr; + wmPtr2 = transientPtr->winPtr->wmInfoPtr; wmPtr2->container = NULL; } } @@ -1175,29 +1183,48 @@ TkWmDeadWindow( ckfree(transientPtr); } - deadNSWindow = (TKWindow *)wmPtr->window; - /* * Remove references to the Tk window from the mouse event processing - * state which is recorded in the NSApplication object. + * state which is recorded in the NSApplication object and notify Tk + * of the new pointer window. */ - if (winPtr == [NSApp tkPointerWindow]) { - NSWindow *w; - NSPoint mouse = [NSEvent mouseLocation]; - [NSApp setTkPointerWindow:nil]; - for (w in [NSApp orderedWindows]) { - if (w == deadNSWindow) { - continue; - } - if (NSPointInRect(mouse, [w frame])) { - TkWindow *winPtr2 = TkMacOSXGetTkWindow(w); - int x = mouse.x, y = TkMacOSXZeroScreenHeight() - mouse.y; - [NSApp setTkPointerWindow:winPtr2]; - Tk_UpdatePointer((Tk_Window) winPtr2, x, y, - [NSApp tkButtonState]); - break; - } + NSPoint mouse = [NSEvent mouseLocation]; + [NSApp setTkPointerWindow:nil]; + winPtr2 = NULL; + + for (w in [NSApp orderedWindows]) { + if (w == deadNSWindow || w == NULL) { + continue; + } + winPtr2 = TkMacOSXGetTkWindow(w); + if (winPtr2 == NULL) { + continue; + } + if (NSPointInRect(mouse, [w frame])) { + [NSApp setTkPointerWindow: winPtr2]; + break; + } + } + if (winPtr2) { + /* + * We now know which toplevel will contain the pointer when the window + * is destroyed. We need to know which Tk window within the + * toplevel will contain the pointer. + */ + NSPoint local = [w tkConvertPointFromScreen: mouse]; + int top_x = floor(local.x), + top_y = floor(w.frame.size.height - local.y); + int root_x = floor(mouse.x), + root_y = floor(TkMacOSXZeroScreenHeight() - mouse.y); + int win_x, win_y; + Tk_Window target = Tk_TopCoordsToWindow((Tk_Window) winPtr2, top_x, top_y, &win_x, &win_y); + /* + * A non-toplevel window can have a NULL parent while it is in the process of + * being destroyed. We should not call Tk_UpdatePointer in that case. + */ + if (Tk_Parent(target) != NULL || Tk_IsTopLevel(target)) { + Tk_UpdatePointer(target, root_x, root_y, [NSApp tkButtonState]); } } @@ -1249,9 +1276,10 @@ TkWmDeadWindow( * set tkEventTarget to NULL when there is no window to send Tk events to. */ TkWindow *newTkEventTarget = NULL; + winPtr2 = NULL; - for (NSWindow *w in [NSApp orderedWindows]) { - TkWindow *winPtr2 = TkMacOSXGetTkWindow(w); + for (w in [NSApp orderedWindows]) { + winPtr2 = TkMacOSXGetTkWindow(w); BOOL isOnScreen; if (!winPtr2 || !winPtr2->wmInfoPtr) { @@ -1277,6 +1305,14 @@ TkWmDeadWindow( [NSApp _setKeyWindow:nil]; [NSApp _setMainWindow:nil]; } + + /* + * Avoid redrawing the view after it is released. + */ + + TKContentView *deadView = [deadNSWindow contentView]; + Tcl_CancelIdleCall(TkMacOSXRedrawViewIdleTask,(void *) deadView); + CGContextRelease(deadView.tkLayerBitmapContext); [deadNSWindow close]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; @@ -2373,8 +2409,7 @@ WmDeiconifyCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; - NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window); - + NSWindow *win = nil; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); return TCL_ERROR; @@ -2393,11 +2428,17 @@ WmDeiconifyCmd( return TCL_ERROR; } + if (winPtr->window) { + win = TkMacOSXGetNSWindowForDrawable(winPtr->window); + } TkpWmSetState(winPtr, TkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState); - [win setExcludedFromWindowsMenu:NO]; - TkMacOSXApplyWindowAttributes(winPtr, win); - [win orderFront:NSApp]; + if (win) { + [win setExcludedFromWindowsMenu:NO]; + TkMacOSXApplyWindowAttributes(winPtr, win); + [win orderFront:NSApp]; + [[win contentView] setNeedsDisplay:YES]; + } if (wmPtr->icon) { Tk_UnmapWindow((Tk_Window)wmPtr->icon); } @@ -2422,8 +2463,7 @@ WmDeiconifyCmd( } } - [[win contentView] setNeedsDisplay:YES]; - Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL); + //Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL); return TCL_OK; } @@ -2524,7 +2564,6 @@ WmForgetCmd( macWin->toplevel->referenceCount++; macWin->flags &= ~TK_HOST_EXISTS; - TkWmDeadWindow(winPtr); RemapWindows(winPtr, (MacDrawable *)winPtr->parentPtr->window); /* @@ -2615,11 +2654,13 @@ WmGeometryCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; - NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window); + NSWindow *win = nil; char xSign = '+', ySign = '+'; int width, height, x = wmPtr->x, y= wmPtr->y; char *argv3; - + if (winPtr && winPtr->window) { + win = TkMacOSXGetNSWindowForDrawable(winPtr->window); + } if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?"); return TCL_ERROR; @@ -3365,18 +3406,23 @@ WmIconwindowCmd( return TCL_ERROR; } if (wmPtr->icon != NULL) { + NSWindow *win = nil; TkWindow *oldIcon = (TkWindow *)wmPtr->icon; - WmInfo *wmPtr3 = oldIcon->wmInfoPtr; - NSWindow *win = TkMacOSXGetNSWindowForDrawable(oldIcon->window); - + if (winPtr && winPtr->window) { + win = TkMacOSXGetNSWindowForDrawable(winPtr->window); + } /* * The old icon should be withdrawn. */ - - TkpWmSetState(oldIcon, WithdrawnState); + if (oldIcon) { + WmInfo *wmPtr3 = oldIcon->wmInfoPtr; + TkpWmSetState(oldIcon, WithdrawnState); + if (wmPtr3) { + wmPtr3->iconFor = NULL; + } + } [win orderOut:NSApp]; - [win setExcludedFromWindowsMenu:YES]; - wmPtr3->iconFor = NULL; + [win setExcludedFromWindowsMenu:YES]; } Tk_MakeWindowExist(tkwin2); wmPtr->hints.icon_window = Tk_WindowId(tkwin2); @@ -3471,6 +3517,7 @@ WmManageCmd( } else if (Tk_IsTopLevel(frameWin)) { /* Already managed by wm - ignore it */ } + Tk_ManageGeometry((Tk_Window)winPtr, &wmMgrType, NULL); return TCL_OK; } @@ -3609,7 +3656,11 @@ WmOverrideredirectCmd( { Bool boolValue; XSetWindowAttributes atts; - TKWindow *win = (TKWindow *)TkMacOSXGetNSWindowForDrawable(winPtr->window); + NSWindow *win = nil; + if (winPtr && winPtr->window) { + win = TkMacOSXGetNSWindowForDrawable(winPtr->window); + } + if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?"); @@ -5598,6 +5649,15 @@ Tk_MoveToplevelWindow( * *---------------------------------------------------------------------- */ +#define PRINT_STACK \ + for (NSWindow *w in [NSApp orderedWindows]) { \ + TkWindow *winPtr2 = TkMacOSXGetTkWindow(w); \ + if (winPtr2) { \ + fprintf(stderr, "%s ", Tk_PathName(winPtr2)); \ + } \ + } \ + fprintf(stderr, "\n"); \ + fflush(stderr) void TkWmRestackToplevel( @@ -5655,8 +5715,14 @@ TkWmRestackToplevel( * Just let the Mac window manager deal with all the subtleties of keeping * track of off-screen windows, etc. */ - +#if 0 + fprintf(stderr, "window order: "); PRINT_STACK; +#endif [macWindow orderWindow:macAboveBelow relativeTo:otherNumber]; +#if 0 + fprintf(stderr, "new window order: "); PRINT_STACK; +#endif +#undef PRINT_STACK } /* @@ -6006,7 +6072,7 @@ Tk_Window TkMacOSXGetContainer( TkWindow *winPtr) { - if (winPtr->wmInfoPtr != NULL) { + if (Tk_PathName(winPtr)) { return (Tk_Window)winPtr->wmInfoPtr->container; } return NULL; @@ -6051,7 +6117,7 @@ TkMacOSXGetXWindow( * void*. * * Results: - * A Tk_Window, or NULL if the NSWindow is not associated with + * A Tk_Window, or None if the NSWindow is not associated with * any Tk window. * * Side effects: @@ -6813,9 +6879,11 @@ TkMacOSXMakeRealWindowExist( * * TkpRedrawWidget -- * - * Mark the bounding rectangle of this widget as needing display so the - * widget will be drawn by [NSView drawRect:]. If this is called within - * the drawRect method, do nothing. + * This is a stub called only from tkTextDisp.c. It was introduced + * to deal with an issue in macOS 10.14 and is not needed + * even for that OS with updateLayer in use. It would add the widget bounds + * to the dirtyRect, which is not currently used, and set the + * TkNeedsDisplay flag. Now it is a no-op. * * Results: * None. @@ -6828,15 +6896,16 @@ TkMacOSXMakeRealWindowExist( void TkpRedrawWidget(Tk_Window tkwin) { + (void) tkwin; +#if 0 TkWindow *winPtr = (TkWindow *)tkwin; - NSWindow *w; + NSWindow *w = nil; Rect tkBounds; NSRect bounds; - if ([NSApp isDrawing]) { - return; + if (winPtr && winPtr->window) { + w = TkMacOSXGetNSWindowForDrawable(winPtr->window); } - w = TkMacOSXGetNSWindowForDrawable(winPtr->window); if (w) { TKContentView *view = [w contentView]; TkMacOSXWinBounds(winPtr, &tkBounds); @@ -6844,8 +6913,9 @@ TkpRedrawWidget(Tk_Window tkwin) { [view bounds].size.height - tkBounds.bottom, tkBounds.right - tkBounds.left, tkBounds.bottom - tkBounds.top); - [view addTkDirtyRect:bounds]; + [view setNeedsDisplay:YES]; } +#endif } @@ -6968,14 +7038,15 @@ TkpWmSetState( * or WithdrawnState. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; - NSWindow *macWin; + NSWindow *macWin = nil; wmPtr->hints.initial_state = state; if (wmPtr->flags & WM_NEVER_MAPPED) { return; } - - macWin = TkMacOSXGetNSWindowForDrawable(winPtr->window); + if (winPtr && winPtr->window) { + macWin = TkMacOSXGetNSWindowForDrawable(winPtr->window); + } /* * Make sure windows are updated before the state change. As an exception, diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 5c29253bfd..322b225288 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -865,6 +865,14 @@ XSetIconName( return Success; } +Bool +XFilterEvent( + TCL_UNUSED(XEvent *), + TCL_UNUSED(Window)) +{ + return 0; +} + int XForceScreenSaver( Display* display, diff --git a/macosx/ttkMacOSXTheme.h b/macosx/ttkMacOSXTheme.h index 1e2b7ae126..2092b02154 100644 --- a/macosx/ttkMacOSXTheme.h +++ b/macosx/ttkMacOSXTheme.h @@ -561,7 +561,7 @@ static ThemeFrameParams #define CHECK_RADIUS(radius, bounds) \ if ((radius) > (bounds).size.width / 2 || (radius) > (bounds).size.height / 2) { \ - return; \ + return; \ } /* diff --git a/tests/button.test b/tests/button.test index a51b997bd5..f18e0ffc88 100644 --- a/tests/button.test +++ b/tests/button.test @@ -1486,7 +1486,7 @@ test button-1.152 {configuration option: "image" for label} -setup { .l configure -image bogus } -cleanup { destroy .l -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test button-1.153 {configuration option: "image" for button} -constraints { testImageType } -setup { @@ -1509,7 +1509,7 @@ test button-1.154 {configuration option: "image" for button} -setup { .b configure -image bogus } -cleanup { destroy .b -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test button-1.155 {configuration option: "image" for checkbutton} -constraints { testImageType } -setup { @@ -1532,7 +1532,7 @@ test button-1.156 {configuration option: "image" for checkbutton} -setup { .c configure -image bogus } -cleanup { destroy .c -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test button-1.157 {configuration option: "image" for radiobutton} -constraints { testImageType } -setup { @@ -1555,7 +1555,7 @@ test button-1.158 {configuration option: "image" for radiobutton} -setup { .r configure -image bogus } -cleanup { destroy .r -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test button-1.159 {configuration option: "indicatoron" for checkbutton} -setup { checkbutton .c -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold} @@ -2124,7 +2124,7 @@ test button-1.216 {configuration option: "selectimage" for checkbutton} -setup { .c configure -selectimage bogus } -cleanup { destroy .c -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test button-1.217 {configuration option: "selectimage" for radiobutton} -constraints { testImageType } -setup { @@ -2147,7 +2147,7 @@ test button-1.218 {configuration option: "selectimage" for radiobutton} -setup { .r configure -selectimage bogus } -cleanup { destroy .r -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test button-1.219 {configuration option: "state" for label} -setup { label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold} @@ -2371,7 +2371,7 @@ test button-1.240 {configuration option: "tristateimage" for checkbutton} -setup .c configure -tristateimage bogus } -cleanup { destroy .c -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test button-1.241 {configuration option: "tristateimage" for radiobutton} -constraints { testImageType } -setup { @@ -2394,7 +2394,7 @@ test button-1.242 {configuration option: "tristateimage" for radiobutton} -setup .r configure -tristateimage bogus } -cleanup { destroy .r -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test button-1.243 {configuration option: "underline" for label} -setup { label .l -borderwidth 2 -highlightthickness 2 -font {Helvetica -12 bold} @@ -3326,7 +3326,7 @@ test button-5.11 {ConfigureButton - bad image name} -body { button .b -image bogus } -cleanup { destroy .b -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test button-5.12 {ConfigureButton - setting variable from current text value} -setup { unset -nocomplain x diff --git a/tests/canvImg.test b/tests/canvImg.test index 62acd61db9..2ac74357c6 100644 --- a/tests/canvImg.test +++ b/tests/canvImg.test @@ -44,7 +44,7 @@ test canvImg-1.4 {options for image items} -body { .c create image 50 50 -image unknown -tags i1 } -cleanup { .c delete all -} -returnCodes error -result {image "unknown" doesn't exist} +} -returnCodes error -result {image "unknown" does not exist} test canvImg-1.5 {options for image items} -constraints testImageType -setup { image create test foo .c delete all @@ -195,7 +195,7 @@ test canvImg-4.3 {ConfiugreImage procedure} -constraints testImageType -setup { } -cleanup { .c delete all image delete foo foo2 -} -returnCodes error -result {image "lousy" doesn't exist} +} -returnCodes error -result {image "lousy" does not exist} test canvImg-5.1 {DeleteImage procedure} -constraints testImageType -setup { diff --git a/tests/event.test b/tests/event.test index e2daa0fdc9..8f13c25ae6 100644 --- a/tests/event.test +++ b/tests/event.test @@ -873,7 +873,313 @@ test event-9.2 {enter toplevel window by destroying a toplevel - bug b1d115fa60} } } -result {.top1} +proc waitForWindowEvent {w event {timeout 1000}} { +# This proc is intended to overcome latency of windowing system +# notifications when toplevel windows are involved. These latencies vary +# considerably with the window manager in use, with the system load, +# with configured scheduling priorities for processes, etc ... +# Waiting for the corresponding window events evades the trouble that is +# associated with the alternative: waiting or halting the Tk process for a +# fixed amount of time (using "after ms"). With the latter strategy it's +# always a gamble how much waiting time is enough on an end user's system. +# It also leads to long fixed waiting times in order to be on the safe side. + + variable _windowEvent + + # Use counter as a unique ID to prevent subsequent waits + # from interfering with each other. + set counter [incr _windowEvent(counter)] + set _windowEvent($counter) 1 + set savedBinding [bind $w $event] + bind $w $event [list +waitForWindowEvent.signal $counter] + set afterID [after $timeout [list set _windowEvent($counter) -1]] + vwait _windowEvent($counter) + set late [expr {$_windowEvent($counter) == -1}] + bind $w $event $savedBinding + unset _windowEvent($counter) + if {$late} { + puts stderr "wait for $event event on $w timed out (> $timeout ms)" + } else { + after cancel $afterID + } +} +proc waitForWindowEvent.signal {counter} { +# Helper proc that records the triggering of a window event. + incr ::_windowEvent($counter) +} + +proc create_and_pack_frames {{w {}}} { + frame $w.f1 -bg blue -width 200 -height 200 + pack propagate $w.f1 0 + frame $w.f1.f2 -bg yellow -width 100 -height 100 + pack $w.f1.f2 $w.f1 -side bottom -anchor se + update idletasks +} + +proc setup_win_mousepointer {w} { +# Position the window and the mouse pointer as an initial state for some tests. +# The so-called "pointer window" is the $w window that will now contain the mouse pointer. + wm geometry . +700+400; # root window out of our way - must not cover windows from event-9.1* + toplevel $w + pack propagate $w 0 + wm geometry $w 300x300+100+100 + tkwait visibility $w + update; # service remaining screen drawing events (e.g. ) + set pointerWin [winfo containing [winfo pointerx $w] [winfo pointery $w]] + event generate $w -warp 1 -x 250 -y 250 + if {($pointerWin ne $w) && ([tk windowingsystem] ne "aqua")} { + waitForWindowEvent $w + } else { + controlPointerWarpTiming + } +} + +test event-9.11 {pointer window container = parent} -setup { + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + wm deiconify .one + tkwait visibility .one.f1.f2 + _pause 200; # needed for Windows + update idletasks; # finish display of window + set result "|" +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .one.f1.f2 + update + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyInferior .one.f1|} + +test event-9.12 {pointer window container != parent} -setup { + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + pack propagate .one.f1.f2 0 + pack [frame .one.g -bg orange -width 80 -height 80] -anchor se -side bottom -in .one.f1.f2 + wm deiconify .one + tkwait visibility .one.g + event generate .one -warp 1 -x 250 -y 250 + _pause 200; # needed for Windows + set result "|" +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .one.g + update + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyNonlinearVirtual .one.f1| NotifyNonlinear .one.f1.f2|} + +test event-9.13 {pointer window is a toplevel, toplevel destination} -setup { + setup_win_mousepointer .one + toplevel .two + wm geometry .two 300x300+150+150 + wm withdraw .two + wm deiconify .two + waitForWindowEvent .two + update idletasks; # finish displaying windows + set result | +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .two + waitForWindowEvent .one + update + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyNonlinear .one|} + +test event-9.14 {pointer window is a toplevel, tk internal destination} -setup { + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + toplevel .two + wm geometry .two 300x300+150+150 + wm withdraw .two + wm deiconify .one + wm deiconify .two + waitForWindowEvent .two + set result "|" +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .two + waitForWindowEvent .one.f1.f2 + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyNonlinearVirtual .one| NotifyNonlinearVirtual .one.f1| NotifyNonlinear .one.f1.f2|} + +test event-9.15 {pointer window is a toplevel, destination is screen root} -setup { + setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) +# destroy .one + toplevel .two + wm geometry .two 300x300+150+150 + wm deiconify .two + waitForWindowEvent .two + update idletasks; # finish displaying .two + event generate .two -warp 1 -x 275 -y 275 + controlPointerWarpTiming + set result "|" +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .two + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {|} + +test event-9.16 {Successive destructions (pointer window + parent), single generation of crossing events} -setup { + # Tests correctness of overwriting the dead window struct in + # TkPointerDeadWindow() and subsequent reading in GenerateEnterLeave(). + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + wm deiconify .one + tkwait visibility .one.f1.f2 + update idletasks; # finish displaying window + _pause 200; # needed for Windows + set result "|" +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .one.f1 + update + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyInferior .one|} + +test event-9.17 {Successive destructions (pointer window + parent), separate crossing events} -setup { + # Tests correctness of overwriting the dead window struct in + # TkPointerDeadWindow() and subsequent reading in GenerateEnterLeave(). + setup_win_mousepointer .one + wm withdraw .one + create_and_pack_frames .one + wm deiconify .one + tkwait visibility .one.f1.f2 + update idletasks; # finish displaying window + _pause 200; # needed for Windows + set result "|" +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .one.f1.f2 + update; # make sure window is gone + destroy .one.f1 + update; # make sure window is gone + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyInferior .one.f1| NotifyInferior .one|} + +test event-9.18 {Successive destructions (pointer window + ancestors including its toplevel), destination is non-root toplevel} -setup { + setup_win_mousepointer .one + toplevel .two + pack propagate .two 0 + wm geometry .two 300x300+100+100 + create_and_pack_frames .two + wm deiconify .two + waitForWindowEvent .two.f1.f2 + set result "|" +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .two + waitForWindowEvent .one + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + unset result +} -result {| NotifyNonlinear .one|} + +test event-9.19 {Successive destructions (pointer window + ancestors including its toplevel), destination is internal window, bypass root win} -setup { + setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) +# destroy .one + toplevel .two + pack propagate .two 0 + wm geometry .two 300x300+100+100 + create_and_pack_frames .two + wm deiconify .two + toplevel .three + pack propagate .three 0 + wm geometry .three 300x300+110+110 + create_and_pack_frames .three + wm deiconify .three + waitForWindowEvent .three.f1.f2 + update idletasks; # finish displaying windows + set result "|" +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .three + waitForWindowEvent .two.f1.f2 + update idletasks; #finish destroying .two + set result +} -cleanup { + bind all {} + bind all {} + destroy .one + destroy .two + unset result +} -result {| NotifyNonlinearVirtual .two| NotifyNonlinearVirtual .two.f1| NotifyNonlinear .two.f1.f2|} + +test event-9.20 {Successive destructions (pointer window + ancestors including its toplevel), destination is screen root} -setup { + setup_win_mousepointer .one; # ensure the mouse pointer is where we want it to be (the .one toplevel is not itself used in this test) + destroy .one + toplevel .two + pack propagate .two 0 + wm geometry .two 300x300+100+100 + create_and_pack_frames .two + wm deiconify .two + waitForWindowEvent .two.f1.f2 + set result "|" +} -body { + bind all {append result " %d %W|"} + bind all {append result " %d %W|"} + destroy .two + update idletasks; #finish destroying .two + set result +} -cleanup { + bind all {} + bind all {} + unset result +} -result {|} + # cleanup +# macOS sometimes has trouble deleting the test window, +# causing a failure in focus.test. +_pause 200; +deleteWindows update unset -nocomplain keypress_lookup rename _init_keypress_lookup {} @@ -882,6 +1188,8 @@ rename _keypress {} rename _pause {} rename _text_ind_to_x_y {} rename _get_selection {} +rename create_and_pack_frames {} +rename setup_win_mousepointer {} cleanupTests return diff --git a/tests/font.test b/tests/font.test index bb27ad9e22..13001c16ba 100644 --- a/tests/font.test +++ b/tests/font.test @@ -2468,6 +2468,7 @@ test font-47.2 {Bug 3049518 - Canvas} -body { apply $circle_text $c FontChanged $textid $circid update bind $c <> [list apply $circle_text %W %d $textid $circid] + update idletasks # Begin test: set results {} diff --git a/tests/frame.test b/tests/frame.test index 0f6d14c5f8..0fc4af5b53 100644 --- a/tests/frame.test +++ b/tests/frame.test @@ -1509,7 +1509,7 @@ test frame-15.2 {TIP 262: frame background images} -setup { .f configure -backgroundimage gorp } -returnCodes error -cleanup { deleteWindows -} -result {image "gorp" doesn't exist} +} -result {image "gorp" does not exist} test frame-15.3 {TIP 262: frame background images} -setup { deleteWindows image create photo gorp -width 10 -height 10 @@ -1689,7 +1689,7 @@ test frame-15.9 {TIP 262: toplevel background images} -setup { .t configure -backgroundimage gorp } -returnCodes error -cleanup { deleteWindows -} -result {image "gorp" doesn't exist} +} -result {image "gorp" does not exist} test frame-15.10 {TIP 262: toplevel background images} -setup { deleteWindows image create photo gorp -width 10 -height 10 diff --git a/tests/image.test b/tests/image.test index bf1ba704e0..7362f2478a 100644 --- a/tests/image.test +++ b/tests/image.test @@ -31,7 +31,7 @@ test image-1.3 {Tk_ImageCmd procedure, "create" option} -body { } -returnCodes error -result {wrong # args: should be "image create type ?name? ?-option value ...?"} test image-1.4 {Tk_ImageCmd procedure, "create" option} -body { image c bad_type -} -returnCodes error -result {image type "bad_type" doesn't exist} +} -returnCodes error -result {image type "bad_type" does not exist} test image-1.5 {Tk_ImageCmd procedure, "create" option} -constraints { testImageType } -body { @@ -177,7 +177,7 @@ test image-2.3 {Tk_ImageCmd procedure, "delete" option} -constraints { image delete myimage gorp img2 } -cleanup { imageCleanup -} -returnCodes error -result {image "gorp" doesn't exist} +} -returnCodes error -result {image "gorp" does not exist} test image-2.4 {Tk_ImageCmd procedure, "delete" option} -constraints { testImageType } -setup { @@ -200,7 +200,7 @@ test image-3.2 {Tk_ImageCmd procedure, "height" option} -body { } -returnCodes error -result {wrong # args: should be "image height name"} test image-3.3 {Tk_ImageCmd procedure, "height" option} -body { image height foo -} -returnCodes error -result {image "foo" doesn't exist} +} -returnCodes error -result {image "foo" does not exist} test image-3.4 {Tk_ImageCmd procedure, "height" option} -constraints { testImageType } -setup { @@ -258,7 +258,7 @@ test image-5.2 {Tk_ImageCmd procedure, "type" option} -body { } -returnCodes error -result {wrong # args: should be "image type name"} test image-5.3 {Tk_ImageCmd procedure, "type" option} -body { image type foo -} -returnCodes error -result {image "foo" doesn't exist} +} -returnCodes error -result {image "foo" does not exist} test image-5.4 {Tk_ImageCmd procedure, "type" option} -constraints { testImageType @@ -281,7 +281,7 @@ test image-5.5 {Tk_ImageCmd procedure, "type" option} -constraints { image type myimage } -cleanup { imageCleanup -} -returnCodes error -result {image "myimage" doesn't exist} +} -returnCodes error -result {image "myimage" does not exist} test image-5.6 {Tk_ImageCmd procedure, "type" option} -constraints { testOldImageType } -setup { @@ -305,7 +305,7 @@ test image-5.7 {Tk_ImageCmd procedure, "type" option} -constraints { } -cleanup { .c delete all imageCleanup -} -returnCodes error -result {image "myimage" doesn't exist} +} -returnCodes error -result {image "myimage" does not exist} test image-6.1 {Tk_ImageCmd procedure, "types" option} -constraints { @@ -326,7 +326,7 @@ test image-7.2 {Tk_ImageCmd procedure, "width" option} -body { } -returnCodes error -result {wrong # args: should be "image width name"} test image-7.3 {Tk_ImageCmd procedure, "width" option} -body { image width foo -} -returnCodes error -result {image "foo" doesn't exist} +} -returnCodes error -result {image "foo" does not exist} test image-7.4 {Tk_ImageCmd procedure, "width" option} -constraints { testImageType } -setup { @@ -370,10 +370,6 @@ test image-9.1 {Tk_ImageChanged procedure} -constraints testImageType -setup { foo changed 5 6 7 8 30 15 update idletasks update - # On MacOS we need to wait for the test image display procedure to run. - while {"timed out" ni $x && [lindex $x end 1] ne "display"} { - vwait x - } after cancel $timer return $x } -cleanup { @@ -408,7 +404,7 @@ test image-10.1 {Tk_GetImage procedure} -setup { .c create image 100 10 -image bad_name } -cleanup { imageCleanup -} -returnCodes error -result {image "bad_name" doesn't exist} +} -returnCodes error -result {image "bad_name" does not exist} test image-10.2 {Tk_GetImage procedure} -constraints testImageType -setup { destroy .l imageCleanup @@ -420,7 +416,7 @@ test image-10.2 {Tk_GetImage procedure} -constraints testImageType -setup { } -cleanup { destroy .l imageCleanup -} -returnCodes error -result {image "mytest" doesn't exist} +} -returnCodes error -result {image "mytest" does not exist} test image-11.1 {Tk_FreeImage procedure} -constraints testImageType -setup { @@ -581,7 +577,7 @@ test image-13.2 {DeleteImage procedure} -constraints testImageType -setup { lappend x | [imageNames] | [catch {image delete foo} msg] | $msg | [imageNames] | } -cleanup { imageCleanup -} -result {{foo free} {foo free} {foo delete} | {} | 1 | {image "foo" doesn't exist} | {} |} +} -result {{foo free} {foo free} {foo delete} | {} | 1 | {image "foo" does not exist} | {} |} test image-13.3 {Tk_SizeOfImage procedure} -constraints testOldImageType -setup { imageCleanup @@ -607,7 +603,7 @@ test image-13.4 {DeleteImage procedure} -constraints testOldImageType -setup { } -cleanup { .c delete all imageCleanup -} -result {{foo free} {foo free} {foo delete} | {} | 1 | {image "foo" doesn't exist} | {} |} +} -result {{foo free} {foo free} {foo delete} | {} | 1 | {image "foo" does not exist} | {} |} test image-14.1 {image command vs hidden commands} -body { catch {image delete hidden} diff --git a/tests/menu.test b/tests/menu.test index 203b57c186..3385cbcfb8 100644 --- a/tests/menu.test +++ b/tests/menu.test @@ -746,11 +746,11 @@ test menu-2.127 {entry configuration options 0 -image bogus tearoff} -body { test menu-2.128 {entry configuration options 1 -image bogus command} -body { .m1 entryconfigure 1 -image bogus -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test menu-2.129 {entry configuration options 2 -image bogus cascade} -body { .m1 entryconfigure 2 -image bogus -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test menu-2.130 {entry configuration options 3 -image bogus separator} -body { .m1 entryconfigure 3 -image bogus @@ -758,11 +758,11 @@ test menu-2.130 {entry configuration options 3 -image bogus separator} -body { test menu-2.131 {entry configuration options 4 -image bogus checkbutton} -body { .m1 entryconfigure 4 -image bogus -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test menu-2.132 {entry configuration options 5 -image bogus radiobutton} -body { .m1 entryconfigure 5 -image bogus -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test menu-2.133 {entry configuration options 0 -image {} tearoff} -body { .m1 entryconfigure 0 -image @@ -1027,11 +1027,11 @@ test menu-2.190 {entry configuration options 3 -selectimage bogus separator} -bo test menu-2.191 {entry configuration options 4 -selectimage bogus checkbutton} -body { .m1 entryconfigure 4 -selectimage bogus -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test menu-2.192 {entry configuration options 5 -selectimage bogus radiobutton} -body { .m1 entryconfigure 5 -selectimage bogus -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test menu-2.193 {entry configuration options 0 -selectimage {} tearoff} -body { .m1 entryconfigure 0 -selectimage diff --git a/tests/menubut.test b/tests/menubut.test index 8dd9872837..2a5aad37c0 100644 --- a/tests/menubut.test +++ b/tests/menubut.test @@ -207,7 +207,7 @@ test menubutton-1.37 {configuration options} -setup { .mb configure -image bogus } -cleanup { .mb configure -image [lindex [.mb configure -image] 3] -} -returnCodes error -result {image "bogus" doesn't exist} +} -returnCodes error -result {image "bogus" does not exist} test menubutton-1.38 {configuration options} -body { .mb configure -indicatoron yes .mb cget -indicatoron diff --git a/tests/pack.test b/tests/pack.test index b23ad6a087..db1bd8877e 100644 --- a/tests/pack.test +++ b/tests/pack.test @@ -1553,6 +1553,11 @@ test pack-17.2 {PackLostContentProc procedure} -setup { # into account while the window is unmapped. # pack-18.1.2 checks that, on Windows, width/height changes are taken into # account on window remapping. +# +# While these tests pass on macOS, one can see by watching the tests +# that the window .pack is sometimes black, even though the frame is +# colored. So, evidently, even though the size changes are honored, +# the window is sometimes not completely configured. test pack-18.1.1 {unmap content when container unmapped} -constraints { macOrUnix failsOnUbuntu failsOnXQuarz } -setup { @@ -1562,7 +1567,8 @@ test pack-18.1.1 {unmap content when container unmapped} -constraints { # as the screen (screen switch causes scale and other tests to fail). wm geometry .pack +100+100 } -body { - frame .pack.a -width 100 -height 50 -relief raised -bd 2 + frame .pack.a -width 100 -height 50 -relief raised -bd 2 -bg green + after 100 pack .pack.a update set result [winfo ismapped .pack.a] @@ -1585,7 +1591,7 @@ test pack-18.1.2 {unmap content when container unmapped} -constraints { # as the screen (screen switch causes scale and other tests to fail). wm geometry .pack +100+100 } -body { - frame .pack.a -width 100 -height 50 -relief raised -bd 2 + frame .pack.a -width 100 -height 50 -relief raised -bd 2 -bg green pack .pack.a update set result [winfo ismapped .pack.a] @@ -1606,8 +1612,8 @@ test pack-18.2 {unmap content when container unmapped} -constraints {failsOnUbun # as the screen (screen switch causes scale and other tests to fail). wm geometry .pack +100+100 } -body { - frame .pack.a -relief raised -bd 2 - frame .pack.b -width 70 -height 30 -relief sunken -bd 2 + frame .pack.a -relief raised -bd 2 -bg green + frame .pack.b -width 70 -height 30 -relief sunken -bd 2 -bg red pack .pack.a pack .pack.b -in .pack.a update diff --git a/tests/raise.test b/tests/raise.test index 2e9e2c6c2d..7e6b0bd3ef 100644 --- a/tests/raise.test +++ b/tests/raise.test @@ -16,6 +16,7 @@ namespace import -force tcltest::test # Procedure to create a bunch of overlapping windows, which should # make it easy to detect differences in order. +wm geometry . +400+400 proc raise_setup {} { destroy {*}[winfo children .raise] update idletasks diff --git a/tests/systray.test b/tests/systray.test index deaf0a9ce7..6f388238e4 100644 --- a/tests/systray.test +++ b/tests/systray.test @@ -143,7 +143,7 @@ test systray-14 {systray icon creation, create one per interp, visibiliy checks} tk systray destroy image delete _book interp delete second -} -returnCodes error -result {image "_book" doesn't exist} +} -returnCodes error -result {image "_book" does not exist} test systray-15 {systray icon creation, create one per interp} -setup { image create photo _book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw== diff --git a/tests/textDisp.test b/tests/textDisp.test index 46f1ed37c2..3555ae73c0 100644 --- a/tests/textDisp.test +++ b/tests/textDisp.test @@ -1107,22 +1107,28 @@ test textDisp-6.9 {DisplayText, horizontal scrollbar updates} { set scrollInfo } [list 0.0 [expr {4.0/11}]] test textDisp-6.10 {DisplayText, redisplay embedded windows after scroll} {aqua} { + # For this test to pass line 8 must be out of the text widget. + # With macOS 14 this requires making the buttons a little larger. + # So we set the pady option. This may depend on the OS version. .t configure -wrap char + update .t delete 1.0 end + update .t insert 1.0 "Line 1" foreach i {2 3 4} { .t insert end "\nLine $i" } .t insert end "\n" .t window create end -create { - button %W.button_one -text "Button 1"} + button %W.button_one -text "Button 1" -pady 5} .t insert end "\nLine 6\n" .t window create end -create { - button %W.button_two -text "Button 2"} + button %W.button_two -text "Button 2" -pady 5} .t insert end "\nLine 8\n" .t window create end -create { - button %W.button_three -text "Button 3"} + button %W.button_three -text "Button 3" -pady 5} update + set tk_textEmbWinDisplay {} .t delete 2.0 3.0 update list $tk_textEmbWinDisplay diff --git a/tests/ttk/image.test b/tests/ttk/image.test index 51f0f008a5..8d58a124f2 100644 --- a/tests/ttk/image.test +++ b/tests/ttk/image.test @@ -5,7 +5,7 @@ loadTestedCommands test image-1.1 "Bad image element" -body { ttk::style element create BadImage image badimage -} -returnCodes error -result {image "badimage" doesn't exist} +} -returnCodes error -result {image "badimage" does not exist} test image-1.2 "Duplicate element" -setup { image create photo test.element -width 10 -height 10 diff --git a/tests/ttk/ttk.test b/tests/ttk/ttk.test index 5215bbb5bc..6f30f189b9 100644 --- a/tests/ttk/ttk.test +++ b/tests/ttk/ttk.test @@ -136,6 +136,8 @@ test ttk-selfdestruct-ok-1 "Intentional self-destruction" -body { # Basic tests. # test ttk-1.1 "Create multiline button showing justified text" -body { + wm geometry . +100+100 + event generate . -warp 1 -x 600 -y 600 pack [ttk::button .t -text "Hello\nWorld!!" -justify center] -expand true -fill both update } @@ -152,6 +154,8 @@ test ttk-1.4 "Original style preserved" -body { .t cget -style } -result "" +# Tests using this will fail if the top-level window contains the cursor + proc checkstate {w} { foreach statespec { {!active !disabled} @@ -166,7 +170,6 @@ proc checkstate {w} { set result } -# NB: this will fail if the top-level window pops up underneath the cursor test ttk-2.0 "Check state" -body { checkstate .t } -result [list 1 0 0 0 0 0] @@ -342,7 +345,7 @@ test ttk-8.1 "Test -compound options" -body { # Exhaustively test each combination. # Main goal is to make sure no code paths crash. foreach image {icon ""} { - foreach text {"Hi!" ""} { + foreach text {"Hi!" ""} { foreach compound $::compoundStrings { .ctb configure -image $image -text $text -compound $compound update; tick @@ -357,7 +360,7 @@ test ttk-8.2 "Test -compound options with regular button" -body { pack .rtb foreach image {"" icon} { - foreach text {"Hi!" ""} { + foreach text {"Hi!" ""} { foreach compound [lrange $::compoundStrings 2 end] { .rtb configure -image $image -text $text -compound $compound update; tick @@ -369,7 +372,7 @@ tock test ttk-8.3 "Rerun test 8.1" -body { foreach image {icon ""} { - foreach text {"Hi!" ""} { + foreach text {"Hi!" ""} { foreach compound $::compoundStrings { .ctb configure -image $image -text $text -compound $compound update; tick diff --git a/tests/unixWm.test b/tests/unixWm.test index ba8863a992..7c26c8415d 100644 --- a/tests/unixWm.test +++ b/tests/unixWm.test @@ -16,18 +16,6 @@ namespace import -force ::tk::test:loadTkCommand testConstraint failsOnUbuntu [expr {![info exists ::env(CI)] || ![string match Linux $::tcl_platform(os)]}] testConstraint failsOnXQuarz [expr {$tcl_platform(os) ne "Darwin" || [tk windowingsystem] ne "x11" }] -# Starting with macOS Ventura it became necessary to wait for windows to be restacked -# or to be raised after creation. - -if {[tk windowingsystem] eq "aqua"} { - proc restackDelay {} { - after 200; - update idletasks - } -} else { - proc restackDelay {} {} -} - proc sleep ms { global x after $ms {set x 1} @@ -105,6 +93,7 @@ foreach geom "+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" { set i 1 foreach geom "+20+80 +80+$Y0 +0+$Y0 -0-0 +0-0 -0+$Y0 -10-5 -10+$Y5 +10-5" { test unixWm-3.$i {moving window while iconified} unix { + update wm iconify .t update idletasks wm geom .t $geom @@ -1373,7 +1362,9 @@ test unixWm-40.1 {Tk_SetGrid procedure, set grid dimensions before turning on gr wm geometry .t } {30x10+0+0} test unixWm-40.2 {Tk_SetGrid procedure, turning on grid when dimensions already set} unix { + update destroy .t + update toplevel .t wm geometry .t 200x100+100+$Y0 listbox .t.l -height 20 -width 20 @@ -1798,6 +1789,8 @@ test unixWm-49.2 {Tk_GetRootCoords procedure, menubars} {unix testmenubar} { } {52 7 12 62} deleteWindows +# Make sure that the root window is out of the way! +wm geom . +700+700 wm withdraw . if {[tk windowingsystem] eq "aqua"} { # Modern mac windows have no border. @@ -1834,14 +1827,12 @@ test unixWm-50.2 {Tk_CoordsToWindow procedure, finding a toplevel, y-coords and tkwait visibility .t wm geom .t +100+100 update - restackDelay toplevel .t2 -width 200 -height 100 -bg blue wm overrideredirect .t2 1 tkwait visibility .t2 wm geom .t2 +200+200 update raise .t2 - restackDelay set x [winfo rootx .t] set y [winfo rooty .t] set y2 [winfo rooty .t2] @@ -1855,11 +1846,10 @@ test unixWm-50.2 {Tk_CoordsToWindow procedure, finding a toplevel, y-coords and [winfo containing [expr $x +200] [expr $y + 450]] } {{} {} .t .t .t2 .t2 .t {}} test unixWm-50.3 { - Tk_CoordsToWindow procedure, finding a toplevel with embedding + Tk_CoordsToWindow procedure, finding a toplevel with embedding } tempNotWin { deleteWindows catch {interp delete child} - toplevel .t -width 300 -height 400 -bg blue wm geom .t +100+100 frame .t.f -container 1 -bg red @@ -1888,7 +1878,6 @@ test unixWm-50.3 { } {{} .x .t .t.f} test unixWm-50.4 {Tk_CoordsToWindow procedure, window in other application} unix { destroy .t - catch {interp delete child} toplevel .t -width 200 -height 200 -bg green tkwait visibility .t @@ -1897,9 +1886,8 @@ test unixWm-50.4 {Tk_CoordsToWindow procedure, window in other application} unix interp create child load {} Tk child child eval {wm geometry . 200x200+100+100; update} - restackDelay set result [list [winfo containing 200 200] \ - [child eval {winfo containing 200 200}]] + [child eval {winfo containing 200 200}]] interp delete child set result } {{} .} @@ -1979,21 +1967,22 @@ test unixWm-50.8 {Tk_CoordsToWindow procedure, more basics} unix { test unixWm-50.9 {Tk_CoordsToWindow procedure, unmapped windows} {unix failsOnUbuntu failsOnXQuarz} { destroy .t destroy .t2 + update toplevel .t -width 200 -height 200 -bg green tkwait visibility .t - update - wm geometry .t +0+0 + wm geometry .t +20+20 + after 200 update toplevel .t2 -width 200 -height 200 -bg red tkwait visibility .t2 + wm geometry .t2 +20+20 + after 200 update - wm geometry .t2 +0+0 - update - restackDelay - set result [list [winfo containing 100 100]] - wm iconify .t2 + set result [list [winfo containing 120 120]] + destroy .t2 + after 200 update - lappend result [winfo containing 100 100] + lappend result [winfo containing 120 120] } {.t2 .t} test unixWm-50.10 {Tk_CoordsToWindow procedure, unmapped windows} unix { destroy .t @@ -2071,7 +2060,6 @@ test unixWm-51.6 {TkWmRestackToplevel procedure, window to be stacked isn't mapp tkwait visibility .t wm geometry .t +0+0 update - restackDelay destroy .t2 toplevel .t2 -width 200 -height 200 -bg red # This test assumes that .t2 is not mapped yet, but that is not really guaranteed. @@ -2083,15 +2071,15 @@ test unixWm-51.7 {TkWmRestackToplevel procedure, other window isn't mapped} {uni toplevel $w -width 200 -height 200 -bg green tkwait visibility $w wm geometry $w +100+100 + after 200 update } + update raise .t .t2 - restackDelay update set result [list [winfo containing 200 200]] lower .t3 - restackDelay - sleep 10 + update lappend result [winfo containing 200 200] } {.t3 .t} test unixWm-51.8 {TkWmRestackToplevel procedure, overrideredirect windows} unix { @@ -2105,7 +2093,6 @@ test unixWm-51.8 {TkWmRestackToplevel procedure, overrideredirect windows} unix wm overrideredirect .t2 1 wm geometry .t2 +0+0 tkwait visibility .t2 - restackDelay # Need to use vrootx and vrooty to make tests work correctly with # virtual root window measures managers: overrideredirect windows @@ -2116,15 +2103,14 @@ test unixWm-51.8 {TkWmRestackToplevel procedure, overrideredirect windows} unix set y [expr 100-[winfo vrooty .]] set result [list [winfo containing $x $y]] raise .t - restackDelay lappend result [winfo containing $x $y] raise .t2 - restackDelay lappend result [winfo containing $x $y] } {.t2 .t .t2} # The mac won't put an overrideredirect window above the root, if {[tk windowingsystem] eq "aqua"} { wm withdraw . + update } test unixWm-51.9 {TkWmRestackToplevel procedure, other window overrideredirect} unix { foreach w {.t .t2 .t3} { @@ -2132,12 +2118,11 @@ test unixWm-51.9 {TkWmRestackToplevel procedure, other window overrideredirect} update toplevel $w -width 200 -height 200 -bg green wm overrideredirect $w 1 - wm geometry $w +0+0 tkwait visibility $w + wm geometry $w +0+0 update } lower .t3 .t2 - restackDelay update # Need to use vrootx and vrooty to make tests work correctly with @@ -2149,11 +2134,12 @@ test unixWm-51.9 {TkWmRestackToplevel procedure, other window overrideredirect} set y [expr 100-[winfo vrooty .]] set result [list [winfo containing $x $y]] lower .t2 - restackDelay + update lappend result [winfo containing $x $y] } {.t2 .t3} if {[tk windowingsystem] eq "aqua"} { wm deiconify . + update } test unixWm-51.10 {TkWmRestackToplevel procedure, don't move window that's already in the right place} unix { makeToplevels diff --git a/tests/window.test b/tests/window.test index d53f6573f4..de34221781 100644 --- a/tests/window.test +++ b/tests/window.test @@ -11,7 +11,8 @@ tcltest::configure {*}$argv tcltest::loadTestedCommands namespace import ::tk::test::loadTkCommand update - +# Move the mouse out of the way for window-2.1 +event generate {} -warp 1 -x 640 -y 10 # XXX This file is woefully incomplete. Right now it only tests # a few parts of a few procedures in tkWindow.c diff --git a/tests/winfo.test b/tests/winfo.test index 6442f74d91..b9949b898b 100644 --- a/tests/winfo.test +++ b/tests/winfo.test @@ -441,8 +441,10 @@ test winfo-13.3 {destroying container window} -setup { test winfo-13.4 {[winfo containing] with embedded windows} -setup { deleteWindows } -body { + wm geometry . +100+100 frame .con -container 1 pack .con -expand yes -fill both + update toplevel .emb -use [winfo id .con] -bd 0 -highlightthickness 0 button .emb.b pack .emb.b -expand yes -fill both diff --git a/tests/xmfbox.test b/tests/xmfbox.test index dcf7902e89..b584aeb3a2 100644 --- a/tests/xmfbox.test +++ b/tests/xmfbox.test @@ -54,6 +54,7 @@ proc cleanup {} { } catch {unset foo} destroy .foo + update } # ---------------------------------------------------------------------- @@ -76,6 +77,7 @@ test xmfbox-1.2 {tk::MotifFDialog_Create, -parent switch} -constraints { } -body { toplevel .bar wm geometry .bar +0+0 + update set x [tk::MotifFDialog_Create foo open {-parent .bar}] } -cleanup { destroy $x @@ -89,6 +91,7 @@ test xmfbox-2.1 {tk::MotifFDialog_InterpFilter, ~ in dir names} -constraints { cleanup file mkdir ./~nosuchuser1 set x [tk::MotifFDialog_Create foo open {}] + update $::tk::dialog::file::foo(fEnt) delete 0 end $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1 file normalize [file join {*}[tk::MotifFDialog_InterpFilter $x]] @@ -100,6 +103,7 @@ test xmfbox-2.2 {tk::MotifFDialog_InterpFilter, ~ in file names} -constraints { cleanup close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}] set x [tk::MotifFDialog_Create foo open {}] + update $::tk::dialog::file::foo(fEnt) delete 0 end $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1 file normalize [file join {*}[tk::MotifFDialog_InterpFilter $x]] @@ -111,6 +115,7 @@ test xmfbox-2.3 {tk::MotifFDialog_Update, ~ in file names} -constraints { cleanup close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}] set x [tk::MotifFDialog_Create foo open {}] + update $::tk::dialog::file::foo(fEnt) delete 0 end $::tk::dialog::file::foo(fEnt) insert 0 [pwd]/~nosuchuser1 tk::MotifFDialog_InterpFilter $x @@ -124,6 +129,7 @@ test xmfbox-2.4 {tk::MotifFDialog_LoadFile, ~ in file names} -constraints { cleanup close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}] set x [tk::MotifFDialog_Create foo open {}] + update set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1] expr {$i >= 0} } -result 1 @@ -134,6 +140,7 @@ test xmfbox-2.5 {tk::MotifFDialog_BrowseFList, ~ in file names} -constraints { cleanup close [open ./~nosuchuser1 {CREAT TRUNC WRONLY}] set x [tk::MotifFDialog_Create foo open {}] + update set i [lsearch [$::tk::dialog::file::foo(fList) get 0 end] ~nosuchuser1] $::tk::dialog::file::foo(fList) selection clear 0 end $::tk::dialog::file::foo(fList) selection set $i From 1176a0ff5baf8ceeab6cf4ce596e824ff9b53983 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 5 Nov 2024 12:36:10 +0000 Subject: [PATCH 2/3] Revert some *.h changes which should be kept. Formatting. --- generic/tkStyle.c | 2 +- macosx/tkMacOSXBitmap.c | 2 +- macosx/tkMacOSXButton.c | 2 +- macosx/tkMacOSXColor.c | 4 +-- macosx/tkMacOSXColor.h | 19 ++++++++++++-- macosx/tkMacOSXDefault.h | 6 ++--- macosx/tkMacOSXDialog.c | 4 +-- macosx/tkMacOSXFont.c | 4 +-- macosx/tkMacOSXHLEvents.c | 12 ++++----- macosx/tkMacOSXImage.c | 6 ++--- macosx/tkMacOSXInt.h | 1 + macosx/tkMacOSXKeyEvent.c | 6 ++--- macosx/tkMacOSXMenu.c | 28 ++++++++++----------- macosx/tkMacOSXMenus.c | 30 +++++++++++----------- macosx/tkMacOSXMouseEvent.c | 26 +++++++++---------- macosx/tkMacOSXNotify.c | 32 ++++++++++++------------ macosx/tkMacOSXPrint.c | 10 ++++---- macosx/tkMacOSXPrivate.h | 4 +-- macosx/tkMacOSXScrlbr.c | 24 +++++++++--------- macosx/tkMacOSXSubwindows.c | 8 +++--- macosx/tkMacOSXSysTray.c | 10 ++++---- macosx/tkMacOSXWm.c | 50 ++++++++++++++++++------------------- macosx/tkMacOSXXStubs.c | 2 +- macosx/ttkMacOSXTheme.c | 4 +-- macosx/ttkMacOSXTheme.h | 2 +- win/tkWinDefault.h | 2 +- win/tkWinEmbed.c | 2 +- win/tkWinMenu.c | 2 +- win/tkWinSysTray.c | 4 +-- xlib/xgc.c | 2 +- 30 files changed, 163 insertions(+), 147 deletions(-) diff --git a/generic/tkStyle.c b/generic/tkStyle.c index b2436748e4..ea397608b7 100644 --- a/generic/tkStyle.c +++ b/generic/tkStyle.c @@ -1358,7 +1358,7 @@ Tk_GetStyle( if (entryPtr == NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "style \"%s\" doesn't exist", name)); + "style \"%s\" does not exist", name)); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "STYLE", name, (char *)NULL); } return NULL; diff --git a/macosx/tkMacOSXBitmap.c b/macosx/tkMacOSXBitmap.c index 39fd6025fc..88bcf71ad2 100644 --- a/macosx/tkMacOSXBitmap.c +++ b/macosx/tkMacOSXBitmap.c @@ -383,7 +383,7 @@ TkMacOSXIconBitmapObjCmd( #if 0 if ((kind == ICON_TYPE || kind == ICON_SYSTEM)) { Tcl_DString ds; - Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman"); + Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman"); (void)Tcl_UtfToExternalDString(encoding, value, TCL_INDEX_NONE, &ds); len = Tcl_DStringLength(&ds); diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index c825920d83..e1211bd023 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -401,7 +401,7 @@ TkpComputeButtonGeometry( } if (mbPtr->btnkind == kThemePushButton) { HIRect tmpRect; - HIRect contBounds; + HIRect contBounds; /* * A PushButton has a minimum size. We make sure that we are not diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 29bd240dfd..6263356451 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -397,8 +397,8 @@ SetCGColorComponents( CGFloat rgba[4] = {0, 0, 0, 1}; if (entry->type == HIBrush) { - OSStatus err = ChkErr(HIThemeBrushCreateCGColor, entry->value, c); - return err == noErr; + OSStatus err = ChkErr(HIThemeBrushCreateCGColor, entry->value, c); + return err == noErr; } /* diff --git a/macosx/tkMacOSXColor.h b/macosx/tkMacOSXColor.h index 54077f80ce..d86f778a02 100644 --- a/macosx/tkMacOSXColor.h +++ b/macosx/tkMacOSXColor.h @@ -38,6 +38,10 @@ enum colorType { rgbColor, /* The 24 bit value is an rgb color. */ clearColor, /* The unique rgba color with all channels 0. */ HIBrush, /* A HITheme brush color.*/ +#if TCL_MAJOR_VERSION < 9 + HIText, /* A HITheme text color (32-bit only). */ + HIBackground, /* A HITheme background color (32-bit only). */ +#endif ttkBackground, /* A background color which indicates nesting level.*/ semantic, /* A semantic NSColor.*/ }; @@ -52,6 +56,17 @@ typedef union MacPixel_t { xpixel pixel; } MacPixel; +/* + * We maintain two colormaps, one for the LightAqua appearance and one for the + * DarkAqua appearance. + */ + +enum macColormap { + noColormap, + lightColormap, + darkColormap, +}; + /* * In TkMacOSXColor.c a Tk hash table is constructed from the static data * below to map system color names to CGColors. @@ -76,10 +91,10 @@ typedef struct { static SystemColorDatum systemColorData[] = { {"Pixel", rgbColor, 0, NULL, 0, NULL }, -{"Transparent", clearColor, 0, NULL, 0, NULL }, +{"Transparent", clearColor, 0, NULL, 0, NULL }, {"Highlight", HIBrush, kThemeBrushPrimaryHighlightColor, NULL, 0, NULL }, -{"HighlightSecondary", HIBrush, kThemeBrushSecondaryHighlightColor, NULL, 0, NULL }, +{"HighlightSecondary", HIBrush, kThemeBrushSecondaryHighlightColor, NULL, 0, NULL }, {"HighlightText", HIBrush, kThemeBrushBlack, NULL, 0, NULL }, {"HighlightAlternate", HIBrush, kThemeBrushAlternatePrimaryHighlightColor, NULL, 0, NULL }, {"PrimaryHighlightColor", HIBrush, kThemeBrushPrimaryHighlightColor, NULL, 0, NULL }, diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h index ca4db03f63..0bfbc71a8b 100644 --- a/macosx/tkMacOSXDefault.h +++ b/macosx/tkMacOSXDefault.h @@ -379,8 +379,8 @@ #define DEF_MESSAGE_HIGHLIGHT NORMAL_FG #define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" #define DEF_MESSAGE_JUSTIFY "left" -#define DEF_MESSAGE_PADX NULL -#define DEF_MESSAGE_PADY NULL +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" #define DEF_MESSAGE_RELIEF "flat" #define DEF_MESSAGE_TAKE_FOCUS "0" #define DEF_MESSAGE_TEXT "" @@ -475,7 +475,7 @@ #define DEF_SCROLLBAR_BORDER_WIDTH "0" #define DEF_SCROLLBAR_COMMAND "" #define DEF_SCROLLBAR_CURSOR "" -#define DEF_SCROLLBAR_EL_BORDER_WIDTH NULL +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" #define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG #define DEF_SCROLLBAR_HIGHLIGHT NORMAL_FG #define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index f2368acf0e..1f1d9eb2ca 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -577,7 +577,7 @@ parseFileFilters( globPtr = globPtr->next) { const char *str = globPtr->pattern; while (*str && (*str == '*' || *str == '.')) { - str++; + str++; } if (*str) { NSString *extension = [[TKNSString alloc] initWithTclUtfBytes:str length:TCL_INDEX_NONE]; @@ -1532,7 +1532,7 @@ Tk_MessageBoxObjCmd( if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 - [alert beginSheetModalForWindow:parent + [alert beginSheetModalForWindow:parent completionHandler:^(NSModalResponse returnCode) { [NSApp tkAlertDidEnd:alert returnCode:returnCode diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index ec8671be95..db28066a0f 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -73,7 +73,7 @@ struct SystemFontMapEntry { #define ThemeFont(n, ...) { kTheme##n##Font, "system" #n "Font", ##__VA_ARGS__ } static const struct SystemFontMapEntry systemFontMap[] = { - ThemeFont(System, "TkDefaultFont", "TkIconFont"), + ThemeFont(System, "TkDefaultFont", "TkIconFont"), ThemeFont(EmphasizedSystem, "TkCaptionFont", NULL), ThemeFont(SmallSystem, "TkHeadingFont", "TkTooltipFont"), ThemeFont(SmallEmphasizedSystem, NULL, NULL), @@ -923,7 +923,7 @@ void TkpGetFontAttrsForChar( TCL_UNUSED(Tk_Window), /* Window on the font's display */ Tk_Font tkfont, /* Font to query */ - int c, /* Character of interest */ + int c, /* Character of interest */ TkFontAttributes* faPtr) /* Output: Font attributes */ { MacFont *fontPtr = (MacFont *) tkfont; diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c index 0d07fdf431..6007050949 100644 --- a/macosx/tkMacOSXHLEvents.c +++ b/macosx/tkMacOSXHLEvents.c @@ -180,7 +180,7 @@ static const char getSdefProc[] = "::tk::mac::GetDynamicSdef"; fileSpecDesc = [event aeDesc]; if (fileSpecDesc == nil ) { - return; + return; } /* @@ -195,12 +195,12 @@ static const char getSdefProc[] = "::tk::mac::GetDynamicSdef"; /* Get a copy of the AppleEvent's descriptor. */ AEGetParamDesc(fileSpecDesc, keyDirectObject, typeWildCard, &contents); if (contents.descriptorType == typeAEList) { - fileSpecDesc = &contents; + fileSpecDesc = &contents; } if (AECountItems(fileSpecDesc, &count) != noErr) { AEDisposeDesc(&contents); - return; + return; } /* @@ -296,10 +296,10 @@ static const char getSdefProc[] = "::tk::mac::GetDynamicSdef"; } if (MissedAnyParameters((AppleEvent*)theDesc)) { - snprintf(errString, sizeof(errString), "AEDoScriptHandler: extra parameters"); - AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, + snprintf(errString, sizeof(errString), "AEDoScriptHandler: extra parameters"); + AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,errString, strlen(errString)); - return; + return; } if (initialType == typeFileURL || initialType == typeAlias) { diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index efd4d0a881..548fdaa0ab 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -1140,10 +1140,10 @@ struct TkMacOSXNSImageModel { int radius; /* Radius for rounded corners. */ int ring; /* Thickness of the focus ring. */ double alpha; /* Transparency, between 0.0 and 1.0*/ - char *imageName ; /* Malloc'ed image name. */ - Tcl_Obj *sourceObj; /* Describing the image. */ + char *imageName; /* Malloc'ed image name. */ + Tcl_Obj *sourceObj; /* Describing the image. */ Tcl_Obj *asObj; /* Interpretation of source */ - int flags; /* Sundry flags, defined below. */ + int flags; /* Sundry flags, defined below. */ bool pressed; /* Image is for use in a pressed button.*/ bool templ; /* Image is for use as a template.*/ TkMacOSXNSImageInstance *instancePtr; /* Start of list of instances associated diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index feb6a32b39..29b20f71e9 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -88,6 +88,7 @@ typedef struct TkWindowPrivate MacDrawable; #define TK_DRAWN_UNDER_MENU 0x08 #define TK_IS_PIXMAP 0x10 #define TK_IS_BW_PIXMAP 0x20 +#define TK_DO_NOT_DRAW 0x40 #define TTK_HAS_CONTRASTING_BG 0x80 /* diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 19c7ba9837..a69df86cf8 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -322,7 +322,7 @@ static NSUInteger textInputModifiers; if (privateWorkingText != nil) { sendingIMEText = YES; - [self deleteWorkingText]; + [self deleteWorkingText]; } /* @@ -385,8 +385,8 @@ static NSUInteger textInputModifiers; macKC.v.o_s |= INDEX_OPTION; } xEvent.xkey.keycode = macKC.uint; - xEvent.xany.type = KeyPress; - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + xEvent.xany.type = KeyPress; + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); xEvent.xkey.state = state; } } diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index bf41d6654d..b8019a43ee 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -345,13 +345,13 @@ static Bool runMenuCommand = true; { if (!runMenuCommand) { - /* - * We are being called for a menu accelerator. Tk will handle it. - * Just update the runMenuCommand flag. - */ + /* + * We are being called for a menu accelerator. Tk will handle it. + * Just update the runMenuCommand flag. + */ - runMenuCommand = true; - return; + runMenuCommand = true; + return; } /* @@ -721,7 +721,7 @@ TkpMenuNewEntry( int TkpConfigureMenuEntry( - TkMenuEntry *mePtr) /* Information about menu entry; may or may + TkMenuEntry *mePtr) /* Information about menu entry; may or may * not already have values for some fields. */ { NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData; @@ -745,7 +745,7 @@ TkpConfigureMenuEntry( } if (mePtr->image) { - Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight); + Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight); image = TkMacOSXGetNSImageFromTkImage(mePtr->menuPtr->display, mePtr->image, imageWidth, imageHeight); } else if (mePtr->bitmapPtr != NULL) { @@ -801,7 +801,7 @@ TkpConfigureMenuEntry( if (gc->background != defaultBg) { NSColor *bgcolor = TkMacOSXGetNSColor(gc, gc->background); [attributes setObject:bgcolor - forKey:NSBackgroundColorAttributeName]; + forKey:NSBackgroundColorAttributeName]; } #else @@ -845,7 +845,7 @@ TkpConfigureMenuEntry( } else { [submenu setTitle:title]; - if ([menuItem isEnabled]) { + if ([menuItem isEnabled]) { /* * This menuItem might have been previously disabled which @@ -973,7 +973,7 @@ TkpPostMenu( return result; } if (itemIndex >= numItems) { - itemIndex = numItems - 1; + itemIndex = numItems - 1; } if (itemIndex >= 0) { item = [menu itemAtIndex:itemIndex]; @@ -985,7 +985,7 @@ TkpPostMenu( */ if (menuPtr->tkwin == NULL) { - return TCL_OK; + return TCL_OK; } [menu popUpMenuPositioningItem:item @@ -1039,7 +1039,7 @@ TkpPostTearoffMenu( TkRecomputeMenu(menuPtr); result = TkPostCommand(menuPtr); if (result != TCL_OK) { - return result; + return result; } /* @@ -1048,7 +1048,7 @@ TkpPostTearoffMenu( */ if (menuPtr->tkwin == NULL) { - return TCL_OK; + return TCL_OK; } /* diff --git a/macosx/tkMacOSXMenus.c b/macosx/tkMacOSXMenus.c index b7173526bf..81660db7d7 100644 --- a/macosx/tkMacOSXMenus.c +++ b/macosx/tkMacOSXMenus.c @@ -101,11 +101,11 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp); nil]]; _defaultWindowsMenuItems = [NSArray arrayWithObjects: - [NSMenuItem itemWithTitle:@"Minimize" - action:@selector(performMiniaturize:) target:nil - keyEquivalent:@"m"], - [NSMenuItem itemWithTitle:@"Zoom" action:@selector(performZoom:) - target:nil], + [NSMenuItem itemWithTitle:@"Minimize" + action:@selector(performMiniaturize:) target:nil + keyEquivalent:@"m"], + [NSMenuItem itemWithTitle:@"Zoom" action:@selector(performZoom:) + target:nil], nil]; /* @@ -117,24 +117,24 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp); arrayByAddingObjectsFromArray: [NSArray arrayWithObjects: [NSMenuItem separatorItem], - [NSMenuItem itemWithTitle:@"Show Previous Tab" + [NSMenuItem itemWithTitle:@"Show Previous Tab" action:@selector(selectPreviousTab:) target:nil keyEquivalent:@"\t" keyEquivalentModifierMask: - NSControlKeyMask|NSShiftKeyMask], + NSControlKeyMask|NSShiftKeyMask], [NSMenuItem itemWithTitle:@"Show Next Tab" action:@selector(selectNextTab:) target:nil keyEquivalent:@"\t" keyEquivalentModifierMask:NSControlKeyMask], - [NSMenuItem itemWithTitle:@"Move Tab To New Window" - action:@selector(moveTabToNewWindow:) - target:nil], - [NSMenuItem itemWithTitle:@"Merge All Windows" - action:@selector(mergeAllWindows:) - target:nil], - [NSMenuItem separatorItem], + [NSMenuItem itemWithTitle:@"Move Tab To New Window" + action:@selector(moveTabToNewWindow:) + target:nil], + [NSMenuItem itemWithTitle:@"Merge All Windows" + action:@selector(mergeAllWindows:) + target:nil], + [NSMenuItem separatorItem], nil]]; } _defaultWindowsMenuItems = [_defaultWindowsMenuItems arrayByAddingObject: @@ -142,7 +142,7 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp); action:@selector(arrangeInFront:)]]; [_defaultWindowsMenuItems retain]; TKMenu *windowsMenu = [TKMenu menuWithTitle:@"Window" menuItems: - _defaultWindowsMenuItems]; + _defaultWindowsMenuItems]; _defaultHelpMenuItems = [[NSArray arrayWithObjects: [NSMenuItem itemWithTitle: [NSString stringWithFormat:@"%@ Help", applicationName] diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 062a12596b..ac94e1f80e 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -374,12 +374,12 @@ enum { } } else { - if (winPtr && winPtr->wmInfoPtr) { - local.x -= winPtr->wmInfoPtr->xInParent; - local.y -= winPtr->wmInfoPtr->yInParent; - } else { - return theEvent; - } + if (winPtr && winPtr->wmInfoPtr) { + local.x -= winPtr->wmInfoPtr->xInParent; + local.y -= winPtr->wmInfoPtr->yInParent; + } else { + return theEvent; + } } /* @@ -509,8 +509,8 @@ enum { Tk_UpdatePointer(new_win, global.x, global.y, state); } else if (eventType == NSMouseExited) { if ([NSApp tkDragTarget]) { - Tk_UpdatePointer((Tk_Window) [NSApp tkDragTarget], - global.x, global.y, state); + Tk_UpdatePointer((Tk_Window) [NSApp tkDragTarget], + global.x, global.y, state); } else { Tk_UpdatePointer(NULL, global.x, global.y, state); } @@ -561,11 +561,11 @@ enum { int deltaY = [theEvent scrollingDeltaY]; delta = (deltaX << 16) | (deltaY & 0xffff); if (delta != 0) { - xEvent.type = TouchpadScroll; - xEvent.xbutton.state = state; - xEvent.xkey.keycode = delta; - xEvent.xany.serial = scrollCounter++; - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + xEvent.type = TouchpadScroll; + xEvent.xbutton.state = state; + xEvent.xkey.keycode = delta; + xEvent.xany.serial = scrollCounter++; + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); } } else { /* diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index bdb1ef9b26..97c63c54af 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -36,24 +36,24 @@ static const char *Tk_EventName[39] = { "", "", "KeyPress", /*2*/ - "KeyRelease", /*3*/ - "ButtonPress", /*4*/ + "KeyRelease", /*3*/ + "ButtonPress", /*4*/ "ButtonRelease", /*5*/ - "MotionNotify", /*6*/ - "EnterNotify", /*7*/ - "LeaveNotify", /*8*/ + "MotionNotify", /*6*/ + "EnterNotify", /*7*/ + "LeaveNotify", /*8*/ "FocusIn", /*9*/ "FocusOut", /*10*/ - "KeymapNotify", /*11*/ + "KeymapNotify", /*11*/ "Expose", /*12*/ "GraphicsExpose", /*13*/ "NoExpose", /*14*/ "VisibilityNotify", /*15*/ - "CreateNotify", /*16*/ + "CreateNotify", /*16*/ "DestroyNotify", /*17*/ - "UnmapNotify", /*18*/ - "MapNotify", /*19*/ - "MapRequest", /*20*/ + "UnmapNotify", /*18*/ + "MapNotify", /*19*/ + "MapRequest", /*20*/ "ReparentNotify", /*21*/ "ConfigureNotify", /*22*/ "ConfigureRequest", /*23*/ @@ -68,7 +68,7 @@ static const char *Tk_EventName[39] = { "ColormapNotify", /*32*/ "ClientMessage", /*33*/ "MappingNotify", /*34*/ - "VirtualEvent", /*35*/ + "VirtualEvent", /*35*/ "ActivateNotify", /*36*/ "DeactivateNotify", /*37*/ "MouseWheelEvent" /*38*/ @@ -354,15 +354,15 @@ TkMacOSXEventsSetupProc( [NSApp _resetAutoreleasePool]; - /* + /* * After calling this setup proc, Tcl_DoOneEvent will call - * Tcl_WaitForEvent. Then it will call check proc to collect the - * events and translate them into XEvents. + * Tcl_WaitForEvent. Then it will call check proc to collect the + * events and translate them into XEvents. * - * If we have any events waiting or if there is any drawing to be done + * If we have any events waiting or if there is any drawing to be done * we want Tcl_WaitForEvent to return immediately. So we set the block * time to 0 and stop the heartbeat. - */ + */ NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask diff --git a/macosx/tkMacOSXPrint.c b/macosx/tkMacOSXPrint.c index ac29714129..bd1e960ebd 100644 --- a/macosx/tkMacOSXPrint.c +++ b/macosx/tkMacOSXPrint.c @@ -68,7 +68,7 @@ int MacPrint_Init(Tcl_Interp * interp); * * StartPrint -- * - * Launch native print dialog. + * Launch native print dialog. * * Results: * Configures values and starts print process. @@ -138,7 +138,7 @@ StartPrint( * * FinishPrint -- * - * Handles print process based on input from dialog. + * Handles print process based on input from dialog. * * Results: * Completes print process. @@ -275,7 +275,7 @@ FinishPrint( * Fork and start new process with command string. Thanks to Peter da Silva * for assistance. */ - pid_t pid; + pid_t pid; if ((pid = fork()) == -1) { return -1; } else if (pid == 0) { @@ -334,7 +334,7 @@ FinishPrint( * * MakePDF-- * - * Converts a Tk canvas to PDF data. + * Converts a Tk canvas to PDF data. * * Results: * Outputs PDF file. @@ -384,7 +384,7 @@ int MakePDF( * * MacPrint_Init-- * - * Initializes the printing module. + * Initializes the printing module. * * Results: * Printing module initialized. diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index c55c8ad5f6..368f35ba52 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -272,10 +272,10 @@ MODULE_SCOPE Tcl_ObjCmdProc TkMacOSXIconBitmapObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TkMacOSXNSImageObjCmd; MODULE_SCOPE void TkMacOSXDrawSolidBorder(Tk_Window tkwin, GC gc, int inset, int thickness); -MODULE_SCOPE int TkMacOSXServices_Init(Tcl_Interp *interp); +MODULE_SCOPE int TkMacOSXServices_Init(Tcl_Interp *interp); MODULE_SCOPE Tcl_ObjCmdProc TkMacOSXRegisterServiceWidgetObjCmd; MODULE_SCOPE unsigned TkMacOSXAddVirtual(unsigned int keycode); -MODULE_SCOPE int TkMacOSXNSImage_Init(Tcl_Interp *interp); +MODULE_SCOPE int TkMacOSXNSImage_Init(Tcl_Interp *interp); MODULE_SCOPE void TkMacOSXWinNSBounds(TkWindow *winPtr, NSView *view, NSRect *bounds); MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin); diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index 48ebd9e07f..431769b489 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -281,16 +281,16 @@ TkpDisplayScrollbar( */ if (scrollPtr->highlightWidth > 0) { - GC fgGC, bgGC; - - bgGC = Tk_GCForColor(scrollPtr->highlightBgColorPtr, (Pixmap) macWin); - if (scrollPtr->flags & GOT_FOCUS) { - fgGC = Tk_GCForColor(scrollPtr->highlightColorPtr, (Pixmap) macWin); - } else { - fgGC = bgGC; - } - Tk_DrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth, - (Pixmap) macWin); + GC fgGC, bgGC; + + bgGC = Tk_GCForColor(scrollPtr->highlightBgColorPtr, (Pixmap) macWin); + if (scrollPtr->flags & GOT_FOCUS) { + fgGC = Tk_GCForColor(scrollPtr->highlightColorPtr, (Pixmap) macWin); + } else { + fgGC = bgGC; + } + Tk_DrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth, + (Pixmap) macWin); } Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder, @@ -641,7 +641,7 @@ UpdateControlValues( if ((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0) || height <= metrics.minHeight) { - msPtr->info.enableState = kThemeTrackHideTrack; + msPtr->info.enableState = kThemeTrackHideTrack; } else { msPtr->info.enableState = kThemeTrackActive; msPtr->info.attributes = @@ -776,7 +776,7 @@ ScrollbarEventProc( case ButtonRelease: case EnterNotify: case LeaveNotify: - ScrollbarEvent(scrollPtr, eventPtr); + ScrollbarEvent(scrollPtr, eventPtr); break; default: TkScrollbarEventProc(scrollPtr, eventPtr); diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 2c154452e1..329517c230 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -58,8 +58,8 @@ XDestroyWindow( MacDrawable *macWin = (MacDrawable *)window; TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(macWin); //fprintf(stderr, "XDestroyWindow: %s with parent %s\n", - // Tk_PathName(macWin->winPtr), - // Tk_PathName(macWin->winPtr->parentPtr)); + // Tk_PathName(macWin->winPtr), + // Tk_PathName(macWin->winPtr->parentPtr)); /* * Remove any dangling pointers that may exist if the window we are @@ -472,7 +472,7 @@ XMoveResizeWindow( CGFloat YOff = (CGFloat) macWin->winPtr->wmInfoPtr->yInParent; NSRect r = NSMakeRect( X + XOff, TkMacOSXZeroScreenHeight() - Y - YOff - Height, - Width, Height); + Width, Height); [w setFrame:[w frameRectForContentRect:r] display:NO]; } @@ -1036,7 +1036,7 @@ TkMacOSXInvalidateWindow( Tk_Window parent = (Tk_Window) winPtr->parentPtr; TkMacOSXInvalClipRgns(tkwin); if ((flag == TK_PARENT_WINDOW) && parent){ - TkMacOSXInvalClipRgns(parent); + TkMacOSXInvalClipRgns(parent); } [view generateExposeEvents:[view bounds]]; [view setNeedsDisplay:YES]; diff --git a/macosx/tkMacOSXSysTray.c b/macosx/tkMacOSXSysTray.c index 99ffc9b274..20ba2968a0 100644 --- a/macosx/tkMacOSXSysTray.c +++ b/macosx/tkMacOSXSysTray.c @@ -149,7 +149,7 @@ typedef TkStatusItem** StatusItemInfo; * * MacSystrayDestroy -- * - * Removes an intepreters icon from the status bar. + * Removes an intepreters icon from the status bar. * * Results: * None. @@ -176,8 +176,8 @@ MacSystrayDestroy( * * MacSystrayObjCmd -- * - * Main command for creating, displaying, and removing icons from the - * status bar. + * Main command for creating, displaying, and removing icons from the + * status bar. * * Results: * @@ -226,7 +226,7 @@ MacSystrayObjCmd( sizeof(char *), "command", 0, &idx); if (result != TCL_OK) { - return TCL_ERROR; + return TCL_ERROR; } switch((optionsEnum)idx) { case TRAY_CREATE: { @@ -453,7 +453,7 @@ static int SysNotifyObjCmd( * * MacSystrayInit -- * - * Initialize this package and create script-level commands. + * Initialize this package and create script-level commands. * This is called from TkpInit for each interpreter. * * Results: diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index debf79b39e..607585c4ba 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1168,12 +1168,12 @@ TkWmDeadWindow( for (Transient *transientPtr = wmPtr->transientPtr; transientPtr != NULL; transientPtr = transientPtr->nextPtr) { - TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer( + TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer( transientPtr->winPtr); - if (containerPtr == winPtr) { - wmPtr2 = transientPtr->winPtr->wmInfoPtr; - wmPtr2->container = NULL; - } + if (containerPtr == winPtr) { + wmPtr2 = transientPtr->winPtr->wmInfoPtr; + wmPtr2->container = NULL; + } } while (wmPtr->transientPtr != NULL) { @@ -1823,10 +1823,10 @@ WmSetAttribute( // Calling XMoveResizeWindow twice is a hack to force a relayout // of the window. XMoveResizeWindow(winPtr->display, winPtr->window, - winPtr->changes.x, winPtr->changes.y, + winPtr->changes.x, winPtr->changes.y, newFrame.size.width, newHeight - 1); XMoveResizeWindow(winPtr->display, winPtr->window, - winPtr->changes.x, winPtr->changes.y, + winPtr->changes.x, winPtr->changes.y, newFrame.size.width, newHeight); } break; @@ -2454,7 +2454,7 @@ WmDeiconifyCmd( WmInfo *wmPtr2 = winPtr2->wmInfoPtr; TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2); - if (containerPtr == winPtr) { + if (containerPtr == winPtr) { if ((wmPtr2->hints.initial_state == WithdrawnState) && ((transientPtr->flags & WITHDRAWN_BY_CONTAINER) != 0)) { TkpWmSetState(winPtr2, NormalState); @@ -2556,8 +2556,8 @@ WmForgetCmd( macWin = (MacDrawable *)winPtr->window; - TkFocusJoin(winPtr); - Tk_UnmapWindow(frameWin); + TkFocusJoin(winPtr); + Tk_UnmapWindow(frameWin); macWin->toplevel->referenceCount--; macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel; @@ -2579,7 +2579,7 @@ WmForgetCmd( TkMapTopFrame(frameWin); } else { - /* + /* * Already not managed by wm - ignore it. */ } @@ -3067,7 +3067,7 @@ WmIconifyCmd( transientPtr != NULL; transientPtr = transientPtr->nextPtr) { TkWindow *winPtr2 = transientPtr->winPtr; TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2); - if (containerPtr == winPtr && + if (containerPtr == winPtr && winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { TkpWmSetState(winPtr2, WithdrawnState); transientPtr->flags |= WITHDRAWN_BY_CONTAINER; @@ -3255,7 +3255,7 @@ WmIconphotoCmd( tk_icon = Tk_GetImage(interp, tkwin, icon, NULL, NULL); if (tk_icon == NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( + Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't use \"%s\" as iconphoto: not a photo image", icon)); Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "PHOTO", NULL); @@ -3463,8 +3463,8 @@ WmIconwindowCmd( static int WmManageCmd( - TCL_UNUSED(Tk_Window), /* Main window of the application. */ - TkWindow *winPtr, /* Toplevel or Frame to work with */ + TCL_UNUSED(Tk_Window), /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel or Frame to work with */ Tcl_Interp *interp, /* Current interpreter. */ TCL_UNUSED(Tcl_Size), /* Number of arguments. */ TCL_UNUSED(Tcl_Obj *const *)) /* Argument objects. */ @@ -4522,7 +4522,7 @@ WmWithdrawCmd( TkWindow *winPtr2 = transientPtr->winPtr; TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2); - if (containerPtr == winPtr && + if (containerPtr == winPtr && winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) { TkpWmSetState(winPtr2, WithdrawnState); transientPtr->flags |= WITHDRAWN_BY_CONTAINER; @@ -6800,7 +6800,7 @@ TkMacOSXMakeRealWindowExist( TKWindow *window = [[winClass alloc] initWithContentRect:contentRect styleMask:styleMask backing:NSBackingStoreBuffered defer:YES]; if (!window) { - Tcl_Panic("couldn't allocate new Mac window"); + Tcl_Panic("couldn't allocate new Mac window"); } #if MAC_OS_X_VERSION_MAX_ALLOWED > 101200 if (tabbingId) { @@ -6861,10 +6861,10 @@ TkMacOSXMakeRealWindowExist( macWin->flags |= TK_HOST_EXISTS; if (overrideRedirect) { - XSetWindowAttributes atts; + XSetWindowAttributes atts; - atts.override_redirect = True; - Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts); + atts.override_redirect = True; + Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts); if ([NSApp macOSVersion] >= 101300) { window.styleMask |= NSWindowStyleMaskDocModalWindow; } else { @@ -7239,12 +7239,12 @@ TkpChangeFocus( } if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)) { - NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window); + NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window); - TkWmRestackToplevel(winPtr, Above, NULL); - if (force) { - [NSApp activateIgnoringOtherApps:YES]; - } + TkWmRestackToplevel(winPtr, Above, NULL); + if (force) { + [NSApp activateIgnoringOtherApps:YES]; + } if (win && [win canBecomeKeyWindow]) { [win makeKeyAndOrderFront:NSApp]; [NSApp setTkEventTarget:TkMacOSXGetTkWindow(win)]; diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 322b225288..661ec999e5 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -1204,7 +1204,7 @@ Tk_GetUserInactiveTime( */ long elapsed = (long)(TkpGetMS() - lastInactivityReset); if (ret > elapsed) { - ret = elapsed; + ret = elapsed; } return ret; diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c index d4a02e2727..3dc92da9d9 100644 --- a/macosx/ttkMacOSXTheme.c +++ b/macosx/ttkMacOSXTheme.c @@ -638,7 +638,7 @@ static void DrawEntry( CGColorRef backgroundColor; CGFloat bgRGBA[4]; if (isDark) { - GetBackgroundColorRGBA(context, tkwin, 0, NO, bgRGBA); + GetBackgroundColorRGBA(context, tkwin, 0, NO, bgRGBA); /* * Lighten the entry background to provide contrast. @@ -1769,7 +1769,7 @@ static void ButtonElementDraw( case kThemeCheckBox: case kThemeRadioButton: case TkSidebarButton: - break; + break; /* * Other buttons have a maximum height. We have to deal with that. diff --git a/macosx/ttkMacOSXTheme.h b/macosx/ttkMacOSXTheme.h index 2092b02154..dcdec08e07 100644 --- a/macosx/ttkMacOSXTheme.h +++ b/macosx/ttkMacOSXTheme.h @@ -528,7 +528,7 @@ static ThemeButtonParams RoundedRectButtonParams = {TkRoundedRectButton, kThemeMetricPushButtonHeight, NoThemeMetric}, RecessedButtonParams = {TkRecessedButton, kThemeMetricPushButtonHeight, - NoThemeMetric}, + NoThemeMetric}, SidebarButtonParams = {TkSidebarButton, NoThemeMetric, NoThemeMetric}, InlineButtonParams = {TkInlineButton, kThemeMetricPushButtonHeight, NoThemeMetric}; diff --git a/win/tkWinDefault.h b/win/tkWinDefault.h index 5230de9115..ef791c4f73 100644 --- a/win/tkWinDefault.h +++ b/win/tkWinDefault.h @@ -254,7 +254,7 @@ #define DEF_MENU_ENTRY_BITMAP NULL #define DEF_MENU_ENTRY_COLUMN_BREAK "0" #define DEF_MENU_ENTRY_COMMAND NULL -#define DEF_MENU_ENTRY_COMPOUND "none" +#define DEF_MENU_ENTRY_COMPOUND "none" #define DEF_MENU_ENTRY_FG NULL #define DEF_MENU_ENTRY_FONT NULL #define DEF_MENU_ENTRY_HIDE_MARGIN "0" diff --git a/win/tkWinEmbed.c b/win/tkWinEmbed.c index 34cd8ca26a..482611952e 100644 --- a/win/tkWinEmbed.c +++ b/win/tkWinEmbed.c @@ -281,7 +281,7 @@ Tk_UseWindow( if (!IsWindow(hwnd)) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "window \"%s\" doesn't exist", string)); + "window \"%s\" does not exist", string)); Tcl_SetErrorCode(interp, "TK", "EMBED", "EXIST", NULL); } return TCL_ERROR; diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index 5f731fe3dd..cd29597df3 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -1435,7 +1435,7 @@ TkWinHandleMenuEvent( TkActivateMenuEntry(menuPtr, TCL_INDEX_NONE); } else { if (mePtr->index >= (int)menuPtr->numEntries) { - Tcl_Panic("Trying to activate an entry which doesn't exist"); + Tcl_Panic("Trying to activate an entry which does not exist"); } TkActivateMenuEntry(menuPtr, mePtr->index); } diff --git a/win/tkWinSysTray.c b/win/tkWinSysTray.c index a710ee6942..6c56735b99 100644 --- a/win/tkWinSysTray.c +++ b/win/tkWinSysTray.c @@ -375,7 +375,7 @@ GetIcoPtr( notfound: Tcl_AppendResult(interp, "icon \"", string, - "\" doesn't exist", NULL); + "\" does not exist", NULL); return NULL; } @@ -983,7 +983,7 @@ WinSystrayCmd( photo = Tk_FindPhoto(interp, Tcl_GetString(imageObj)); if (photo == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "image \"%s\" doesn't exist", Tcl_GetString(imageObj))); + "image \"%s\" does not exist", Tcl_GetString(imageObj))); return TCL_ERROR; } Tk_PhotoGetSize(photo, &width, &height); diff --git a/xlib/xgc.c b/xlib/xgc.c index d9648ac289..7998196f0f 100644 --- a/xlib/xgc.c +++ b/xlib/xgc.c @@ -768,7 +768,7 @@ XRegisterIMInstantiateCallback( Bool XUnregisterIMInstantiateCallback( - TCL_UNUSED(Display *) /* dpy */, + TCL_UNUSED(Display *) /* dpy */, TCL_UNUSED(struct _XrmHashBucketRec *) /* rdb */, TCL_UNUSED(char *) /* res_name */, TCL_UNUSED(char *) /* res_class */, From 9e75799b4c2aa31ab6d6d35b52d4172ceff7fd01 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 5 Nov 2024 18:27:20 +0000 Subject: [PATCH 3/3] Make everything compile (again) against Tcl 8.6 headers --- macosx/tkMacOSXDraw.c | 6 +++--- macosx/tkMacOSXFont.c | 42 +++++++++++------------------------------ macosx/tkMacOSXNotify.c | 28 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 34 deletions(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index e93f9cf33e..1432fa1b27 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -86,7 +86,7 @@ TkMacOSXInitCGDrawing( } if (Tcl_LinkVar(interp, "::tk::mac::CGAntialiasLimit", - &cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) { + (char *)&cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) { Tcl_ResetResult(interp); } cgAntiAliasLimit = limit; @@ -96,11 +96,11 @@ TkMacOSXInitCGDrawing( */ if (Tcl_LinkVar(interp, "::tk::mac::useThemedToplevel", - &useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) { + (char *)&useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); } if (Tcl_LinkVar(interp, "::tk::mac::useThemedFrame", - &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) { + (char *)&useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); } transparentColor = TkMacOSXClearPixel(); diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index db28066a0f..053cebd8f5 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -24,26 +24,6 @@ #endif */ -/* - * TclNumUtfChars() is the same as Tcl_NumUtfChars(), but counting - * in UTF-16 in stead of UTF-32. For Tcl 8.7 it's a little bit - * tricky to get this function, because we are compiling with - * TCL_UTF_MAX=4. Same for TclUtfAtIndex() - */ -#if TCL_MAJOR_VERSION < 9 -# undef TclNumUtfChars -# undef TclUtfAtIndex -# ifdef USE_TCL_STUBS -# define TclNumUtfChars \ - (tclStubsPtr->tcl_NumUtfChars) /* 312 */ -# define TclUtfAtIndex \ - (tclStubsPtr->tcl_UtfAtIndex) /* 325 */ -# else -# define TclNumUtfChars Tcl_NumUtfChars -# define TclUtfAtIndex Tcl_UtfAtIndex -# endif -#endif - /* * The following structure represents our Macintosh-specific implementation * of a font object. @@ -73,7 +53,7 @@ struct SystemFontMapEntry { #define ThemeFont(n, ...) { kTheme##n##Font, "system" #n "Font", ##__VA_ARGS__ } static const struct SystemFontMapEntry systemFontMap[] = { - ThemeFont(System, "TkDefaultFont", "TkIconFont"), + ThemeFont(System, "TkDefaultFont", "TkIconFont"), ThemeFont(EmphasizedSystem, "TkCaptionFont", NULL), ThemeFont(SmallSystem, "TkHeadingFont", "TkTooltipFont"), ThemeFont(SmallEmphasizedSystem, NULL, NULL), @@ -476,7 +456,7 @@ startOfClusterObjCmd( if (stringArg == NULL) { return TCL_ERROR; } - Tcl_Size ulen = Tcl_GetCharLength(objv[1]); + Tcl_Size ulen = TkGetCharLength(objv[1]); S = [[TKNSString alloc] initWithTclUtfBytes:stringArg length:len]; len = [S length]; if (TkGetIntForIndex(objv[2], ulen - 1, 0, &idx) != TCL_OK) { @@ -490,7 +470,7 @@ startOfClusterObjCmd( /* The string contains codepoints > \uFFFF. Determine UTF-16 index */ Tcl_Size newIdx = 0; for (Tcl_Size i = 0; i < idx; i++) { - newIdx += 1 + (((newIdx < len-1) && ([S characterAtIndex:newIdx]&0xFC00) == 0xD800) && (([S characterAtIndex:newIdx+1]&0xFC00) == 0xDC00)); + newIdx += 1 + (((newIdx < (Tcl_Size)len-1) && ([S characterAtIndex:newIdx]&0xFC00) == 0xD800) && (([S characterAtIndex:newIdx+1]&0xFC00) == 0xDC00)); } idx = newIdx; } @@ -533,7 +513,7 @@ endOfClusterObjCmd( if (stringArg == NULL) { return TCL_ERROR; } - Tcl_Size ulen = Tcl_GetCharLength(objv[1]); + Tcl_Size ulen = TkGetCharLength(objv[1]); S = [[TKNSString alloc] initWithTclUtfBytes:stringArg length:len]; len = [S length]; if (TkGetIntForIndex(objv[2], ulen - 1, 0, &idx) != TCL_OK) { @@ -923,7 +903,7 @@ void TkpGetFontAttrsForChar( TCL_UNUSED(Tk_Window), /* Window on the font's display */ Tk_Font tkfont, /* Font to query */ - int c, /* Character of interest */ + int c, /* Character of interest */ TkFontAttributes* faPtr) /* Output: Font attributes */ { MacFont *fontPtr = (MacFont *) tkfont; @@ -1082,8 +1062,8 @@ TkpMeasureCharsInContext( attributes:fontPtr->nsAttributes]; typesetter = CTTypesetterCreateWithAttributedString( (CFAttributedStringRef)attributedString); - start = TclNumUtfChars(source, rangeStart); - len = TclNumUtfChars(source + rangeStart, rangeLength); + start = Tcl_NumUtfChars(source, rangeStart); + len = Tcl_NumUtfChars(source + rangeStart, rangeLength); if (start > 0) { range.length = start; line = CTTypesetterCreateLine(typesetter, range); @@ -1184,7 +1164,7 @@ TkpMeasureCharsInContext( [attributedString release]; [string release]; length = ceil(width - offset); - fit = (TclUtfAtIndex(source, index) - source) - rangeStart; + fit = (Tcl_UtfAtIndex(source, index) - source) - rangeStart; done: #ifdef TK_MAC_DEBUG_FONTS TkMacOSXDbgMsg("measure: source=\"%s\" range=\"%.*s\" maxLength=%d " @@ -1383,8 +1363,8 @@ TkpDrawAngledCharsInContext( -textX, -textY); } CGContextConcatCTM(context, t); - start = TclNumUtfChars(source, rangeStart); - length = TclNumUtfChars(source, rangeStart + rangeLength) - start; + start = Tcl_NumUtfChars(source, rangeStart); + length = Tcl_NumUtfChars(source, rangeStart + rangeLength) - start; line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, length)); if (start > 0) { @@ -1552,7 +1532,7 @@ TkMacOSXUseAntialiasedText( Tcl_ResetResult(interp); } if (Tcl_LinkVar(interp, "::tk::mac::antialiasedtext", - &antialiasedTextEnabled, + (char *)&antialiasedTextEnabled, TCL_LINK_INT) != TCL_OK) { Tcl_ResetResult(interp); } diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index 97c63c54af..a573e1ba9f 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -16,6 +16,34 @@ #include "tkMacOSXPrivate.h" #include "tkMacOSXInt.h" #include "tkMacOSXConstants.h" +#if TCL_MAJOR_VERSION < 9 +#undef Tcl_MacOSXNotifierAddRunLoopMode +#ifdef USE_TCL_STUBS +#ifdef __cplusplus +extern "C" { +#endif +/* Little hack to eliminate the need for "tclInt.h" here: + Just copy a small portion of TclIntPlatStubs, just + enough to make it work. See [600b72bfbc] */ +typedef struct TclIntPlatStubs { + int magic; + void *hooks; + void (*dummy[19]) (void); /* dummy entries 0-18, not used */ + void (*tclMacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 19 */ +} TclIntPlatStubs; +extern const TclIntPlatStubs *tclIntPlatStubsPtr; +#ifdef __cplusplus +} +#endif +#define Tcl_MacOSXNotifierAddRunLoopMode \ + (tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */ +#elif TCL_MINOR_VERSION < 7 + extern void TclMacOSXNotifierAddRunLoopMode(const void *runLoopMode); +# define Tcl_MacOSXNotifierAddRunLoopMode TclMacOSXNotifierAddRunLoopMode +#else + extern void Tcl_MacOSXNotifierAddRunLoopMode(const void *runLoopMode); +#endif +#endif #import /* This is not used for anything at the moment. */