Tcl/TkAqua FAQ
Note: This FAQ is an updated version of the old Mac-Tk FAQ, now lost in the Internet archives. That document, last revised in 2002, covered Tcl/Tk under Mac OS 9 and earlier and does not reflect the port of Tk to Mac OS X. This new FAQ builds on the earlier document, consolidates material in various documents such as the Tcl/TkAqua README documents, various entries at the Tcl wiki, relevant mailing list items, and other online resources/tutorials.--Kevin Walzer
Tcl/TkAqua is the most common and attractive build of the Tcl/Tk system for Mac OS X. "Aqua" means the graphical interface has a native OS X look and feel - unlike builds linked to Xorg/X11.
Tcl/TkAqua can be built against either the Carbon or Cocoa API. Carbon is Apple's older, now deprecated API. Cocoa is the modern build, but it has some major unresolved problems. (See BUGS for more information).
Tcl/TkAqua requires MacOS X to run. Support for Classic MacOS was discontinued in 2004. To download a current version of Tcl/Tk, download ActiveTcl from http://www.activestate.com/ .
Tcl/Tk were originally developed on Unix in the late 1980s, and were ported to Windows and Mac OS in the mid-1990s by Sun Microsystems. (The original author of Tcl/Tk, John Ousterhout, was a professor at Berkeley but later left to join Sun.). Apple Computer helped to port Tk to OS X in late 2001. (Because OS X is a variant of Unix, no special effort was required to port Tcl, the command-line scripting component.)
The Tcl/TkAqua files are stored in /Library/Frameworks. The entry page for document is in /Library/Frameworks/Tcl.framework/Versions/8.5/Resources/Documentation/Reference/Tcl/contents.htm and /Library/Frameworks/Tk.framework/Versions/8.5/Resources/Documentation/Reference/Tk/contents.htm.
Apple's Developer Tools CD needs to be installed (the version matching your OS release, but no earlier than April 2002). This CD should have come with Mac OS X retail or should be present as a disk image on new macs that came with OSX preinstalled. It can also be downloaded from http://connect.apple.com (after you register for free ADC membership).
ln -fs /path_to_tcl/build /path_to_tk/build
(where /path_to_{tcl,tk} is the directory containing the tcl resp. tk tree) or you can pass an argument of BUILD_DIR=/somewhere to the tcl and tk make.)
Setup the shell variable as follows:
set ver="8.4.2" ;: if your shell is csh ver="8.4.2" ;: if your shell is sh
The source trees will be named this way only if you are building from a release archive, if you are building from CVS, the version numbers will be missing; so set ${ver} to the empty string instead:
set ver="" ;: if your shell is csh ver="" ;: if your shell is sh
make -C tcl${ver}/macosx make -C tk${ver}/macosx
and the following will then install Tcl and Tk onto the root volume (admin password required):
sudo make -C tcl${ver}/macosx install sudo make -C tk${ver}/macosx install
if you don't have the admin password, you can install into your home directory, instead by passing an INSTALL_ROOT argument to make:
make -C tcl${ver}/macosx install INSTALL_ROOT="${HOME}/" make -C tk${ver}/macosx install INSTALL_ROOT="${HOME}/"
The default Makefile targets will build _both_ debug and optimized versions of the Tcl and Tk frameworks with the standard convention of naming the debug library Tcl.framework/Tcl_debug resp. Tk.framework/Tk_debug. This allows you to dynamically link to the debug libraries at runtime by setting
setenv DYLD_IMAGE_SUFFIX _debug
(c.f. man dyld for more details)
If you only want to build and install the debug or optimized build, use the 'develop' or 'deploy' target variants of the Makefiles, respectively. For example, to build and install only the optimized versions:
make -C tcl${ver}/macosx deploy make -C tk${ver}/macosx deploy sudo make -C tcl${ver}/macosx install-deploy sudo make -C tk${ver}/macosx install-deploy
The Makefiles can also build a version of 'Wish Shell' that has the Tcl and Tk frameworks embedded in its application package. This allows for standalone deployment of the application with no installation required, e.g. from read-only media. To build & install in this manner, use the 'embedded' target variants of the Makefiles. For example, to build a standalone 'Wish Shell.app' in ./embedded/Applications/Utilities:
make -C tcl${ver}/macosx embedded make -C tk${ver}/macosx embedded sudo make -C tcl${ver}/macosx install-embedded INSTALL_ROOT=`pwd`/embedded/ sudo make -C tk${ver}/macosx install-embedded INSTALL_ROOT=`pwd`/embedded/
Notes:
It is possible to build Tk without without the tcl sourcetree; but in that case you need to tell the Tk Makefile where the copies of 'Tcl.framework' and 'tclsh8.4' are located that you want to build & link against (their default location is ${BUILD_DIR}/tcl).
For instance to use their default systemwide install locations:
make -C tk${ver}/macosx \ TCL_FRAMEWORK_DIR=/Library/Frameworks TCLSH_DIR=/usr/bin sudo make -C tk${ver}/macosx install \ TCL_FRAMEWORK_DIR=/Library/Frameworks TCLSH_DIR=/usr/bin
Of course this will only work if /Library/Frameworks does indeed contain a Tcl.framework corresponding in version to the Tk.framework you're trying to ]build, and if TCLSH_DIR contains a corresponding /usr/bin/tclsh8.4
or to use an earlier install of Tcl into ˇINSTALL_ROOT="${TCLTK}/"ˇ :
make -C tk${ver}/macosx \ TCL_FRAMEWORK_DIR=${TCLTK}/Library/Frameworks TCLSH_DIR=${TCLTK}/usr/bin sudo make -C tk${ver}/macosx install INSTALL_ROOT="${TCLTK}/" \ TCL_FRAMEWORK_DIR=${TCLTK}/Library/Frameworks TCLSH_DIR=${TCLTK}/usr/bin
The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added in Tk 8.4.3.
Note that html help in Tk.framework is only built if TCL_FRAMEWORK_DIR contains the tcl Makefile (as is the case for the default value of TCL_FRAMEWORK_DIR).
Thanks to Daniel Steffen's work, Mactel/universal binaries for Tcl/Tk Aqua are now simple. You can now build for 64bit on a G5 with the usual ˇ--enable-64bitˇ flag, or you can build as a fat ppc & ppc64 (& i386) binary on any ppc. Details on universal builds are in macosx/README of the Tcl/Tk source tree, but in short it suffices to set ˇCFLAGSˇ as follows:
export CFLAGS="-arch ppc -arch ppc64 -arch i386 \ -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4"
Mac OS X 10.4, Xcode 2.2, and the appropriate SDK's are required to build Tcl/Tk Aqua in this fashion.
You may also need to add -fpascal-strings to CFLAGS for menus to work properly (particularly the default menu), otherwise you get may get menus with labels like "\pEdit\pCut/X\pCopy" where these should be separate menu items. --MAK
With Tcl/Tk 8.5/OS X 10.5, some different steps might be necessary.
The result of this is that the Tcl/Tk frameworks are installed in /Library/Frameworks, as expected, and are universal binaries. The process for building an embedded/standalone Wish remains as before.
To build an embedded/standalone Wish, follow this process:
make -C tcl${ver}/macosx embedded make -C tk${ver}/macosx embedded sudo make -C tcl${ver}/macosx install-embedded INSTALL_ROOT=`pwd`/embedded/ sudo make -C tk${ver}/macosx install-embedded INSTALL_ROOT=`pwd`/embedded/
Why are the last two commands sudoed?
if you've already built standard TclTkAqua, building embedded does not require any new compiling or linking, so you can skip the first two makes. (making relinking unnecessary was added in 8.4.2) The embedded frameworks include only optimized builds and no documentation. The standalone Wish has the directory Wish\ Shell.app/Contents/lib in its auto_path. Thus you can place tcl extensions in this directory (i.e. embed them in the app package) and load them with package require.
To build TEA based extensions, the following configure invocation should do the trick:
./configure \ --prefix=/usr/local --libdir=/Library/Tcl \ --with-tcl=/Library/Frameworks/Tcl.framework \ --with-tclinclude=/Library/Frameworks/Tcl.framework/Headers \ --with-tk=/Library/Frameworks/Tk.framework \ --with-tkinclude=/Library/Frameworks/Tk.framework/Headers \ --enable-threads
Binary extensions can also be built as universal binaries. This is a good thing, if you need to use the extension with different Tcl versions that are built for different architectures. The important thing is to link against a universal build of Tcl/Tk, because you cannot build a universal binary extension against a single architecture Tcl/Tk. So be sure to do '--with-tcl=...' in the ./configure call for the extension using a universal Tcl/Tk. Before you do the ./configure call, be sure to export the CFLAGS as noted above (e.g. -arch i386 -arch x86_64), and then configure/build as needed.
If you don't do this right, you might end up with error messages like the following, that indicate, you don't use the right combination of Tcl and extension architecture:
dlopen(libsqlite3.6.20.dylib, 10): image not found
load libsqlite2.6.20.dylib image not found NSCreateObjectFileImageFromFile() error: not a Mach-O MH_BUNDLE file Error in startup script: no suitable image found. Did find: libsqlite3.6.20.dylib: mach-o, but wrong architecture NSCreateObjectFileImageFromFile() error: not a Mach-O MH_BUNDLE file
You may even get a 'bus error' on these conflicts.
When trying to build a universal binary extension and not using a universal Tcl build, this is a typical error you get, indicating the wrong combination:
ld: warning: in libtclstub8.4.a, file is not of required architecture Undefined symbols: "_Tcl_InitStubs", referenced from: _Sqlite3_Init in tclsqlite3.o "_tclStubsPtr", referenced from: _tclStubsPtr$non_lazy_ptr in tclsqlite3.o ld: symbol(s) not found collect2: ld returned 1 exit status lipo: can't open input file: /var/folders/V+/V+EH4NTNHFyVqsfQUXAau++++TI/-Tmp-//ccf2zTQp.out (No such file or directory) make: *** [libsqlite3.6.20.dylib] Error 1
Note: use the 'file' shell command on a binary to find out for which architectures it was built.
For GUI building, tools include TkProE (http://tkproe.sourceforge.net/ ), SpecTcl (http://spectcl.sourceforge.net ), and Visual Tcl (http://vtcl.sourceforge.net ). However, these tools are either no longer actively developed (SpecTcl and VTcl) or do not have a large user base (TkProE). The best commercial development environment for Tk, ActiveState's Komodo (http://www.activestate.com/Products/Komodo/ ), is now available on OS X, and has a free version. Many Tcl/Tk developers prefer to write their GUI code by hand; as Tk is a simple and elegant system for creating graphical interfaces, learning to code a GUI by hand is not difficult.
Alpha is a fine code editor that is mostly written in Tcl; various flavors of the program (OS X-specific and cross-platform) are available. Alpha is shareware. Other popular editors include such Mac-specific tools as Textwrangler (free) and BBEdit (commercial) from Bare Bones Software (http://www.barebones.com ). BBEdit is a legendary program on the Mac, with powerful code editing and text management features; Textwrangler offers much of the functionality of the commercial product, includes good support for Tcl, and is free. An alternate Tcl language module for TextWrangler and BBEdit is also available. It features improved recognition of procedure definitions which use the namespace:: syntax. [L1 ]
The leading Unix-based code editors include Vim and Emacs. Both originated as command-line applications, and can be used on the Mac in this fashion by calling them in the Terminal application. However, both are also available in Mac-native GUI formats. The official site for an Aqua-native version of Vim is http://www.macvim.org . While there is not yet an officially available version of Emacs for OS X, unofficial builds can be download from a variety of locations, including http://www.aquamacs.org , http://home.att.ne.jp/alpha/z123/emacs-mac-e.html , and http://emacs-on-aqua.sourceforge.net .
AOL's webserver (http://www.aol.com ), one of the busiest in the world, makes extensive use of Tcl. Tcl is used by such companies as Motorola (http://www.motorola.com ) and Cisco (http://www.cisco.com ) for internal product testing and development. ActiveState has built a successful business providing programming tools to Tcl developers, as well as developers in other languages. Other commercial developers include Mark Roseman (http://www.courseforum.com ), Michael Kirkham (http://www.muonics.com ), Kevin Walzer (http://www.codebykevin.com ), Simulistics, developer of the modeling/simulation program Simile (http://www.simulistics.com/ ); Inivis, developer of the 3-D graphics program AC3D (http://www.ac3d.org ); Bitrock, developer of InstallBuilder, an installer development toolkit (http://www.bitrock.com ); Peter Caffin, developer of RReplace (file search and replace, http://rreplace.autons.net ) and Padded, a PAD file builder (http://padded.autons.net ).
Numerous open-source developers also make use of Tcl/Tk, including Mats Bengtsson (http://thecoccinella.org/ ); Tom Hennigan, the Mac maintainer of aMSN (http://www.amsn-project.net ), Andres Garcia, developer of Getleft, a web-site downloader (http://personal1.iddeo.es/andresgarci/getleft/english/ ); Randolf Schultz, developer of Ayam, a 3-D/OpenGL modeler (http://www.ayam3d.org ); and others.
The tcl-mac mailing list on sourceforge is the canonical place for questions specific to Tcl & Tk on Mac OS X:
http://lists.sourceforge.net/lists/listinfo/tcl-mac
(this page also has a link to searchable archives of the list, please check them before asking on the list, many questions have already been answered).
The jumping-off point for information about Tcl/Tk is https://www.tcl-lang.org . You can find links to documentation, applications, and other resources. The Tcl Wiki at https://wiki.tcl-lang.org is a more informal, but continuously updated, source of information on specific Tcl/Tk topics. This is an excellent resource to find specific information and code samples on almost any aspect of Tcl/Tk programming. A wiki can be edited by anyone, so you are also welcome to contribute pages, code samples, updates and clarification to existing pages, and so forth.
The wiki has a page listing known bugs in Mac OS X Tcl/Tk (and other tips)
https://wiki.tcl-lang.org/MacOS%20X
as well as a page with info on building Tcl/Tk on Mac OS X
https://wiki.tcl-lang.org/Steps%20to%20build%20Tcl/Tk%208.4.0%20on%20MacOS%20X
The final essential Tcl/Tk resource is the usenet group comp.lang.tcl.
Tclsh (tcl shell) is the main shell for running command-line Tcl scripts. That shell can be invoked only from the command line, in the Terminal application, and is located at /usr/bin/tclsh on OS X.
Wish (windowing shell) is the shell used to run Tk. Wish comes in two forms: a command-line version that is installed in /usr/bin/wish; and an application bundle, Wish Shell.app, that is installed in /Applications/Utilities.
Define a proc named:
proc ::tk::mac::OpenDocument args { # args will be a list of all the documents dropped on your app, or double-clicked }
in your AppMain.tcl script. Tk will feed this the file names from any Open Document events sent to Wish.
The Tcl/TkAqua Batteries Included distribution includes a utility called Launcher that will activate Wish if you double-click on a Tcl script. Wish will then run the script.
There are two ways to do this:
The best way to do this is to package your new command into a shared library, and then either load it directly into Tcl using the load command, or set it up as a Tcl package, and use the package require mechanism.
Tcl/Tk Aqua is built using Xcode and GCC (Gnu compiler). These tools are free installs from Apple.
Each toplevel has a menu associated with it. You set it with the -menu option of the toplevel thusly:
menu .mbar -tearoff 0 . configure -menu .mbar
This menu is displayed in the Main Macintosh menubar whenever the toplevel that owns it (in this example, .) is in the foreground.
To make the menu entries in the menubar, you add cascade entries to the menu you have installed for that toplevel. Each cascade entry will show up as a separate pulldown of the main menu bar. So the following code installs a pulldown called "File" with "New", "Open...", "Save" and "Quit" entries into the menubar .mbar:
.mbar add cascade -label File -menu .mbar.file menu .mbar.file -tearoff 0 .mbar.file add command -label New -accelerator Command-N -command "NewDoc" .mbar.file add command -label Open... -accelerator Command-O -command "OpenFile" .mbar.file add command -label Close -accelerator Command-W -command "CloseDoc" .mbar.file add separator .mbar.file add command -label Save -accelerator Command-S -command "SaveDoc" .mbar.file add command -label "Save As..." -command "SaveDocAs" .mbar.file add separator .mbar.file add command -label Quit -accelerator Command-Q -command exit
No. By default all toplevels inherit the menubar of their parent. Since everything is a child of ".", this means that changing the menubar for "." propagates that change to all the toplevels in your application. So if you create a new toplevel with:
toplevel .top
then ".top" will display the same menubar as ".". If later on, you make a new menubar for .top, and then create a child of .top thusly:
.top configure -menu .top.mbar toplevel .top.child
Then . will have its original menubar, and .top AND .top.child will share the menubar given by .top.mbar.
Yes. To install an entry in the Application menu, you need to create a special cascade entry for your menubar where the last part of the name is apple. If the menubar you are using is called ".mbar", then create a cascade menu entry, whose menu is ".mbar.apple":
menu .mbar.apple .mbar add cascade -menu .mbar.apple
Then all the menu entries that you add to .mbar.apple will appear under the Application Menu pulldow and will be put at the top of the menu (called "Wish" or "Wish Shell" unless you change the Application name as described below). Note, that the above two lines will also remove the "About Tcl & Tk..." entry in the Application menu. This enables you to put your own "About ..." entry there (perhaps specific to Tk 8.5):
.mbar.apple add command -label "About this software ..." -command myAboutCmd .mbar.apple add separator
For this to work correctly on the Cocoas based Tk 8.6, configuring the main menu should be the last thing you do in setting up the menu. i.e.
. configure -menu .mbar
must be the LAST line of menu-setup-code. Tk-Cocoa sets everything up first. If you do not do this, you will get an additional menu with your apple menu items in. Since this approach also works for Tk 8.5 and 8.4, just make it a habit to configure the toplevel as the last thing.
Note also, the name "apple" is historical, on Mac OS 9 the place for Application-wide menu items was in the Apple Menu. But on Mac OS X, those items now go in the Application Menu. It is no longer possible for Applications to add to the Apple menu.
To install entries in the help menu, create a cascade entry whose menu is .mbar.help (i.e., with the last component being called help):
menu .mbar.help .mbar add cascade -menu .mbar.help
No. This menubar is a simple Macintosh menubar, and cannot be modified. However, the only substantial code in the default menu, namely that which implements the Cut, Copy, Paste and Clear entries, is easily duplicated using the Tk virtual event generation. Just use:
menu .mbar -tearoff 0 .mbar add cascade -menu .mbar.file -label File .mbar add cascade -menu .mbar.edit -label Edit menu .mbar.edit -tearoff 0 .mbar.edit add command -label Cut -accel Command-X -command { event generate [focus] <<Cut>> } .mbar.edit add command -label Copy -accel Command-C -command { event generate [focus] <<Copy>> } .mbar.edit add command -label Paste -accel Command-V -command { event generate [focus] <<Paste>> } .mbar.edit add command -label Clear -command { event generate [focus] <<Clear>> }
Yes. You can do this in a couple of different ways. The simplest is to call the Tclapplescript package, which is a standard part of the ActiveState distribution, at the beginning of your script. Use this syntax:
package require Tclapplescript
Then, when you are ready to call AppleScript specifically, you can set it up like this:
AppleScript execute { tell application "Finder" display dialog "Tk Aqua rocks!" end tell }
Another way to call AppleScript is to do so via the osascript command line tool, like this:
exec osascript -e { tell application "Finder" display dialog "Cool" end tell }
Yet another way to access the same functionality is to use TclAE. This allows you to handle AppleEvents directly instead of expressing your commands in the somewhat woolly AppleScript language.
Use the AppleScript load command to load the script, and then the run subcommand to run it:
set myScript [AppleScript load myAppleScriptFile] button .b1 -text "Run Script" -command [list AppleScript run $myScript]
Tk will respond to the "do script" Apple Event, so you can send Tcl scripts that way.
Otherwise you can use TclAE to install your own AppleEvent handlers.
As mentioned in section 2.2 above, the application-specific Tcl procedure ::tk::mac::OpenDocument is called when the user drops a document on your application or double-clicks a document created by your application. The list of Apple events that trigger application-specific Tcl procedures is:
Event | Handler |
---|---|
kAEOpenDocuments | ::tk::mac::OpenDocument |
kEventAppHidden | ::tk::mac::OnHide |
kEventAppShown | ::tk::mac::OnShow |
kAEShowPreferences | ::tk::mac::ShowPreferences |
kAEQuitApplication | exit (not application specific but can be made so using rename) |
Only the OpenDocument procedure receives any arguments. Handling the arguments is discussed in section 2.2 above.
The Wish application is not just a tool for launching scripts; it can also serve as a wrapper for standalone applications. Wish, like all GUI Aqua applications, is actually a file directory diguised as a single file with its own icon. It is designed by the Tcl/Tk Aqua developers to package entire Tcl/Tk application suites.
The first thing to do is find the Wish Shell-standalone application (with the frameworks installed). Copy the application to another directory, such as your desktop. Then, right-click on the application and choose "Show Package Contents." You will see a "Contents" folder; navigate into this folder and you will see the "MacOS" and "Resources" directory. Add a "Scripts" folder to the "Resources" directory.
The next thing to do is to navigate to the source code folder for your script. If you have one main script, copy it to the "Scripts" folder. Then, set up another script called "AppMain.tcl" and put the following material in it:
if {[string first "-psn" [lindex $argv 0]] == 0} { set argv [lrange $argv 1 end] } console show if [catch {source [file join [file dirname [info script]] foo.tcl]}] { puts $errorInfo }
If you don't want the console to show (it is useful for debugging the application while you are packaging it), comment out that line with the # symbol. You can also use "console hide". Be sure to replace "foo.tcl" with the actual name of your main application script.
The next thing to do is navigate up a level to the "Contents" directory. If you have supporting packages/libraries (such as Tclapplescript), copy the libraries to this directory.
Next, navigate to the Resources directory. You should find a file called "Wish.icns." This is the generic Wish Shell application icon; "icns" is the Macintosh icon file format. If you want a custom icon, open Icon Composer, found in your Developer directory. Find another graphic image to import, select "Thumbnail 32-bit Data" from the import options, and then save the graphic as an icon file ("title.icns") in the "Resources" directory of the Visual Tcl app bundle. You may want to test the application at this point by double-clicking on the icon (find the application icon in the Finder; don't try to click on the "icns" file inside the resources directory). If it launches, then the hard part is over and you are almost finished.
Next, navigate up one level from the Resources directory. You should find a file called "Info.plist." This is an XML file that includes a variety of information about the application bundle, including the name of the executable file, the name of the application bundle itself, and the name of the icon file. Find the line marked "CFBundleIcon" and change the name from "Wish.icns" to "title.icns" or whatever name you choose. If you want to change the application name, then find the line "CFBundleName" and change the name from "Wish" to whatever you choose, such as "MyCoolAppName." Save and close the file. Navigate to /Contents/MacOS and change the name of the executable in that directory, "Wish Shell," to "MyCoolAppName." If your application defines an own document type and you want documents of this type to carry the application icon and want the application to be connected to the documents so that it starts if documents are opened (double-click) in the Finder you have to add appropriate keys and values to the "CFBundleDocumentTypes" array (see also [L2 ]). Beware, this connection only works if the application bundle is later copied to your "Programs" directory and you may need to log out and in again to make the Finder aware of the changes. If your application startup sequence takes some time, a small ::tk::mac::OpenDocument procedure should be defined in your "AppMain.tcl" that saves the arguments (file names of documents double clicked in the finder) in a global variable for later processing after application startup finished. Otherwise your application might miss the OpenDocument event while starting up.
Now close the entire application directory. Don't forget to rename the application itself in the Finder with the new name you provided in the "Info.plist" file, just as if you were renaming any other file or folder.
If you follow these steps, you'll have a standalone application bundle of your Tcl script: it won't even need a separate installation of Tcl/Tk on another machine.
For a more detailed set of instructions on preparing a Mac application bundle, including screenshots, see https://www.codebykevin.com/tutorial.html .
anoved finds Starpack-based application packages easier to manage and has written a tutorial on the topic here: [L3 ]
Building Stand-Alone Tcl/Tk Applications under Mac OS X contains more information about packaging Tcl/Tk programs as Macintosh applications.
peterc notes: ActiveState's commercial Tcl Dev Kit 4 software now supports the generation of starpacks on Mac OS X and it will even package your application into an .app program through its UI. It's well worth the money.
Making an Application Bundle is much the same for Tcl applications as for any other software, however, there are some things worth noting:
There is a Tcl global variable called tcl_platform that contains this information. To check this, just type in "tclsh" into your Terminal application, which will launch the Tcl command-line shell (not Wish). Then, type parray tcl_platform. Here is the output you'll see:
% parray tcl_platform tcl_platform(byteOrder) = bigEndian tcl_platform(machine) = ppc tcl_platform(os) = Darwin tcl_platform(osVersion) = 7.6 tcl_platform(platform) = unix
There is also the useful
tk windowingsystem
command, which returns one of
aqua win32 x11
On MacOS X, you might see either "aqua" or "x11" depending on whether you are using TkAqua or not.
There are two ways to do this. The cleanest way to is to make a set of abstract button events, <<LeftMousePress>>, <<CenterMousePress>>, and <<RightMousePress>>, say, and use these everywhere in your code. Then somewhere at startup, use the "event add" command to bind <<LeftMousePress>> to ButtonPress-1, and on Unix bind <<CenterMousePress>> to <ButtonPress-2>, but on the Mac, bind it to <Control-ButtonPress-1>, or something else that you are not using...
The second way is to dispatch your own ButtonPress-2,3 events, with something like:
bind all <Control-ButtonPress-1> {event generate %W <ButtonPress-2> \ -x %x -y %y -rootx %X -rooty %Y -button 2 -time %t}
You do have to populate all the detail fields of the event that you are likely to use in your bindings, as this example demonstrates.
Duoas 2009-01-14: Here's a shameless plug for VirtualMouse Cross Platform Mouse Handling. I'd love some feedback from all you folks working on a Mac.
For historical reasons, MacMice buttons 2 and 3 refer to the right and middle buttons respectively, which is indeed the opposite way round from Windows and *nix systems.
$::tcl_platform(osVersion) returns the kernel's version number, not the product version number. To get the product version number, use:
set version [exec sw_vers -productVersion]
Product Version numbers for Mac OS:
Descriptive Name | Version | Notes |
Yosemite | 10.10 | |
El Capitan | 10.11.6 | Graphite appearance |
Sierra | 10.12.6 | |
High Sierra | 10.13.6 | |
Mojave | 10.14.6 | dark mode, multiple accent colors |
Catalina | 10.15.5 | as of 2020-6-5 |
As of 2011, most pre-packaged versions of Tcl/Tk are based on the Cocoa API and have some serious unresolved issues; especially concerning the event loop. Cocoa is also the default build from source code. These issues evidence in various ways, but notably as very slow screen redraws in non-trivial Tk apps. They are currently the focus of much discussion at the tcl-mac mailing list. http://sourceforge.net/mailarchive/forum.php?forum_name=tcl-mac
You should report bugs to the sourceforge bug trackers as usual:
please make sure that you report Tk-specific bugs to the tktoolkit bug tracker and not the tcl one.
Given a potential package directory $pkg, Tcl on OSX checks for the file $pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl. This allows building extensions as frameworks with all script files contained in the Resources/Scripts directory of the framework.
The old QD code is retained for now, just in case there are any compatibility problems. To switch back to the QD drawing, just put:
set tk::mac::useCGDrawing 0
in your script before you do drawing. Also the CG drawing can anti-alias line drawing. However, anti-aliased thin lines look washed out, so the threshold for antialiasing is set to 3 pixel width lines. You can change this if you want by putting:
set tk::mac::CGAntialiasLimit <limit>
in your script before drawing, in which case only lines thinner that <limit> pixels will not be antialiased.
Name | Description |
---|---|
spinning | The circular B&W circular spinner |
countinguphand | The counting up hand |
countingdownhand | The counting down hand |
countingupanddownhand | The counting up then down hand |
watch | The watch cursor |
Then to get the sequential variants, add an integer to the end of the base name. So, for instance this code will spin the spinner:
proc spinCursor {widget count} { $widget configure -cursor spinning$count after 100 spinCursor [incr count] }
This was added in Tk 8.4.2.
NEM: Excellent effort. I haven't had time to read through it all yet, but it seems to cover most of the material. This will be a big help for those of us on OS X. One point I did notice: In section 1.5 (Commercial apps) you say AOLServer is built on top of tclhttpd. I don't think this is the case. Both use Tcl heavily, but AOLServer is primarily written in C, as I understand things, whereas tclhttpd is 100% pure Tcl.
Brian Theado: I have a question about packaging applications. Is it possible to package an application from a different platform? I'd like to distribute an application for the Mac, but don't have access to a Mac.
Kevin Walzer: You can always package an application as a starkit on any platform, but it would be difficult to give it all the Mac bells and whistles unless it's packaged on that platform. Things like the Apple menu look weird on other platforms, the icon "icns" format is proprietary to Apple, and so forth.
jcw 2004-11-19: A workable (but not-so-terrific) fallback option right now is to package a starpack using the tclkit-darwin-ppc binary. This runs with Apple's X11 system, which is a separate download (see [L4 ]) and which needs to be running. There is no Aqua based tclkit, i.e. using the starkit/starpack approach, though it looks like it could technically be done. Note that Daniel Steffen's BI distro is set up to run .kit files with "wishkit", which is Aqua, so you can deploy starkits, tell people to install the BI distro, and end up with a double-clickable solution which uses Aqua. Making the GUI look well in that context is going to require a Mac, though.
Lars H: JCW, when you say "wishkit" is not a "tclkit", then what do you mean? Is this merely a matter of names, or is there some technical difference?
They are two different binaries. From [L5 ]: "Note the presence in the distribution of both Tclkit and the new Wishkit, which allows the running of starkits under either Tk/X11 or Tk/Aqua." -jcw
Lars H: Yeah, I knew that much, but it doesn't address my point. From the above "There is no Aqua based tclkit" and "wishkit is Aqua" it should follow that, in your authorative opinion, "Wishkit is not a tclkit", should it not? What property of Wishkit disqualifies it from being "a tclkit"?
DAS: Wishkit is simply a standalone Wish.app with the necessary extensions embedded to allow it to source starkits, and its auto_path adjusted to not look outside the Wishkit.app bundle. It has nothing directly to do with tclkit, hence the distinction. Now that TkAqua is dynamically loadable, it should be possible to build an aqua tclkit, but somebody first needs to implement a way to build a single file Tk.dylib in the macosx Tk build system (i.e. not a framework), the main problem with that scenario is how to deal with the Tk.rsrc file...
Kevin Walzer: Recent builds of tclkit make it possible to bundle up Tcl scripts as starpacks under Mac OS X, either in the Aqua or X11 environment. These can be placed inside a standard Mac application bundle. See http://www.codebykevin.com/opensource/tutorial.html for more information.
jt: Section 1.4 needs to be amended a bit. Apple delivers a precompiled vi and emacs within the Mac OS X Developer Tools package [L6 ] (downloadable through a free ADC account). I personally use emacs-x11 [L7 ] (not to be confused with xemacs [L8 ]) which is installable through Fink [L9 ].
UKo 2005-01-19: just tweaked the layout a little bit to get a better handling. (there is absolutely a need for wikit to support structure for documents)
I have to investigate some questions to make my Tcl apps behave and look better on OS X:
How to bind something to the 'Quit' menu?
DAS: do you mean the application menu 'Quit' item? all this does is send Wish a kAEQuitApplication apple event, the default handler for that event runs [exit], you can either rename that command, or install your own kAEQuitApplication apple event handler, e.g. with TclAE.
UKo: Can you give an example on how to achieve this? I was not able to understand the TclAE documentation -- there is so much more to give than just the event name ...
Ashley Ward: The following did some of what I wanted: not sure if it is quite what you need, UKo...
bind . <Command-q> { exit }
Why is java able to change the apps name in the first menu and Tcl isn't? The normal java program just displays the class name but this can be changed from within the program (without using a app-bundle!).
DAS: there is no public API to change the application name, Java uses a private Apple-internal SPI.
UKo: Wouldn't it be a "good thing to do", to make something like the com.apple.mrj package for Tcl (or integrate it into the core) that gives us all the nuts and bolts to make real OSX applications?
Kevin Walzer: You can change the application name in the menu by editing the info.plist file in the Wish application bundle, and defining your own "Apple" menu in the code of your script. It's not hard to make your application compliant with the Apple/Aqua HIG via these methods, and you can also use the Tile extension package to help with the Aqua-native appearance as well. See http://www.codebykevin.com/opensource/tutorial.html for more information.
peterc: ActiveState's TDK provides convenient support for generating application bundles as one of the final steps in the starpack wrapping process. It provides a handy dialog for editing info.plist data and also allows you to specify a custom .icns icon file. Other things to watch out for if you're doing cross-platform apps is OS-specific conventions for menu item placement. For example, your About and Check For Updates entries go in your Help menu on Windows/X11 but in the Apple menu on Mac.
Jasper Taylor: I have a question that doesn't appear to be answered here. The Wish application includes a help menu, and I can install extra entries in it as described in section 4.4 above. However I cannot set a command to execute when the 'Wish Help' entry in this menu is selected, nor can I delete this command since it isn't actually listed as a menu entry. I wondered if there was an AppleEvent corresponding to it, since like the Preferences command it exists in all Mac apps. However I had a quick look through the Apple documentation and can see no reference to an event for the default Help command. So, anyone out there with a clue?
Kevin Walzer: I'm not sure I follow your question: Wish.app does not include a help menu by default. Launch Wish.app without sourcing a Tcl script and you'll see. You have to define the help menu item and the command procedures to launch it. There are no built-in Apple Events to do this: many Tcl/Tk applications simply define the help procedure as a varation of exec open /path/to/help/index.html, which opens the help index page in the default browser. Now, if you do include a help menu, that is automatically placed at the end of the menu: perhaps that's what you are thinking of?
I have written a Tcl wrapper for the most common Apple Carbon Help API functions, which will register a standard Apple Help book and load the help book into the Help Viewer. See tclAppleHelp for the particulars. This extension can be easily compiled with critcl. This extension provides the Apple events you are referring to, though you still have to prepare the help documents with the correct HTML tags, correct identification in the info.plist file, and so on, in accordance with the Apple documentation.
Gary Newby: Or.. just set the creator code of the doc you want opened in Help Viewer to "hbwr" "TEXT" and issue an "exec open docname.htm". Works fine for me in Tiger/Panther.
peterc 2008-11-19: Personally, I use a urlOpen proc which sends the user to the documentation index on my web site. However, I do like Gary Newby's idea above: often the time you need documentation is the day the networks are playing up (Murphy's Law).
hans: I found '::tk::mac::Quit', which seems like a better option than overriding 'exit' for handling kAEQuitApplication events.
chrstphrchvz - 2019-07-17: The old Mac Tk FAQ can still be found from a search engine: https://www.tcl-lang.org/software/mac/macFAQ.tml?sc_format=wider . Should it be taken down?
2019-09-03: The tcl-mac mailing list has been virtually dead for the past few years; I have opened a ticket to see if it can be discontinued. I would recommend new questions be asked on comp.lang.tcl or the issue trackers instead, where they are much more likely to get a response.