summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--macosx/tkMacOSXHLEvents.c7
-rw-r--r--macosx/tkMacOSXWindowEvent.c58
-rw-r--r--macosx/tkMacOSXWm.c286
-rw-r--r--tests/unixWm.test45
-rw-r--r--tests/wm.test29
5 files changed, 305 insertions, 120 deletions
diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c
index 468e41c..9b874a5 100644
--- a/macosx/tkMacOSXHLEvents.c
+++ b/macosx/tkMacOSXHLEvents.c
@@ -93,12 +93,7 @@ static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
- ProcessSerialNumber thePSN = {0, kCurrentProcess};
- SetFrontProcess(&thePSN);
-#else
- [[NSApplication sharedApplication] activateIgnoringOtherApps: YES];
-#endif
+ [NSApp activateIgnoringOtherApps: YES];
if (_eventInterp && Tcl_FindCommand(_eventInterp,
"::tk::mac::ReopenApplication", NULL, 0)) {
int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ReopenApplication",
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index b234e72..ad6af30 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -31,7 +31,7 @@
*/
static int GenerateUpdates(HIShapeRef updateRgn,
- CGRect *updateBounds, TkWindow *winPtr);
+ CGRect *updateBounds, TkWindow *winPtr);
static int GenerateActivateEvents(TkWindow *winPtr,
int activeFlag);
static void DoWindowActivate(ClientData clientData);
@@ -69,18 +69,19 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
#endif
BOOL movedOnly = [[notification name]
isEqualToString:NSWindowDidMoveNotification];
-
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
WmInfo *wmPtr = winPtr->wmInfoPtr;
NSRect bounds = [w frame];
+ NSRect screenRect = [[w screen] frame];
int x, y, width = -1, height = -1, flags = 0;
+ int minY = 1 + [[NSApp mainMenu] menuBarHeight];
x = bounds.origin.x;
- y = tkMacOSXZeroScreenHeight - (bounds.origin.y + bounds.size.height);
- if (winPtr->changes.x != x || winPtr->changes.y != y){
+ y = screenRect.size.height - (bounds.origin.y + bounds.size.height);
+ if (winPtr->changes.x != x || winPtr->changes.y != y) {
flags |= TK_LOCATION_CHANGED;
} else {
x = y = -1;
@@ -99,8 +100,24 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
}
+
+ /*
+ * Mac windows cannot go higher than the bottom of the menu bar. The
+ * Tk window manager can request that a window be drawn so that it
+ * overlaps the menu bar, but it will actually be drawn immediately
+ * below the menu bar. In such a case it saves a lot of trouble and
+ * causes no harm if we let Tk think that the window is located at the
+ * requested point. (Many of the the tests assume that this is the
+ * case, especially for windows with upper left corner at (0,0).) So
+ * we just tell a harmless white lie here.
+ */
+
+ if (y == minY && wmPtr->y < minY) {
+ y = wmPtr->y;
+ }
TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
}
+
}
- (void) windowExpanded: (NSNotification *) notification
@@ -136,6 +153,19 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
}
}
+- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
+ defaultFrame:(NSRect)newFrame
+{
+
+ /*
+ * This method needs to be implemented in order for [NSWindow isZoomed]
+ * to give the correct answer. But it suffices to always validate
+ * every request.
+ */
+
+ return newFrame;
+}
+
- (NSSize)window:(NSWindow *)window
willUseFullScreenContentSize:(NSSize)proposedSize
{
@@ -146,7 +176,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
* be sized to the screen's visibleFrame, leaving black bands at
* the top and bottom.
*/
-
return proposedSize;
}
@@ -297,6 +326,20 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
#endif
}
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender
+ hasVisibleWindows:(BOOL)flag
+{
+ /*
+ * Allowing the default response means that withdrawn windows will get
+ * displayed on the screen with unresponsive title buttons. We don't
+ * really want that. Besides, we can write our own code to handle this
+ * with ::tk::mac::ReopenApplication. So we just say NO.
+ */
+
+ return NO;
+}
+
+
- (void) applicationShowHide: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
@@ -637,7 +680,7 @@ TkGenWMConfigureEvent(
if (flags & TK_LOCATION_CHANGED) {
wmPtr->x = x;
wmPtr->y = y;
- wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
+ //wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
}
if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) &&
((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) {
@@ -680,6 +723,7 @@ TkGenWMConfigureEvent(
}
}
+
/*
* Now set up the changes structure. Under X we wait for the
* ConfigureNotify to set these values. On the Mac we know imediatly that
@@ -968,7 +1012,7 @@ ConfigureRestrictProc(
/*
* Finally, unlock the main autoreleasePool.
*/
-
+
[NSApp _unlockAutoreleasePool];
}
}
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index 7f707b0..5cf0820 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.c
@@ -389,7 +389,7 @@ static void RemapWindows(TkWindow *winPtr,
*/
if ([self styleMask] & NSFullScreenWindowMask) {
- frameRect = [NSWindow frameRectForContentRect:NSZeroRect
+ frameRect = [NSWindow frameRectForContentRect:NSZeroRect
styleMask:[self styleMask]];
} else {
frameRect = [self frameRectForContentRect:NSZeroRect];
@@ -414,7 +414,6 @@ static void RemapWindows(TkWindow *winPtr,
}
#endif
-
- (NSSize)windowWillResize:(NSWindow *)sender
toSize:(NSSize)frameSize
{
@@ -935,7 +934,8 @@ TkWmDeadWindow(
if (title == nil) {
title = "unnamed window";
}
- printf(">>>> Closing <%s>. Count is: %lu\n", title, [window retainCount]);
+ fprintf(stderr, ">>>> Closing <%s>. Count is: %lu\n", title,
+ [window retainCount]);
}
#endif
[window close];
@@ -1736,6 +1736,7 @@ WmDeiconifyCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
+ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "window");
@@ -1758,6 +1759,12 @@ WmDeiconifyCmd(
TkpWmSetState(winPtr, TkMacOSXIsWindowZoomed(winPtr) ?
ZoomState : NormalState);
+ [win setExcludedFromWindowsMenu:NO];
+ TkMacOSXApplyWindowAttributes(winPtr, win);
+ [win orderFront:nil];
+ if (wmPtr->icon) {
+ Tk_UnmapWindow((Tk_Window)wmPtr->icon);
+ }
return TCL_OK;
}
@@ -1947,8 +1954,9 @@ WmGeometryCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
register WmInfo *wmPtr = winPtr->wmInfoPtr;
- char xSign, ySign;
- int width, height;
+ NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ char xSign = '+', ySign = '+';
+ int width, height, x = wmPtr->x, y= wmPtr->y;
char *argv3;
if ((objc != 3) && (objc != 4)) {
@@ -1956,8 +1964,6 @@ WmGeometryCmd(
return TCL_ERROR;
}
if (objc == 3) {
- xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+';
- ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+';
if (wmPtr->gridWin != NULL) {
width = wmPtr->reqGridWidth + (winPtr->changes.width
- winPtr->reqWidth)/wmPtr->widthInc;
@@ -1967,8 +1973,20 @@ WmGeometryCmd(
width = winPtr->changes.width;
height = winPtr->changes.height;
}
+ if (win) {
+ if (wmPtr->flags & WM_NEGATIVE_X) {
+ xSign = '-';
+ x = wmPtr->vRootWidth - wmPtr->x
+ - (width + (wmPtr->parentWidth - winPtr->changes.width));
+ }
+ if (wmPtr->flags & WM_NEGATIVE_Y) {
+ ySign = '-';
+ y = wmPtr->vRootHeight - wmPtr->y
+ - (height + (wmPtr->parentHeight - winPtr->changes.height));
+ }
+ }
Tcl_SetObjResult(interp, Tcl_ObjPrintf("%dx%d%c%d%c%d",
- width, height, xSign, wmPtr->x, ySign, wmPtr->y));
+ width, height, xSign, x, ySign, y));
return TCL_OK;
}
argv3 = Tcl_GetString(objv[3]);
@@ -2266,6 +2284,9 @@ WmIconifyCmd(
}
TkpWmSetState(winPtr, IconicState);
+ if (wmPtr->icon) {
+ Tk_MapWindow((Tk_Window)wmPtr->icon);
+ }
return TCL_OK;
}
@@ -2584,8 +2605,17 @@ WmIconwindowCmd(
return TCL_ERROR;
}
if (wmPtr->icon != NULL) {
- WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
+ TkWindow *oldIcon = (TkWindow *)wmPtr->icon;
+ WmInfo *wmPtr3 = oldIcon->wmInfoPtr;
+ NSWindow *win = TkMacOSXDrawableWindow(oldIcon->window);
+ /*
+ * The old icon should be withdrawn.
+ */
+
+ TkpWmSetState(oldIcon, WithdrawnState);
+ [win orderOut:nil];
+ [win setExcludedFromWindowsMenu:YES];
wmPtr3->iconFor = NULL;
}
Tk_MakeWindowExist(tkwin2);
@@ -2594,11 +2624,16 @@ WmIconwindowCmd(
wmPtr->icon = tkwin2;
wmPtr2->iconFor = (Tk_Window) winPtr;
if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
+
/*
- * Don't have iconwindows on the Mac. We just withdraw.
+ * If the window is in normal or zoomed state, the icon should be
+ * unmapped.
*/
- Tk_UnmapWindow(tkwin2);
+ if (wmPtr->hints.initial_state == NormalState ||
+ wmPtr->hints.initial_state == ZoomState) {
+ Tk_UnmapWindow(tkwin2);
+ }
}
}
return TCL_OK;
@@ -2802,8 +2837,9 @@ WmOverrideredirectCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- int boolean;
+ int flag;
XSetWindowAttributes atts;
+ TKWindow *win = (TKWindow *)TkMacOSXDrawableWindow(winPtr->window);
if ((objc != 3) && (objc != 4)) {
Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
@@ -2816,12 +2852,12 @@ WmOverrideredirectCmd(
return TCL_OK;
}
- if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) {
+ if (Tcl_GetBooleanFromObj(interp, objv[3], &flag) != TCL_OK) {
return TCL_ERROR;
}
- atts.override_redirect = (boolean) ? True : False;
+ atts.override_redirect = flag ? True : False;
Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
- ApplyMasterOverrideChanges(winPtr, NULL);
+ ApplyMasterOverrideChanges(winPtr, win);
return TCL_OK;
}
@@ -3477,6 +3513,7 @@ WmTransientCmd(
}
TkWindow* masterPtr = (TkWindow*) master;
while (!Tk_TopWinHierarchy(masterPtr)) {
+
/*
* Ensure that the master window is actually a Tk toplevel.
*/
@@ -3563,8 +3600,8 @@ WmWithdrawCmd(
return TCL_ERROR;
}
TkpWmSetState(winPtr, WithdrawnState);
- /*Remove window from Window menu.*/
NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ [win orderOut:nil];
[win setExcludedFromWindowsMenu:YES];
return TCL_OK;
@@ -3947,27 +3984,8 @@ UpdateGeometryInfo(
} else if ((max > 0) && (height > max)) {
height = max;
}
-
- /*
- * Compute the new position for the upper-left pixel of the window's
- * decorative frame. This is tricky, because we need to include the border
- * widths supplied by a reparented parent in this calculation, but can't
- * use the parent's current overall size since that may change as a result
- * of this code.
- */
-
- if (wmPtr->flags & WM_NEGATIVE_X) {
- x = wmPtr->vRootWidth - wmPtr->x
- - (width + (wmPtr->parentWidth - winPtr->changes.width));
- } else {
- x = wmPtr->x;
- }
- if (wmPtr->flags & WM_NEGATIVE_Y) {
- y = wmPtr->vRootHeight - wmPtr->y
- - (height + (wmPtr->parentHeight - winPtr->changes.height));
- } else {
- y = wmPtr->y;
- }
+ x = wmPtr->x;
+ y = wmPtr->y;
/*
* If the window's size is going to change and the window is supposed to
@@ -4128,8 +4146,8 @@ ParseGeometry(
width = wmPtr->width;
height = wmPtr->height;
- x = wmPtr->x;
- y = wmPtr->y;
+ x = -1;
+ y = -1;
flags = wmPtr->flags;
if (isdigit(UCHAR(*p))) {
width = strtoul(p, &end, 10);
@@ -4193,24 +4211,45 @@ ParseGeometry(
* Everything was parsed OK. Update the fields of *wmPtr and arrange for
* the appropriate information to be percolated out to the window manager
* at the next idle moment.
+ *
+ * Computing the new position for the upper-left pixel of the window's
+ * decorative frame is tricky because we need to include the border
+ * widths supplied by a reparented parent in the calculation, but we can't
+ * use the parent's current overall size since that may change as a result
+ * of this code.
*/
wmPtr->width = width;
wmPtr->height = height;
- if ((x != wmPtr->x) || (y != wmPtr->y)
- || ((flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y))
- != (wmPtr->flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y)))) {
- if (wmPtr->flags & WM_FULLSCREEN) {
- wmPtr->configX = x;
- wmPtr->configY = y;
- } else {
- wmPtr->x = x;
- wmPtr->y = y;
- }
- flags |= WM_MOVE_PENDING;
+ if (flags & WM_NEGATIVE_X) {
+ int borderwidth = wmPtr->parentWidth - winPtr->changes.width;
+ int newWidth = width == -1 ? winPtr->changes.width : width;
+ x = (x == -1) ?
+ wmPtr->x + winPtr->changes.width - newWidth :
+ wmPtr->vRootWidth - x - newWidth - borderwidth;
+ }
+ if (x == -1) {
+ x = wmPtr->x;
+ }
+ if (flags & WM_NEGATIVE_Y) {
+ int borderheight = wmPtr->parentHeight - winPtr->changes.height;
+ int newHeight = height == -1 ? winPtr->changes.height : height;
+ y = (y == -1) ?
+ wmPtr->y + winPtr->changes.height - newHeight :
+ wmPtr->vRootHeight - y - newHeight - borderheight;
+ }
+ if (y == -1) {
+ y = wmPtr->y;
+ }
+ if (wmPtr->flags & WM_FULLSCREEN) {
+ wmPtr->configX = x;
+ wmPtr->configY = y;
+ } else {
+ wmPtr->x = x;
+ wmPtr->y = y;
}
+ flags |= WM_MOVE_PENDING;
wmPtr->flags = flags;
-
if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr);
wmPtr->flags |= WM_UPDATE_PENDING;
@@ -4671,7 +4710,7 @@ Tk_MoveToplevelWindow(
wmPtr->x = x;
wmPtr->y = y;
wmPtr->flags |= WM_MOVE_PENDING;
- wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
+ // wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
if (!(wmPtr->sizeHintsFlags & (USPosition|PPosition))) {
wmPtr->sizeHintsFlags |= USPosition;
wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
@@ -5199,7 +5238,8 @@ MODULE_SCOPE int
TkMacOSXIsWindowZoomed(
TkWindow *winPtr)
{
- return [TkMacOSXDrawableWindow(winPtr->window) isZoomed];
+ NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ return [macWindow isZoomed];
}
@@ -5244,13 +5284,13 @@ TkMacOSXZoomToplevel(
* Do nothing if already in desired zoom state.
*/
- if ((![window isZoomed] == (zoomPart == inZoomIn))) {
+ if (([window isZoomed] == (zoomPart == inZoomOut))) {
return false;
}
- [window zoom:NSApp];
+ [window zoom:NSApp];
- wmPtr->hints.initial_state =
- (zoomPart == inZoomIn ? NormalState : ZoomState);
+ wmPtr->hints.initial_state =
+ (zoomPart == inZoomIn ? NormalState : ZoomState);
return true;
}
@@ -5424,21 +5464,6 @@ WmWinStyle(
{ "moveToActiveSpace", tkMoveToActiveSpaceAttribute },
{ "nonActivating", tkNonactivatingPanelAttribute },
{ "hud", tkHUDWindowAttribute },
- { "black", 0 },
- { "dark", 0 },
- { "light", 0 },
- { "gray", 0 },
- { "red", 0 },
- { "green", 0 },
- { "blue", 0 },
- { "cyan", 0 },
- { "yellow", 0 },
- { "magenta", 0 },
- { "orange", 0 },
- { "purple", 0 },
- { "brown", 0 },
- { "clear", 0 },
- { "opacity", 0 },
{ NULL }
};
@@ -5520,10 +5545,8 @@ WmWinStyle(
macClassAttrs[macClass].validAttrs);
wmPtr->flags |= macClassAttrs[macClass].flags;
wmPtr->macClass = macClass;
-
ApplyWindowAttributeFlagChanges(winPtr, NULL, oldAttributes, oldFlags,
0, 1);
-
return TCL_OK;
badClassAttrs:
@@ -5664,6 +5687,8 @@ TkMacOSXMakeRealWindowExist(
{
WmInfo *wmPtr = winPtr->wmInfoPtr;
MacDrawable *macWin;
+ WindowClass macClass;
+ Bool overrideRedirect = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
if (TkMacOSXHostToplevelExists(winPtr)) {
return;
@@ -5700,7 +5725,16 @@ TkMacOSXMakeRealWindowExist(
* TODO: Here we should handle out of process embedding.
*/
}
- WindowClass macClass = wmPtr->macClass;
+
+ /*
+ * 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 |
@@ -5753,12 +5787,10 @@ TkMacOSXMakeRealWindowExist(
*/
[window setMovableByWindowBackground:NO];
}
-
[window setDocumentEdited:NO];
wmPtr->window = window;
macWin->view = window.contentView;
TkMacOSXApplyWindowAttributes(winPtr, window);
-
NSRect geometry = InitialWindowBounds(winPtr, window);
geometry.size.width += structureRect.size.width;
geometry.size.height += structureRect.size.height;
@@ -5766,7 +5798,14 @@ TkMacOSXMakeRealWindowExist(
geometry.size.height);
[window setFrame:geometry display:YES];
TkMacOSXRegisterOffScreenWindow((Window) macWin, window);
+
macWin->flags |= TK_HOST_EXISTS;
+ if (overrideRedirect) {
+ XSetWindowAttributes atts;
+ atts.override_redirect = True;
+ Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
+ ApplyMasterOverrideChanges(winPtr, NULL);
+ }
}
/*
@@ -6474,21 +6513,35 @@ ApplyWindowAttributeFlagChanges(
* This behavior, which makes the green button expand a window to
* full screen, was included in the default as of OSX 10.13. For
* uniformity we use the new default in all versions of the OS
- * where the behavior exists.
+ * after 10.10.
*/
-#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
+#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101000)
if (!(macWindow.styleMask & NSUtilityWindowMask)) {
- NSSize screenSize = [[macWindow screen]frame].size;
- b |= NSWindowCollectionBehaviorFullScreenPrimary;
- /* The default max size has height less than the screen height.
- * This causes the window manager to refuse to allow the window
- * to be resized when it is a split window. To work around
- * this we make the max size equal to the screen size.
+ /*
+ * Exclude overrideredirect, transient, and "help"-styled
+ * windows from moving into their own fullscreen space.
+ *
*/
-
- [macWindow setMaxFullScreenContentSize:screenSize];
+
+ if ((winPtr->atts.override_redirect) ||
+ (wmPtr->master != None) ||
+ (winPtr->wmInfoPtr->macClass == kHelpWindowClass)) {
+ b |= (NSWindowCollectionBehaviorCanJoinAllSpaces |
+ NSWindowCollectionBehaviorFullScreenAuxiliary);
+ } else {
+ NSSize screenSize = [[macWindow screen]frame].size;
+ b |= NSWindowCollectionBehaviorFullScreenPrimary;
+
+ /* The default max size has height less than the screen height.
+ * This causes the window manager to refuse to allow the window
+ * to be resized when it is a split window. To work around
+ * this we make the max size equal to the screen size.
+ */
+
+ [macWindow setMaxFullScreenContentSize:screenSize];
+ }
}
#endif
@@ -6548,6 +6601,14 @@ ApplyMasterOverrideChanges(
WmInfo *wmPtr = winPtr->wmInfoPtr;
UInt64 oldAttributes = wmPtr->attributes;
int oldFlags = wmPtr->flags;
+ unsigned long styleMask;
+ NSRect structureRect;
+
+ if (!macWindow && winPtr->window != None &&
+ TkMacOSXHostToplevelExists(winPtr)) {
+ macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ }
+ styleMask = [macWindow styleMask];
/*
* FIX: We need an UpdateWrapper equivalent to make this 100% correct
@@ -6559,6 +6620,11 @@ ApplyMasterOverrideChanges(
wmPtr->attributes = macClassAttrs[kSimpleWindowClass].defaultAttrs;
}
wmPtr->attributes |= kWindowNoActivatesAttribute;
+ if ([NSApp macMinorVersion] == 6) {
+ styleMask = 0;
+ } else {
+ styleMask &= ~NSTitledWindowMask;
+ }
} else {
if (wmPtr->macClass == kSimpleWindowClass &&
oldAttributes == kWindowNoActivatesAttribute) {
@@ -6567,18 +6633,50 @@ ApplyMasterOverrideChanges(
macClassAttrs[kDocumentWindowClass].defaultAttrs;
}
wmPtr->attributes &= ~kWindowNoActivatesAttribute;
- }
- if (!macWindow && winPtr->window != None &&
- TkMacOSXHostToplevelExists(winPtr)) {
- macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ if ([NSApp macMinorVersion] == 6) {
+ styleMask = NSTitledWindowMask |
+ NSClosableWindowMask |
+ NSMiniaturizableWindowMask |
+ NSResizableWindowMask;
+ } else {
+ styleMask |= NSTitledWindowMask;
+ }
}
if (macWindow) {
- if (winPtr->atts.override_redirect && wmPtr->master != None) {
- wmPtr->flags |= WM_TOPMOST;
+ NSWindow *parentWindow = [macWindow parentWindow];
+ structureRect = [NSWindow frameRectForContentRect:NSZeroRect
+ styleMask:styleMask];
+
+ /*
+ * Synchronize the wmInfoPtr to match the new window configuration
+ * so windowBoundsChanged won't corrupt the window manager info.
+ */
+
+ wmPtr->xInParent = -structureRect.origin.x;
+ wmPtr->yInParent = structureRect.origin.y + structureRect.size.height;
+ wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width;
+ wmPtr->parentHeight = winPtr->changes.height + structureRect.size.height;
+ if (winPtr->atts.override_redirect) {
+ [macWindow setExcludedFromWindowsMenu:YES];
+ [macWindow setStyleMask:styleMask];
+ if (wmPtr->hints.initial_state == NormalState) {
+ [macWindow orderFront:nil];
+ }
+ if (wmPtr->master != None) {
+ wmPtr->flags |= WM_TOPMOST;
+ } else {
+ wmPtr->flags &= ~WM_TOPMOST;
+ }
} else {
+ const char *title = winPtr->wmInfoPtr->titleUid;
+ if (!title) {
+ title = winPtr->nameUid;
+ }
+ [macWindow setStyleMask:styleMask];
+ [macWindow setTitle:[NSString stringWithUTF8String:title]];
+ [macWindow setExcludedFromWindowsMenu:NO];
wmPtr->flags &= ~WM_TOPMOST;
}
- NSWindow *parentWindow = [macWindow parentWindow];
if (wmPtr->master != None) {
TkDisplay *dispPtr = TkGetDisplayList();
TkWindow *masterWinPtr = (TkWindow *)
diff --git a/tests/unixWm.test b/tests/unixWm.test
index d579fc7..a0224a1 100644
--- a/tests/unixWm.test
+++ b/tests/unixWm.test
@@ -19,6 +19,16 @@ proc sleep ms {
vwait x
}
+# The macOS window manager shows an animation when a window is deiconified.
+# Tests which check the geometry of a window after deiconifying it should
+# wait for the animation to finish.
+
+ proc animationDelay {} {
+ if {[tk windowingsystem] == "aqua"} {
+ sleep 250
+ }
+ }
+
# Procedure to set up a collection of top-level windows
proc makeToplevels {} {
@@ -76,6 +86,7 @@ foreach geom {+20+80 +80+20 +0+0 -0-0 +0-0 -0+0 -10-5 -10+5 +10-5} {
wm geom .t $geom
update
wm deiconify .t
+ animationDelay
scan [wm geom .t] %dx%d%1s%d%1s%d width height xsign x ysign y
format "%s%d%s%d" $xsign [eval expr $x$xsign$xerr] $ysign \
[eval expr $y$ysign$yerr]
@@ -91,6 +102,7 @@ foreach geom {+20+80 +100+40 +0+0} {
wm geom .t $geom
update
wm deiconify .t
+ animationDelay
wm geom .t
} 100x150$geom
incr i
@@ -400,6 +412,7 @@ test unixWm-9.4 {TkWmMapWindow procedure, icon windows} unix {
destroy .t
sleep 500
toplevel .t -width 100 -height 50 -bg blue
+ tkwait visibility .t
wm iconwindow . .t
update
set result [winfo ismapped .t]
@@ -795,9 +808,14 @@ test unixWm-22.2 {Tk_WmCmd procedure, "iconbitmap" option} {unix testwrapper} {
WM_HINTS] 0]]]
lappend result [wm iconbitmap .t] $bit
} {{} questhead 0x4 {} 0x0}
-test unixWm-22.3 {Tk_WmCmd procedure, "iconbitmap" option} unix {
+test unixWm-22.3.1 {Tk_WmCmd procedure, "iconbitmap" option for unix only} \
+{unix notAqua} {
list [catch {wm iconbitmap .t bad-bitmap} msg] $msg
} {1 {bitmap "bad-bitmap" not defined}}
+test unixWm-22.3.2 {Tk_WmCmd procedure, "iconbitmap" option for Aqua only} \
+Aqua {
+ list [catch {wm iconbitmap .t bad-bitmap} msg] $msg
+} {1 {}}
test unixWm-23.1 {Tk_WmCmd procedure, "iconify" option} unix {
list [catch {wm iconify .t 12} msg] $msg
@@ -1201,9 +1219,12 @@ test unixWm-34.3 {Tk_WmCmd procedure, "sizefrom" option} unix {
list [catch {wm sizefrom .t none} msg] $msg
} {1 {bad argument "none": must be program or user}}
-test unixWm-35.1 {Tk_WmCmd procedure, "state" option} unix {
+test unixWm-35.1.1 {Tk_WmCmd procedure, "state" option} {unix notAqua} {
list [catch {wm state .t 1} msg] $msg
} {1 {bad argument "1": must be normal, iconic, or withdrawn}}
+test unixWm-35.1.2 {Tk_WmCmd procedure, "state" option} Aqua {
+ list [catch {wm state .t 1} msg] $msg
+} {1 {bad argument "1": must be normal, iconic, withdrawn, or zoomed}}
test unixWm-35.2 {Tk_WmCmd procedure, "state" option} unix {
list [catch {wm state .t iconic 1} msg] $msg
} {1 {wrong # args: should be "wm state window ?state?"}}
@@ -1415,9 +1436,11 @@ test unixWm-42.1 {WrapperEventProc procedure, map and unmap events} unix {
bind .t <Unmap> {set x "unmapped"}
set x {no event}
wm iconify .t
+ animationDelay
lappend result $x [winfo ismapped .t]
set x {no event}
wm deiconify .t
+ animationDelay
lappend result $x [winfo ismapped .t]
} {unmapped 0 mapped 1}
@@ -1507,9 +1530,9 @@ test unixWm-44.5 {UpdateGeometryInfo procedure, negative width} unix {
update
list [winfo width .t] [winfo height .t]
} {1 72}
+destroy .t
+toplevel .t -width 80 -height 60
test unixWm-44.6 {UpdateGeometryInfo procedure, negative height} unix {
- destroy .t
- toplevel .t -width 80 -height 60
wm grid .t 18 7 10 12
wm geometry .t +30+40
wm overrideredirect .t 1
@@ -1518,22 +1541,24 @@ test unixWm-44.6 {UpdateGeometryInfo procedure, negative height} unix {
update
list [winfo width .t] [winfo height .t]
} {100 1}
-
destroy .t
toplevel .t -width 80 -height 60
test unixWm-44.7 {UpdateGeometryInfo procedure, computing position} unix {
- wm geometry .t +5-10
- wm overrideredirect .t 1
tkwait visibility .t
+ wm overrideredirect .t 1
+ update
+ wm geometry .t +5-10
+ update
list [winfo x .t] [winfo y .t]
} [list 5 [expr [winfo screenheight .t] - 70]]
-
destroy .t
toplevel .t -width 80 -height 60
test unixWm-44.8 {UpdateGeometryInfo procedure, computing position} unix {
- wm geometry .t -30+2
- wm overrideredirect .t 1
tkwait visibility .t
+ wm overrideredirect .t 1
+ update
+ wm geometry .t -30+2
+ update
list [winfo x .t] [winfo y .t]
} [list [expr [winfo screenwidth .t] - 110] 2]
destroy .t
diff --git a/tests/wm.test b/tests/wm.test
index 9cbe49a..f56eaa7 100644
--- a/tests/wm.test
+++ b/tests/wm.test
@@ -1516,9 +1516,10 @@ test wm-stackorder-5.1 {a menu is not a toplevel} -body {
} -cleanup {
destroy .t
} -result {.t .}
-test wm-stackorder-5.2 {A normal toplevel can't be\
- raised above an overrideredirect toplevel} -body {
+test wm-stackorder-5.2 {A normal toplevel can't be raised above an \
+ overrideredirect toplevel on unix} -constraints x11 -body {
toplevel .t
+ tkwait visibility .t
wm overrideredirect .t 1
raise .
update
@@ -1527,9 +1528,22 @@ test wm-stackorder-5.2 {A normal toplevel can't be\
} -cleanup {
destroy .t
} -result 0
+test wm-stackorder-5.2.1 {A normal toplevel can be raised above an \
+ overrideredirect toplevel on macOS or win} -constraints aquaOrWin32 -body {
+ toplevel .t
+ tkwait visibility .t
+ wm overrideredirect .t 1
+ raise .
+ update
+ raiseDelay
+ wm stackorder . isabove .t
+} -cleanup {
+ destroy .t
+} -result 1
test wm-stackorder-5.3 {An overrideredirect window\
can be explicitly lowered} -body {
toplevel .t
+ tkwait visibility .t
wm overrideredirect .t 1
lower .t
update
@@ -1540,7 +1554,7 @@ test wm-stackorder-5.3 {An overrideredirect window\
} -result 1
test wm-stackorder-6.1 {An embedded toplevel does not\
- appear in the stacking order} -body {
+ appear in the stacking order on unix or win} -constraints notAqua -body {
toplevel .real -container 1
toplevel .embd -bg blue -use [winfo id .real]
update
@@ -1548,6 +1562,15 @@ test wm-stackorder-6.1 {An embedded toplevel does not\
} -cleanup {
deleteWindows
} -result {. .real}
+test wm-stackorder-6.1.1 {An embedded toplevel does\
+ appear in the stacking order on macOS} -constraints aqua -body {
+ toplevel .real -container 1
+ toplevel .embd -bg blue -use [winfo id .real]
+ update
+ wm stackorder .
+} -cleanup {
+ deleteWindows
+} -result {. .embd}
stdWindow