diff options
author | culler <culler> | 2023-01-28 21:17:09 (GMT) |
---|---|---|
committer | culler <culler> | 2023-01-28 21:17:09 (GMT) |
commit | a0af2d9146b4ac1bded38cb44b1ef3f75c8de8c6 (patch) | |
tree | 3f15bcc65677ab4fbb6788fdb353b9604a73c850 /macosx | |
parent | fc8e9734ff0e11d124a033cdfed77fb3b8553bd8 (diff) | |
download | tk-a0af2d9146b4ac1bded38cb44b1ef3f75c8de8c6.zip tk-a0af2d9146b4ac1bded38cb44b1ef3f75c8de8c6.tar.gz tk-a0af2d9146b4ac1bded38cb44b1ef3f75c8de8c6.tar.bz2 |
Implementation of TIP 655
Diffstat (limited to 'macosx')
-rw-r--r-- | macosx/tkMacOSXMouseEvent.c | 11 | ||||
-rw-r--r-- | macosx/tkMacOSXPrivate.h | 3 | ||||
-rw-r--r-- | macosx/tkMacOSXSubwindows.c | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.c | 453 |
4 files changed, 399 insertions, 70 deletions
diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 53292b3..7be71de 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -88,7 +88,7 @@ enum { NSEventType eventType = [theEvent type]; TKContentView *contentView = [eventWindow contentView]; NSPoint location = [theEvent locationInWindow]; - NSPoint viewLocation = [contentView convertPoint:location fromView:nil]; + //NSPoint viewLocation = [contentView convertPoint:location fromView:nil]; TkWindow *winPtr = NULL, *grabWinPtr, *scrollTarget = NULL; Tk_Window tkwin = NULL, capture, target; NSPoint local, global; @@ -117,7 +117,8 @@ enum { * window attribute set to nil. */ - if (![eventWindow isMemberOfClass:[TKWindow class]]) { + if (![eventWindow isMemberOfClass:[TKWindow class]] && + ![eventWindow isMemberOfClass:[TKPanel class]]) { if ([theEvent timestamp] == 0) { isTestingEvent = YES; eventWindow = [NSApp keyWindow]; @@ -130,7 +131,7 @@ enum { if (!isTestingEvent && !isMotionEvent) { return theEvent; } - } else if (!NSPointInRect(viewLocation, [contentView bounds])) { + } else if (!NSPointInRect(location, [contentView bounds])) { isOutside = YES; } button = [theEvent buttonNumber] + Button1; @@ -246,10 +247,10 @@ enum { NSRect bounds = [contentView bounds]; NSRect grip = NSMakeRect(bounds.size.width - 10, 0, 10, 10); bounds = NSInsetRect(bounds, 2.0, 2.0); - if (!NSPointInRect(viewLocation, bounds)) { + if (!NSPointInRect(location, bounds)) { return theEvent; } - if (NSPointInRect(viewLocation, grip)) { + if (NSPointInRect(location, grip)) { return theEvent; } if ([NSApp tkLiveResizeEnded]) { diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 71cceb9..d7cf540 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -465,6 +465,9 @@ VISIBILITY_HIDDEN @property Window tkWindow; @end +@interface TKPanel(TKWm) +- (void) tkLayoutChanged; +@end #pragma mark NSMenu & NSMenuItem Utilities @interface NSMenu(TKUtils) diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 49778ef..ae2b149 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -403,7 +403,7 @@ XResizeWindow( if (w) { if ([w styleMask] & NSFullScreenWindowMask) { - [w tkLayoutChanged]; + [(TKWindow *)w tkLayoutChanged]; } else { NSRect r = [w contentRectForFrameRect:[w frame]]; diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 5feb6e4..ac57be7 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -37,7 +37,7 @@ */ /* - * Window attributes and classes + * Carbon window attributes and classes. */ #define WM_NSMASK_SHIFT 36 @@ -150,19 +150,85 @@ static const struct { (macClassAttrs[(class)].forceOnAttrs & ~kWindowResizableAttribute))) /* - * Data for [wm attributes] command: + * Structures and data for the wm attributes command (macOS 10.12 and later): */ +enum NSWindowSubclass { + subclassNSWindow = 0, + subclassNSPanel = 1 +}; +/* This array must be indexed by the enum above.*/ +static const char *subclassNames[] = {"nswindow", "nspanel", NULL}; +static Tcl_HashTable pathnameToSubclass; + +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 >= 101200 +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, 0} +}; +#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_BUTTONS, WMATT_FULLSCREEN, WMATT_MODIFIED, WMATT_NOTIFY, + WMATT_TITLEPATH, WMATT_TOPMOST, WMATT_TRANSPARENT, WMATT_STYLEMASK, WMATT_TYPE, + _WMATT_LAST_ATTRIBUTE } WmAttribute; static const char *const WmAttributeNames[] = { - "-alpha", "-fullscreen", "-modified", "-notify", - "-titlepath", "-topmost", "-transparent", - "-type", NULL + "-alpha", "-buttons", "-fullscreen", "-modified", "-notify", "-titlepath", + "-topmost", "-transparent", "-stylemask", "-type", NULL }; /* @@ -193,7 +259,7 @@ 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, @@ -345,19 +411,71 @@ static void RemoveTransient(TkWindow *winPtr); NSRect pointrect = {point, {0,0}}; return [self convertRectToScreen:pointrect].origin; } +/* + * 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; + frameRect = [NSWindow frameRectForContentRect:NSZeroRect + styleMask:[self styleMask]]; + WmInfo *wmPtr = winPtr->wmInfoPtr; + + // The parent included the titlebar and window frame. + 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; + } +} - (NSPoint) tkConvertPointFromScreen: (NSPoint)point { NSRect pointrect = {point, {0,0}}; return [self convertRectFromScreen:pointrect].origin; } #endif - @end #pragma mark - @implementation TKPanel: NSPanel @synthesize tkWindow = _tkWindow; + +/* + * 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; + frameRect = [NSWindow frameRectForContentRect:NSZeroRect + styleMask:[self styleMask]]; + WmInfo *wmPtr = winPtr->wmInfoPtr; + + // The parent included the titlebar and window frame. + 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; + } +} @end @implementation TKDrawerWindow: NSWindow @@ -387,21 +505,11 @@ static void RemoveTransient(TkWindow *winPtr); 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 + frameRect = [NSWindow frameRectForContentRect:NSZeroRect styleMask:[self styleMask]]; - } else { - frameRect = [self frameRectForContentRect:NSZeroRect]; - } - WmInfo *wmPtr = winPtr->wmInfoPtr; + // The parent included the titlebar and window frame. wmPtr->xInParent = -frameRect.origin.x; wmPtr->yInParent = frameRect.origin.y + frameRect.size.height; wmPtr->parentWidth = winPtr->changes.width + frameRect.size.width; @@ -727,6 +835,8 @@ TkWmNewWindow( wmPtr->window = nil; winPtr->wmInfoPtr = wmPtr; + // initialize wmPtr->NSWindowSubclass here + UpdateVRootGeometry(wmPtr); /* @@ -1213,11 +1323,26 @@ Tk_WmObjCmd( goto wrongNumArgs; } - if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr) + if (index == WMOPT_ATTRIBUTES && objc == 5 && + strcmp(Tcl_GetString(objv[3]), "-type") == 0) { + if (TkGetWindowFromObj(NULL, tkwin, objv[2], (Tk_Window *) &winPtr) + == TCL_OK) { + if (winPtr->wmInfoPtr->window != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "Cannot change type after the mac window is created.",-1)); + Tcl_SetErrorCode(interp, "TK", "TYPE_CHANGE", NULL); + return TCL_ERROR; + } else { + fprintf(stderr, "Setting type for %s\n", Tk_PathName(winPtr)); + } + } else { + winPtr = NULL; + } + } else if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr) != TCL_OK) { - return TCL_ERROR; + return TCL_ERROR; } - if (!Tk_IsTopLevel(winPtr) + if (winPtr && !Tk_IsTopLevel(winPtr) && (index != WMOPT_MANAGE) && (index != WMOPT_FORGET)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "window \"%s\" isn't a top-level window", winPtr->pathName)); @@ -1418,6 +1543,34 @@ WmSetAttribute( [macWindow setAlphaValue:dval]; 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) { return TCL_ERROR; @@ -1455,6 +1608,71 @@ WmSetAttribute( tkMacOSXWmAttrNotifyVal = boolean; } 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; + } + } + 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]; +#if 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; + if ([macWindow respondsToSelector: @selector (tkLayoutChanged)]) { + [(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_TITLEPATH: { const char *path = (const char *)Tcl_FSGetNativePath(value); NSString *filename = @""; @@ -1504,9 +1722,11 @@ WmSetAttribute( TK_PARENT_WINDOW); } break; - case WMATT_TYPE: - TKLog(@"The type attribute is ignored on macOS."); + case WMATT_TYPE: { + char *subclass = Tcl_GetString(value); + fprintf(stderr, "Setting subclass %s for %s\n", subclass, Tk_PathName(winPtr)); break; + } case _WMATT_LAST_ATTRIBUTE: default: return TCL_ERROR; @@ -1538,6 +1758,19 @@ WmGetAttribute( case WMATT_ALPHA: result = Tcl_NewDoubleObj([macWindow alphaValue]); break; + case WMATT_BUTTONS: { + result = Tcl_NewListObj(3, NULL); + if ([macWindow standardWindowButton:NSWindowCloseButton].enabled) { + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj("close", -1)); + } + if ([macWindow standardWindowButton:NSWindowMiniaturizeButton].enabled) { + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj("miniaturize", -1)); + } + if ([macWindow standardWindowButton:NSWindowZoomButton].enabled) { + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj("zoom", -1)); + } + break; + } case WMATT_FULLSCREEN: result = Tcl_NewBooleanObj([macWindow styleMask] & NSFullScreenWindowMask); break; @@ -1547,6 +1780,18 @@ WmGetAttribute( 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, -1)); + } + } + break; + } case WMATT_TITLEPATH: result = Tcl_NewStringObj([[macWindow representedFilename] UTF8String], -1); @@ -1558,7 +1803,11 @@ WmGetAttribute( result = Tcl_NewBooleanObj(wmPtr->flags & WM_TRANSPARENT); break; case WMATT_TYPE: - result = Tcl_NewStringObj("unsupported", -1); + if ([macWindow isKindOfClass:[NSPanel class]]) { + result = Tcl_NewStringObj(subclassNames[subclassNSPanel], -1); + } else { + result = Tcl_NewStringObj(subclassNames[subclassNSWindow], -1); + } break; case _WMATT_LAST_ATTRIBUTE: default: @@ -1586,7 +1835,7 @@ WmGetAttribute( static int WmAttributesCmd( - 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. */ @@ -1594,7 +1843,25 @@ WmAttributesCmd( { int attribute = 0; NSWindow *macWindow; - + if (winPtr == NULL && objc == 5 && + strcmp(Tcl_GetString(objv[3]), "-type") == 0) { + /* + * We are setting the type of a future window. We just save the type + * in a hash table so we can look it up when the window is actually + * created. + */ + int index, isNew = 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; + } + } if (winPtr->window == None) { Tk_MakeWindowExist((Tk_Window)winPtr); } @@ -3096,7 +3363,7 @@ 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. */ @@ -3122,7 +3389,15 @@ WmOverrideredirectCmd( } atts.override_redirect = flag ? True : False; Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts); - ApplyContainerOverrideChanges(winPtr, win); + if ([NSApp macOSVersion] >= 101200) { + if (flag) { + win.styleMask |= NSWindowStyleMaskDocModalWindow; + } else { + win.styleMask &= ~NSWindowStyleMaskDocModalWindow; + } + } else { + ApplyContainerOverrideChanges(winPtr, win); + } return TCL_OK; } @@ -6186,12 +6461,16 @@ 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; + static int initialized = 0; if (TkMacOSXHostToplevelExists(winPtr)) { return; } - + macWin = (MacDrawable *)winPtr->window; /* @@ -6217,48 +6496,90 @@ 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] >= 101200) { + /* + * 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); + 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; + } + if (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"); } @@ -6298,7 +6619,11 @@ TkMacOSXMakeRealWindowExist( atts.override_redirect = True; Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts); - ApplyContainerOverrideChanges(winPtr, NULL); + if ([NSApp macOSVersion] >= 101200) { + window.styleMask |= NSWindowStyleMaskDocModalWindow; + } else { + ApplyContainerOverrideChanges(winPtr, NULL); + } } [window display]; } |