• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..17-Jun-2021-

Tk.xcode/H17-Jun-2021-6,1606,148

Tk.xcodeproj/H17-Jun-2021-6,3186,306

Credits.html.inH A D07-Jun-2021793 2524

GNUmakefileH A D07-Jun-202111.3 KiB315221

READMEH A D07-Jun-202140.2 KiB763660

Tk-Common.xcconfigH A D07-Jun-20212 KiB4745

Tk-Debug.xcconfigH A D07-Jun-2021661 2017

Tk-Info.plist.inH A D07-Jun-20211.5 KiB4234

Tk-Release.xcconfigH A D07-Jun-2021673 2017

Wish-Info.plist.inH A D07-Jun-20213.1 KiB109101

Wish.sdefH A D07-Jun-20211.7 KiB4738

configureH A D09-Jun-2021268.9 KiB9,7007,743

configure.acH A D07-Jun-2021429 128

license.termsH A D07-Jun-20212.2 KiB4136

tkMacOSX.hH A D07-Jun-20211,016 3512

tkMacOSXBitmap.cH A D07-Jun-202111.1 KiB426268

tkMacOSXButton.cH A D07-Jun-202132.9 KiB1,199720

tkMacOSXClipboard.cH A D07-Jun-20217.7 KiB304152

tkMacOSXColor.cH A D07-Jun-202120.6 KiB783438

tkMacOSXColor.hH A D07-Jun-202111 KiB200124

tkMacOSXConfig.cH A D07-Jun-20211.2 KiB5712

tkMacOSXConstants.hH A D07-Jun-20214.7 KiB12089

tkMacOSXCursor.cH A D07-Jun-202119.7 KiB569373

tkMacOSXCursors.hH A D07-Jun-20214.2 KiB9066

tkMacOSXDebug.cH A D07-Jun-20214.3 KiB16797

tkMacOSXDebug.hH A D07-Jun-2021953 3514

tkMacOSXDefault.hH A D07-Jun-202118.2 KiB572428

tkMacOSXDialog.cH A D07-Jun-202157.9 KiB2,1341,525

tkMacOSXDraw.cH A D07-Jun-202145.1 KiB1,7731,040

tkMacOSXEmbed.cH A D07-Jun-202132.8 KiB1,202530

tkMacOSXEntry.cH A D07-Jun-20217.7 KiB284133

tkMacOSXEvent.cH A D07-Jun-20213.4 KiB13794

tkMacOSXFont.cH A D07-Jun-202143.2 KiB1,444776

tkMacOSXFont.hH A D07-Jun-2021798 339

tkMacOSXHLEvents.cH A D07-Jun-202119.6 KiB655390

tkMacOSXImage.cH A D07-Jun-202129 KiB1,021592

tkMacOSXInit.cH A D07-Jun-202121.8 KiB800383

tkMacOSXInt.hH A D07-Jun-20214.4 KiB18698

tkMacOSXKeyEvent.cH A D07-Jun-202123.3 KiB887521

tkMacOSXKeyboard.cH A D07-Jun-202128.7 KiB968405

tkMacOSXKeysyms.hH A D07-Jun-202148.9 KiB1,3091,259

tkMacOSXMenu.cH A D07-Jun-202154.5 KiB2,0361,113

tkMacOSXMenubutton.cH A D07-Jun-202123.3 KiB819454

tkMacOSXMenus.cH A D07-Jun-202115.1 KiB561414

tkMacOSXMouseEvent.cH A D07-Jun-202120.5 KiB797461

tkMacOSXNotify.cH A D07-Jun-202117.4 KiB625312

tkMacOSXPort.hH A D07-Jun-20213.7 KiB17492

tkMacOSXPrivate.hH A D07-Jun-202118.7 KiB586397

tkMacOSXRegion.cH A D07-Jun-202112.2 KiB615280

tkMacOSXScale.cH A D07-Jun-202111.4 KiB471235

tkMacOSXScrlbr.cH A D07-Jun-202123.3 KiB802424

tkMacOSXSend.cH A D07-Jun-202115.5 KiB517186

tkMacOSXServices.cH A D07-Jun-20214.1 KiB16386

tkMacOSXSubwindows.cH A D07-Jun-202135.1 KiB1,460710

tkMacOSXSysTray.cH A D07-Jun-202123.1 KiB870496

tkMacOSXTest.cH A D07-Jun-202110 KiB391251

tkMacOSXWindowEvent.cH A D07-Jun-202136.4 KiB1,340753

tkMacOSXWm.cH A D07-Jun-2021205 KiB7,3114,481

tkMacOSXWm.hH A D07-Jun-202110 KiB27879

tkMacOSXXCursors.hH A D07-Jun-202136.9 KiB712618

tkMacOSXXStubs.cH A D07-Jun-202124.7 KiB1,259789

ttkMacOSXTheme.cH A D07-Jun-2021102.3 KiB3,3272,339

README

