Import Tk 8.6.10

This commit is contained in:
Steve Dower
2020-09-24 22:55:34 +01:00
parent 5ba5cbc9af
commit 42c69189d9
365 changed files with 24323 additions and 12832 deletions

View File

@@ -16,19 +16,17 @@ before asking on the list, many questions have already been answered).
http://groups.google.com/group/comp.lang.tcl/
- The Tcl'ers Wiki also has many pages dealing with Tcl & Tk on macOS, see
http://wiki.tcl.tk/_/ref?N=3753
http://wiki.tcl.tk/_/ref?N=8361
https://wiki.tcl-lang.org/page/MacOS
- Please report bugs with Tk on macOS to the tracker:
http://core.tcl.tk/tk/reportlist
https://core.tcl-lang.org/tk/reportlist
2. Using Tcl/Tk on macOS
---------------------------
- There are two versions of Tk available on macOS: TkAqua using the native
aqua widgets and look&feel, and TkX11 using the traditional unix X11 wigets.
TkX11 requires an X11 server to be installed, such as Apple's X11 (which is
available as an optional or default install on recent macOS).
aqua widgets and look&feel, and TkX11 using the traditional unix X11 widgets.
TkX11 requires an X11 server to be installed, such as XQuartz (available from www.xquartz.org).
TkAqua and TkX11 can be distinguished at runtime via [tk windowingsystem].
- At a minimum, macOS 10.3 is required to run Tcl and TkX11.
@@ -51,19 +49,14 @@ brings up the Tk console window at startup. This is the case when double
clicking Wish in the Finder (or using 'open Wish.app' from the Terminal).
- Tcl extensions can be installed in any of:
$HOME/Library/Tcl /Library/Tcl /System/Library/Tcl
$HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
$HOME/Library/Tcl /Library/Tcl
$HOME/Library/Frameworks /Library/Frameworks
(searched in that order).
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.
- [load]able binary extensions can linked as either ordinary shared libraries
(.dylib) or as MachO bundles (since 8.4.10/8.5a3); bundles have the advantage
that they are [load]ed more efficiently from a tcl VFS (no temporary copy to the
native filesystem required).
- The 'deploy' target of macosx/GNUmakefile installs the html manpages into the
standard documentation location in the Tcl/Tk frameworks:
Tcl.framework/Resources/Documentation/Reference/Tcl
@@ -72,7 +65,7 @@ No nroff manpages are installed by default by the GNUmakefile.
- The Tcl and Tk frameworks can be installed in any of the system's standard
framework directories:
$HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
$HOME/Library/Frameworks /Library/Frameworks
- ${prefix}/bin/wish8.x is a script that calls a copy of 'Wish' contained in
Tk.framework/Resources
@@ -87,28 +80,6 @@ particular PATH may not be what you expect. (Wish started by LaunchServices
inherits loginwindow's environment variables, which are essentially those set in
$HOME/.MacOSX/environment.plist, and are unrelated to those set in your shell).
- TkAqua drawing is antialiased by default, but (outline) linewidth can be used
to control whether a line/shape is drawn antialiased. The antialiasing threshold
is 0 by default (i.e. antialias everything), it can be changed by setting
set tk::mac::CGAntialiasLimit <limit>
in your script before drawing, in which case lines (or shapes with outlines)
thinner than <limit> pixels will not be antialiased.
- Text antialiasing by default uses the standard OS antialising settings.
Setting the global variable '::tk::mac::antialiasedtext' allows to control text
antialiasing from Tcl: a value of 1 enables AA, 0 disables AA and -1 restores
the default behaviour of respecting the OS settings.
- Scrollbars: There are two scrollbar variants in Aqua, normal & small. The
normal scrollbar has a small dimension of 15, the small variant 11.
Access to the small variant was added in Tk 8.4.2.
- The default metrics of native buttons, radiobuttons, checkboxes and
menubuttons in the Cocoa-based Tk 8.5.7 and later preserve compatibility with
the older Carbon-based implementation, you can turn off the compatibility
metrics to get more native-looking spacing by setting:
set tk::mac::useCompatibilityMetrics 0
- TkAqua provides access to native OS X images via the Tk native bitmap facility
(including any image file readable by NSImage). A native bitmap name is
interpreted as follows (in order):
@@ -152,14 +123,13 @@ app bundle files used by the about panel.
This support was added with the Cocoa-based Tk 8.5.7.
- TkAqua has three special menu names that give access to the standard
Application, Window and Help menus, see menu.n for details.
By default, the platform-specific standard Help menu item "YourApp Help" peforms
the default Cocoa action of showing the Help Book configured in the
application's Info.plist (or displaying an alert if no Help Book is set). This
action can be customized by defining a procedure named [tk::mac::ShowHelp], if
present, this procedure is invoked instead by the standard Help menu item.
Support for the Window menu and [tk::mac::ShowHelp] was added with the
Cocoa-based Tk 8.5.7.
Application, Window and Help menus, see menu.n for details. By default, the
platform-specific standard Help menu item "YourApp Help" performs the default
Cocoa action of showing the Help Book configured in the application's
Info.plist (or displaying an alert if no Help Book is set). This action can be
customized by defining a procedure named [tk::mac::ShowHelp]. If present, this
procedure is invoked instead by the standard Help menu item. Support for the
Window menu and [tk::mac::ShowHelp] was added with the Cocoa-based Tk 8.5.7.
- The TkAqua-specific command [tk::unsupported::MacWindowStyle style] is used to
get and set macOS-specific toplevel window class and attributes. Note that
@@ -180,26 +150,168 @@ Window attribute names:
noActivates, hideOnSuspend, inWindowMenu, ignoreClicks, doesNotHide,
canJoinAllSpaces, moveToActiveSpace, nonActivating
Note that not all attributes are valid for all window classes.
Support for the 3 argument form was added with the Cocoa-based Tk 8.5.7, at the
same time support for some legacy Carbon-specific classes and attributes was
removed (they are still accepted by the command but no longer have any effect).
Note that not all attributes are valid for all window classes. Support for the
3 argument form was added with the Cocoa-based Tk 8.5.7, at the same time
support for some legacy Carbon-specific classes and attributes was removed
(they are still accepted by the command but no longer have any effect).
If you want to use Remote Debugging with Xcode, you need to set the
- Another command available in the tk::unsupported::MacWindowStyle namespace is:
tk::unsupported::MacWindowStyle tabbingid window ?newId?
which can be used to get or set the tabbingIdentifier for the NSWindow
associated with a Tk Window. See section 3 for details.
- The command:
tk::unsupported::MacWindowStyle appearance window ?newAppearance?
is available when Tk is built and run on macOS 10.14 (Mojave) or later. In
that case the Ttk widgets all support the "Dark Mode" appearance which was
introduced in 10.14. The command accepts the following values for the optional
newAppearance option: "aqua", "darkaqua", or "auto". If the appearance is set
to aqua or darkaqua then the window will be displayed with the corresponding
appearance independent of any preferences settings. If it is set to "auto"
the appearance will be determined by the preferences. This command can be
used 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.
- To determine the current appearance of a window in macOS 10.14 (Mojave) and
higher, one can use the command:
tk::unsupported::MacWindowStyle isdark window?
The boolean return value is true if the window is currently displayed with the
dark appearance.
- If you want to use Remote Debugging with Xcode, you need to set the
environment variable XCNOSTDIN to 1 in the Executable editor for Wish. That will
cause us to force closing stdin & stdout. Otherwise, given how Xcode launches
Wish remotely, they will be left open and then Wish & gdb will fight for stdin.
3. FullScreen, Split View and Tabbed Windows
--------------------------------------------
3. Building Tcl/Tk on macOS
Since the release of OSX 10.6 (Snow Leopard) a steadily expanding sequence of
high level window operations have been added to Apple's window manager. These
operations are launched by user actions which are handled directly by the
window manager; they are not initiated by the application. In some, but not
all cases, the application is notified before and after the operations are
carried out.
In OSX releases up to and including 10.6 there were three buttons with
stoplight colors located on the left side of a window's title bar. The
function of the green button was to "zoom" or "maximize" the window, i.e. to
expand the window so that it fills the entire screen, while preserving the
appearance of the window including its title bar. The release of OSX 10.7
(Lion) introduced the "FullScreen" window which not only filled the screen but
also hid the window's title bar and the menu bar which normally appears at the
top of the screen. These hidden objects would only become visible when the
mouse hovered near the top of the screen. FullScreen mode was initiated by
pressing a button showing two outward pointing arrows located on the right side
of the title bar; it was terminated by pressing a similar button with inward
pointing arrows on the right hand side of the menu bar. In OSX 10.10
(Yosemite) the FullScreen button was removed. The green button was repurposed
to cause a window to become a FullScreen window. To zoom a window the user had
to hold down the option key while pressing the green button. The release of
OSX 10.11 added a third function to the green button: to create two half-screen
windows with hidden title bars and a hidden menu bar, called Split View
windows. If the green button is held down for one second its window expands to
fill half of the screen. It can be moved to one side or the other with the
mouse. The opposite side shows thumbnail images of other windows. Selecting
one of the thumbnails expands its window to fill that half of the screen. The
divider between the two windows can be moved to adjust the percentage of the
screen occupied by each of the two tiles. In OSX 10.12 (Sierra) Tabbed windows
were introduced. These allow an application with multiple windows to display
its windows as tabs within a single window frame. Clicking on a tab brings its
window into view. Tabs can be rearranged by dragging. Dragging a tab to the
desktop turns it into a separate window. Items in the Window menu can be used
to cycle through the tabs, move tabbed windows to separate windows, or merge a
set of separate windows as tabs in the same window frame.
Tk now fully supports all of these high level window operations on any system
where the operation exists. The FullScreen and Split View windows are handled
automatically with no action required on the part of the programmer. Tabbed
windows, on the other hand, require some attention from the programmer.
Because many of the operations with tabs are handled through the application's
Window menu, it is essential that an application provide a Windows menu to
avoid presenting a confusing interface to the user. This cannot be ignored, in
part because the systemwide Dock Preferences offers an option to always attempt
to open application windows as tabs. An application which does not provide a
Window menu will necessarily present a confusing interface to any user who has
selected this option.
A further complication is that it is not neccessarily appropriate for all of an
application's windows to be grouped together as tabs in the same frame. In
fact, the Apple guidelines insist that windows which are grouped together as
tabs should be similar to each other. The mechanism provided for arranging
this was to assign to each NSwindow a tabbingIdentifier, and to require that
all windows grouped together as tabs in the same window frame must have the
same tabbingIdentifier. A tabbingIdentifier is implemented as an arbitrary
string, and a system-generated default tabbingIdentifier is provided to all new
windows.
Tk provides a means for getting and setting the tabbingIdentifier of
the NSWindow underlying a Tk Window. This is handled by the command
tk::unsupported::MacWindowStyle tabbingid window ?newId?
(This command generates an error if used on OSX 10.11 or earlier, since the
tabbingIdentifier does not exist on those systems.) The command returns the
tabbingIdentifier which had been assigned to the window prior to execution of
the command. If the optional newId argument is omitted, the window's
tabbingIdentifier is not changed. Otherwise it is set to the string specified
by the argument.
Since NSWindows can only be grouped together as tabs if they all have the same
tabbingIdentifier, one can prevent a window from becoming a tab by giving it a
unique tabbingIdentifier. This is independent of any preferences setting. To
ensure that we maintain consistency, changing the tabbingIdentifier of a window
which is already displayed as a tab will also cause it to become a separate
window.
4. Ttk, Dark Mode and semantic colors
---------------------------------------
With the release of OSX 10.14 (Mojave), Apple introduced the DarkAqua
appearance. Part of the implementation of the Dark Mode was to make
some of the named NSColors have dynamic values. Apple calls these
"semantic colors" because the name does not specify a specific color,
but rather refers to the context in which the color should be used.
Tk now provides the following semantic colors as system colors:
systemTextColor, systemTextBackgroundColor, systemSelectedTextColor,
systemSelectedTextBackgroundColor, systemControlTextColor,
systemDisabledControlTextColor, systemLabelColor, and
systemControlAccentColor. All of these except the last two were
present in OSX 10.0 (and those two are simulated in systems where they
do not exist). The change in 10.14 was that the RGB color value of
these colors became dynamic, meaning that the color value can change
when the application appearance changes. In particular, when a user
selects Dark Mode in the system preferences these colors change
appearance. For example systemTextColor is dark in Aqua and light in
DarkAqua. One additional color, systemSelectedTabTextColor, does not
exist in macOS but is used by Tk to match the different colors used
for Notebook tab text in different OS versions.
The default background and foreground colors of most of the Tk widgets
have been set to semantic colors, which means that the widgets will change
appearance, and remain usable, when Dark Mode is selected in the system
preferences. However, to get a close match to the native Dark Mode style it
is recommended to use Ttk widgets when possible.
Apple's tab view and GroupBox objects delimit their content by
displaying it within a rounded rectangle with a background color that
contrasts with the background of the containing object. This means
that the background color of a Ttk widget depends on how deeply it is
nested inside of other widgets that use contrasting backgrounds. To
support this, there are 8 contrasting system colors named
systemWindowBackgroundColor, and systemWindowBackgroundColor1 - 7.
The systemWindowBackgroundColor is the standard background for a
dialog window and the others match the contrasting background colors
used in ttk::notebooks and ttk::labelframes which are nested to the
corresponding depth.
5. Building Tcl/Tk on macOS
------------------------------
- At least macOS 10.3 is required to build Tcl and TkX11, and macOS 10.6
is required to build TkAqua. The XCode application provides everything
needed to build Tk, but it is not necessary to install the full XCode.
- 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.
It suffices to install the Command Line Tools package, which can be done
by running the command:
xcode-selecct --install
xcode-select --install
- Tcl/Tk are most easily built as macOS frameworks via GNUmakefile in
tcl/macosx and tk/macosx (see below for details), but can also be built with the
@@ -255,17 +367,6 @@ need to manually change the TCL_SRCROOT and TK_SRCROOT settings by editing your
${USER}.pbxuser file (located inside the Tk.xcodeproj bundle directory) with a
text editor.
- To build universal binaries outside of the Xcode IDE, set CFLAGS as follows:
export CFLAGS="-arch i386 -arch x86_64 -arch ppc"
This requires macOS 10.4 and Xcode 2.4 (or Xcode 2.2 if -arch x86_64 is
omitted, but _not_ Xcode 2.1) and will work on any architecture (on PowerPC
Tiger you need to add "-isysroot /Developer/SDKs/MacOSX10.4u.sdk").
Note that configure requires CFLAGS to contain a least one architecture that can
be run on the build machine (i.e. ppc on G3/G4, ppc or ppc64 on G5, ppc or i386
on Core and ppc, i386 or x86_64 on Core2/Xeon).
Universal builds of Tcl TEA extensions are also possible with CFLAGS set as
above, they will be [load]able by universal as well as thin binaries of Tcl.
- To enable weak-linking, set the MACOSX_DEPLOYMENT_TARGET environment variable
to the minimal OS version the binaries should be able to run on, e.g:
export MACOSX_DEPLOYMENT_TARGET=10.6
@@ -354,10 +455,10 @@ make overrides to the tk/macosx GNUmakefile, e.g.
TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.
4. Details regarding the macOS port of Tk.
5. Details regarding the macOS port of Tk.
-------------------------------------------
4.1 About the event loop
5.1 About the event loop
~~~~~~~~~~~~~~~~~~~~~~~~
The main program in a typical OSX application looks like this (see
@@ -388,7 +489,7 @@ The macOS Tk application does not call the [NSApp run] method at
all. Instead it uses the event loop built in to Tk. So the
application must take care to replicate the important features of the
method ourselves. The way that autorelease pools are handled is
discussed in 4.2 below. Here we discuss the event handling itself.
discussed in 5.2 below. Here we discuss the event handling itself.
The Tcl event loop simply consists of repeated calls to TclDoOneEvent.
Each call to TclDoOneEvent begins by collecting all pending events from
@@ -416,12 +517,12 @@ for each dirty rectangle of the NSView, and then adds the expose
event to the Tcl queue.
4.2 Autorelease pools
5.2 Autorelease pools
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In order to carry out the job of managing autorelease pools, which
would normally be handled by the [NSApp run] method, a private
NSAUtoreleasePool* property is added to the TkApplication subclass of
NSAutoreleasePool* property is added to the TkApplication subclass of
NSApplication. The TkpInit function calls [NSApp _setup] which
initializes this property by creating an NSAutoreleasePool prior to
calling [NSApp finishLaunching]. This mimics the behavior of the
@@ -446,12 +547,12 @@ in nested calls to CheckProc.
One additional minor caveat for developers is that there are several
steps of the Tk initialization which precede the call to TkpInit.
Notably, the font package is initialized first. Since there is no
NSAUtoreleasePool in scope prior to calling TkpInit, the functions
NSAutoreleasePool in scope prior to calling TkpInit, the functions
called in these preliminary stages need to create and drain their own
NSAutoreleasePools whenever they call methods of Appkit objects
(e.g. NSFont).
4.3 Clipping regions and "ghost windows"
5.3 Clipping regions and "ghost windows"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Another unusual aspect of the macOS port is its use of clipping
@@ -466,7 +567,7 @@ window. (Normally, the clipping rectangle is the same as the bounding
rectangle, but drawing can be clipped to a smaller rectangle by
calling TkpClipDrawableToRect.) The aboveVisRgn is the intersection of
the window's bounding rectangle with the bounding rectangle of the
parent window. Much of the code in tkMacOSXSubindows.c is devoted to
parent window. Much of the code in tkMacOSXSubwindows.c is devoted to
rebuilding these clipping regions whenever something changes in the
layout of the windows. This turns out to be a tricky thing to do and
it is extremely prone to errors which can be difficult to trace.
@@ -561,7 +662,7 @@ source and destination rectangles for the scrolling. The embedded
windows are redrawn within the DisplayText function by some
conditional code which is only used for macOS.
5.0 Virtual events on 10.14
6.0 Virtual events on 10.14
~~~~~~~~~~~~~~~~~~~~~~~~~~~
10.14 supports system appearance changes, and has added a "Dark Mode"
@@ -570,3 +671,54 @@ virtual events, <<LightAqua>> and <<DarkAqua>>, to allow you to update
your Tk app's appearance when the system appearance changes. Just bind
your appearance-updating code to these virtual events and you will see
it triggered when the system appearance toggles between dark and light.
7.0 Mac Services
~~~~~~~~~~~~~~~~~~~~~~~~~~~
With 8.6.10, Tk supports the Mac's NSServices API, documented at
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/SysServices/introduction.html#//apple_ref/doc/uid/10000101-SW1
and in TIP 536 and Tk's man page. Tk presents a simple,
straightforward API to implement the Services functionality.
The Tk implementation of the NSServices API is intended for standalone
applications, such as one wrapped by the standalone version of Wish
and re-named into a different application. In particular such an
application would specify its own unique CFBundleIdentifier in its
Info.plist file. During development, however, if Wish itself is being
used as the receiver, it may be necessary to take some care to ensure
that the correct version of Wish.app is available as a receiver of
NSServices data.
When one macOS app uses NSServices to send data to another app that is
not running, LaunchServices will launch the receiver. LaunchServices
assumes that the CFBundleIdentifier uniquely identifies an app among
all of the apps installed on a system. But this may not be the case
for Wish.app if, for example, you have compiled Tk from source at some
time in the past. In that case the Tk build directory will contain
its own copy of Wish.app that will be visible to LaunchServices. It
may be necessary when testing your app to take some steps to ensure
that LaunchServices is launching the correct Wish.app. Instructions
for doing this are provided below.
The command line tool which manages the LaunchServices database has
an amazingly unwieldy path name. So, first, run this command:
alias lsregister='/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister'
Then you can reset the LaunchServices database like this:
$ lsregister -kill
$ lsregister -seed
To find out which versions of Wish.app have been located by
LaunchServices, run:
$ lsregister -dump | grep path | grep Wish
If more than one version of Wish is showing up in this list, eliminate
all of the unintended targets by running
lsregister -u /path/to/bad/Wish.app
Continue this until only the correct version of Wish shows up in the
list.