summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXInit.c
diff options
context:
space:
mode:
authordas <das>2004-11-11 01:24:29 (GMT)
committerdas <das>2004-11-11 01:24:29 (GMT)
commitfa61ec1dd665487c5513d7db7255a2e09ed3e3e1 (patch)
treec22d22b2f3ad690eeadd7c8e57c9cf5b9eb56b0d /macosx/tkMacOSXInit.c
parentb7be4e0e9de6b6cb325269f53ce18596d73b4426 (diff)
downloadtk-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.c213
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);
+ }
+ }
+}