1Tcl/Tk macOS README
2----------------------
3
4This is the README file for the macOS/Darwin version of Tcl/Tk.
5
61. Where to go for support
7--------------------------
8
9- The tcl-mac mailing list on sourceforge is the best place to ask questions
10specific to Tcl & Tk on macOS:
11	http://lists.sourceforge.net/lists/listinfo/tcl-mac
12(this page also has a link to searchable archives of the list, please check them
13before asking on the list, many questions have already been answered).
14
15- For general Tcl/Tk questions, the newsgroup comp.lang.tcl is your best bet:
16	http://groups.google.com/group/comp.lang.tcl/
17
18- The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on macOS, see
19	https://wiki.tcl-lang.org/page/MacOS
20
21- Please report bugs with Tk on macOS to the tracker:
22	https://core.tcl-lang.org/tk/reportlist
23
242. Using Tcl/Tk on macOS
25---------------------------
26
27- There are two versions of Tk available on macOS: TkAqua using the native
28aqua widgets and look&feel, and TkX11 using the traditional unix X11 widgets.
29TkX11 requires an X11 server to be installed, such as XQuartz (available from www.xquartz.org).
30TkAqua and TkX11 can be distinguished at runtime via [tk windowingsystem].
31
32- At a minimum, macOS 10.3 is required to run Tcl and TkX11.
33TkAqua requires macOS 10.6 or later.
34
35- Unless weak-linking is used, Tcl/Tk built on macOS 10.x will not run on
3610.y with y < x; on the other hand Tcl/Tk built on 10.y will always run on 10.x
37with y <= x (but without any of the fixes and optimizations that would be
38available in a binary built on 10.x).
39Weak-linking is available on OS X 10.2 or later, it additionally allows Tcl/Tk
40built on 10.x to run on any 10.y with x > y >= z (for a chosen z >= 2).
41
42- Wish checks the Resources/Scripts directory in its application bundle for a
43file called AppMain.tcl, if found it is used as the startup script and the
44Scripts folder is added to the auto_path. This can be used to emulate the old
45OS9 TclTk droplets.
46
47- If standard input is a special file of zero length (e.g. /dev/null), Wish
48brings up the Tk console window at startup. This is the case when double
49clicking Wish in the Finder (or using 'open Wish.app' from the Terminal).
50
51- Tcl extensions can be installed in any of:
52	$HOME/Library/Tcl /Library/Tcl
53	$HOME/Library/Frameworks /Library/Frameworks
54	(searched in that order).
55Given a potential package directory $pkg, Tcl on OSX checks for the file
56$pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl.
57This allows building extensions as frameworks with all script files contained in
58the Resources/Scripts directory of the framework.
59
60- The 'deploy' target of macosx/GNUmakefile installs the html manpages into the
61standard documentation location in the Tcl/Tk frameworks:
62	Tcl.framework/Resources/Documentation/Reference/Tcl
63	Tk.framework/Resources/Documentation/Reference/Tk
64No nroff manpages are installed by default by the GNUmakefile.
65
66- The Tcl and Tk frameworks can be installed in any of the system's standard
67framework directories:
68	$HOME/Library/Frameworks /Library/Frameworks
69
70- ${prefix}/bin/wish8.x is a script that calls a copy of 'Wish' contained in
71	Tk.framework/Resources
72
73- if 'Wish' is started from the Finder or via 'open', $argv may contain a
74"-psn_XXXX" argument. This is the process serial number, you may need to filter
75it out for cross platform compatibility of your scripts.
76
77- the env array is different when Wish is started from the Finder (i.e. via
78LaunchServices) than when it (or tclsh) is invoked from the Terminal, in
79particular PATH may not be what you expect. (Wish started by LaunchServices
80inherits loginwindow's environment variables, which are essentially those set in
81$HOME/.MacOSX/environment.plist, and are unrelated to those set in your shell).
82
83- TkAqua provides access to native OS X images via the Tk native bitmap facility
84(including any image file readable by NSImage). A native bitmap name is
85interpreted as follows (in order):
86    - predefined builtin 32x32 icon name (stop, caution, document, etc)
87    - name defined by [tk::mac::iconBitmap]
88    - NSImage named image name
89    - NSImage url string
90    - 4-char OSType of IconServices icon
91the syntax of [tk::mac::iconBitmap] is as follows:
92	tk::mac::iconBitmap name width height -kind value
93where -kind is one of
94    -file	    icon of file at given path
95    -fileType	    icon of given file type
96    -osType	    icon of given 4-char OSType file type
97    -systemType	    icon for given IconServices 4-char OSType
98    -namedImage	    named NSImage for given name
99    -imageFile	    image at given path
100This support was added with the Cocoa-based Tk 8.5.7.
101
102- TkAqua cursor names are interpred as follows (in order):
103    - standard or platform-specific Tk cursor name (c.f. cursors.n)
104    - @path to any image file readable by NSImage
105    - NSImage named image name
106Support for the latter two was added with the Cocoa-based Tk 8.5.7.
107
108- The standard Tk dialog commands [tk_getOpenFile], [tk_chooseDirectory],
109[tk_getSaveFile] and [tk_messageBox] all take an additional optional -command
110parameter on TkAqua. If it is present, the given command prefix is evaluated at
111the global level when the dialog closes, with the dialog command's result
112appended (the dialog command itself returning an emtpy result). If the -parent
113option is also present, the dialog is configured as a modeless (window-modal)
114sheet attached to the parent window and the dialog command returns immediately.
115Support for -command was added with the Cocoa-based Tk 8.5.7.
116
117- The TkAqua-specific [tk::mac::standardAboutPanel] command brings the standard
118Cocoa about panel to the front, with all its information filled in from your
119application bundle files (i.e. standard about panel with no options specified).
120See Apple Technote TN2179 and the AppKit documentation for -[NSApplication
121orderFrontStandardAboutPanelWithOptions:] for details on the Info.plist keys and
122app bundle files used by the about panel.
123This support was added with the Cocoa-based Tk 8.5.7.
124
125- TkAqua has three special menu names that give access to the standard
126Application, Window and Help menus, see menu.n for details.  By default, the
127platform-specific standard Help menu item "YourApp Help" performs the default
128Cocoa action of showing the Help Book configured in the application's
129Info.plist (or displaying an alert if no Help Book is set). This action can be
130customized by defining a procedure named [tk::mac::ShowHelp]. If present, this
131procedure is invoked instead by the standard Help menu item.  Support for the
132Window menu and [tk::mac::ShowHelp] was added with the Cocoa-based Tk 8.5.7.
133
134- The TkAqua-specific command [tk::unsupported::MacWindowStyle style] is used to
135get and set macOS-specific toplevel window class and attributes. Note that
136the window class and many attributes have to be set before the window is first
137mapped for the change to have any effect.
138The command has the following syntax:
139	tk::unsupported::MacWindowStyle style window ?class? ?attributes?
140The 2 argument form returns a list of the current class and attributes for the
141given window. The 3 argument form sets the class for the given window using the
142default attributes for that class. The 4 argument form sets the class and the
143list of attributes for the given window.
144Window class names:
145    document, modal, floating, utility, toolbar, simple, help, overlay
146Window attribute names:
147    standardDocument, standardFloating, resizable, fullZoom, horizontalZoom,
148    verticalZoom, closeBox, collapseBox, toolbarButton, sideTitlebar,
149    noTitleBar, unifiedTitleAndToolbar, metal, hud, noShadow, doesNotCycle,
150    noActivates, hideOnSuspend, inWindowMenu, ignoreClicks, doesNotHide,
151    canJoinAllSpaces, moveToActiveSpace, nonActivating
152
153Note that not all attributes are valid for all window classes.  Support for the
1543 argument form was added with the Cocoa-based Tk 8.5.7, at the same time
155support for some legacy Carbon-specific classes and attributes was removed
156(they are still accepted by the command but no longer have any effect).
157
158- Another command available in the tk::unsupported::MacWindowStyle namespace is:
159  tk::unsupported::MacWindowStyle tabbingid window ?newId?
160which can be used to get or set the tabbingIdentifier for the NSWindow
161associated with a Tk Window.  See section 3 for details.
162
163- The command:
164  tk::unsupported::MacWindowStyle appearance window ?newAppearance?
165is available when Tk is built and run on macOS 10.14 (Mojave) or later.  In
166that case the Ttk widgets all support the "Dark Mode" appearance which was
167introduced in 10.14. The command accepts the following values for the optional
168newAppearance option: "aqua", "darkaqua", or "auto".  If the appearance is set
169to aqua or darkaqua then the window will be displayed with the corresponding
170appearance independent of any preferences settings.  If it is set to "auto"
171the appearance will be determined by the preferences.  This command can be
172used to opt out of Dark Mode on a per-window basis.  It may be best to run the "update" command before setting the appearance property, to allow the event loop to run.
173
174
175- To determine the current appearance of a window in macOS 10.14 (Mojave) and
176higher, one can use the command:
177  tk::unsupported::MacWindowStyle isdark
178The boolean return value is true if the window is currently displayed with the
179dark appearance.
180
181- If you want to use Remote Debugging with Xcode, you need to set the
182environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
183cause us to force closing stdin & stdout.  Otherwise, given how Xcode launches
184Wish remotely, they will be left open and then Wish & gdb will fight for stdin.
185
1863. FullScreen, Split View and Tabbed Windows
187--------------------------------------------
188
189Since the release of OSX 10.6 (Snow Leopard) a steadily expanding sequence of
190high level window operations have been added to Apple's window manager.  These
191operations are launched by user actions which are handled directly by the
192window manager; they are not initiated by the application.  In some, but not
193all cases, the application is notified before and after the operations are
194carried out.
195
196In OSX releases up to and including 10.6 there were three buttons with
197stoplight colors located on the left side of a window's title bar.  The
198function of the green button was to "zoom" or "maximize" the window, i.e. to
199expand the window so that it fills the entire screen, while preserving the
200appearance of the window including its title bar.  The release of OSX 10.7
201(Lion) introduced the "FullScreen" window which not only filled the screen but
202also hid the window's title bar and the menu bar which normally appears at the
203top of the screen. These hidden objects would only become visible when the
204mouse hovered near the top of the screen.  FullScreen mode was initiated by
205pressing a button showing two outward pointing arrows located on the right side
206of the title bar; it was terminated by pressing a similar button with inward
207pointing arrows on the right hand side of the menu bar.  In OSX 10.10
208(Yosemite) the FullScreen button was removed. The green button was repurposed
209to cause a window to become a FullScreen window. To zoom a window the user had
210to hold down the option key while pressing the green button.  The release of
211OSX 10.11 added a third function to the green button: to create two half-screen
212windows with hidden title bars and a hidden menu bar, called Split View
213windows.  If the green button is held down for one second its window expands to
214fill half of the screen.  It can be moved to one side or the other with the
215mouse.  The opposite side shows thumbnail images of other windows.  Selecting
216one of the thumbnails expands its window to fill that half of the screen.  The
217divider between the two windows can be moved to adjust the percentage of the
218screen occupied by each of the two tiles.  In OSX 10.12 (Sierra) Tabbed windows
219were introduced.  These allow an application with multiple windows to display
220its windows as tabs within a single window frame.  Clicking on a tab brings its
221window into view.  Tabs can be rearranged by dragging.  Dragging a tab to the
222desktop turns it into a separate window.  Items in the Window menu can be used
223to cycle through the tabs, move tabbed windows to separate windows, or merge a
224set of separate windows as tabs in the same window frame.
225
226Tk now fully supports all of these high level window operations on any system
227where the operation exists.  The FullScreen and Split View windows are handled
228automatically with no action required on the part of the programmer.  Tabbed
229windows, on the other hand, require some attention from the programmer.
230Because many of the operations with tabs are handled through the application's
231Window menu, it is essential that an application provide a Windows menu to
232avoid presenting a confusing interface to the user. This cannot be ignored, in
233part because the systemwide Dock Preferences offers an option to always attempt
234to open application windows as tabs. An application which does not provide a
235Window menu will necessarily present a confusing interface to any user who has
236selected this option.
237
238A further complication is that it is not neccessarily appropriate for all of an
239application's windows to be grouped together as tabs in the same frame.  In
240fact, the Apple guidelines insist that windows which are grouped together as
241tabs should be similar to each other.  The mechanism provided for arranging
242this was to assign to each NSwindow a tabbingIdentifier, and to require that
243all windows grouped together as tabs in the same window frame must have the
244same tabbingIdentifier.  A tabbingIdentifier is implemented as an arbitrary
245string, and a system-generated default tabbingIdentifier is provided to all new
246windows.
247
248Tk provides a means for getting and setting the tabbingIdentifier of
249the NSWindow underlying a Tk Window. This is handled by the command
250
251tk::unsupported::MacWindowStyle tabbingid window ?newId?
252
253(This command generates an error if used on OSX 10.11 or earlier, since the
254tabbingIdentifier does not exist on those systems.)  The command returns the
255tabbingIdentifier which had been assigned to the window prior to execution of
256the command.  If the optional newId argument is omitted, the window's
257tabbingIdentifier is not changed.  Otherwise it is set to the string specified
258by the argument.
259
260Since NSWindows can only be grouped together as tabs if they all have the same
261tabbingIdentifier, one can prevent a window from becoming a tab by giving it a
262unique tabbingIdentifier. This is independent of any preferences setting. To
263ensure that we maintain consistency, changing the tabbingIdentifier of a window
264which is already displayed as a tab will also cause it to become a separate
265window.
266
2674. Ttk, Dark Mode and semantic colors
268---------------------------------------
269
270With the release of OSX 10.14 (Mojave), Apple introduced the DarkAqua
271appearance.  Part of the implementation of the Dark Mode was to make
272some of the named NSColors have dynamic values.  Apple calls these
273"semantic colors" because the name does not specify a specific color,
274but rather refers to the context in which the color should be used.
275In particular, when a user selects Dark Mode in the system preferences
276these colors change appearance.  For example systemTextColor is dark in
277Aqua and light in DarkAqua.
278
279Tk now provides colors corresponding to all of the NSColors in Apple's System
280ColorList.  The convention for naming these colors is that the Tk name is
281generated by capitalizing the macOS name and adding the prefix "system". The
282System ColorList differs between releases of macOS and some colors, such as
283systemLinkColor and systemControlAccentColor, are simulated on older systems
284which did not provide them.  The following colors are available on all
285supported macOS releases, although newer systems will support additional
286colors: systemControlAccentColor, systemControlTextColor,
287systemDisabledControlTextColor, systemLabelColor, systemLinkColor,
288systemPlaceholderTextColor, systemSelectedTextBackgroundColor,
289systemSelectedTextColor, systemSeparatorColor, systemTextBackgroundColor, and
290systemTextColor.  One additional color, systemSelectedTabTextColor, does not
291exist in macOS but is used by Tk to match the different colors used for
292Notebook tab titles in different OS versions.
293
294The default background and foreground colors of most of the Tk widgets
295have been set to semantic colors, which means that the widgets will change
296appearance, and remain usable, when Dark Mode is selected in the system
297preferences.  However, to get a close match to the native Dark Mode style it
298is recommended to use Ttk widgets when possible.
299
300Apple's tab view and GroupBox objects delimit their content by
301displaying it within a rounded rectangle with a background color that
302contrasts with the background of the containing object.  This means
303that the background color of a Ttk widget depends on how deeply it is
304nested inside of other widgets that use contrasting backgrounds.  To
305support this, there are 8 contrasting system colors named
306systemWindowBackgroundColor, and systemWindowBackgroundColor1 - 7.
307The systemWindowBackgroundColor is the standard background for a
308dialog window and the others match the contrasting background colors
309used in ttk::notebooks and ttk::labelframes which are nested to the
310corresponding depth.
311
3125. Building Tcl/Tk on macOS
313------------------------------
314
315- macOS 10.6 is required to build TkAqua and TkX11.  The XCode application provides everything needed to build Tk, but it is not necessary to install the full XCode.
316It suffices to install the Command Line Tools package, which can be done
317by running the command:
318xcode-select --install
319
320- Tcl/Tk are most easily built as macOS frameworks via GNUmakefile in
321tcl/macosx and tk/macosx (see below for details), but can also be built with the
322standard unix configure and make buildsystem in tcl/unix resp. tk/unix as on any
323other unix platform (indeed, the GNUmakefiles are just wrappers around the unix
324buildsystem).
325The macOS specific configure flags are --enable-aqua, --enable-framework and
326--disable-corefoundation (which disables CF and notably reverts to the standard
327select based notifier). Note that --enable-aqua is incompatible with
328--disable-corefoundation (for both Tcl and Tk configure).
329
330- It was once possible to build with the Xcode IDE via the projects in
331tk/macosx, but this has not been tested recently. Take care to use the
332project matching your DevTools and OS version:
333	Tk.xcode: 		    for Xcode 3.1 on 10.5
334	Tk.xcodeproj:		    for Xcode 3.2 on 10.6
335These have the following targets:
336	Tk:			    calls through to tk/macosx/GNUMakefile,
337				    requires a corresponding build of the Tcl
338				    target of tcl/macosx/Tcl.xcode.
339	tktest:			    static build of TkAqua tktest for debugging.
340	tktest-X11:		    static build of TkX11 tktest for debugging.
341The following build configurations are available:
342	Debug:			    debug build for the active architecture,
343				    with Fix & Continue enabled.
344	Debug clang:		    use clang compiler.
345	Debug llvm-gcc:		    use llvm-gcc compiler.
346	Debug gcc40:		    use gcc 4.0 compiler.
347	DebugNoGC:		    disable Objective-C garbage collection.
348	DebugNoFixAndContinue:      disable Fix & Continue.
349	DebugUnthreaded:	    disable threading.
350	DebugNoCF:		    disable corefoundation (X11 only).
351	DebugNoCFUnthreaded:	    disable corefoundation an threading.
352	DebugMemCompile:	    enable memory and bytecode debugging.
353	DebugLeaks:		    define PURIFY.
354	DebugGCov:		    enable generation of gcov data files.
355	Debug64bit:		    configure with --enable-64bit (requires
356				    building on a 64bit capable processor).
357	Release:		    release build for the active architecture.
358	ReleaseUniversal:	    32/64-bit universal build.
359	ReleaseUniversal clang:	    use clang compiler.
360	ReleaseUniversal llvm-gcc:  use llvm-gcc compiler.
361	ReleaseUniversal gcc40:	    use gcc 4.0 compiler.
362	ReleaseUniversal10.5SDK:    build against the 10.5 SDK (with 10.5
363				    deployment target).
364	Note that the non-SDK configurations have their deployment target set to
365	10.5 (Tk.xcode) resp. 10.6 (Tk.xcodeproj).
366The Xcode projects refer to the toplevel tcl and tk source directories via the
367the TCL_SRCROOT and TK_SRCROOT user build settings, by default these are set to
368the project-relative paths '../../tcl' and '../../tk', if your source
369directories are named differently, e.g. '../../tcl8.6' and '../../tk8.6', you
370need to manually change the TCL_SRCROOT and TK_SRCROOT settings by editing your
371${USER}.pbxuser file (located inside the Tk.xcodeproj bundle directory) with a
372text editor.
373
374- To enable weak-linking, set the MACOSX_DEPLOYMENT_TARGET environment variable
375to the minimal OS version the binaries should be able to run on, e.g:
376	export MACOSX_DEPLOYMENT_TARGET=10.6
377This requires at least gcc 3.1; with gcc 4 or later, set/add to CFLAGS instead:
378	export CFLAGS="-mmacosx-version-min=10.6"
379Support for weak-linking was added with 8.4.14/8.5a5.
380
381Detailed Instructions for building with macosx/GNUmakefile
382----------------------------------------------------------
383
384- Unpack the Tcl and Tk source release archives and place the tcl and tk source
385trees in a common parent directory.
386[ If you don't want have the two source trees in one directory, you'll need to ]
387[ create the following symbolic link for the build to work as setup by default ]
388[      ln -fs /path_to_tcl/build /path_to_tk/build			       ]
389[ (where /path_to_{tcl,tk} is the directory containing the tcl resp. tk tree)  ]
390[ or you can pass an argument of BUILD_DIR=/somewhere to the tcl and tk make.  ]
391
392- The following instructions assume the Tcl and Tk source trees are named
393"tcl${ver}" and "tk${ver}" (where ${ver} is a shell variable containing the
394Tcl/Tk version number, e.g. '8.6').
395Setup this shell variable as follows:
396	ver="8.6"
397If you are building from CVS, omit this step (CVS source tree names usually do
398not contain a version number).
399
400- Setup environment variables as desired, e.g. for a universal build on 10.5:
401	CFLAGS="-arch i386 -arch x86_64 -arch ppc -mmacosx-version-min=10.5"
402	export CFLAGS
403
404- Change to the directory containing the Tcl and Tk source trees and build:
405	make -C tcl${ver}/macosx
406	make -C tk${ver}/macosx
407
408- Install Tcl and Tk onto the root volume (admin password required):
409	sudo make -C tcl${ver}/macosx install
410	sudo make -C tk${ver}/macosx  install
411if you don't have an admin password, you can install into your home directory
412instead by passing an INSTALL_ROOT argument to make:
413	make -C tcl${ver}/macosx install INSTALL_ROOT="${HOME}/"
414	make -C tk${ver}/macosx  install INSTALL_ROOT="${HOME}/"
415
416- The default GNUmakefile targets will build _both_ debug and optimized versions
417of the Tcl and Tk frameworks with the standard convention of naming the debug
418library Tcl.framework/Tcl_debug resp. Tk.framework/Tk_debug.
419This allows switching to the debug libraries at runtime by setting
420	export DYLD_IMAGE_SUFFIX=_debug
421(c.f. man dyld for more details)
422
423If you only want to build and install the debug or optimized build, use the
424'develop' or 'deploy' target variants of the GNUmakefile, respectively.
425For example, to build and install only the optimized versions:
426	make -C tcl${ver}/macosx deploy
427	make -C tk${ver}/macosx deploy
428	sudo make -C tcl${ver}/macosx install-deploy
429	sudo make -C tk${ver}/macosx  install-deploy
430
431- The GNUmakefile can also build a version of Wish.app that has the Tcl and Tk
432frameworks embedded in its application package. This allows for standalone
433deployment of the application with no installation required, e.g. from read-only
434media. To build & install in this manner, use the 'embedded' variants of
435the GNUmakefile targets.
436For example, to build a standalone 'Wish.app' in ./emb/Applications/Utilities:
437	make -C tcl${ver}/macosx embedded
438	make -C tk${ver}/macosx embedded
439	sudo make -C tcl${ver}/macosx install-embedded INSTALL_ROOT=`pwd`/emb/
440	sudo make -C tk${ver}/macosx  install-embedded INSTALL_ROOT=`pwd`/emb/
441Notes:
442  * if you've already built standard TclTkAqua, building embedded does not
443  require any new compiling or linking, so you can skip the first two makes.
444  (making relinking unnecessary was added with 8.4.2)
445  * the embedded frameworks include only optimized builds and no documentation.
446  * the standalone Wish has the directory Wish.app/Contents/lib in its
447  auto_path. Thus you can place tcl extensions in this directory (i.e. embed
448  them in the app package) and load them with [package require].
449
450- It is possible to build Tk against an installed Tcl.framework; but you will
451still need a tcl sourcetree in the location specified in TCL_SRC_DIR in
452Tcl.framework/tclConfig.sh. Also, linking with Tcl.framework has to work exactly
453as indicated in TCL_LIB_SPEC in Tcl.framework/tclConfig.sh.
454If you used non-default install locations for Tcl.framework, specify them as
455make overrides to the tk/macosx GNUmakefile, e.g.
456	make -C tk${ver}/macosx \
457	    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
458	sudo make -C tk${ver}/macosx install \
459	    TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
460The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.
461
462- To build a Tcl.framework and Tk.framework for use as subframeworks in another
463framework, use the install-embedded target and set SUBFRAMEWORK=1.  Set the
464DYLIB_INSTALL_DIR variable to the path which should be the install_name path of
465the shared library and set the DESTDIR variable to the pathname of a staging
466directory where the frameworks will be written.  The Tcl framework must be
467built first.
468For example, running the commands:
469	make -C ../tcl8.6/macosx install-embedded SUBFRAMEWORK=1 DESTDIR=/tmp/tcltk \
470	DYLIB_INSTALL_DIR=/Library/Frameworks/Some.framework/Versions/X.Y/Frameworks/Tcl.framework
471	make -C macosx install-embedded SUBFRAMEWORK=1 DESTDIR=/tmp/tcltk \
472	DYLIB_INSTALL_DIR=/Library/Frameworks/Some.framework/Versions/X.Y/Frameworks/Tk.framework
473will produce a Tcl.framework and a Tk.framework usable as subframeworks of
474Some.framework.  The frameworks will be found in /tmp/tcltk/Frameworks/
475
4765. Details regarding the macOS port of Tk.
477-------------------------------------------
478
4795.1 About the event loop
480~~~~~~~~~~~~~~~~~~~~~~~~
481
482The main program in a typical OSX application looks like this (see
483https://developer.apple.com/library/mac/documentation/Cocoa/\
484Reference/ApplicationKit/Classes/NSApplication_Class)
485
486    void NSApplicationMain(int argc, char *argv[]) {
487        [NSApplication sharedApplication];
488        [NSBundle loadNibNamed:@"myMain" owner:NSApp];
489        [NSApp run];
490    }
491Here NSApp is a standard global variable, initialized by the OS, which
492points to an object in a subclass of NSApplication (called
493TKApplication in the case of the macOS port of Tk).
494
495The [NSApp run] method implements the event loop for a typical Mac
496application.  There are three key steps in the run method.  First it
497calls [NSApp finishLaunching], which creates the bouncing application
498icon and does other mysterious things. Second it creates an
499NSAutoreleasePool.  Third, it starts an event loop which drains the
500NSAutoreleasePool every time the queue is empty, and replaces the
501drained pool with a new one.  This third step is essential to
502preventing memory leaks, since the internal methods of Appkit objects
503all assume that an autorelease pool is in scope and will be drained
504when the event processing cycle ends.
505
506The macOS Tk application does not call the [NSApp run] method at
507all.  Instead it uses the event loop built in to Tk.  So the
508application must take care to replicate the important features of the
509method ourselves.  The way that autorelease pools are handled is
510discussed in 5.2 below.  Here we discuss the event handling itself.
511
512The Tcl event loop simply consists of repeated calls to TclDoOneEvent.
513Each call to TclDoOneEvent begins by collecting all pending events from
514an "event source", converting them to Tcl events and adding them
515to the Tcl event queue. For macOS, the event source is the NSApp
516object, which maintains an event queue even though its run method
517will never be called to process them.  The NSApp provides methods for
518inspecting the queue and removing events from it as well as the
519[NSApp sendevent] which sends an event to all of the application's
520NSWindows which can then send it to subwindows, etc.
521
522The event collection process consists of first calling a platform
523specific SetupProc and then a platform specific CheckProc.  In
524the macOS port, these are named TkMacOSXEventsSetupProc and
525TkMacOSXEventsCheckProc.
526
527It is important to understand that the Apple window manager does not
528have the concept of an expose event.  Their replacement for an expose
529event is to have the window manager call the [NSView drawRect] method
530in any situation where an expose event for that NSView would be
531generated in X11.  The [NSView drawRect] method is a no-op which is
532expected to be overridden by any application.  In the case of Tcl, the
533replacement [NSView drawRect] method creates a Tcl expose event
534for each dirty rectangle of the NSView, and then adds the expose
535event to the Tcl queue.
536
537
5385.2 Autorelease pools
539~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
540
541In order to carry out the job of managing autorelease pools, which
542would normally be handled by the [NSApp run] method, a private
543NSAutoreleasePool* property is added to the TkApplication subclass of
544NSApplication. The TkpInit function calls [NSApp _setup] which
545initializes this property by creating an NSAutoreleasePool prior to
546calling [NSApp finishLaunching].  This mimics the behavior of the
547[NSApp run] method, which calls [NSApp finishLaunching] just before
548starting the event loop.
549
550Since the CheckProc function gets called for every Tk event, it is an
551appropriate place to drain the main NSAutoreleasePool and replace it
552with a new pool.  This is done by calling the method [NSApp
553_resetAutoreleasePool], where _resetAutoreleasePool is a method which
554we define for the subclass.  Unfortunately, by itself this is not
555sufficient for safe memory managememt because, as was made painfully
556evident with the release of OS X 10.13, it is possible for calls to
557TclDoOneEvent, and hence to CheckProc, to be nested.  Draining the
558autorelease pool in a nested call leads to crashes as objects in use
559by the outer call can get freed by the inner call and then reused later.
560One particular situation where this happens is when a modal dialogue
561gets posted by a Tk Application.  To address this, the NSApp object
562also implements a semaphore to prevent draining the autorelease pool
563in nested calls to CheckProc.
564
565One additional minor caveat for developers is that there are several
566steps of the Tk initialization which precede the call to TkpInit.
567Notably, the font package is initialized first.  Since there is no
568NSAutoreleasePool in scope prior to calling TkpInit, the functions
569called in these preliminary stages need to create and drain their own
570NSAutoreleasePools whenever they call methods of Appkit objects
571(e.g. NSFont).
572
5735.3 Clipping regions and "ghost windows"
574~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
575
576Another unusual aspect of the macOS port is its use of clipping
577regions.  It was part of Daniel Steffen's original design that the
578TkWindowPrivate struct maintains three HIShapeRef regions, named
579visRgn, aboveVisRgn and drawRgn.  These regions are used as clipping
580masks whenever drawing into an NSView.  The visRgn is the bounding box
581of the window with a rectangle removed for each subwindow and for each
582sibling window at a higher stacking level.  The drawRgn is the
583intersection of the visRgn with the clipping rectangle of the
584window. (Normally, the clipping rectangle is the same as the bounding
585rectangle, but drawing can be clipped to a smaller rectangle by
586calling TkpClipDrawableToRect.) The aboveVisRgn is the intersection of
587the window's bounding rectangle with the bounding rectangle of the
588parent window.  Much of the code in tkMacOSXSubwindows.c is devoted to
589rebuilding these clipping regions whenever something changes in the
590layout of the windows.  This turns out to be a tricky thing to do and
591it is extremely prone to errors which can be difficult to trace.
592
593It is not entirely clear what the original reason for using these
594clipping regions was.  But one benefit is that if they are correctly
595maintained then it allows windows to be drawn in any order.  You do
596not have to draw them in the order of the window hierarchy.  Each
597window can draw its entire rectangle through its own mask and never
598have to worry about drawing in the wrong place.  It is likely that
599the need for using clipping regions arose because, as Apple explicitly
600states in the documentation for [NSView subviews],
601
602    "The order of the subviews may be considered as being
603    back-to-front, but this does not imply invalidation and drawing
604    behavior."
605
606In the early versions of the macOS port, buttons were implemented as
607subviews of class TkButton.  This probably exacerbated the likelihood
608that Tk windows would need to be drawn in arbitrary order.
609
610The most obvious side effect caused by not maintaining the clipping
611regions is the appearance of so-called "ghost windows".  A common
612situation where these may arise is when a window containing buttons
613is being scrolled.  A user may see two images of the same button on
614the screen, one in the pre-scroll location and one in the post-scroll
615location.
616
617To see how these 'ghost windows' can arise, think about what happens if
618the clipping regions are not maintained correctly.  A window might
619have a rectangle missing from its clipping region because that
620rectangle is the bounding rectangle for a subwindow, say a button.
621The parent should not draw in the missing rectangle since doing so
622would trash the button.  The button is responsible for drawing
623there. Now imagine that the button gets moved, say by a scroll, but
624the missing rectangle in the parent's clipping region does not get
625moved correctly, or it gets moved later on, after the parent has
626redrawn itself.  The parent would still not be allowed to draw in the
627old rectangle, so the user would continue to see the image of the
628button in its old location, as well as another image in the new
629location.  This is a prototypical example of a "ghost window".
630Anytime you see a "ghost window", you should suspect problems with the
631updates to the clipping region visRgn.  It is natural to look for
632timing issues, race conditions, or other "event loop problems".  But
633in fact, the whole design of the code is to make those timing issues
634irrelevant.  As long as the clipping regions are correctly maintained
635the timing does not matter.  And if they are not correctly maintained
636then you will see "ghost windows".
637
638It is worth including a detailed description of one specific place
639where the failure to correctly maintain clipping regions caused "ghost
640window" artifacts that plagued the macOS port for years.  These
641occurred when scrolling a Text widget which contained embedded
642subwindows.  It involved some specific differences between the
643low-level behavior of Apple's window manager versus those of the other
644platforms, and the fix ultimately required changes in the generic Tk
645implementation (documented in the comments in the DisplayText
646function).
647
648The Text widget attempts to improve perfomance when scrolling by
649minimizing the number of text lines which need to be redisplayed.  It
650does this by calling the platform-specific TkScrollWindow function
651which uses a low-level routine to map one rectangle of the window to
652another.  The TkScrollWindow function returns a damage region which is
653then used by the Text widget's DisplayText function to determine which
654text lines need to be redrawn.  On the unix and win platforms, this
655damage region includes bounding rectangles for all embedded windows
656inside the Text widget.  The way that this works is system dependent.
657On unix, the low level scrolling is done by XCopyRegion, which
658generates a GraphicsExpose event for each embedded window.  These
659GraphicsExposed events are processsed within TkScrollWindow, using a
660special handler which adds the bounding rectangle of each subwindow to
661the damage region.  On the win platform the damage region is built by
662the low level function ScrollWindowEx, and it also includes bounding
663rectangles for all embedded windows.  This is possible because on X11
664and Windows every Tk widget is also known to the window manager as a
665window.  The situation is different on macOS.  The underlying object
666for a top level window on macOS is the NSView.  However, Apple
667explicitly warns in its documentation that performance degradation
668occurs when an NSView has more than about 100 subviews.  A Text widget
669with thousands of lines of text could easily contain more than 100
670embedded windows.  In fact, while the original Cocoa port of Tk did
671use the NSButton object, which is derived from NSView, as the basis
672for its Tk Buttons, that was changed in order to improve performance.
673Moreover, the low level routine used for scrolling on macOS, namely
674[NSView scrollrect:by], does not provide any damage information.  So
675TkScrollWindow needs to work differently on macOS.  Since it would be
676inefficient to iterate through all embedded windows in a Text widget,
677looking for those which meet the scrolling area, the damage region
678constructed by TkScrollWindow contains only the difference between the
679source and destination rectangles for the scrolling.  The embedded
680windows are redrawn within the DisplayText function by some
681conditional code which is only used for macOS.
682
6836.0 Virtual events on macOS 10.14 and later
684~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
685
686The 10.14 release added support for system appearance changes,
687including a "Dark Mode" that renders all window frames and menus in
688dark colors. Tk 8.6.11 provides three virtual events <<LightAqua>>,
689<<DarkAqua>> and <<AppearanceChanged>>, to allow you to update your Tk
690app's appearance when the system appearance changes.  These events are
691generated in [NSView effectiveAppearanceChanged], which is called by
692the Apple window manager when the General Preferences is changed
693either by switching between Light Mode and Dark Mode or by changing
694the Accent Color or Highlight Color.
695
696The <<AppearanceChanged>> virtual event has a data string which can be
697accessed with the %d substitution.  The format of the data string is
698that it consists of 6 words:
699  "Appearance XXXX Accent YYYY Highlight ZZZZ"
700For example, the following code will print the current appearance
701name, accent color and highlight color when the <<AppearanceChanged>>
702virtual event fires:
703
704bind . <<AppearanceChanged>> {
705    array set data [split %d]
706    puts "  Appearance: $data(Appearance)"
707    puts "  Accent: $data(Accent)"
708    puts "  Highlight: $data(Highlight)\n"
709}
710
711
712
7137.0 Mac Services
714~~~~~~~~~~~~~~~~~~~~~~~~~~~
715
716With 8.6.10, Tk supports the Mac's NSServices API, documented at
717https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/SysServices/introduction.html#//apple_ref/doc/uid/10000101-SW1
718and in TIP 536 and Tk's man page. Tk presents a simple,
719straightforward API to implement the Services functionality.
720
721The Tk implementation of the NSServices API is intended for standalone
722applications, such as one wrapped by the standalone version of Wish
723and re-named into a different application.  In particular such an
724application would specify its own unique CFBundleIdentifier in its
725Info.plist file.  During development, however, if Wish itself is being
726used as the receiver, it may be necessary to take some care to ensure
727that the correct version of Wish.app is available as a receiver of
728NSServices data.
729
730When one macOS app uses NSServices to send data to another app that is
731not running, LaunchServices will launch the receiver.  LaunchServices
732assumes that the CFBundleIdentifier uniquely identifies an app among
733all of the apps installed on a system.  But this may not be the case
734for Wish.app if, for example, you have compiled Tk from source at some
735time in the past.  In that case the Tk build directory will contain
736its own copy of Wish.app that will be visible to LaunchServices.  It
737may be necessary when testing your app to take some steps to ensure
738that LaunchServices is launching the correct Wish.app.  Instructions
739for doing this are provided below.
740
741The command line tool which manages the LaunchServices database has
742an amazingly unwieldy path name.  So, first, run this command:
743
744alias lsregister='/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister'
745
746Then you can reset the LaunchServices database like this:
747
748$ lsregister -kill
749$ lsregister -seed
750
751To find out which versions of Wish.app have been located by
752LaunchServices, run:
753
754$ lsregister -dump | grep path | grep Wish
755
756If more than one version of Wish is showing up in this list, eliminate
757all of the unintended targets by running
758
759lsregister -u /path/to/bad/Wish.app
760
761Continue this until only the correct version of Wish shows up in the
762list.
763