diff options
author | marc_culler <marc.culler@gmail.com> | 2020-09-09 19:25:22 (GMT) |
---|---|---|
committer | marc_culler <marc.culler@gmail.com> | 2020-09-09 19:25:22 (GMT) |
commit | 22e941ecb6c39df473fa3ed938bdaeb0784aff76 (patch) | |
tree | 3dc6aad5318db4c0ef8251851ac29fa1291092be /macosx | |
parent | c0cbf2de196d27643e7267a53c37d4bf4810ffef (diff) | |
download | tk-22e941ecb6c39df473fa3ed938bdaeb0784aff76.zip tk-22e941ecb6c39df473fa3ed938bdaeb0784aff76.tar.gz tk-22e941ecb6c39df473fa3ed938bdaeb0784aff76.tar.bz2 |
Fix [ab1feaea9c]: Aqua initialization issues exposed by Scid vs Mac.
Diffstat (limited to 'macosx')
-rw-r--r-- | macosx/tkMacOSXInit.c | 91 | ||||
-rw-r--r-- | macosx/tkMacOSXSubwindows.c | 27 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.c | 6 |
3 files changed, 78 insertions, 46 deletions
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index 51c1e37..2cf4b0c 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -285,7 +285,6 @@ TkpInit( if (!initialized) { struct stat st; - initialized = 1; /* @@ -340,15 +339,15 @@ TkpInit( [NSApp _setup:interp]; /* - * WARNING: The finishLaunching method runs asynchronously, apparently - * in a separate thread. This creates a race between the - * initialization of the NSApplication and the initialization of Tk. - * If Tk wins the race bad things happen with the root window (see - * below). If the NSApplication wins then an AppleEvent created during - * launch, e.g. by dropping a file icon on the application icon, will - * be delivered before the procedure meant to to handle the AppleEvent - * has been defined. This is now handled by processing the AppleEvent - * as an idle task. See tkMacOSXHLEvents.c. + * WARNING: The finishLaunching method runs asynchronously. This + * creates a race between the initialization of the NSApplication and + * the initialization of Tk. If Tk wins the race bad things happen + * with the root window (see below). If the NSApplication wins then an + * AppleEvent created during launch, e.g. by dropping a file icon on + * the application icon, will be delivered before the procedure meant + * to to handle the AppleEvent has been defined. This is now handled + * by processing the AppleEvent as an idle task. See + * tkMacOSXHLEvents.c. */ [NSApp finishLaunching]; @@ -377,35 +376,47 @@ TkpInit( Tcl_DoOneEvent(TCL_WINDOW_EVENTS | TCL_DONT_WAIT); /* - * If we don't have a TTY and stdin is a special character file of + * If we don't have a TTY or stdin is a special character file of * length 0, (e.g. /dev/null, which is what Finder sets when double * clicking Wish) then use the Tk based console interpreter. */ - if (getenv("TK_CONSOLE") || - (!isatty(0) && (fstat(0, &st) || - (S_ISCHR(st.st_mode) && st.st_blocks == 0)))) { - Tk_InitConsoleChannels(interp); - Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN)); - Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT)); - Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR)); - - /* - * Only show the console if we don't have a startup script and - * tcl_interactive hasn't been set already. - */ - - if (Tcl_GetStartupScript(NULL) == NULL) { - const char *intvar = Tcl_GetVar2(interp, - "tcl_interactive", NULL, TCL_GLOBAL_ONLY); - - if (intvar == NULL) { - Tcl_SetVar2(interp, "tcl_interactive", NULL, "1", - TCL_GLOBAL_ONLY); + if (!isatty(0) && (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0))) { + if (getenv("TK_CONSOLE")) { + Tk_InitConsoleChannels(interp); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN)); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT)); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR)); + + /* + * Only show the console if we don't have a startup script and + * tcl_interactive hasn't been set already. + */ + + if (Tcl_GetStartupScript(NULL) == NULL) { + const char *intvar = Tcl_GetVar2(interp, + "tcl_interactive", NULL, TCL_GLOBAL_ONLY); + + if (intvar == NULL) { + Tcl_SetVar2(interp, "tcl_interactive", NULL, "1", + TCL_GLOBAL_ONLY); + } } - } - if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) { - return TCL_ERROR; + if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) { + return TCL_ERROR; + } + } else { + + /* + * When launched as a macOS application with no console, + * redirect stderr and stdout to /dev/null. This avoids waiting + * forever for those files to become writable if the underlying + * Tcl program tries to write to them with a puts command. + */ + + FILE *null = fopen("/dev/null", "w"); + dup2(fileno(null), STDOUT_FILENO); + dup2(fileno(null), STDERR_FILENO); } } @@ -433,6 +444,18 @@ TkpInit( TkMacOSXIconBitmapObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath", TkMacOSXGetAppPathCmd, NULL, NULL); + + /* + * The root window has been created and mapped, but XMapWindow deferred its + * call to makeKeyAndOrderFront because the first call to XMapWindow + * occurs too early in the initialization process for that. Process idle + * tasks now, so the root window is configured, then order it front. + */ + + while(Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}; + for (NSWindow *window in [NSApp windows]) { + [window makeKeyAndOrderFront:NSApp]; + } return TCL_OK; } diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 002eae6..682fbb3 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -143,6 +143,7 @@ XMapWindow( TkWindow *winPtr = macWin->winPtr; NSWindow *win = TkMacOSXGetNSWindowForDrawable(window); XEvent event; + static Bool initialized = NO; /* * Under certain situations it's possible for this function to be called @@ -172,12 +173,14 @@ XMapWindow( TkMacOSXApplyWindowAttributes(winPtr, win); [win setExcludedFromWindowsMenu:NO]; - [NSApp activateIgnoringOtherApps:NO]; + [NSApp activateIgnoringOtherApps:initialized]; [view addTkDirtyRect: [view bounds]]; - if ([win canBecomeKeyWindow]) { - [win makeKeyAndOrderFront:NSApp]; - } else { - [win orderFrontRegardless]; + if (initialized) { + if ([win canBecomeKeyWindow]) { + [win makeKeyAndOrderFront:NSApp]; + } else { + [win orderFrontRegardless]; + } } } else { TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); @@ -233,11 +236,15 @@ XMapWindow( * Generate VisibilityNotify events for window and all mapped children. */ - event.xany.send_event = False; - event.xany.display = display; - event.xvisibility.type = VisibilityNotify; - event.xvisibility.state = VisibilityUnobscured; - NotifyVisibility(winPtr, &event); + if (initialized) { + event.xany.send_event = False; + event.xany.display = display; + event.xvisibility.type = VisibilityNotify; + event.xvisibility.state = VisibilityUnobscured; + NotifyVisibility(winPtr, &event); + } else { + initialized = YES; + } return Success; } diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 6b7871f..a72874e 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -1827,7 +1827,7 @@ WmDeiconifyCmd( ZoomState : NormalState); [win setExcludedFromWindowsMenu:NO]; TkMacOSXApplyWindowAttributes(winPtr, win); - [win orderFront:nil]; + [win orderFront:NSApp]; if (wmPtr->icon) { Tk_UnmapWindow((Tk_Window)wmPtr->icon); } @@ -6124,6 +6124,8 @@ TkMacOSXMakeRealWindowExist( 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) { @@ -6921,7 +6923,7 @@ ApplyContainerOverrideChanges( [macWindow setExcludedFromWindowsMenu:YES]; [macWindow setStyleMask:styleMask]; if (wmPtr->hints.initial_state == NormalState) { - [macWindow orderFront:nil]; + [macWindow orderFront:NSApp]; } if (wmPtr->container != NULL) { wmPtr->flags |= WM_TOPMOST; |