diff options
Diffstat (limited to 'macosx/tkMacOSXWm.c')
-rw-r--r-- | macosx/tkMacOSXWm.c | 1334 |
1 files changed, 942 insertions, 392 deletions
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 2fa9434..2f134f7 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -18,7 +18,7 @@ #include "tkMacOSXPrivate.h" #include "tkScrollbar.h" #include "tkMacOSXWm.h" -#include "tkMacOSXEvent.h" +#include "tkMacOSXInt.h" #include "tkMacOSXDebug.h" #include "tkMacOSXConstants.h" @@ -37,7 +37,7 @@ */ /* - * Window attributes and classes + * Carbon window attributes and classes. */ #define WM_NSMASK_SHIFT 36 @@ -111,7 +111,8 @@ static const struct { .defaultAttrs = kWindowHideOnSuspendAttribute, .forceOnAttrs = kWindowNoTitleBarAttribute | kWindowDoesNotCycleAttribute, - .flags = WM_TOPMOST, }, + .flags = WM_TOPMOST, + .styleMask = 0}, [kSheetWindowClass] = { .validAttrs = kWindowResizableAttribute, .forceOnAttrs = kWindowNoTitleBarAttribute | @@ -150,19 +151,161 @@ static const struct { (macClassAttrs[(class)].forceOnAttrs & ~kWindowResizableAttribute))) /* - * Data for [wm attributes] command: + * Structures and data for the wm attributes command (macOS 10.13 and later): + */ + +/* Hash tables for attributes which can be set before a window exists */ +static Tcl_HashTable pathnameToSubclass; +static Tcl_HashTable pathnameToTabbingId; +static Tcl_HashTable pathnameToTabbingMode; + +enum NSWindowSubclass { + subclassNSWindow = 0, + subclassNSPanel = 1 +}; +/* This array must be indexed by the enum above.*/ +static const char *subclassNames[] = {"nswindow", "nspanel", NULL}; + +typedef struct buttonField_t { + unsigned zoom: 1; + unsigned miniaturize: 1; + unsigned close: 1; +} buttonField; + +/* The order of these names must match the order of the bits above! */ +static const char *buttonNames[] = {"zoom", "miniaturize", "close", NULL}; + +typedef union windowButtonState_t { + int intvalue; + buttonField bits; +} windowButtonState; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 +enum NSWindowClass { + NSWindowClass_any = 0, + NSWindowClass_window = 1, + NSWindowClass_panel = 2 +}; +typedef struct styleMaskBit_t { + const char *bitname; + unsigned long bitvalue; + enum NSWindowClass allowed; +} styleMaskBit; + +static const styleMaskBit styleMaskBits[] = { + /* Make the titlebar visible and use round corners. */ + {"titled", NSWindowStyleMaskTitled, NSWindowClass_window}, + /* Enable the close button. */ + {"closable", NSWindowStyleMaskClosable, NSWindowClass_window}, + /* Enable the miniaturize button. */ + {"miniaturizable", NSWindowStyleMaskMiniaturizable, NSWindowClass_window}, + /* Allow the user to resize the window. */ + {"resizable", NSWindowStyleMaskResizable, NSWindowClass_window}, + /* + * Make the content view extend under the titlebar. We force + * titlebarAppearsTransparent when this bit is set. Otherwise it is + * pretty useless. + */ + {"fullsizecontentview", NSWindowStyleMaskFullSizeContentView, NSWindowClass_window}, + /* Rounded corners, cannot have a titlebar (overrides titled bit). */ + {"docmodal", NSWindowStyleMaskDocModalWindow, NSWindowClass_any}, + /* ============================================ + * The following bits are only valid for panels. + */ + /* Make the title bar thinner. */ + {"utility", NSWindowStyleMaskUtilityWindow, NSWindowClass_panel}, + /* Do not activate the app when the window is activated. */ + {"nonactivatingpanel", NSWindowStyleMaskNonactivatingPanel, NSWindowClass_panel}, + /* + * Requires utility. Cannot be resizable. Close button is an X; no other buttons. + * Cannot be a docmodal. + */ + {"HUDwindow", NSWindowStyleMaskHUDWindow, NSWindowClass_panel}, + {NULL, 0, NSWindowClass_any} +}; + +typedef struct tabbingMode_t { + const char *modeName; + long modeValue; +} tabbingMode; + +static const tabbingMode tabbingModes[] = { + {"auto", NSWindowTabbingModeAutomatic}, + {"disallowed", NSWindowTabbingModeDisallowed}, + {"preferred", NSWindowTabbingModePreferred}, + {NULL, -1} +}; + +static const char *const appearanceStrings[] = { + "aqua", "auto", "darkaqua", NULL +}; +enum appearances { + APPEARANCE_AQUA, APPEARANCE_AUTO, APPEARANCE_DARKAQUA +}; + +static Bool wantsToBeTab(NSWindow *macWindow) { + Bool result; + switch ([macWindow tabbingMode]) { + case NSWindowTabbingModeDisallowed: + result = False; + break; + case NSWindowTabbingModePreferred: + result = True; + break; + case NSWindowTabbingModeAutomatic: + result = ([NSWindow userTabbingPreference] == + NSWindowUserTabbingPreferenceAlways); + break; + default: + result = False; + break; + } + return result; +} + +/* + * Helper for the tkLayoutChanged methods. Synchronizes Tk's understanding of + * the bounds of a contentView with the window's. It is needed because there + * are situations when the window manager can change the layout of an NSWindow + * without having been requested to do so by Tk. Examples are when a window + * goes FullScreen or shows a tab bar. NSWindow methods which involve such + * layout changes should be overridden or protected by methods which call this. */ +static void syncLayout(NSWindow *macWindow) +{ + TkWindow *winPtr = TkMacOSXGetTkWindow(macWindow); + + if (winPtr) { + // Using screen coordinates with origin at bottom left. + NSRect frameRect = [macWindow frame]; + // This accounts for the tab bar, if there is one. + NSRect contentRect = [macWindow contentRectForFrameRect: frameRect]; + WmInfo *wmPtr = winPtr->wmInfoPtr; + + // The parent includes the title bar, tab bar and window frame. + wmPtr->xInParent = frameRect.origin.x - contentRect.origin.x; + wmPtr->yInParent = (frameRect.origin.y + frameRect.size.height - + contentRect.origin.y - contentRect.size.height); + wmPtr->parentWidth = winPtr->changes.width + frameRect.size.width - + contentRect.size.width; + wmPtr->parentHeight = winPtr->changes.height + frameRect.size.height - + contentRect.size.height; + } +} +#endif + typedef enum { - WMATT_ALPHA, WMATT_FULLSCREEN, WMATT_MODIFIED, WMATT_NOTIFY, - WMATT_TITLEPATH, WMATT_TOPMOST, WMATT_TRANSPARENT, - WMATT_TYPE, _WMATT_LAST_ATTRIBUTE + WMATT_ALPHA, WMATT_APPEARANCE, WMATT_BUTTONS, WMATT_FULLSCREEN, + WMATT_ISDARK, WMATT_MODIFIED, WMATT_NOTIFY, WMATT_TITLEPATH, WMATT_TOPMOST, + WMATT_TRANSPARENT, WMATT_STYLEMASK, WMATT_CLASS, WMATT_TABBINGID, + WMATT_TABBINGMODE, WMATT_TYPE, _WMATT_LAST_ATTRIBUTE } WmAttribute; static const char *const WmAttributeNames[] = { - "-alpha", "-fullscreen", "-modified", "-notify", - "-titlepath", "-topmost", "-transparent", - "-type", NULL + "-alpha", "-appearance", "-buttons", "-fullscreen", "-isdark", "-modified", + "-notify", "-titlepath", "-topmost", "-transparent", "-stylemask", "-class", + "-tabbingid", "-tabbingmode", "-type", NULL }; /* @@ -178,12 +321,12 @@ static int wmTracing = 0; * of top-level windows. */ -static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin); +static void TopLevelReqProc(void *dummy, Tk_Window tkwin); static const Tk_GeomMgr wmMgrType = { "wm", /* name */ TopLevelReqProc, /* requestProc */ - NULL, /* lostSlaveProc */ + NULL, /* lostContentProc */ }; /* @@ -193,123 +336,124 @@ static const Tk_GeomMgr wmMgrType = { static int tkMacOSXWmAttrNotifyVal = 0; /* - * Forward declarations for procedures defined in this file: + * Declarations of static functions defined in this file: */ static NSRect InitialWindowBounds(TkWindow *winPtr, NSWindow *macWindow); static int ParseGeometry(Tcl_Interp *interp, char *string, TkWindow *winPtr); -static void TopLevelEventProc(ClientData clientData, +static void TopLevelEventProc(void *clientData, XEvent *eventPtr); static void WmStackorderToplevelWrapperMap(TkWindow *winPtr, Display *display, Tcl_HashTable *table); -static void UpdateGeometryInfo(ClientData clientData); +static void UpdateGeometryInfo(void *clientData); static void UpdateSizeHints(TkWindow *winPtr); static void UpdateVRootGeometry(WmInfo *wmPtr); static int WmAspectCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmAttributesCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmClientCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmColormapwindowsCmd(Tk_Window tkwin, - TkWindow *winPtr, Tcl_Interp *interp, int objc, + TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmCommandCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmDeiconifyCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmFocusmodelCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmForgetCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmFrameCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmGeometryCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmGridCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmGroupCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, + Tcl_Obj *const objv[]); +static int WmIconbadgeCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmIconbitmapCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmIconifyCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmIconmaskCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmIconnameCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmIconphotoCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmIconpositionCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmIconwindowCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmManageCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmMaxsizeCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmMinsizeCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmOverrideredirectCmd(Tk_Window tkwin, - TkWindow *winPtr, Tcl_Interp *interp, int objc, + TkWindow *winPtr, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmPositionfromCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmProtocolCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmResizableCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmSizefromCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmStackorderCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmStateCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmTitleCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmTransientCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int WmWithdrawCmd(Tk_Window tkwin, TkWindow *winPtr, - Tcl_Interp *interp, int objc, + Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static void WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr); static int WmWinStyle(Tcl_Interp *interp, TkWindow *winPtr, - int objc, Tcl_Obj *const objv[]); -static int WmWinTabbingId(Tcl_Interp *interp, TkWindow *winPtr, - int objc, Tcl_Obj *const objv[]); + Tcl_Size objc, Tcl_Obj *const objv[]); static int WmWinAppearance(Tcl_Interp *interp, TkWindow *winPtr, - int objc, Tcl_Obj *const objv[]); + Tcl_Size objc, Tcl_Obj *const objv[]); static void ApplyWindowAttributeFlagChanges(TkWindow *winPtr, NSWindow *macWindow, UInt64 oldAttributes, int oldFlags, int create, int initial); @@ -323,6 +467,90 @@ static void RemapWindows(TkWindow *winPtr, MacDrawable *parentWin); static void RemoveTransient(TkWindow *winPtr); +#if MAC_OS_X_VERSION_MAX_ALLOWED > 101300 + +/* + * Add a window as a tab in the group specified by its tabbingid, or + * make it a standalone window if it is the only window with that + * tabbingid. Adjust the window size if a tab bar appeared or + * disappeared. + */ + +static void placeAsTab(TKWindow *macWindow) { + TkWindow *winPtr = NULL, *winPtr2 = NULL; + TKWindow *target = NULL, *sibling = NULL; + NSString *identifier = [macWindow tabbingIdentifier]; + if (!wantsToBeTab(macWindow)) { + [macWindow moveTabToNewWindow:NSApp]; + [(TKWindow *)target tkLayoutChanged]; + return; + } + for (NSWindow *window in [NSApp windows]) { + if (window == macWindow) { + continue; + } + if ([identifier isEqualTo: [window tabbingIdentifier]] && + wantsToBeTab(window)) { + target = (TKWindow*) window; + syncLayout(target); + break; + } + } + syncLayout(macWindow); + NSArray<NSWindow *> *tabs = [macWindow tabbedWindows]; + if ([tabs count] == 2) { + sibling = tabs[0] == macWindow ? (TKWindow *)tabs[1] : (TKWindow *)tabs[0]; + syncLayout(sibling); + winPtr2 = TkMacOSXGetTkWindow(sibling); + } + if (target) { + CGFloat winHeight = [macWindow contentRectForFrameRect: + [macWindow frame]].size.height; + CGFloat winDelta = 0, targetHeight, targetDelta = 0; + targetHeight = [target contentRectForFrameRect: + [target frame]].size.height; + [target addTabbedWindow:macWindow ordered:NSWindowAbove]; + targetDelta = targetHeight - [target contentRectForFrameRect: + [target frame]].size.height; + winDelta = winHeight - [target contentRectForFrameRect: + [target frame]].size.height; + if (winDelta) { + winPtr = TkMacOSXGetTkWindow(macWindow); + XMoveResizeWindow(winPtr->display, winPtr->window, + winPtr->changes.x, winPtr->changes.y, + winPtr->changes.width, winPtr->changes.height + winDelta ); + if (sibling) { + winPtr = TkMacOSXGetTkWindow(sibling); + XMoveResizeWindow(winPtr->display, winPtr->window, + winPtr->changes.x, winPtr->changes.y, + winPtr->changes.width, winPtr->changes.height - winDelta ); + } + } + if (targetDelta) { + winPtr = TkMacOSXGetTkWindow(target); + XMoveResizeWindow(winPtr->display, winPtr->window, + winPtr->changes.x, winPtr->changes.y, + winPtr->changes.width, winPtr->changes.height + targetDelta ); + } + } else { + CGFloat height = [macWindow contentRectForFrameRect: + [macWindow frame]].size.height; + [macWindow moveTabToNewWindow:NSApp]; + CGFloat delta = height - [macWindow contentRectForFrameRect: + [macWindow frame]].size.height; + winPtr = TkMacOSXGetTkWindow(macWindow); + XMoveResizeWindow(winPtr->display, winPtr->window, + winPtr->changes.x, winPtr->changes.y, + winPtr->changes.width, winPtr->changes.height + delta); + if (winPtr2) { + XMoveResizeWindow(winPtr2->display, winPtr2->window, + winPtr2->changes.x, winPtr2->changes.y, + winPtr2->changes.width, winPtr2->changes.height + delta ); + } + } +} +#endif + #pragma mark NSWindow(TKWm) @implementation NSWindow(TKWm) @@ -349,13 +577,18 @@ static void RemoveTransient(TkWindow *winPtr); return [self convertRectFromScreen:pointrect].origin; } #endif - @end #pragma mark - @implementation TKPanel: NSPanel @synthesize tkWindow = _tkWindow; + +- (void) tkLayoutChanged +{ + syncLayout(self); +} + @end @implementation TKDrawerWindow: NSWindow @@ -370,44 +603,12 @@ static void RemoveTransient(TkWindow *winPtr); @implementation TKWindow(TKWm) -/* - * This method synchronizes Tk's understanding of the bounds of a contentView - * with the window's. It is needed because there are situations when the - * window manager can change the layout of an NSWindow without having been - * requested to do so by Tk. Examples are when a window goes FullScreen or - * shows a tab bar. NSWindow methods which involve such layout changes should - * be overridden or protected by methods which call this. - */ - - (void) tkLayoutChanged { - TkWindow *winPtr = TkMacOSXGetTkWindow(self); - - if (winPtr) { - NSRect frameRect; - - /* - * This avoids including the title bar for full screen windows - * but does include it for normal windows. - */ - - if ([self styleMask] & NSFullScreenWindowMask) { - frameRect = [NSWindow frameRectForContentRect:NSZeroRect - styleMask:[self styleMask]]; - } else { - frameRect = [self frameRectForContentRect:NSZeroRect]; - } - - WmInfo *wmPtr = winPtr->wmInfoPtr; - - wmPtr->xInParent = -frameRect.origin.x; - wmPtr->yInParent = frameRect.origin.y + frameRect.size.height; - wmPtr->parentWidth = winPtr->changes.width + frameRect.size.width; - wmPtr->parentHeight = winPtr->changes.height + frameRect.size.height; - } + syncLayout(self); } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 - (void)toggleTabBar:(id)sender { TkWindow *winPtr = TkMacOSXGetTkWindow(self); @@ -725,6 +926,8 @@ TkWmNewWindow( wmPtr->window = nil; winPtr->wmInfoPtr = wmPtr; + // initialize wmPtr->NSWindowSubclass here + UpdateVRootGeometry(wmPtr); /* @@ -1155,7 +1358,7 @@ TkWmSetClass( int Tk_WmObjCmd( - ClientData clientData, /* Main window associated with interpreter. */ + void *clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ @@ -1164,7 +1367,7 @@ Tk_WmObjCmd( static const char *const optionStrings[] = { "aspect", "attributes", "client", "colormapwindows", "command", "deiconify", "focusmodel", "forget", - "frame", "geometry", "grid", "group", + "frame", "geometry", "grid", "group", "iconbadge", "iconbitmap", "iconify", "iconmask", "iconname", "iconphoto", "iconposition", "iconwindow", "manage", "maxsize", "minsize", "overrideredirect", @@ -1174,7 +1377,7 @@ Tk_WmObjCmd( enum options { WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS, WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET, - WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, + WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBADGE, WMOPT_ICONBITMAP, WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, WMOPT_ICONPHOTO, WMOPT_ICONPOSITION, WMOPT_ICONWINDOW, WMOPT_MANAGE, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, @@ -1182,7 +1385,7 @@ Tk_WmObjCmd( WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, WMOPT_WITHDRAW }; int index; - int length; + Tcl_Size length; char *argv1; TkWindow *winPtr; @@ -1210,13 +1413,36 @@ Tk_WmObjCmd( sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - if (objc < 3) { goto wrongNumArgs; } - - if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr) - != TCL_OK) { + if (index == WMOPT_ATTRIBUTES && objc == 5 && + strcmp(Tcl_GetString(objv[3]), "-class") == 0) { + if (TkGetWindowFromObj(NULL, tkwin, objv[2], (Tk_Window *) &winPtr) + == TCL_OK) { + if (winPtr->wmInfoPtr->window != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Cannot change the class after the mac window is created.",-1)); + Tcl_SetErrorCode(interp, "TK", "CLASS_CHANGE", NULL); + return TCL_ERROR; + } + } else { + winPtr = NULL; + } + } else if (index == WMOPT_ATTRIBUTES && objc == 5 && + strcmp(Tcl_GetString(objv[3]), "-tabbingid") == 0) { + if (TkGetWindowFromObj(NULL, tkwin, objv[2], (Tk_Window *) &winPtr) + != TCL_OK) { + winPtr = NULL; + } + } else if (index == WMOPT_ATTRIBUTES && objc == 5 && + strcmp(Tcl_GetString(objv[3]), "-tabbingmode") == 0) { + if (TkGetWindowFromObj(NULL, tkwin, objv[2], (Tk_Window *) &winPtr) + != TCL_OK) { + winPtr = NULL; + } + } else if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr) + != TCL_OK) { return TCL_ERROR; } if (winPtr && !Tk_IsTopLevel(winPtr) @@ -1253,6 +1479,8 @@ Tk_WmObjCmd( return WmGridCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_GROUP: return WmGroupCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONBADGE: + return WmIconbadgeCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_ICONBITMAP: return WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_ICONIFY: @@ -1321,7 +1549,7 @@ WmAspectCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -1336,10 +1564,10 @@ WmAspectCmd( if (wmPtr->sizeHintsFlags & PAspect) { Tcl_Obj *results[4]; - results[0] = Tcl_NewIntObj(wmPtr->minAspect.x); - results[1] = Tcl_NewIntObj(wmPtr->minAspect.y); - results[2] = Tcl_NewIntObj(wmPtr->maxAspect.x); - results[3] = Tcl_NewIntObj(wmPtr->maxAspect.y); + results[0] = Tcl_NewWideIntObj(wmPtr->minAspect.x); + results[1] = Tcl_NewWideIntObj(wmPtr->minAspect.y); + results[2] = Tcl_NewWideIntObj(wmPtr->maxAspect.x); + results[3] = Tcl_NewWideIntObj(wmPtr->maxAspect.y); Tcl_SetObjResult(interp, Tcl_NewListObj(4, results)); } return TCL_OK; @@ -1356,7 +1584,7 @@ WmAspectCmd( if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) || (denom2 <= 0)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "aspect number can't be <= 0", -1)); + "aspect number can't be <= 0", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TK", "WM", "ASPECT", NULL); return TCL_ERROR; } @@ -1396,7 +1624,8 @@ WmSetAttribute( Tcl_Obj *value) /* New value */ { WmInfo *wmPtr = winPtr->wmInfoPtr; - int boolean; + int boolValue; + NSString *identifier; switch (attribute) { case WMATT_ALPHA: { @@ -1418,11 +1647,63 @@ WmSetAttribute( [macWindow setAlphaValue:dval]; break; } + case WMATT_APPEARANCE: { + int index; + if (Tcl_GetIndexFromObjStruct(interp, value, appearanceStrings, + sizeof(char *), "appearancename", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum appearances) index) { + case APPEARANCE_AQUA: + macWindow.appearance = [NSAppearance appearanceNamed: + NSAppearanceNameAqua]; + break; + case APPEARANCE_DARKAQUA: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + if (@available(macOS 10.14, *)) { + macWindow.appearance = [NSAppearance appearanceNamed: + NSAppearanceNameDarkAqua]; + } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + break; + default: + macWindow.appearance = nil; + } + break; + } + case WMATT_BUTTONS: { + windowButtonState state = {0}; + Tcl_Obj **elements; + Tcl_Size nElements, i; + if (Tcl_ListObjGetElements(interp, value, &nElements, &elements) == TCL_OK) { + int index = 0; + for (i = 0; i < nElements; i++) { + if (Tcl_GetIndexFromObjStruct(interp, elements[i], buttonNames, + sizeof(char *), "window button name", 0, &index) != TCL_OK) { + return TCL_ERROR; + } else { + state.intvalue |= (1 << index); + } + } + } else if (Tcl_GetIntFromObj(interp, value, &state.intvalue) != TCL_OK) { + return TCL_ERROR; + } + NSButton *closer = [macWindow standardWindowButton: + NSWindowCloseButton]; + NSButton *miniaturizer = [macWindow standardWindowButton: + NSWindowMiniaturizeButton]; + NSButton *zoomer = [macWindow standardWindowButton: + NSWindowZoomButton]; + closer.enabled = (state.bits.close != 0); + miniaturizer.enabled = (state.bits.miniaturize != 0); + zoomer.enabled = (state.bits.zoom != 0); + break; + } case WMATT_FULLSCREEN: - if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { + if (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) { return TCL_ERROR; } - if (boolean != (([macWindow styleMask] & NSFullScreenWindowMask) != 0)) { + if (boolValue != (([macWindow styleMask] & NSFullScreenWindowMask) != 0)) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 [macWindow toggleFullScreen:macWindow]; #else @@ -1431,30 +1712,145 @@ WmSetAttribute( } break; case WMATT_MODIFIED: - if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { + if (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) { return TCL_ERROR; } - if (boolean != [macWindow isDocumentEdited]) { - [macWindow setDocumentEdited:(BOOL)boolean]; + if (boolValue != [macWindow isDocumentEdited]) { + [macWindow setDocumentEdited:(BOOL)boolValue]; } break; case WMATT_NOTIFY: - if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { + if (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) { return TCL_ERROR; } - if (boolean == !tkMacOSXWmAttrNotifyVal) { + if (boolValue == !tkMacOSXWmAttrNotifyVal) { static NSInteger request = -1; if (request >= 0) { [NSApp cancelUserAttentionRequest:request]; request = -1; } - if (boolean) { + if (boolValue) { request = [NSApp requestUserAttention:NSCriticalRequest]; } - tkMacOSXWmAttrNotifyVal = boolean; + tkMacOSXWmAttrNotifyVal = boolValue; + } + break; + case WMATT_STYLEMASK: { + unsigned long styleMaskValue = 0; + Tcl_Obj **elements; + Tcl_Size nElements, i; + if (Tcl_ListObjGetElements(interp, value, &nElements, &elements) == TCL_OK) { + int index; + for (i = 0; i < nElements; i++) { + if (Tcl_GetIndexFromObjStruct(interp, elements[i], styleMaskBits, + sizeof(styleMaskBit), "styleMask bit", 0, &index) != TCL_OK) { + return TCL_ERROR; + } else if (![macWindow isKindOfClass: [NSPanel class]] && + styleMaskBits[index].allowed == NSWindowClass_panel) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "styleMask bit \"%s\" can only be used with an NSPanel", + styleMaskBits[index].bitname)); + Tcl_SetErrorCode(interp, "TK", "INVALID_STYLEMASK_BIT", NULL); + return TCL_ERROR; + } else { + styleMaskValue |= styleMaskBits[index].bitvalue; + } + /* + * Be sure not to change the fullscreen bit. + */ + styleMaskValue |= (NSWindowStyleMaskFullScreen & macWindow.styleMask); + } + /* + * A resizable docmodal NSWindow or NSPanel does not work + * correctly. It cannot be resized from the top edge. Other bits, + * such as titled are ignored for docmodals. To be safe, we clear + * all other bits when the docmodal bit is set. + */ + if (styleMaskValue & NSDocModalWindowMask) { + styleMaskValue &= ~NSWindowStyleMaskResizable; + } + if ([macWindow isKindOfClass: [NSPanel class]]) { + /* + * We always make NSPanels titled, nonactivating utility windows, + * even if these bits are not requested in the command. + */ + if (!(styleMaskValue & NSWindowStyleMaskTitled) ) { + styleMaskValue |= NSWindowStyleMaskTitled; + styleMaskValue |= NSWindowStyleMaskUtilityWindow; + styleMaskValue |= NSWindowStyleMaskNonactivatingPanel; + } + } + if (styleMaskValue & NSWindowStyleMaskFullSizeContentView) { + macWindow.titlebarAppearsTransparent = YES; + } else { + macWindow.titlebarAppearsTransparent = NO; + } + } else { + return TCL_ERROR; + } + NSRect oldFrame = [macWindow frame]; +#ifdef DEBUG + fprintf(stderr, "Current styleMask: %lx\n", [macWindow styleMask]); + fprintf(stderr, "Setting styleMask to %lx\n", styleMaskValue); +#endif + macWindow.styleMask = (unsigned long) styleMaskValue; + NSRect newFrame = [macWindow frame]; + int heightDiff = newFrame.size.height - oldFrame.size.height; + int newHeight = heightDiff < 0 ? newFrame.size.height : + newFrame.size.height - heightDiff; + [(TKWindow *)macWindow tkLayoutChanged]; + if (heightDiff) { + //Calling XMoveResizeWindow twice is a hack to force a relayout + //of the window. + XMoveResizeWindow(winPtr->display, winPtr->window, + winPtr->changes.x, winPtr->changes.y, + newFrame.size.width, newHeight - 1); + XMoveResizeWindow(winPtr->display, winPtr->window, + winPtr->changes.x, winPtr->changes.y, + newFrame.size.width, newHeight); + } + break; + } + case WMATT_TABBINGID: { + NSString *oldId = [macWindow tabbingIdentifier]; + char *valueString; + Tcl_Size length; + if ([NSApp macOSVersion] < 101300) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Tabbing identifiers require macOS 10.13", TCL_INDEX_NONE)); + Tcl_SetErrorCode(interp, "TK", "WM", "TABBINGID", NULL); + return TCL_ERROR; + } + valueString = Tcl_GetStringFromObj(value, &length); + identifier = [NSString stringWithUTF8String:valueString]; + [macWindow setTabbingIdentifier: identifier]; + + /* + * If the tabbingIdentifier of a tab is changed we move it into + * the tab group with that identifier. + */ + + if ([oldId compare:identifier] != NSOrderedSame) { + placeAsTab((TKWindow *)macWindow); } break; + } + case WMATT_TABBINGMODE: { + int index; + tabbingMode mode; + if (Tcl_GetIndexFromObjStruct(interp, value, tabbingModes, + sizeof(tabbingMode), "NSWindow Tabbing Mode", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + mode = tabbingModes[index]; + [macWindow setTabbingMode: mode.modeValue]; + placeAsTab((TKWindow *)macWindow); + break; + } + case WMATT_ISDARK: { + break; + } case WMATT_TITLEPATH: { const char *path = (const char *)Tcl_FSGetNativePath(value); NSString *filename = @""; @@ -1466,13 +1862,13 @@ WmSetAttribute( break; } case WMATT_TOPMOST: - if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { + if (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) { return TCL_ERROR; } - if (boolean != ((wmPtr->flags & WM_TOPMOST) != 0)) { + if (boolValue != ((wmPtr->flags & WM_TOPMOST) != 0)) { int oldFlags = wmPtr->flags; - if (boolean) { + if (boolValue) { wmPtr->flags |= WM_TOPMOST; } else { wmPtr->flags &= ~WM_TOPMOST; @@ -1482,14 +1878,14 @@ WmSetAttribute( } break; case WMATT_TRANSPARENT: - if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { + if (Tcl_GetBooleanFromObj(interp, value, &boolValue) != TCL_OK) { return TCL_ERROR; } - if (boolean != ((wmPtr->flags & WM_TRANSPARENT) != 0)) { + if (boolValue != ((wmPtr->flags & WM_TRANSPARENT) != 0)) { UInt64 oldAttributes = wmPtr->attributes; int oldFlags = wmPtr->flags; - if (boolean) { + if (boolValue) { wmPtr->flags |= WM_TRANSPARENT; wmPtr->attributes |= kWindowNoShadowAttribute; } else { @@ -1498,12 +1894,14 @@ WmSetAttribute( } ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes, oldFlags, 1, 0); - [macWindow setBackgroundColor:boolean ? [NSColor clearColor] : nil]; - [macWindow setOpaque:!boolean]; + [macWindow setBackgroundColor:boolValue ? [NSColor clearColor] : nil]; + [macWindow setOpaque:!boolValue]; TkMacOSXInvalidateWindow((MacDrawable *)winPtr->window, TK_PARENT_WINDOW); } break; + case WMATT_CLASS: + break; case WMATT_TYPE: TKLog(@"The type attribute is ignored on macOS."); break; @@ -1538,18 +1936,91 @@ WmGetAttribute( case WMATT_ALPHA: result = Tcl_NewDoubleObj([macWindow alphaValue]); break; + case WMATT_APPEARANCE: { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + NSAppearanceName appearance; +#else + NSString *appearance; +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + const char *resultString = "unrecognized"; + appearance = macWindow.appearance.name; + if (appearance == nil) { + resultString = appearanceStrings[APPEARANCE_AUTO]; + } else if (appearance == NSAppearanceNameAqua) { + resultString = appearanceStrings[APPEARANCE_AQUA]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + } else if (@available(macOS 10.14, *)) { + if (appearance == NSAppearanceNameDarkAqua) { + resultString = appearanceStrings[APPEARANCE_DARKAQUA]; + } +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 + } + result = Tcl_NewStringObj(resultString, TCL_INDEX_NONE); + break; + } + case WMATT_BUTTONS: { + result = Tcl_NewListObj(3, NULL); + if ([macWindow standardWindowButton:NSWindowCloseButton].enabled) { + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj("close", TCL_INDEX_NONE)); + } + if ([macWindow standardWindowButton:NSWindowMiniaturizeButton].enabled) { + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj("miniaturize", TCL_INDEX_NONE)); + } + if ([macWindow standardWindowButton:NSWindowZoomButton].enabled) { + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj("zoom", TCL_INDEX_NONE)); + } + break; + } + case WMATT_CLASS: + if ([macWindow isKindOfClass:[NSPanel class]]) { + result = Tcl_NewStringObj(subclassNames[subclassNSPanel], TCL_INDEX_NONE); + } else { + result = Tcl_NewStringObj(subclassNames[subclassNSWindow], TCL_INDEX_NONE); + } + break; case WMATT_FULLSCREEN: result = Tcl_NewBooleanObj([macWindow styleMask] & NSFullScreenWindowMask); break; + case WMATT_ISDARK: + result = Tcl_NewBooleanObj(TkMacOSXInDarkMode((Tk_Window)winPtr)); + break; case WMATT_MODIFIED: result = Tcl_NewBooleanObj([macWindow isDocumentEdited]); break; case WMATT_NOTIFY: result = Tcl_NewBooleanObj(tkMacOSXWmAttrNotifyVal); break; + case WMATT_STYLEMASK: { + unsigned long styleMaskValue = [macWindow styleMask]; + const styleMaskBit *bit; + result = Tcl_NewListObj(9, NULL); + for (bit = styleMaskBits; bit->bitname != NULL; bit++) { + if (styleMaskValue & bit->bitvalue) { + Tcl_ListObjAppendElement(NULL, result, + Tcl_NewStringObj(bit->bitname, TCL_INDEX_NONE)); + } + } + break; + } + case WMATT_TABBINGID: + result = Tcl_NewStringObj([[macWindow tabbingIdentifier] UTF8String], + -1); + break; + case WMATT_TABBINGMODE: { + long mode = [macWindow tabbingMode]; + const char *name = "unrecognized"; + for (const tabbingMode *m = tabbingModes; m->modeName != NULL; m++) { + if (m->modeValue == mode) { + name = m->modeName; + break; + } + } + result = Tcl_NewStringObj(name, TCL_INDEX_NONE); + break; + } case WMATT_TITLEPATH: result = Tcl_NewStringObj([[macWindow representedFilename] UTF8String], - -1); + TCL_INDEX_NONE); break; case WMATT_TOPMOST: result = Tcl_NewBooleanObj(wmPtr->flags & WM_TOPMOST); @@ -1558,7 +2029,7 @@ WmGetAttribute( result = Tcl_NewBooleanObj(wmPtr->flags & WM_TRANSPARENT); break; case WMATT_TYPE: - result = Tcl_NewStringObj("unsupported", -1); + result = Tcl_NewStringObj("unsupported", TCL_INDEX_NONE); break; case _WMATT_LAST_ATTRIBUTE: default: @@ -1589,13 +2060,64 @@ WmAttributesCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int attribute = 0; NSWindow *macWindow; + if (winPtr == NULL && objc == 5) { + int index, isNew = 0; + Tcl_Size length; - if (winPtr->window == None) { + /* + * If we are setting an atttribute of a future window, save the value + * in a hash table so we can look it up when the window is actually + * created. + */ + + if (strcmp(Tcl_GetString(objv[3]), "-class") == 0) { + if (Tcl_GetIndexFromObjStruct(interp, objv[4], subclassNames, + sizeof(char *), "NSWindow subclass", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&pathnameToSubclass, + Tcl_GetString(objv[2]), &isNew); + if (hPtr) { + Tcl_SetHashValue(hPtr, INT2PTR(index)); + return TCL_OK; + } + } else if (strcmp(Tcl_GetString(objv[3]), "-tabbingid") == 0) { + char *identifier = Tcl_GetStringFromObj(objv[4], &length); + char *value = (char *)ckalloc(length + 1); + strncpy(value, identifier, length + 1); + Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&pathnameToTabbingId, + Tcl_GetString(objv[2]), &isNew); + if (hPtr) { + Tcl_SetHashValue(hPtr, value); + return TCL_OK; + } + } else if (strcmp(Tcl_GetString(objv[3]), "-tabbingmode") == 0) { + long value = NSWindowTabbingModeAutomatic; + int modeIndex; + if (Tcl_GetIndexFromObjStruct(interp, objv[4], tabbingModes, + sizeof(tabbingMode), "NSWindow Tabbing Mode", 0, &modeIndex) == TCL_OK) { + value = tabbingModes[modeIndex].modeValue; + } + Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&pathnameToTabbingMode, + Tcl_GetString(objv[2]), &isNew); + if (hPtr) { + Tcl_SetHashValue(hPtr, value); + return TCL_OK; + } + } + } + if (!winPtr) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "Only -class, -tabbingid, or -tabbingmode can be set before the window exists.")); + Tcl_SetErrorCode(interp, "TK", "NO_WINDOW", NULL); + return TCL_ERROR; + } + if (winPtr && winPtr->window == None) { Tk_MakeWindowExist((Tk_Window)winPtr); } if (!TkMacOSXHostToplevelExists(winPtr)) { @@ -1608,7 +2130,7 @@ WmAttributesCmd( for (attribute = 0; attribute < _WMATT_LAST_ATTRIBUTE; ++attribute) { Tcl_ListObjAppendElement(NULL, result, - Tcl_NewStringObj(WmAttributeNames[attribute], -1)); + Tcl_NewStringObj(WmAttributeNames[attribute], TCL_INDEX_NONE)); Tcl_ListObjAppendElement(NULL, result, WmGetAttribute(winPtr, macWindow, (WmAttribute)attribute)); } @@ -1620,7 +2142,7 @@ WmAttributesCmd( } Tcl_SetObjResult(interp, WmGetAttribute(winPtr, macWindow, (WmAttribute)attribute)); } else if ((objc - 3) % 2 == 0) { /* wm attributes $win -att value... */ - int i; + Tcl_Size i; for (i = 3; i < objc; i += 2) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], WmAttributeNames, @@ -1661,12 +2183,12 @@ WmClientCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; char *argv3; - int length; + Tcl_Size length; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?name?"); @@ -1675,7 +2197,7 @@ WmClientCmd( if (objc == 3) { if (wmPtr->clientMachine != NULL) { Tcl_SetObjResult(interp, - Tcl_NewStringObj(wmPtr->clientMachine, -1)); + Tcl_NewStringObj(wmPtr->clientMachine, TCL_INDEX_NONE)); } return TCL_OK; } @@ -1717,12 +2239,12 @@ WmColormapwindowsCmd( Tk_Window tkwin, /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; TkWindow **cmapList, *winPtr2; - int i, windowObjc; + Tcl_Size i, windowObjc; int gotToplevel = 0; Tcl_Obj **windowObjv, *resultObj; @@ -1739,7 +2261,7 @@ WmColormapwindowsCmd( break; } Tcl_ListObjAppendElement(NULL, resultObj, - TkNewWindowObj((Tk_Window)wmPtr->cmapList[i])); + Tk_NewWindowObj((Tk_Window)wmPtr->cmapList[i])); } Tcl_SetObjResult(interp, resultObj); return TCL_OK; @@ -1807,11 +2329,11 @@ WmCommandCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; - int len; + Tcl_Size len; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?value?"); @@ -1864,7 +2386,7 @@ WmDeiconifyCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -1944,7 +2466,7 @@ WmFocusmodelCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -1960,7 +2482,7 @@ WmFocusmodelCmd( } if (objc == 3) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - wmPtr->hints.input ? "passive" : "active", -1)); + wmPtr->hints.input ? "passive" : "active", TCL_INDEX_NONE)); return TCL_OK; } @@ -1998,7 +2520,7 @@ WmForgetCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel or Frame to work with */ TCL_UNUSED(Tcl_Interp *), /* Current interpreter. */ - TCL_UNUSED(int), /* Number of arguments. */ + TCL_UNUSED(Tcl_Size), /* Number of arguments. */ TCL_UNUSED(Tcl_Obj *const *)) /* Argument objects. */ { Tk_Window frameWin = (Tk_Window)winPtr; @@ -2064,7 +2586,7 @@ WmFrameCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2080,7 +2602,7 @@ WmFrameCmd( window = Tk_WindowId((Tk_Window)winPtr); } snprintf(buf, sizeof(buf), "0x%" TCL_Z_MODIFIER "x", (size_t)window); - Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE)); return TCL_OK; } @@ -2106,7 +2628,7 @@ WmGeometryCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2177,7 +2699,7 @@ WmGridCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2193,10 +2715,10 @@ WmGridCmd( if (wmPtr->sizeHintsFlags & PBaseSize) { Tcl_Obj *results[4]; - results[0] = Tcl_NewIntObj(wmPtr->reqGridWidth); - results[1] = Tcl_NewIntObj(wmPtr->reqGridHeight); - results[2] = Tcl_NewIntObj(wmPtr->widthInc); - results[3] = Tcl_NewIntObj(wmPtr->heightInc); + results[0] = Tcl_NewWideIntObj(wmPtr->reqGridWidth); + results[1] = Tcl_NewWideIntObj(wmPtr->reqGridHeight); + results[2] = Tcl_NewWideIntObj(wmPtr->widthInc); + results[3] = Tcl_NewWideIntObj(wmPtr->heightInc); Tcl_SetObjResult(interp, Tcl_NewListObj(4, results)); } return TCL_OK; @@ -2244,7 +2766,7 @@ WmGridCmd( return TCL_OK; error: - Tcl_SetObjResult(interp, Tcl_NewStringObj(errorMsg, -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(errorMsg, TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TK", "WM", "GRID", NULL); return TCL_ERROR; } @@ -2271,13 +2793,13 @@ WmGroupCmd( Tk_Window tkwin, /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; Tk_Window tkwin2; char *argv3; - int length; + Tcl_Size length; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?"); @@ -2285,7 +2807,7 @@ WmGroupCmd( } if (objc == 3) { if (wmPtr->hints.flags & WindowGroupHint) { - Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->leaderName, -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->leaderName, TCL_INDEX_NONE)); } return TCL_OK; } @@ -2313,6 +2835,74 @@ WmGroupCmd( return TCL_OK; } + /*---------------------------------------------------------------------- + * + * WmIconbadgeCmd -- + * + * This procedure is invoked to process the "wm iconbadge" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconbadgeCmd( + TCL_UNUSED(Tk_Window), /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + Tcl_Size objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + (void) winPtr; + NSString *label; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv,"window badge"); + return TCL_ERROR; + } + + label = [NSString stringWithUTF8String:Tcl_GetString(objv[3])]; + + int number = [label intValue]; + NSDockTile *dockicon = [NSApp dockTile]; + + /* + * First, check that the label is not a decimal. If it is, + * return an error. + */ + + if ([label containsString:@"."]) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't use \"%s\" as icon badge", Tcl_GetString(objv[3]))); + return TCL_ERROR; + } + + /* + * Next, check that label is an int, empty string, or exclamation + * point. If so, set the icon badge on the Dock icon. Otherwise, + * return an error. + */ + + NSArray *array = @[@"", @"!"]; + if ([array containsObject: label]) { + [dockicon setBadgeLabel:label]; + } else if (number > 0) { + NSString *str = [@(number) stringValue]; + [dockicon setBadgeLabel:str]; + } else { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't use \"%s\" as icon badge", Tcl_GetString(objv[3]))); + return TCL_ERROR; + } + return TCL_OK; +} + /* *---------------------------------------------------------------------- * @@ -2335,13 +2925,13 @@ WmIconbitmapCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; Pixmap pixmap; char *str; - int len; + Tcl_Size len; if ((objc != 3) && (objc != 4)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?"); @@ -2404,7 +2994,7 @@ WmIconifyCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2427,13 +3017,13 @@ WmIconifyCmd( return TCL_ERROR; } else if (wmPtr->iconFor != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't iconify %s: it is an icon for %s", + "can't iconify \"%s\": it is an icon for \"%s\"", winPtr->pathName, Tk_PathName(wmPtr->iconFor))); Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "ICON", NULL); return TCL_ERROR; } else if (winPtr->flags & TK_EMBEDDED) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't iconify %s: it is an embedded window", + "can't iconify \"%s\": it is an embedded window", winPtr->pathName)); Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "EMBEDDED", NULL); return TCL_ERROR; @@ -2485,7 +3075,7 @@ WmIconmaskCmd( Tk_Window tkwin, /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2545,12 +3135,12 @@ WmIconnameCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; const char *argv3; - int length; + Tcl_Size length; if (objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?"); @@ -2558,7 +3148,7 @@ WmIconnameCmd( } if (objc == 3) { if (wmPtr->iconName != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->iconName, -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->iconName, TCL_INDEX_NONE)); } return TCL_OK; } @@ -2598,7 +3188,7 @@ WmIconphotoCmd( Tk_Window tkwin, /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Image tk_icon; @@ -2686,7 +3276,7 @@ WmIconpositionCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2701,8 +3291,8 @@ WmIconpositionCmd( if (wmPtr->hints.flags & IconPositionHint) { Tcl_Obj *results[2]; - results[0] = Tcl_NewIntObj(wmPtr->hints.icon_x); - results[1] = Tcl_NewIntObj(wmPtr->hints.icon_y); + results[0] = Tcl_NewWideIntObj(wmPtr->hints.icon_x); + results[1] = Tcl_NewWideIntObj(wmPtr->hints.icon_y); Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); } return TCL_OK; @@ -2744,7 +3334,7 @@ WmIconwindowCmd( Tk_Window tkwin, /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2758,7 +3348,7 @@ WmIconwindowCmd( if (objc == 3) { if (wmPtr->icon != NULL) { - Tcl_SetObjResult(interp, TkNewWindowObj(wmPtr->icon)); + Tcl_SetObjResult(interp, Tk_NewWindowObj(wmPtr->icon)); } return TCL_OK; } @@ -2847,7 +3437,7 @@ WmManageCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel or Frame to work with */ Tcl_Interp *interp, /* Current interpreter. */ - TCL_UNUSED(int), /* Number of arguments. */ + TCL_UNUSED(Tcl_Size), /* Number of arguments. */ TCL_UNUSED(Tcl_Obj *const *)) /* Argument objects. */ { Tk_Window frameWin = (Tk_Window)winPtr; @@ -2920,10 +3510,10 @@ WmManageCmd( static int WmMaxsizeCmd( - TCL_UNUSED(Tk_Window), /* Main window of the application. */ + Tk_Window tkwin, /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2938,14 +3528,14 @@ WmMaxsizeCmd( Tcl_Obj *results[2]; GetMaxSize(winPtr, &width, &height); - results[0] = Tcl_NewIntObj(width); - results[1] = Tcl_NewIntObj(height); + results[0] = Tcl_NewWideIntObj(width); + results[1] = Tcl_NewWideIntObj(height); Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); return TCL_OK; } - if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) - || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { + if ((Tk_GetPixelsFromObj(interp, tkwin, objv[3], &width) != TCL_OK) + || (Tk_GetPixelsFromObj(interp, tkwin, objv[4], &height) != TCL_OK)) { return TCL_ERROR; } wmPtr->maxWidth = width; @@ -2974,10 +3564,10 @@ WmMaxsizeCmd( static int WmMinsizeCmd( - TCL_UNUSED(Tk_Window), /* Main window of the application. */ + Tk_Window tkwin, /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2992,14 +3582,14 @@ WmMinsizeCmd( Tcl_Obj *results[2]; GetMinSize(winPtr, &width, &height); - results[0] = Tcl_NewIntObj(width); - results[1] = Tcl_NewIntObj(height); + results[0] = Tcl_NewWideIntObj(width); + results[1] = Tcl_NewWideIntObj(height); Tcl_SetObjResult(interp, Tcl_NewListObj(2, results)); return TCL_OK; } - if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) - || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { + if ((Tk_GetPixelsFromObj(interp, tkwin, objv[3], &width) != TCL_OK) + || (Tk_GetPixelsFromObj(interp, tkwin, objv[4], &height) != TCL_OK)) { return TCL_ERROR; } wmPtr->minWidth = width; @@ -3028,13 +3618,13 @@ WmMinsizeCmd( static int WmOverrideredirectCmd( - TCL_UNUSED(Tk_Window), /* Main window of the application. */ + TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int flag; + Bool boolValue; XSetWindowAttributes atts; TKWindow *win = (TKWindow *)TkMacOSXGetNSWindowForDrawable(winPtr->window); @@ -3049,12 +3639,20 @@ WmOverrideredirectCmd( return TCL_OK; } - if (Tcl_GetBooleanFromObj(interp, objv[3], &flag) != TCL_OK) { + if (Tcl_GetBooleanFromObj(interp, objv[3], &boolValue) != TCL_OK) { return TCL_ERROR; } - atts.override_redirect = flag ? True : False; + atts.override_redirect = boolValue; Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts); - ApplyContainerOverrideChanges(winPtr, win); + if ([NSApp macOSVersion] >= 101300) { + if (boolValue) { + win.styleMask |= NSWindowStyleMaskDocModalWindow; + } else { + win.styleMask &= ~NSWindowStyleMaskDocModalWindow; + } + } else { + ApplyContainerOverrideChanges(winPtr, win); + } return TCL_OK; } @@ -3080,7 +3678,7 @@ WmPositionfromCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -3097,9 +3695,9 @@ WmPositionfromCmd( if (objc == 3) { if (wmPtr->sizeHintsFlags & USPosition) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("user", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("user", TCL_INDEX_NONE)); } else if (wmPtr->sizeHintsFlags & PPosition) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("program", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("program", TCL_INDEX_NONE)); } return TCL_OK; } @@ -3146,14 +3744,14 @@ WmProtocolCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; ProtocolHandler *protPtr, *prevPtr; Atom protocol; char *cmd; - int cmdLength; + Tcl_Size cmdLength; Tcl_Obj *resultObj; if ((objc < 3) || (objc > 5)) { @@ -3186,7 +3784,7 @@ WmProtocolCmd( protPtr = protPtr->nextPtr) { if (protPtr->protocol == protocol) { Tcl_SetObjResult(interp, - Tcl_NewStringObj(protPtr->command, -1)); + Tcl_NewStringObj(protPtr->command, TCL_INDEX_NONE)); return TCL_OK; } } @@ -3247,7 +3845,7 @@ WmResizableCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -3324,7 +3922,7 @@ WmSizefromCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -3341,9 +3939,9 @@ WmSizefromCmd( if (objc == 3) { if (wmPtr->sizeHintsFlags & USSize) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("user", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("user", TCL_INDEX_NONE)); } else if (wmPtr->sizeHintsFlags & PSize) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("program", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("program", TCL_INDEX_NONE)); } return TCL_OK; } @@ -3390,7 +3988,7 @@ WmStackorderCmd( Tk_Window tkwin, /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { TkWindow **windows, **windowPtr; @@ -3414,7 +4012,7 @@ WmStackorderCmd( resultObj = Tcl_NewObj(); for (windowPtr = windows; *windowPtr ; windowPtr++) { Tcl_ListObjAppendElement(NULL, resultObj, - TkNewWindowObj((Tk_Window)*windowPtr)); + Tk_NewWindowObj((Tk_Window)*windowPtr)); } Tcl_SetObjResult(interp, resultObj); ckfree(windows); @@ -3459,7 +4057,7 @@ WmStackorderCmd( windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr); if (windows == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "TkWmStackorderToplevel failed", -1)); + "TkWmStackorderToplevel failed", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TK", "WM", "STACK", "FAIL", NULL); return TCL_ERROR; } @@ -3516,14 +4114,14 @@ WmStateCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; static const char *const optionStrings[] = { - "normal", "iconic", "withdrawn", "zoomed", NULL }; + "iconic", "normal", "withdrawn", "zoomed", NULL }; enum options { - OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN, OPT_ZOOMED }; + OPT_ICONIC, OPT_NORMAL, OPT_WITHDRAWN, OPT_ZOOMED }; int index; if ((objc < 3) || (objc > 4)) { @@ -3534,14 +4132,14 @@ WmStateCmd( if (objc == 4) { if (wmPtr->iconFor != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't change state of %s: it is an icon for %s", + "can't change state of \"%s\": it is an icon for \"%s\"", Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor))); Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "ICON", NULL); return TCL_ERROR; } if (winPtr->flags & TK_EMBEDDED) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't change state of %s: it is an embedded window", + "can't change state of \"%s\": it is an embedded window", winPtr->pathName)); Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "EMBEDDED", NULL); return TCL_ERROR; @@ -3589,7 +4187,7 @@ WmStateCmd( break; } } else if (wmPtr->iconFor != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("icon", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("icon", TCL_INDEX_NONE)); } else { if (wmPtr->hints.initial_state == NormalState || wmPtr->hints.initial_state == ZoomState) { @@ -3598,16 +4196,16 @@ WmStateCmd( } switch (wmPtr->hints.initial_state) { case NormalState: - Tcl_SetObjResult(interp, Tcl_NewStringObj("normal", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("normal", TCL_INDEX_NONE)); break; case IconicState: - Tcl_SetObjResult(interp, Tcl_NewStringObj("iconic", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("iconic", TCL_INDEX_NONE)); break; case WithdrawnState: - Tcl_SetObjResult(interp, Tcl_NewStringObj("withdrawn", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("withdrawn", TCL_INDEX_NONE)); break; case ZoomState: - Tcl_SetObjResult(interp, Tcl_NewStringObj("zoomed", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj("zoomed", TCL_INDEX_NONE)); break; } } @@ -3636,12 +4234,12 @@ WmTitleCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; char *argv3; - int length; + Tcl_Size length; if (objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?"); @@ -3650,7 +4248,7 @@ WmTitleCmd( if (objc == 3) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - wmPtr->titleUid ? wmPtr->titleUid : winPtr->nameUid, -1)); + wmPtr->titleUid ? wmPtr->titleUid : winPtr->nameUid, TCL_INDEX_NONE)); return TCL_OK; } @@ -3684,7 +4282,7 @@ WmTransientCmd( Tk_Window tkwin, /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -3694,13 +4292,13 @@ WmTransientCmd( Transient *transient; if ((objc != 3) && (objc != 4)) { - Tcl_WrongNumArgs(interp, 2, objv, "window ?master?"); + Tcl_WrongNumArgs(interp, 2, objv, "window ?window?"); return TCL_ERROR; } if (objc == 3) { if (wmPtr->container != NULL) { Tcl_SetObjResult(interp, - Tcl_NewStringObj(Tk_PathName(wmPtr->container), -1)); + Tcl_NewStringObj(Tk_PathName(wmPtr->container), TCL_INDEX_NONE)); } return TCL_OK; } @@ -3737,7 +4335,7 @@ WmTransientCmd( if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "can't make \"%s\" a master: it is an icon for %s", + "can't make \"%s\" a container: it is an icon for %s", Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor))); Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL); return TCL_ERROR; @@ -3747,7 +4345,7 @@ WmTransientCmd( w = (TkWindow *)w->wmInfoPtr->container) { if (w == winPtr) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "setting \"%s\" as master creates a transient/master cycle", + "can't set \"%s\" as container: would cause management loop", Tk_PathName(containerPtr))); Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL); return TCL_ERROR; @@ -3865,7 +4463,7 @@ WmWithdrawCmd( TCL_UNUSED(Tk_Window), /* Main window of the application. */ TkWindow *winPtr, /* Toplevel to work with */ Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -4101,7 +4699,7 @@ Tk_UnsetGrid( static void TopLevelEventProc( - ClientData clientData, /* Window for which event occurred. */ + void *clientData, /* Window for which event occurred. */ XEvent *eventPtr) /* Event that just happened. */ { TkWindow *winPtr = (TkWindow *)clientData; @@ -4188,7 +4786,7 @@ TopLevelReqProc( static void UpdateGeometryInfo( - ClientData clientData) /* Pointer to the window's record. */ + void *clientData) /* Pointer to the window's record. */ { TkWindow *winPtr = (TkWindow *)clientData; WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -4317,7 +4915,7 @@ UpdateGeometryInfo( */ if (Tk_IsEmbedded(winPtr)) { - TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); + Tk_Window contWinPtr = Tk_GetOtherWindow((Tk_Window)winPtr); /* * TODO: Here we should handle out of process embedding. @@ -4334,7 +4932,7 @@ UpdateGeometryInfo( wmPtr->x = wmPtr->y = 0; wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y); - Tk_GeometryRequest((Tk_Window)contWinPtr, width, height); + Tk_GeometryRequest(contWinPtr, width, height); } return; } @@ -4607,29 +5205,8 @@ Tk_GetRootCoords( break; } - otherPtr = TkpGetOtherWindow(winPtr); + otherPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr); if (otherPtr == NULL) { - if (tkMacOSXEmbedHandler->getOffsetProc != NULL) { - Point theOffset; - - /* - * We do not require that the changes.x & changes.y for a - * non-Tk container window be kept up to date. So we - * first subtract off the possibly bogus values that have - * been added on at the top of this pass through the - * loop, and then call out to the getOffsetProc to give - * us the correct offset. - */ - - x -= winPtr->changes.x + winPtr->changes.border_width; - y -= winPtr->changes.y + winPtr->changes.border_width; - - tkMacOSXEmbedHandler->getOffsetProc((Tk_Window)winPtr, - &theOffset); - - x += theOffset.h; - y += theOffset.v; - } break; } @@ -4711,7 +5288,7 @@ Tk_CoordsToWindow( */ if (Tk_IsContainer(winPtr)) { - childPtr = TkpGetOtherWindow(winPtr); + childPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr); if (childPtr != NULL) { if (Tk_IsMapped(childPtr)) { tmpx = x - childPtr->changes.x; @@ -4805,7 +5382,7 @@ Tk_TopCoordsToWindow( */ if (Tk_IsContainer(winPtr)) { - childPtr = TkpGetOtherWindow(winPtr); + childPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr); if (childPtr != NULL) { if (Tk_IsMapped(childPtr) && x > childPtr->changes.x && @@ -5424,7 +6001,7 @@ TkSetWMName( return; } - NSString *title = [[TKNSString alloc] initWithTclUtfBytes:titleUid length:-1]; + NSString *title = [[TKNSString alloc] initWithTclUtfBytes:titleUid length:TCL_INDEX_NONE]; [TkMacOSXGetNSWindowForDrawable(winPtr->window) setTitle:title]; [title release]; } @@ -5617,16 +6194,16 @@ TkMacOSXZoomToplevel( int TkUnsupported1ObjCmd( - ClientData clientData, /* Main window associated with interpreter. */ + void *clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const subcmds[] = { - "style", "tabbingid", "appearance", "isdark", NULL + "appearance", "isdark", "style", NULL }; enum SubCmds { - TKMWS_STYLE, TKMWS_TABID, TKMWS_APPEARANCE, TKMWS_ISDARK + TKMWS_APPEARANCE, TKMWS_ISDARK, TKMWS_STYLE }; Tk_Window tkwin = (Tk_Window)clientData; TkWindow *winPtr; @@ -5660,22 +6237,10 @@ TkUnsupported1ObjCmd( return TCL_ERROR; } return WmWinStyle(interp, winPtr, objc, objv); - case TKMWS_TABID: - if ([NSApp macOSVersion] < 101200) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "Tabbing identifiers did not exist until OSX 10.12.", -1)); - Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "TABBINGID", NULL); - return TCL_ERROR; - } - if ((objc < 3) || (objc > 4)) { - Tcl_WrongNumArgs(interp, 2, objv, "window ?newid?"); - return TCL_ERROR; - } - return WmWinTabbingId(interp, winPtr, objc, objv); case TKMWS_APPEARANCE: if ([NSApp macOSVersion] < 100900) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "Window appearances did not exist until OSX 10.9.", -1)); + "Window appearances did not exist until OSX 10.9.", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL); return TCL_ERROR; } @@ -5726,7 +6291,7 @@ static int WmWinStyle( Tcl_Interp *interp, /* Current interpreter. */ TkWindow *winPtr, /* Window to be manipulated. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj * const objv[]) /* Argument objects. */ { struct StrIntMap { @@ -5798,7 +6363,7 @@ WmWinStyle( }; int index; - int i; + Tcl_Size i; WmInfo *wmPtr = winPtr->wmInfoPtr; if (objc == 3) { @@ -5807,7 +6372,7 @@ WmWinStyle( for (i = 0; classMap[i].strValue != NULL; i++) { if (wmPtr->macClass == classMap[i].intValue) { - newResult = Tcl_NewStringObj(classMap[i].strValue, -1); + newResult = Tcl_NewStringObj(classMap[i].strValue, TCL_INDEX_NONE); break; } } @@ -5832,13 +6397,13 @@ WmWinStyle( for (i = 0; attrMap[i].strValue != NULL; i++) { if (attributes & attrMap[i].intValue) { Tcl_ListObjAppendElement(NULL, attributeList, - Tcl_NewStringObj(attrMap[i].strValue, -1)); + Tcl_NewStringObj(attrMap[i].strValue, TCL_INDEX_NONE)); } } Tcl_ListObjAppendElement(NULL, newResult, attributeList); Tcl_SetObjResult(interp, newResult); } else { - int attrObjc; + Tcl_Size attrObjc; Tcl_Obj **attrObjv = NULL; WindowClass macClass; UInt64 oldAttributes = wmPtr->attributes; @@ -5891,87 +6456,6 @@ WmWinStyle( /* *---------------------------------------------------------------------- * - * WmWinTabbingId -- - * - * This procedure is invoked to process the - * "::tk::unsupported::MacWindowStyle tabbingid" subcommand. The command - * allows you to get or set the tabbingIdentifier for the NSWindow - * associated with a Tk Window. The syntax is: - * - * tk::unsupported::MacWindowStyle tabbingid window ?newId? - * - * Results: - * Returns the tabbingIdentifier of the window prior to calling this - * function. If the optional newId argument is omitted, the window's - * tabbingIdentifier is not changed. - * - * Side effects: - * Windows may only be grouped together as tabs if they all have the same - * tabbingIdentifier. In particular, by giving a window a unique - * tabbingIdentifier one can prevent it from becoming a tab in any other - * window. Changing the tabbingIdentifier of a window which is already - * a tab causes it to become a separate window. - * - *---------------------------------------------------------------------- - */ - -static int -WmWinTabbingId( - Tcl_Interp *interp, /* Current interpreter. */ - TkWindow *winPtr, /* Window to be manipulated. */ - int objc, /* Number of arguments. */ - Tcl_Obj * const objv[]) /* Argument objects. */ -{ -#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 - (void) interp; - (void) winPtr; - (void) objc; - (void) objv; - return TCL_OK; -#else - Tcl_Obj *result = NULL; - NSString *idString; - NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window); - if (win) { - idString = win.tabbingIdentifier; - result = Tcl_NewStringObj(idString.UTF8String, [idString length]); - } - if (result == NULL) { - NSLog(@"Failed to read tabbing identifier; try calling update idletasks" - " before getting/setting the tabbing identifier of the window."); - return TCL_OK; - } - Tcl_SetObjResult(interp, result); - if (objc == 3) { - return TCL_OK; - } else if (objc == 4) { - int len; - char *newId = Tcl_GetStringFromObj(objv[3], &len); - NSString *newIdString = [NSString stringWithUTF8String:newId]; - [win setTabbingIdentifier: newIdString]; - - /* - * If the tabbingIdentifier of a tab is changed we also turn it into a - * separate window so we don't violate the rule that all tabs in the - * same frame must have the same tabbingIdentifier. - */ - - if ([idString compare:newIdString] != NSOrderedSame -#if MAC_OS_X_VERSION_MIN_REQUIRED > 101200 - && [win tab] -#endif - ) { - [win moveTabToNewWindow:nil]; - } - return TCL_OK; - } - return TCL_ERROR; -#endif -} - -/* - *---------------------------------------------------------------------- - * * WmWinAppearance -- * * This procedure is invoked to process the @@ -6004,7 +6488,7 @@ static int WmWinAppearance( Tcl_Interp *interp, /* Current interpreter. */ TkWindow *winPtr, /* Window to be manipulated. */ - int objc, /* Number of arguments. */ + Tcl_Size objc, /* Number of arguments. */ Tcl_Obj * const objv[]) /* Argument objects. */ { #if MAC_OS_X_VERSION_MAX_ALLOWED <= 1090 @@ -6014,12 +6498,6 @@ WmWinAppearance( (void) objv; return TCL_OK; #else - static const char *const appearanceStrings[] = { - "aqua", "darkaqua", "auto", NULL - }; - enum appearances { - APPEARANCE_AQUA, APPEARANCE_DARKAQUA, APPEARANCE_AUTO - }; Tcl_Obj *result = NULL; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 NSAppearanceName appearance; @@ -6138,7 +6616,14 @@ TkMacOSXMakeRealWindowExist( WmInfo *wmPtr = winPtr->wmInfoPtr; MacDrawable *macWin; WindowClass macClass; + Class winClass = nil; Bool overrideRedirect = Tk_Attributes((Tk_Window)winPtr)->override_redirect; + Tcl_HashEntry *hPtr = NULL; + NSUInteger styleMask; + NSString *identifier; + char *tabbingId = NULL; + long tabbingMode = NSWindowTabbingModeAutomatic; + static int initialized = 0; if (TkMacOSXHostToplevelExists(winPtr)) { return; @@ -6152,7 +6637,7 @@ TkMacOSXMakeRealWindowExist( */ if (Tk_IsEmbedded(winPtr)) { - TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); + TkWindow *contWinPtr = (TkWindow *)Tk_GetOtherWindow((Tk_Window)winPtr); if (contWinPtr != NULL) { TkMacOSXMakeRealWindowExist( @@ -6161,14 +6646,7 @@ TkMacOSXMakeRealWindowExist( return; } - if (tkMacOSXEmbedHandler == NULL) { - Tcl_Panic("TkMacOSXMakeRealWindowExist could not find container"); - } - if (tkMacOSXEmbedHandler->containerExistProc && - tkMacOSXEmbedHandler->containerExistProc((Tk_Window)winPtr) - != TCL_OK) { - Tcl_Panic("ContainerExistProc could not make container"); - } + Tcl_Panic("TkMacOSXMakeRealWindowExist could not find container"); return; /* @@ -6176,51 +6654,119 @@ TkMacOSXMakeRealWindowExist( */ } - /* - * If this is an override-redirect window, the NSWindow is created first as - * a document window then converted to a simple window. - */ + if ([NSApp macOSVersion] >= 101300) { + /* + * Prior to macOS 10.12 the styleMask was readonly. From macOS 10.12 + * onward, the styleMask can replace the Carbon window classes and + * attributes. + */ + int index; + if (!initialized) { + Tcl_InitHashTable(&pathnameToSubclass, TCL_STRING_KEYS); + Tcl_InitHashTable(&pathnameToTabbingId, TCL_STRING_KEYS); + Tcl_InitHashTable(&pathnameToTabbingMode, TCL_STRING_KEYS); + initialized = 1; + } + hPtr = Tcl_FindHashEntry(&pathnameToSubclass, Tk_PathName(winPtr)); + index = hPtr ? PTR2INT(Tcl_GetHashValue(hPtr)) : subclassNSWindow; + switch(index) { + case subclassNSPanel: + winClass = [TKPanel class]; + styleMask = (NSWindowStyleMaskTitled | + NSWindowStyleMaskClosable | + NSWindowStyleMaskResizable | + NSWindowStyleMaskUtilityWindow | + NSWindowStyleMaskNonactivatingPanel ); + break; + default: + winClass = [TKWindow class]; + styleMask = (NSWindowStyleMaskTitled | + NSWindowStyleMaskClosable | + NSWindowStyleMaskMiniaturizable | + NSWindowStyleMaskResizable ); + break; + } + if (overrideRedirect) { + styleMask |= NSWindowStyleMaskDocModalWindow; + } + /* Help windows (used for tooltips) should have stylemask 0. */ + if (wmPtr->macClass == kHelpWindowClass) { + styleMask = 0; + } + if (hPtr) { + Tcl_DeleteHashEntry(hPtr); + } + hPtr = Tcl_FindHashEntry(&pathnameToTabbingId, Tk_PathName(winPtr)); + if (hPtr) { + tabbingId = (char *)Tcl_GetHashValue(hPtr); + Tcl_DeleteHashEntry(hPtr); + } + hPtr = Tcl_FindHashEntry(&pathnameToTabbingMode, Tk_PathName(winPtr)); + if (hPtr) { + tabbingMode = PTR2INT(Tcl_GetHashValue(hPtr)); + Tcl_DeleteHashEntry(hPtr); + } + } else { - if (overrideRedirect) { - wmPtr->macClass = kDocumentWindowClass; - } - macClass = wmPtr->macClass; - wmPtr->attributes &= (tkAlwaysValidAttributes | - macClassAttrs[macClass].validAttrs); - wmPtr->flags |= macClassAttrs[macClass].flags | + /* + * If this is an override-redirect window, the NSWindow is created first as + * a document window then converted to a simple window. + */ + + if (overrideRedirect) { + wmPtr->macClass = kDocumentWindowClass; + } + macClass = wmPtr->macClass; + wmPtr->attributes &= (tkAlwaysValidAttributes | + macClassAttrs[macClass].validAttrs); + wmPtr->flags |= macClassAttrs[macClass].flags | ((wmPtr->attributes & kWindowResizableAttribute) ? 0 : - WM_WIDTH_NOT_RESIZABLE|WM_HEIGHT_NOT_RESIZABLE); - UInt64 attributes = (wmPtr->attributes & - ~macClassAttrs[macClass].forceOffAttrs) | + WM_WIDTH_NOT_RESIZABLE|WM_HEIGHT_NOT_RESIZABLE); + UInt64 attributes = (wmPtr->attributes & + ~macClassAttrs[macClass].forceOffAttrs) | macClassAttrs[macClass].forceOnAttrs; - NSUInteger styleMask = macClassAttrs[macClass].styleMask | - ((attributes & kWindowNoTitleBarAttribute) ? 0 : NSTitledWindowMask) | - ((attributes & kWindowCloseBoxAttribute) ? NSClosableWindowMask : 0) | - ((attributes & kWindowCollapseBoxAttribute) ? - NSMiniaturizableWindowMask : 0) | - ((attributes & kWindowResizableAttribute) ? NSResizableWindowMask : 0) | - ((attributes & kWindowMetalAttribute) ? - NSTexturedBackgroundWindowMask : 0) | - ((attributes & kWindowUnifiedTitleAndToolbarAttribute) ? - NSUnifiedTitleAndToolbarWindowMask : 0) | - ((attributes & kWindowSideTitlebarAttribute) ? 1 << 9 : 0) | - (attributes >> WM_NSMASK_SHIFT); - Class winClass = (macClass == kDrawerWindowClass ? [TKDrawerWindow class] : - (styleMask & (NSUtilityWindowMask|NSDocModalWindowMask| - NSNonactivatingPanelMask|NSHUDWindowMask)) ? [TKPanel class] : - [TKWindow class]); + styleMask = macClassAttrs[macClass].styleMask | + ((attributes & kWindowNoTitleBarAttribute) ? 0 : NSTitledWindowMask) | + ((attributes & kWindowCloseBoxAttribute) ? NSClosableWindowMask : 0) | + ((attributes & kWindowCollapseBoxAttribute) ? + NSMiniaturizableWindowMask : 0) | + ((attributes & kWindowResizableAttribute) ? NSResizableWindowMask : 0) | + ((attributes & kWindowMetalAttribute) ? + NSTexturedBackgroundWindowMask : 0) | + ((attributes & kWindowUnifiedTitleAndToolbarAttribute) ? + NSUnifiedTitleAndToolbarWindowMask : 0) | + ((attributes & kWindowSideTitlebarAttribute) ? 1 << 9 : 0) | + (attributes >> WM_NSMASK_SHIFT); + winClass = (macClass == kDrawerWindowClass ? [TKDrawerWindow class] : + (styleMask & (NSUtilityWindowMask|NSDocModalWindowMask| + NSNonactivatingPanelMask|NSHUDWindowMask)) ? + [TKPanel class] : [TKWindow class]); + } NSRect structureRect = [winClass frameRectForContentRect:NSZeroRect styleMask:styleMask]; NSRect contentRect = NSMakeRect(5 - structureRect.origin.x, TkMacOSXZeroScreenHeight() - (TkMacOSXZeroScreenTop() + 5 + structureRect.origin.y + structureRect.size.height + 200), 200, 200); if (wmPtr->hints.initial_state == WithdrawnState) { + //// ??????? } TKWindow *window = [[winClass alloc] initWithContentRect:contentRect styleMask:styleMask backing:NSBackingStoreBuffered defer:YES]; if (!window) { Tcl_Panic("couldn't allocate new Mac window"); } +#if MAC_OS_X_VERSION_MAX_ALLOWED > 101200 + if (tabbingId) { + identifier = [NSString stringWithUTF8String:tabbingId]; + } else { + identifier = [NSString stringWithUTF8String:Tk_PathName(winPtr)]; + } + [window setTabbingIdentifier: identifier]; + [window setTabbingMode: tabbingMode]; +#endif + if (tabbingId) { + ckfree(tabbingId); + } TKContentView *contentView = [[TKContentView alloc] initWithFrame:NSZeroRect]; #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 @@ -6272,7 +6818,11 @@ TkMacOSXMakeRealWindowExist( atts.override_redirect = True; Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts); - ApplyContainerOverrideChanges(winPtr, NULL); + if ([NSApp macOSVersion] >= 101300) { + window.styleMask |= NSWindowStyleMaskDocModalWindow; + } else { + ApplyContainerOverrideChanges(winPtr, NULL); + } } [window display]; } |