summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXInit.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2024-10-25 21:06:25 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2024-10-25 21:06:25 (GMT)
commit0d5336db012f45753abace489f18f0ca299c6961 (patch)
treeb1bf3280a9046df99226158978502eeb26f5b0a3 /macosx/tkMacOSXInit.c
parente97381a6d921de403516d5b761539a450f4af83c (diff)
parent1320b8a2a9c1269a345d44d673a7a35707fbbe9c (diff)
downloadtk-core-tip-626.zip
tk-core-tip-626.tar.gz
tk-core-tip-626.tar.bz2
Merge 9.0core-tip-626
Diffstat (limited to 'macosx/tkMacOSXInit.c')
-rw-r--r--macosx/tkMacOSXInit.c144
1 files changed, 82 insertions, 62 deletions
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index ea4d4e4..bcae214 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -15,6 +15,7 @@
#include "tkMacOSXPrivate.h"
#include "tkMacOSXConstants.h"
+#include "tkMacOSXWm.h"
#include <dlfcn.h>
#include <objc/objc-auto.h>
#include <sys/stat.h>
@@ -41,9 +42,8 @@ static Tcl_ObjCmdProc2 TkMacOSVersionObjCmd;
@implementation TKApplication
@synthesize poolLock = _poolLock;
@synthesize macOSVersion = _macOSVersion;
-@synthesize isDrawing = _isDrawing;
-@synthesize isSigned = _isSigned;
@synthesize tkLiveResizeEnded = _tkLiveResizeEnded;
+@synthesize tkWillExit = _tkWillExit;
@synthesize tkPointerWindow = _tkPointerWindow;
- (void) setTkPointerWindow: (TkWindow *)winPtr
{
@@ -137,6 +137,7 @@ static Tcl_ObjCmdProc2 TkMacOSVersionObjCmd;
- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app
{
+ (void) app;
return YES;
}
@@ -181,7 +182,6 @@ static Tcl_ObjCmdProc2 TkMacOSVersionObjCmd;
*/
TkMacOSXInitAppleEvents(_eventInterp);
-
}
@@ -204,18 +204,7 @@ static Tcl_ObjCmdProc2 TkMacOSVersionObjCmd;
*/
Ttk_MacOSXInit();
-
- /*
- * It is not safe to force activation of the NSApp until this method is
- * called. Activating too early can cause the menu bar to be unresponsive.
- * The call to activateIgnoringOtherApps was moved here to avoid this.
- * However, with the release of macOS 10.15 (Catalina) that was no longer
- * sufficient. (See ticket bf93d098d7.) The call to setActivationPolicy
- * needed to be moved into this function as well.
- */
-
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
- [NSApp activateIgnoringOtherApps: YES];
/*
* Add an event monitor so we continue to receive NSMouseMoved and
@@ -230,15 +219,6 @@ static Tcl_ObjCmdProc2 TkMacOSVersionObjCmd;
{
return event;
}];
-
- /*
- * Process events to ensure that the root window is fully initialized. See
- * ticket 56a1823c73.
- */
-
- [NSApp _lockAutoreleasePool];
- while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}
- [NSApp _unlockAutoreleasePool];
}
- (void) _setup: (Tcl_Interp *) interp
@@ -290,12 +270,6 @@ static Tcl_ObjCmdProc2 TkMacOSVersionObjCmd;
[NSApp setMacOSVersion: 10000*majorVersion + 100*minorVersion];
/*
- * We are not drawing right now.
- */
-
- [NSApp setIsDrawing:NO];
-
- /*
* Be our own delegate.
*/
@@ -394,7 +368,7 @@ static void closePanels(
[[NSFontPanel sharedFontPanel] orderOut:nil];
}
if ([NSColorPanel sharedColorPanelExists]) {
- [[NSColorPanel sharedColorPanel] orderOut:nil];
+ [[NSColorPanel sharedColorPanel] orderOut:nil];
}
}
@@ -431,6 +405,21 @@ TCL_NORETURN void TkpExitProc(
}
/*
+ * At this point it is too late to be looking up the Tk window associated
+ * to any NSWindows, but it can happen. This makes sure the answer is None
+ * if such a query is attempted. It is also too late to be running any
+ * event loops, as happens in updateLayer. Set the tkWillExit flag to
+ * prevent this.
+ */
+
+ [NSApp setTkWillExit:YES];
+ for (TKWindow *w in [NSApp orderedWindows]) {
+ if ([w respondsToSelector: @selector (tkWindow)]) {
+ [w setTkWindow: None];
+ }
+ }
+
+ /*
* Tcl_Exit does not call Tcl_Finalize if there is an exit proc installed.
*/
@@ -457,6 +446,26 @@ static void TkMacOSXSignalHandler(TCL_UNUSED(int)) {
Tcl_Exit(1);
}
+/*
+ * This static function is run as an idle task to order the root window front.
+ * This is only done if the window is in the normal state. This avoids
+ * flashing the root window on the screen if it was withdrawn immediately after
+ * loading Tk.
+ */
+
+static void showRootWindow(void *clientData) {
+ NSWindow *root = (NSWindow *) clientData;
+ if ([NSApp tkWillExit]) {
+ return;
+ }
+ TkWindow *winPtr = TkMacOSXGetTkWindow(root);
+ WmInfo *wmPtr = winPtr->wmInfoPtr;
+ if (wmPtr->hints.initial_state == NormalState) {
+ [root makeKeyAndOrderFront:NSApp];
+ }
+ [NSApp activateIgnoringOtherApps: YES];
+}
+
int
TkpInit(
Tcl_Interp *interp)
@@ -471,15 +480,15 @@ TkpInit(
if (!initialized) {
struct stat st;
Bool shouldOpenConsole = NO;
- Bool stdinIsNullish = (!isatty(0) &&
+ Bool stdinIsNullish = (!isatty(0) &&
(fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0)));
/*
* Initialize/check OS version variable for runtime checks.
*/
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
-# error Mac OS X 10.6 required
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
+# error Mac OS X 10.9 required
#endif
initialized = 1;
@@ -495,7 +504,7 @@ TkpInit(
if (Tcl_MacOSXOpenVersionedBundleResources(interp,
"com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 0, PATH_MAX,
tkLibPath) != TCL_OK) {
- # if 0 /* This is not really an error. Wish still runs fine. */
+ # if 0 /* This is not really an error. Wish still runs fine. */
TkMacOSXDbgMsg("Tcl_MacOSXOpenVersionedBundleResources failed");
# endif
}
@@ -517,40 +526,40 @@ TkpInit(
[TKApplication sharedApplication];
[pool drain];
- /*
- * 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 handled in
- * tkMacOSXHLEvents.c by scheduling a timer event to handle the
- * AppleEvent later, after the required procedure has been defined.
- */
+ /*
+ * 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 handled in
+ * tkMacOSXHLEvents.c by scheduling a timer event to handle the
+ * AppleEvent later, after the required procedure has been defined.
+ */
[NSApp _setup:interp];
[NSApp finishLaunching];
- /*
- * Create a Tk event source based on the Appkit event queue.
- */
+ /*
+ * Create a Tk event source based on the Appkit event queue.
+ */
Tk_MacOSXSetupTkNotifier();
/*
* If Tk initialization wins the race, the root window is mapped before
- * the NSApplication is initialized. This can cause bad things to
- * happen. The root window can open off screen with no way to make it
- * appear on screen until the app icon is clicked. This will happen if
- * a Tk application opens a modal window in its startup script (see
- * ticket 56a1823c73). In other cases, an empty root window can open
- * on screen and remain visible for a noticeable amount of time while
- * the Tk initialization finishes (see ticket d1989fb7cf). The call
- * below forces Tk to block until the Appkit event queue has been
- * created. This seems to be sufficient to ensure that the
- * NSApplication initialization wins the race, avoiding these bad
- * window behaviors.
+ * the NSApplication is initialized. This can cause bad things to
+ * happen. The root window can open off screen with no way to make it
+ * appear on screen until the app icon is clicked. This will happen if
+ * a Tk application opens a modal window in its startup script (see
+ * ticket 56a1823c73). In other cases, an empty root window can open
+ * on screen and remain visible for a noticeable amount of time while
+ * the Tk initialization finishes (see ticket d1989fb7cf). The call
+ * below forces Tk to block until the Appkit event queue has been
+ * created. This seems to be sufficient to ensure that the
+ * NSApplication initialization wins the race, avoiding these bad
+ * window behaviors.
*/
Tcl_DoOneEvent(TCL_WINDOW_EVENTS | TCL_DONT_WAIT);
@@ -600,6 +609,9 @@ TkpInit(
#if defined(USE_CUSTOM_EXIT_PROC)
doCleanupFromExit = YES;
#endif
+ } else if (getenv("TK_NO_STDERR") != NULL) {
+ FILE *null = fopen("/dev/null", "w");
+ dup2(fileno(null), STDERR_FILENO);
}
/*
@@ -625,14 +637,22 @@ TkpInit(
* 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.
+ * tasks now, so the root window is configured.
*/
while(Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {};
+
for (NSWindow *window in [NSApp windows]) {
TkWindow *winPtr = TkMacOSXGetTkWindow(window);
if (winPtr && Tk_IsMapped(winPtr)) {
- [window makeKeyAndOrderFront:NSApp];
+
+ /*
+ * Ordering the root window front in an idle task allows
+ * checking whether it was immediately withdrawn, and
+ * therefore does not need to be placed on the screen.
+ */
+
+ Tcl_DoWhenIdle(showRootWindow, window);
break;
}
}
@@ -675,7 +695,7 @@ TkpInit(
Tcl_CreateObjCommand2(interp, "::tk::mac::GetAppPath",
TkMacOSXGetAppPathObjCmd, NULL, NULL);
Tcl_CreateObjCommand2(interp, "::tk::mac::macOSVersion",
- TkMacOSVersionObjCmd, NULL, NULL);
+ TkMacOSVersionObjCmd, NULL, NULL);
MacSystrayInit(interp);
MacPrint_Init(interp);