Index: .github/workflows/mac-build.yml ================================================================== --- .github/workflows/mac-build.yml +++ .github/workflows/mac-build.yml @@ -11,11 +11,11 @@ contents: read env: ERROR_ON_FAILURES: 1 jobs: xcode: - runs-on: macos-14 + runs-on: macos-15 defaults: run: shell: bash working-directory: tk/macosx steps: @@ -55,11 +55,11 @@ echo "::error::Failure during Test" exit 1 fi timeout-minutes: 30 clang: - runs-on: macos-14 + runs-on: macos-15 strategy: matrix: symbols: - 'no' - 'mem' Index: README.md ================================================================== --- README.md +++ README.md @@ -8,14 +8,14 @@ 9.0 (production release, daily build) [![Build Status](https://github.com/tcltk/tk/actions/workflows/linux-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tk/actions/workflows/linux-build.yml?query=branch%3Amain) [![Build Status](https://github.com/tcltk/tk/actions/workflows/win-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tk/actions/workflows/win-build.yml?query=branch%3Amain) [![Build Status](https://github.com/tcltk/tk/actions/workflows/mac-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tk/actions/workflows/mac-build.yml?query=branch%3Amain)
-8.7 (in development, daily build) -[![Build Status](https://github.com/tcltk/tk/actions/workflows/linux-build.yml/badge.svg?branch=core-8-branch)](https://github.com/tcltk/tk/actions/workflows/linux-build.yml?query=branch%3Acore-8-branch) -[![Build Status](https://github.com/tcltk/tk/actions/workflows/win-build.yml/badge.svg?branch=core-8-branch)](https://github.com/tcltk/tk/actions/workflows/win-build.yml?query=branch%3Acore-8-branch) -[![Build Status](https://github.com/tcltk/tk/actions/workflows/mac-build.yml/badge.svg?branch=core-8-branch)](https://github.com/tcltk/tk/actions/workflows/mac-build.yml?query=branch%3Acore-8-branch) +8.6 (legacy release, daily build) +[![Build Status](https://github.com/tcltk/tk/actions/workflows/linux-build.yml/badge.svg?branch=core-8-6-branch)](https://github.com/tcltk/tk/actions/workflows/linux-build.yml?query=branch%3Acore-8-6-branch) +[![Build Status](https://github.com/tcltk/tk/actions/workflows/win-build.yml/badge.svg?branch=core-8-6-branch)](https://github.com/tcltk/tk/actions/workflows/win-build.yml?query=branch%3Acore-8-6-branch) +[![Build Status](https://github.com/tcltk/tk/actions/workflows/mac-build.yml/badge.svg?branch=core-8-6-branch)](https://github.com/tcltk/tk/actions/workflows/mac-build.yml?query=branch%3Acore-8-6-branch) ## 1. Introduction This directory contains the sources and documentation for Tk, a cross-platform GUI toolkit implemented with the Tcl scripting language. Index: generic/tkConfig.c ================================================================== --- generic/tkConfig.c +++ generic/tkConfig.c @@ -139,11 +139,10 @@ static Tcl_Obj * GetObjectForOption(void *recordPtr, Option *optionPtr, Tk_Window tkwin); static Option * GetOption(const char *name, OptionTable *tablePtr); static Option * GetOptionFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, OptionTable *tablePtr); -static int ObjectIsEmpty(Tcl_Obj *objPtr); static void FreeOptionInternalRep(Tcl_Obj *objPtr); static void DupOptionInternalRep(Tcl_Obj *, Tcl_Obj *); /* * The structure below defines an object type that is used to cache the result @@ -628,11 +627,11 @@ nullOK = (optionPtr->specPtr->flags & (TK_OPTION_NULL_OK|TCL_NULL_OK|1)); switch (optionPtr->specPtr->type) { case TK_OPTION_BOOLEAN: { int newBool; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newBool = -1; } else if (Tcl_GetBooleanFromObj(nullOK ? NULL : interp, valuePtr, &newBool) != TCL_OK) { if (nullOK && interp) { Tcl_AppendResult(interp, "expected boolean value or \"\" but got \"", @@ -660,11 +659,11 @@ } case TK_OPTION_INT: { int newInt; if ((optionPtr->specPtr->flags & TYPE_MASK) == 0) { - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newInt = INT_MIN; } else if (Tcl_GetIntFromObj(nullOK ? NULL : interp, valuePtr, &newInt) != TCL_OK) { invalidIntValue: if (nullOK && interp) { @@ -678,11 +677,11 @@ *((int *)oldInternalPtr) = *((int *)internalPtr); *((int *)internalPtr) = newInt; } } else if ((optionPtr->specPtr->flags & TYPE_MASK) == TYPE_MASK) { Tcl_WideInt newWideInt; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newWideInt = (sizeof(long) > sizeof(int)) ? LONG_MIN : LLONG_MIN; } else if (Tcl_GetWideIntFromObj(nullOK ? NULL : interp, valuePtr, &newWideInt) != TCL_OK) { goto invalidIntValue; } @@ -722,11 +721,11 @@ break; } case TK_OPTION_DOUBLE: { double newDbl; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; #if defined(NAN) newDbl = NAN; #else newDbl = 0.0; @@ -754,11 +753,11 @@ case TK_OPTION_STRING: { char *newStr; const char *value; Tcl_Size length; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; } if (internalPtr != NULL) { if (valuePtr != NULL) { value = Tcl_GetStringFromObj(valuePtr, &length); @@ -773,11 +772,11 @@ break; } case TK_OPTION_STRING_TABLE: { int newValue; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newValue = -1; } else { if (Tcl_GetIndexFromObjStruct(interp, valuePtr, optionPtr->specPtr->clientData, sizeof(char *), @@ -808,11 +807,11 @@ break; } case TK_OPTION_COLOR: { XColor *newPtr; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newPtr = NULL; } else { newPtr = Tk_AllocColorFromObj(interp, tkwin, valuePtr); if (newPtr == NULL) { @@ -826,11 +825,11 @@ break; } case TK_OPTION_FONT: { Tk_Font newFont; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newFont = NULL; } else { newFont = Tk_AllocFontFromObj(interp, tkwin, valuePtr); if (newFont == NULL) { @@ -844,11 +843,11 @@ break; } case TK_OPTION_STYLE: { Tk_Style newStyle; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newStyle = NULL; } else { newStyle = Tk_AllocStyleFromObj(interp, valuePtr); if (newStyle == NULL) { @@ -862,11 +861,11 @@ break; } case TK_OPTION_BITMAP: { Pixmap newBitmap; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newBitmap = None; } else { newBitmap = Tk_AllocBitmapFromObj(interp, tkwin, valuePtr); if (newBitmap == None) { @@ -880,11 +879,11 @@ break; } case TK_OPTION_BORDER: { Tk_3DBorder newBorder; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newBorder = NULL; } else { newBorder = Tk_Alloc3DBorderFromObj(interp, tkwin, valuePtr); if (newBorder == NULL) { @@ -898,11 +897,11 @@ break; } case TK_OPTION_RELIEF: { int newRelief; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newRelief = TK_RELIEF_NULL; } else if (Tcl_GetIndexFromObj(interp, valuePtr, tkReliefStrings, "relief", (nullOK ? TCL_NULL_OK : 0), &newRelief) != TCL_OK) { return TCL_ERROR; @@ -930,11 +929,11 @@ break; } case TK_OPTION_CURSOR: { Tk_Cursor newCursor; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { newCursor = NULL; valuePtr = NULL; } else { newCursor = Tk_AllocCursorFromObj(interp, tkwin, valuePtr); if (newCursor == NULL) { @@ -949,11 +948,11 @@ break; } case TK_OPTION_JUSTIFY: { int newJustify; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newJustify = -1; } else if (Tcl_GetIndexFromObj(interp, valuePtr, tkJustifyStrings, "justification", (nullOK ? TCL_NULL_OK : 0), &newJustify) != TCL_OK) { return TCL_ERROR; @@ -981,11 +980,11 @@ break; } case TK_OPTION_ANCHOR: { int newAnchor; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newAnchor = -1; } else if (Tcl_GetIndexFromObj(interp, valuePtr, tkAnchorStrings, "anchor", (nullOK ? TCL_NULL_OK : 0), &newAnchor) != TCL_OK) { return TCL_ERROR; @@ -1013,11 +1012,11 @@ break; } case TK_OPTION_PIXELS: { int newPixels; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newPixels = INT_MIN; } else if (Tk_GetPixelsFromObj(nullOK ? NULL : interp, tkwin, valuePtr, &newPixels) != TCL_OK) { if (nullOK) { @@ -1034,11 +1033,11 @@ break; } case TK_OPTION_WINDOW: { Tk_Window newWin; - if (nullOK && ObjectIsEmpty(valuePtr)) { + if (nullOK && TkObjIsEmpty(valuePtr)) { valuePtr = NULL; newWin = NULL; } else if (TkGetWindowFromObj(interp, tkwin, valuePtr, &newWin) != TCL_OK) { return TCL_ERROR; @@ -1087,40 +1086,10 @@ Tcl_IncrRefCount(valuePtr); } } return TCL_OK; } - -/* - *---------------------------------------------------------------------- - * - * ObjectIsEmpty -- - * - * This function tests whether the string value of an object is empty. - * - * Results: - * The return value is 1 if the string value of objPtr has length zero, - * and 0 otherwise. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -ObjectIsEmpty( - Tcl_Obj *objPtr) /* Object to test. May be NULL. */ -{ - if (objPtr == NULL) { - return 1; - } - if (objPtr->bytes == NULL) { - Tcl_GetString(objPtr); - } - return (objPtr->length == 0); -} /* *---------------------------------------------------------------------- * * GetOption -- Index: generic/tkInt.h ================================================================== --- generic/tkInt.h +++ generic/tkInt.h @@ -1259,10 +1259,11 @@ int x, int y, int width, int height); MODULE_SCOPE Tcl_Command TkMakeEnsemble(Tcl_Interp *interp, const char *nsname, const char *name, void *clientData, const TkEnsemble *map); MODULE_SCOPE double TkScalingLevel(Tk_Window tkwin); +MODULE_SCOPE int TkObjIsEmpty(Tcl_Obj *objPtr); MODULE_SCOPE int TkInitTkCmd(Tcl_Interp *interp, void *clientData); MODULE_SCOPE int TkInitFontchooser(Tcl_Interp *interp, void *clientData); MODULE_SCOPE void TkInitEmbeddedConfigurationInformation( Index: generic/tkPanedWindow.c ================================================================== --- generic/tkPanedWindow.c +++ generic/tkPanedWindow.c @@ -225,11 +225,10 @@ char *internalPtr, char *oldInternalPtr); static void AdjustForSticky(int sticky, int cavityWidth, int cavityHeight, int *xPtr, int *yPtr, int *paneWidthPtr, int *paneHeightPtr); static void MoveSash(PanedWindow *pwPtr, int sash, int diff); -static int ObjectIsEmpty(Tcl_Obj *objPtr); static void * ComputeSlotAddress(void *recordPtr, Tcl_Size offset); static int PanedWindowIdentifyCoords(PanedWindow *pwPtr, Tcl_Interp *interp, int x, int y); /* @@ -2500,11 +2499,11 @@ void *internalPtr; const char *string; internalPtr = ComputeSlotAddress(recordPtr, internalOffset); - if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) { + if (flags & TK_OPTION_NULL_OK && TkObjIsEmpty(*value)) { *value = NULL; } else { /* * Convert the sticky specifier into an integer value. */ @@ -3024,41 +3023,10 @@ break; } return TCL_OK; } - -/* - *---------------------------------------------------------------------- - * - * ObjectIsEmpty -- - * - * This function tests whether the string value of an object is empty. - * - * Results: - * The return value is 1 if the string value of objPtr has length zero, - * and 0 otherwise. - * - * Side effects: - * May cause object shimmering, since this function can force a - * conversion to a string object. - * - *---------------------------------------------------------------------- - */ - -static int -ObjectIsEmpty( - Tcl_Obj *objPtr) /* Object to test. May be NULL. */ -{ - if (objPtr == NULL) { - return 1; - } - if (objPtr->bytes == NULL) { - Tcl_GetString(objPtr); - } - return (objPtr->length == 0); -} /* *---------------------------------------------------------------------- * * ComputeInternalPointer -- Index: generic/tkText.c ================================================================== --- generic/tkText.c +++ generic/tkText.c @@ -18,13 +18,11 @@ #include "tkInt.h" #include "tkText.h" #include "tkTextUndo.h" #include "tkTextTagSet.h" #include "tkBitField.h" -#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 7) #include "tkFont.h" -#endif #include #include #include "default.h" /* needed for strncasecmp */ @@ -8046,10 +8044,51 @@ } /* *---------------------------------------------------------------------- * + * TkObjIsEmpty -- + * + * This function tests whether the string value of an object is empty. + * + * Results: + * The return value is 1 if the string value of objPtr has length zero, + * and 0 otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +#if defined(USE_TCL_STUBS) +# undef Tcl_IsEmpty +# define Tcl_IsEmpty \ + ((int (*)(Tcl_Obj *))(void *)((&(tclStubsPtr->tcl_PkgProvideEx))[690])) +#endif + +int +TkObjIsEmpty( + Tcl_Obj *objPtr) /* Object to test. May be NULL. */ +{ + if (objPtr == NULL) { + return 1; + } + if (objPtr->bytes == NULL) { +#if defined(USE_TCL_STUBS) + if (Tcl_IsEmpty) { + return Tcl_IsEmpty(objPtr); + } +#endif + Tcl_GetString(objPtr); + } + return (objPtr->length == 0); +} + +/* + *---------------------------------------------------------------------- + * * TkTextInspectOptions -- * * Build information from option table for "inspect". * * Results: @@ -8149,11 +8188,11 @@ Tcl_Obj *valObj = argv[4]; Tcl_Obj *myValObj; Tcl_Obj *nameObj; int myFlags = flags; - if (GetByteLength(valObj) == 0) { + if (TkObjIsEmpty(valObj)) { continue; } if (!(myFlags & INSPECT_INCLUDE_DATABASE_CONFIG) || myFlags & (INSPECT_INCLUDE_SYSTEM_CONFIG|INSPECT_INCLUDE_DEFAULT_CONFIG)) { @@ -11322,17 +11361,10 @@ * that the specified string was empty and that is acceptable. * *---------------------------------------------------------------------- */ -static int -ObjectIsEmpty( - Tcl_Obj *objPtr) /* Object to test. May be NULL. */ -{ - return objPtr ? GetByteLength(objPtr) == 0 : 1; -} - static int SetTextStartEnd( TCL_UNUSED(void *), TCL_UNUSED(Tcl_Interp *), /* Current interp; may be used for errors. */ TCL_UNUSED(Tk_Window), /* Window for which option is being set. */ @@ -11350,11 +11382,11 @@ const TkText *textPtr = (const TkText *) recordPtr; assert(!*objPtr); *oldObjPtr = NULL; - if ((flags & TK_OPTION_NULL_OK) && ObjectIsEmpty(*value)) { + if ((flags & TK_OPTION_NULL_OK) && TkObjIsEmpty(*value)) { *value = NULL; *objPtr = Tcl_NewStringObj((objPtr == &textPtr->newStartIndex) ? "begin" : "end", TCL_INDEX_NONE); } else { *objPtr = *value; } @@ -11501,11 +11533,11 @@ internalPtr = (char *)recordPtr + internalOffset; } else { internalPtr = NULL; } - if ((flags & TK_OPTION_NULL_OK) && ObjectIsEmpty(*value)) { + if ((flags & TK_OPTION_NULL_OK) && TkObjIsEmpty(*value)) { *value = NULL; } else { int line; if (Tcl_GetIntFromObj(interp, *value, &line) != TCL_OK) { Index: generic/tkText.h ================================================================== --- generic/tkText.h +++ generic/tkText.h @@ -1865,10 +1865,11 @@ /* * Declarations for procedures that are used by the text-related files but * shouldn't be used anywhere else in Tk (or by Tk clients): */ +MODULE_SCOPE int TkObjIsEmpty(Tcl_Obj *objPtr); inline TkSharedText * TkBTreeGetShared(TkTextBTree tree); inline int TkBTreeGetNumberOfDisplayLines(const TkTextPixelInfo *pixelInfo); MODULE_SCOPE void TkBTreeAdjustPixelHeight(const TkText *textPtr, TkTextLine *linePtr, int newPixelHeight, unsigned mergedLogicalLines, unsigned oldNumDispLines); Index: generic/tkTextTag.c ================================================================== --- generic/tkTextTag.c +++ generic/tkTextTag.c @@ -39,10 +39,13 @@ static const char *const justifyStrings[] = { "left", "right", "center", "full", NULL }; +#ifndef TK_OPTION_NEG_OK +# define TK_OPTION_NEG_OK (1 << 6) +#endif /* TK_OPTION_NEG_OK */ static const Tk_OptionSpec tagOptionSpecs[] = { {TK_OPTION_BORDER, "-background", NULL, NULL, NULL, TCL_INDEX_NONE, offsetof(TkTextTag, attrs.border), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BITMAP, "-bgstipple", NULL, NULL, @@ -84,11 +87,11 @@ {TK_OPTION_PIXELS, "-lmargin2", NULL, NULL, NULL, offsetof(TkTextTag, lMargin2Obj), offsetof(TkTextTag, lMargin2), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BORDER, "-lmargincolor", NULL, NULL, NULL, TCL_INDEX_NONE, offsetof(TkTextTag, lMarginColor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-offset", NULL, NULL, - NULL, offsetof(TkTextTag, offsetObj), offsetof(TkTextTag, offset), TK_OPTION_NULL_OK, 0, 0}, + NULL, offsetof(TkTextTag, offsetObj), offsetof(TkTextTag, offset), TK_OPTION_NULL_OK|TK_OPTION_NEG_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-overstrike", NULL, NULL, NULL, TCL_INDEX_NONE, offsetof(TkTextTag, overstrike), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_COLOR, "-overstrikecolor", NULL, NULL, NULL, TCL_INDEX_NONE, offsetof(TkTextTag, overstrikeColor), TK_OPTION_NULL_OK, 0, 0}, #if SUPPORT_DEPRECATED_TAG_OPTIONS Index: generic/tkTextWind.c ================================================================== --- generic/tkTextWind.c +++ generic/tkTextWind.c @@ -150,22 +150,27 @@ } alignMode; /* * Information used for parsing window configuration options: */ + +#ifndef TK_OPTION_NEG_OK +# define TK_OPTION_NEG_OK (1 << 6) +#endif /* TK_OPTION_NEG_OK */ + static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_STRING_TABLE, "-align", NULL, NULL, "center", TCL_INDEX_NONE, offsetof(TkTextEmbWindow, align), 0, alignStrings, 0}, {TK_OPTION_STRING, "-create", NULL, NULL, NULL, offsetof(TkTextEmbWindow, createObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-owner", NULL, NULL, "1", TCL_INDEX_NONE, offsetof(TkTextEmbWindow, isOwner), 0, 0, 0}, {TK_OPTION_PIXELS, "-padx", NULL, NULL, - "0", offsetof(TkTextEmbWindow, padXObj), offsetof(TkTextEmbWindow, padX), 0, 0, 0}, + "0", offsetof(TkTextEmbWindow, padXObj), offsetof(TkTextEmbWindow, padX), TK_OPTION_NEG_OK, 0, 0}, {TK_OPTION_PIXELS, "-pady", NULL, NULL, - "0", offsetof(TkTextEmbWindow, padYObj), offsetof(TkTextEmbWindow, padY), 0, 0, 0}, + "0", offsetof(TkTextEmbWindow, padYObj), offsetof(TkTextEmbWindow, padY), TK_OPTION_NEG_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-stretch", NULL, NULL, "0", TCL_INDEX_NONE, offsetof(TkTextEmbWindow, stretch), 0, 0, 0}, {TK_OPTION_STRING, "-tags", NULL, NULL, NULL, TCL_INDEX_NONE, TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_WINDOW, "-window", NULL, NULL, Index: tests/config.test ================================================================== --- tests/config.test +++ tests/config.test @@ -1115,26 +1115,26 @@ } -cleanup { killTables } -result {THIS IS A TEST} -test config-5.1 {ObjectIsEmpty - object is already string} -constraints { +test config-5.1 {TkObjIsEmpty - object is already string} -constraints { testobjconfig } -body { testobjconfig alltypes .foo -color [format ""] .foo cget -color } -cleanup { killTables } -result {} -test config-5.2 {ObjectIsEmpty - object is already string} -constraints { +test config-5.2 {TkObjIsEmpty - object is already string} -constraints { testobjconfig } -body { testobjconfig alltypes .foo -color [format " "] } -cleanup { killTables } -returnCodes error -result {unknown color name " "} -test config-5.3 {ObjectIsEmpty - must convert back to string} -constraints { +test config-5.3 {TkObjIsEmpty - must convert back to string} -constraints { testobjconfig } -body { testobjconfig alltypes .foo -color [list] .foo cget -color } -cleanup { Index: tests/focus.test ================================================================== --- tests/focus.test +++ tests/focus.test @@ -44,17 +44,17 @@ proc focusClear {} { dobg {after 200; focus -force .; update} after 400 if {[tk windowingsystem] eq "aqua"} { - # In Aqua we need to explicitly wait until focus is cleared. + # In Aqua we need to explicitly wait until focus is cleared. while {[focus] != ""} { after 100 {set y 1} tkwait variable y } } - + update } # Button used in some tests in the whole test file