diff options
author | das <das> | 2004-11-11 01:24:29 (GMT) |
---|---|---|
committer | das <das> | 2004-11-11 01:24:29 (GMT) |
commit | fa61ec1dd665487c5513d7db7255a2e09ed3e3e1 (patch) | |
tree | c22d22b2f3ad690eeadd7c8e57c9cf5b9eb56b0d /macosx/tkMacOSXInit.c | |
parent | b7be4e0e9de6b6cb325269f53ce18596d73b4426 (diff) | |
download | tk-fa61ec1dd665487c5513d7db7255a2e09ed3e3e1.zip tk-fa61ec1dd665487c5513d7db7255a2e09ed3e3e1.tar.gz tk-fa61ec1dd665487c5513d7db7255a2e09ed3e3e1.tar.bz2 |
* generic/tkMain.c:
* macosx/tkMacOSXAppInit.c (removed):
* macosx/Wish.pbproj/project.pbxproj:
* macosx/tkMacOSXInit.c:
* macosx/tkMacOSXInt.h: changes to make TkAqua dynamically loadable,
enabling [package require Tk] from tclsh. Startup code from
tkMacOSXAppInit.c moved into tkMacOSXInit.c, added code that
notifies the window server that an unbundled executable is a full
GUI application after loading Tk. [Patch 1035348]
* doc/wm.n: documented [wm attributes] on Mac OS X. [Bug 606665]
* macosx/tkMacOSXWm.c: implemented TIP 222 [wm attributes -alpha] on
Mac OS X. [Patch 892194]
WmIconbitmapCmd: adopted FSRef changes from [wm atttrs -titlepath].
* macosx/tkMacOSXSubwindows.c: synced spacing/formatting with
core-8-4-branch.
* generic/tkRectOval.c:
* macosx/README:
* macosx/tkMacOSXDefault.h:
* macosx/tkMacOSXDraw.c:
* macosx/tkMacOSXInit.c:
* macosx/tkMacOSXInt.h:
* macosx/tkMacOSXMenu.c:
* macosx/tkMacOSXWm.c: forward port from core-8-4-branch of Jim's
and my changes for CG drawing and [wm attributes] (corresponds to
8.4 changes dating from 09-18, 07-27, 07-24).
* macosx/tkMacOSXMouseEvent.c: endianness fixes.
* macosx/Wish.pbproj/project.pbxproj: corrected path to html help
inside framework.
* macosx/Makefile: prevent parallel make from building several
targets at the same time.
Diffstat (limited to 'macosx/tkMacOSXInit.c')
-rw-r--r-- | macosx/tkMacOSXInit.c | 213 |
1 files changed, 188 insertions, 25 deletions
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index df7f255..07127eb 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -10,11 +10,14 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXInit.c,v 1.5 2004/02/16 00:19:42 wolfsuit Exp $ + * RCS: @(#) $Id: tkMacOSXInit.c,v 1.6 2004/11/11 01:24:32 das Exp $ */ #include "tkInt.h" #include "tkMacOSXInt.h" +#include "tclInt.h" +#include <sys/stat.h> +#include <mach-o/dyld.h> /* * The Init script (common to Windows and Unix platforms) is @@ -23,6 +26,15 @@ #include "tkInitScript.h" /* + * Define the following to 0 to not attempt to use an undocumented SPI + * to notify the window server that an unbundled executable is a full + * GUI application after loading Tk. + */ +#ifndef MAC_OSX_TK_USE_CPS_SPI +#define MAC_OSX_TK_USE_CPS_SPI 1 +#endif + +/* * The following structures are used to map the script/language codes of a * font to the name that should be passed to Tcl_GetEncoding() to obtain * the encoding for that font. The set of numeric constants is fixed and @@ -72,6 +84,11 @@ static Map scriptMap[] = { Tcl_Encoding TkMacOSXCarbonEncoding = NULL; +/* + * If the App is in an App package, then we want to add the Scripts + * directory to the auto_path. + */ +static char scriptPath[PATH_MAX + 1] = ""; /* *---------------------------------------------------------------------- @@ -95,30 +112,28 @@ int TkpInit(interp) Tcl_Interp *interp; { - char tkLibPath[1024]; - int result; - static int menusInitialized = false; - static int carbonEncodingInitialized = false; + static char tkLibPath[PATH_MAX + 1]; + static int tkMacOSXInitialized = false; /* * Since it is possible for TkInit to be called multiple times - * and we don't want to do the menu initialization multiple times + * and we don't want to do the initialization multiple times * we protect against doing it more than once. */ - if (menusInitialized == false) { - menusInitialized = true; + if (tkMacOSXInitialized == false) { + CFStringEncoding encoding; + char *encodingStr = NULL; + int i; + + tkMacOSXInitialized = true; + Tk_MacOSXSetupTkNotifier(); TkMacOSXInitAppleEvents(interp); TkMacOSXInitCarbonEvents(interp); TkMacOSXInitMenus(interp); TkMacOSXUseAntialiasedText(interp, TRUE); - } - - if (carbonEncodingInitialized == false) { - CFStringEncoding encoding; - char *encodingStr = NULL; - int i; + TkMacOSXInitCGDrawing(interp, TRUE, 3); encoding = CFStringGetSystemEncoding(); @@ -136,20 +151,112 @@ TkpInit(interp) if (TkMacOSXCarbonEncoding == NULL) { TkMacOSXCarbonEncoding = Tcl_GetEncoding (NULL, NULL); } - } + + /* + * When Tk is in a framework, force tcl_findLibrary to look in the + * framework scripts directory. + * FIXME: Should we come up with a more generic way of doing this? + */ + + Tcl_MacOSXOpenVersionedBundleResources(interp, + "com.tcltk.tklibrary", TK_VERSION, 1, 1024, tkLibPath); + + /* + * If we don't have a TTY and 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. + */ - /* - * When Tk is in a framework, force tcl_findLibrary to look in the - * framework scripts directory. - * FIXME: Should we come up with a more generic way of doing this? - */ - - result = Tcl_MacOSXOpenVersionedBundleResources(interp, - "com.tcltk.tklibrary", TK_VERSION, 1, 1024, tkLibPath); - - if (result != TCL_ERROR) { + if (!isatty(0)) { + struct stat st; + if (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)); + if (Tk_CreateConsoleWindow(interp) == TCL_OK) { + /* Only show the console if we don't have a startup script */ + if (Tcl_GetStartupScript(NULL) == NULL) { + Tcl_Eval(interp, "console show"); + } + } + } + } +#if MAC_OSX_TK_USE_CPS_SPI + /* + * If we are loaded into an executable that is not a bundled application, + * the window server does not let us come to the foreground. + * For such an executable, we attempt to use an undocumented SPI to + * notify the window server that we are now a full GUI application. + */ + { + /* Check whether we are a bundled executable: */ + int bundledExecutable = 0; + CFBundleRef bundleRef = CFBundleGetMainBundle(); + CFURLRef bundleUrl = NULL; + if (bundleRef) { + bundleUrl = CFBundleCopyBundleURL(bundleRef); + } + if (bundleUrl) { + /* + * A bundled executable is two levels down from its main bundle + * directory (e.g. Wish.app/Contents/MacOS/Wish), whereas + * an unbundled executable's main bundle directory is just + * the directory containing the executable. + * So to check whether we are bundled, we delete the last three + * path components of the executable's url and compare the + * resulting url with the main bundle url. + */ + int j = 3; + CFURLRef url = CFBundleCopyExecutableURL(bundleRef); + while (url && j--) { + CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(NULL, url); + CFRelease(url); + url = parent; + } + if (url) { + bundledExecutable = CFEqual(bundleUrl, url); + CFRelease(url); + } + CFRelease(bundleUrl); + } + + /* If we are not a bundled executable, attempt to use the CPS SPI: */ + if (!bundledExecutable) { + /* + * Load the CPS SPI symbol dynamically, so that we don't break + * if it every disappears or changes its name. + */ + OSErr (*cpsEnableForegroundOperation)(ProcessSerialNumberPtr) = NULL; + NSSymbol nsSymbol; + if(NSIsSymbolNameDefinedWithHint( + "_CPSEnableForegroundOperation", "CoreGraphics")) { + nsSymbol = NSLookupAndBindSymbolWithHint( + "_CPSEnableForegroundOperation", "CoreGraphics"); + if(nsSymbol) { + cpsEnableForegroundOperation = NSAddressOfSymbol(nsSymbol); + } + } + if (cpsEnableForegroundOperation) { + ProcessSerialNumber psn = { 0, kCurrentProcess }; + /* + * Let the window server know that we are a foregroundable app + */ + cpsEnableForegroundOperation(&psn); + } + } + } +#endif /* MAC_OSX_TK_USE_CPS_SPI */ + } + + if (tkLibPath[0] != '\0') { Tcl_SetVar(interp, "tk_library", tkLibPath, TCL_GLOBAL_ONLY); } + + if (scriptPath[0] != '\0') { + Tcl_SetVar(interp, "auto_path", scriptPath, + TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE); + } return Tcl_Eval(interp, initScript); } @@ -221,3 +328,59 @@ TkpDisplayWarning(msg, title) Tcl_WriteChars(errChannel, "\n", 1); } } + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXDefaultStartupScript -- + * + * + * On MacOS X, we look for a file in the Resources/Scripts + * directory called AppMain.tcl and if found, we set argv[1] to + * that, so that the rest of the code will find it, and add the + * Scripts folder to the auto_path. If we don't find the startup + * script, we just bag it, assuming the user is starting up some + * other way. + * + * Results: + * None. + * + * Side effects: + * Tcl_SetStartupScript() called when AppMain.tcl found. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXDefaultStartupScript(void) +{ + CFBundleRef bundleRef; + + bundleRef = CFBundleGetMainBundle(); + + if (bundleRef != NULL) { + CFURLRef appMainURL; + appMainURL = CFBundleCopyResourceURL(bundleRef, + CFSTR("AppMain"), + CFSTR("tcl"), + CFSTR("Scripts")); + + if (appMainURL != NULL) { + CFURLRef scriptFldrURL; + char startupScript[PATH_MAX + 1]; + + if (CFURLGetFileSystemRepresentation (appMainURL, true, + startupScript, PATH_MAX)) { + Tcl_SetStartupScript(Tcl_NewStringObj(startupScript, -1), NULL); + scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent( + NULL, appMainURL); + if (scriptFldrURL != NULL) { + CFURLGetFileSystemRepresentation(scriptFldrURL, + true, scriptPath, PATH_MAX); + CFRelease(scriptFldrURL); + } + } + CFRelease(appMainURL); + } + } +} |