Import Tk 8.6.10
This commit is contained in:
@@ -225,22 +225,6 @@ ifeq (${EMBEDDED_BUILD},1)
|
||||
@rm -f "${INSTALL_ROOT}${BINDIR}/${WISH}" && \
|
||||
rmdir -p "${INSTALL_ROOT}${BINDIR}" 2>&- || true
|
||||
else
|
||||
# redo prebinding (when not building for Mac OS X 10.4 or later only)
|
||||
@if [ "`echo "$${MACOSX_DEPLOYMENT_TARGET}" | \
|
||||
awk -F '10\\.' '{print int($$2)}'`" -lt 4 -a "`echo "$${CFLAGS}" | \
|
||||
awk -F '-mmacosx-version-min=10\\.' '{print int($$2)}'`" -lt 4 ]; \
|
||||
then cd ${INSTALL_ROOT}/; \
|
||||
if [ ! -d usr/lib ]; then mkdir -p usr && ln -fs /usr/lib usr/ && RM_USRLIB=1; fi; \
|
||||
if [ -n "${TK_X11}" -a ! -d usr/X11R6 ]; then mkdir -p usr && ln -fs /usr/X11R6 usr/ && RM_USRX11=1; fi; \
|
||||
if [ ! -d System ]; then ln -fs /System . && RM_SYSTEM=1; fi; \
|
||||
if [ ! -d "./${LIBDIR}/Tcl.framework" ]; then ln -fs "${TCL_FRAMEWORK_DIR}/Tcl.framework" "./${LIBDIR}"; RM_TCL=1; fi; \
|
||||
redo_prebinding -r . "./${TK_FMWK_DIR}/${PRODUCT_NAME}"; \
|
||||
if [ -z "${TK_X11}" ]; then redo_prebinding -r . "./${TK_FMWK_DIR}/Resources/Wish.app/Contents/MacOS/Wish"; \
|
||||
else redo_prebinding -r . "./${BINDIR}/${WISH}"; fi; \
|
||||
if [ -n "$${RM_USRLIB:-}" ]; then rm -f usr/lib; rmdir -p usr 2>&-; fi; \
|
||||
if [ -n "$${RM_USRX11:-}" ]; then rm -f usr/X11R6; rmdir -p usr 2>&-; fi; \
|
||||
if [ -n "$${RM_SYSTEM:-}" ]; then rm -f System; fi; \
|
||||
if [ -n "$${RM_TCL:-}" ]; then rm -f "./${LIBDIR}/Tcl.framework"; fi; fi
|
||||
# install wish symbolic link
|
||||
@ln -fs ${WISH} "${INSTALL_ROOT}${BINDIR}/${wish}"
|
||||
endif
|
||||
|
||||
300
macosx/README
300
macosx/README
@@ -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.
|
||||
|
||||
@@ -8,75 +8,101 @@
|
||||
this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
-->
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>tcl</string>
|
||||
<string>TCL</string>
|
||||
<string>*</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/x-tcl</string>
|
||||
<string>text/plain</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>NSStringPboardType</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>TEXT</string>
|
||||
<string>****</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<string>tcl</string>
|
||||
<string>TCL</string>
|
||||
<string>*</string>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Wish</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>Wish Shell @TK_VERSION@@TK_PATCH_LEVEL@,
|
||||
Copyright © 1989-@TK_YEAR@ Tcl Core Team,
|
||||
Copyright © 1989-@TK_YEAR@ Contributors,
|
||||
Copyright © 2011-@TK_YEAR@ Kevin Walzer/WordTech
|
||||
Communications LLC,
|
||||
Copyright © 2014-@TK_YEAR@ Marc Culler,
|
||||
Copyright © 2002-@TK_YEAR@ Daniel A. Steffen,
|
||||
Copyright © 2001-2009 Apple Inc.,
|
||||
Copyright © 2001-2002 Jim Ingham & Ian Reid</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Wish.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.tcltk.wish</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLocalizations</key>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
@CFBUNDLELOCALIZATIONS@
|
||||
<string>application/x-tcl</string>
|
||||
<string>text/plain</string>
|
||||
</array>
|
||||
<key>CFBundleName</key>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>NSStringPboardType</string>
|
||||
<key>CFBundleTypeOSTypes</key>
|
||||
<array>
|
||||
<string>TEXT</string>
|
||||
<string>****</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>foo</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Get Foo</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Wish</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>Wish Shell @TK_VERSION@@TK_PATCH_LEVEL@,
|
||||
Copyright © 1989-@TK_YEAR@ Tcl Core Team,
|
||||
Copyright © 1989-@TK_YEAR@ Contributors,
|
||||
Copyright © 2011-@TK_YEAR@ Kevin Walzer/WordTech Communications LLC,
|
||||
Copyright © 2014-@TK_YEAR@ Marc Culler,
|
||||
Copyright © 2002-@TK_YEAR@ Daniel A. Steffen,
|
||||
Copyright © 2001-2009 Apple Inc.,
|
||||
Copyright © 2001-2002 Jim Ingham & Ian Reid</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Wish.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.tcltk.wish</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLocalizations</key>
|
||||
<array>
|
||||
@CFBUNDLELOCALIZATIONS@
|
||||
</array>
|
||||
<key>CFBundleName</key>
|
||||
<string>Wish</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>WiSH</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.6.0</string>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<true/>
|
||||
<key>OSAScriptingDefinition</key>
|
||||
<string>Wish.sdef</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>NSServices</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSMessage</key>
|
||||
<string>provideService</string>
|
||||
<key>NSPortName</key>
|
||||
<string>Wish</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>WiSH</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@TK_VERSION@@TK_PATCH_LEVEL@</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.6.0</string>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<true/>
|
||||
<key>OSAScriptingDefinition</key>
|
||||
<string>Wish.sdef</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
</dict>
|
||||
<key>NSSendTypes</key>
|
||||
<array>
|
||||
<string>NSStringPboardType</string>
|
||||
<string>NSPasteboardTypeString</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -33,5 +33,14 @@
|
||||
<type type="text"/>
|
||||
</result>
|
||||
</command>
|
||||
<command name="open location" code="GURLGURL"
|
||||
description="Open a URL.">
|
||||
<direct-parameter description="URL" type="text">
|
||||
<type type="text"/>
|
||||
</direct-parameter>
|
||||
<result description="Result">
|
||||
<type type="text"/>
|
||||
</result>
|
||||
</command>
|
||||
</suite>
|
||||
</dictionary>
|
||||
|
||||
19
macosx/configure
vendored
19
macosx/configure
vendored
@@ -2287,7 +2287,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
TK_VERSION=8.6
|
||||
TK_MAJOR_VERSION=8
|
||||
TK_MINOR_VERSION=6
|
||||
TK_PATCH_LEVEL=".9"
|
||||
TK_PATCH_LEVEL=".10"
|
||||
VERSION=${TK_VERSION}
|
||||
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
|
||||
|
||||
@@ -2362,7 +2362,6 @@ $as_echo "$as_me: WARNING: --with-tcl argument should refer to directory contain
|
||||
for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
|
||||
`ls -d /Library/Frameworks 2>/dev/null` \
|
||||
`ls -d /Network/Library/Frameworks 2>/dev/null` \
|
||||
`ls -d /System/Library/Frameworks 2>/dev/null` \
|
||||
; do
|
||||
if test -f "$i/Tcl.framework/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
|
||||
@@ -2379,6 +2378,7 @@ $as_echo "$as_me: WARNING: --with-tcl argument should refer to directory contain
|
||||
`ls -d /usr/local/lib 2>/dev/null` \
|
||||
`ls -d /usr/contrib/lib 2>/dev/null` \
|
||||
`ls -d /usr/pkg/lib 2>/dev/null` \
|
||||
`ls -d /usr/lib/tcl8.6 2>/dev/null` \
|
||||
`ls -d /usr/lib 2>/dev/null` \
|
||||
`ls -d /usr/lib64 2>/dev/null` \
|
||||
`ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
|
||||
@@ -4527,6 +4527,9 @@ $as_echo "$as_me: WARNING: can't find uname command" >&2;}
|
||||
if test "`uname -s`" = "AIX" ; then
|
||||
tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
|
||||
fi
|
||||
if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then
|
||||
tcl_cv_sys_version=NetBSD-Debian
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -5596,12 +5599,6 @@ fi
|
||||
SHLIB_SUFFIX=".dylib"
|
||||
DL_OBJS="tclLoadDyld.o"
|
||||
DL_LIBS=""
|
||||
# Don't use -prebind when building for Mac OS X 10.4 or later only:
|
||||
if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \
|
||||
"`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then :
|
||||
|
||||
LDFLAGS="$LDFLAGS -prebind"
|
||||
fi
|
||||
LDFLAGS="$LDFLAGS -headerpad_max_install_names"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5
|
||||
$as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; }
|
||||
@@ -8123,8 +8120,8 @@ $as_echo "$enable_xft" >&6; }
|
||||
XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
|
||||
if test "$found_xft" = "no" ; then
|
||||
found_xft=yes
|
||||
XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no"
|
||||
XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no"
|
||||
XFT_CFLAGS=`pkg-config --cflags xft fontconfig 2>/dev/null` || found_xft="no"
|
||||
XFT_LIBS=`pkg-config --libs xft fontconfig 2>/dev/null` || found_xft="no"
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_xft" >&5
|
||||
$as_echo "$found_xft" >&6; }
|
||||
@@ -8614,7 +8611,7 @@ if test "${SHARED_BUILD}" = "1" -a "${SHLIB_SUFFIX}" != ""; then
|
||||
TCL_STUB_FLAGS="-DUSE_TCL_STUBS"
|
||||
fi
|
||||
|
||||
TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
|
||||
test -z "$TK_LIBRARY" && TK_LIBRARY='$(prefix)/lib/tk$(VERSION)'
|
||||
PRIVATE_INCLUDE_DIR='$(includedir)'
|
||||
HTML_DIR='$(DISTDIR)/html'
|
||||
TK_PKG_DIR='tk$(VERSION)'
|
||||
|
||||
@@ -49,6 +49,9 @@ static BuiltInIcon builtInIcons[] = {
|
||||
|
||||
#define builtInIconSize 32
|
||||
|
||||
#define OSTYPE_TO_UTI(x) (NSString *)UTTypeCreatePreferredIdentifierForTag( \
|
||||
kUTTagClassOSType, UTCreateStringForOSType(x), nil)
|
||||
|
||||
static Tcl_HashTable iconBitmapTable = {};
|
||||
typedef struct {
|
||||
int kind, width, height;
|
||||
@@ -107,14 +110,15 @@ TkpDefineNativeBitmaps(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* GetBitmapForIcon --
|
||||
* PixmapFromImage --
|
||||
*
|
||||
* Results:
|
||||
* Bitmap for the given IconRef.
|
||||
* Returns a Pixmap with an NSImage drawn into it.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
@@ -123,9 +127,9 @@ TkpDefineNativeBitmaps(void)
|
||||
*/
|
||||
|
||||
static Pixmap
|
||||
GetBitmapForIcon(
|
||||
PixmapFromImage(
|
||||
Display *display,
|
||||
IconRef icon,
|
||||
NSImage* image,
|
||||
CGSize size)
|
||||
{
|
||||
TkMacOSXDrawingContext dc;
|
||||
@@ -134,18 +138,22 @@ GetBitmapForIcon(
|
||||
pixmap = Tk_GetPixmap(display, None, size.width, size.height, 0);
|
||||
if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
|
||||
if (dc.context) {
|
||||
const CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
|
||||
.tx = 0, .ty = size.height };
|
||||
const CGRect r = { .origin = { .x = 0, .y = 0 }, .size = size };
|
||||
|
||||
CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
|
||||
.tx = 0, .ty = size.height};
|
||||
CGContextConcatCTM(dc.context, t);
|
||||
PlotIconRefInContext(dc.context, &r, kAlignAbsoluteCenter,
|
||||
kTransformNone, NULL, kPlotIconRefNormalFlags, icon);
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
[NSGraphicsContext setCurrentContext:[NSGraphicsContext
|
||||
graphicsContextWithGraphicsPort:dc.context
|
||||
flipped:NO]];
|
||||
[image drawAtPoint:NSZeroPoint fromRect:NSZeroRect
|
||||
operation:NSCompositeCopy fraction:1.0];
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
}
|
||||
TkMacOSXRestoreDrawingContext(&dc);
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -168,22 +176,14 @@ TkpCreateNativeBitmap(
|
||||
Display *display,
|
||||
const void *source) /* Info about the icon to build. */
|
||||
{
|
||||
Pixmap pixmap;
|
||||
IconRef icon;
|
||||
OSErr err;
|
||||
|
||||
err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator,
|
||||
PTR2UINT(source), &icon);
|
||||
if (err == noErr) {
|
||||
pixmap = GetBitmapForIcon(display, icon, CGSizeMake(builtInIconSize,
|
||||
builtInIconSize));
|
||||
ReleaseIconRef(icon);
|
||||
} else {
|
||||
pixmap = Tk_GetPixmap(display, None, builtInIconSize,
|
||||
builtInIconSize, 0);
|
||||
}
|
||||
NSString *iconUTI = OSTYPE_TO_UTI(PTR2UINT(source));
|
||||
NSImage *iconImage = [[NSWorkspace sharedWorkspace]
|
||||
iconForFileType: iconUTI];
|
||||
CGSize size = CGSizeMake(builtInIconSize, builtInIconSize);
|
||||
Pixmap pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -210,7 +210,7 @@ OSTypeFromString(const char *s, OSType *t) {
|
||||
Tcl_UtfToExternalDString(encoding, s, -1, &ds);
|
||||
if (Tcl_DStringLength(&ds) <= 4) {
|
||||
char string[4] = {};
|
||||
memcpy(string, Tcl_DStringValue(&ds), (size_t) Tcl_DStringLength(&ds));
|
||||
memcpy(string, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
|
||||
*t = (OSType) string[0] << 24 | (OSType) string[1] << 16 |
|
||||
(OSType) string[2] << 8 | (OSType) string[3];
|
||||
result = TCL_OK;
|
||||
@@ -219,6 +219,7 @@ OSTypeFromString(const char *s, OSType *t) {
|
||||
Tcl_FreeEncoding(encoding);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -309,50 +310,17 @@ TkpGetNativeAppBitmap(
|
||||
}
|
||||
}
|
||||
if (image) {
|
||||
TkMacOSXDrawingContext dc;
|
||||
int depth = 0;
|
||||
|
||||
#ifdef MAC_OSX_TK_TODO
|
||||
for (NSImageRep *r in [image representations]) {
|
||||
NSInteger bitsPerSample = [r bitsPerSample];
|
||||
if (bitsPerSample && bitsPerSample > depth) {
|
||||
depth = bitsPerSample;
|
||||
};
|
||||
}
|
||||
if (depth == 1) {
|
||||
/* TODO: convert BW NSImage to CGImageMask */
|
||||
}
|
||||
#endif
|
||||
pixmap = Tk_GetPixmap(display, None, size.width, size.height, depth);
|
||||
*width = size.width;
|
||||
*height = size.height;
|
||||
if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
|
||||
if (dc.context) {
|
||||
CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1,
|
||||
.tx = 0, .ty = size.height};
|
||||
|
||||
CGContextConcatCTM(dc.context, t);
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
[NSGraphicsContext setCurrentContext:[NSGraphicsContext
|
||||
graphicsContextWithGraphicsPort:dc.context flipped:NO]];
|
||||
[image drawAtPoint:NSZeroPoint fromRect:NSZeroRect
|
||||
operation:NSCompositeCopy fraction:1.0];
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
}
|
||||
TkMacOSXRestoreDrawingContext(&dc);
|
||||
}
|
||||
pixmap = PixmapFromImage(display, image, NSSizeToCGSize(size));
|
||||
} else if (name) {
|
||||
OSType iconType;
|
||||
if (OSTypeFromString(name, &iconType) == TCL_OK) {
|
||||
IconRef icon;
|
||||
OSErr err = ChkErr(GetIconRef, kOnSystemDisk, kSystemIconsCreator,
|
||||
iconType, &icon);
|
||||
if (err == noErr) {
|
||||
pixmap = GetBitmapForIcon(display, icon, NSSizeToCGSize(size));
|
||||
*width = size.width;
|
||||
*height = size.height;
|
||||
ReleaseIconRef(icon);
|
||||
}
|
||||
NSString *iconUTI = OSTYPE_TO_UTI(iconType);
|
||||
printf("Found image for UTI %s\n", iconUTI.UTF8String);
|
||||
NSImage *iconImage = [[NSWorkspace sharedWorkspace]
|
||||
iconForFileType: iconUTI];
|
||||
pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));
|
||||
}
|
||||
}
|
||||
return pixmap;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,10 +35,7 @@ static Tk_Window clipboardOwner = NULL;
|
||||
targetPtr->type == dispPtr->utf8Atom) {
|
||||
for (TkClipboardBuffer *cbPtr = targetPtr->firstBufferPtr;
|
||||
cbPtr; cbPtr = cbPtr->nextPtr) {
|
||||
NSString *s = [[NSString alloc] initWithBytesNoCopy:
|
||||
cbPtr->buffer length:cbPtr->length
|
||||
encoding:NSUTF8StringEncoding freeWhenDone:NO];
|
||||
|
||||
NSString *s = TclUniToNSString(cbPtr->buffer, cbPtr->length);
|
||||
[string appendString:s];
|
||||
[s release];
|
||||
}
|
||||
@@ -123,8 +120,9 @@ TkSelGetSelection(
|
||||
{
|
||||
int result = TCL_ERROR;
|
||||
TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
|
||||
int haveExternalClip =
|
||||
([[NSPasteboard generalPasteboard] changeCount] != changeCount);
|
||||
|
||||
int haveExternalClip = ([[NSPasteboard generalPasteboard] changeCount] != changeCount);
|
||||
if (dispPtr && (haveExternalClip || dispPtr->clipboardActive)
|
||||
&& selection == dispPtr->clipboardAtom
|
||||
&& (target == XA_STRING || target == dispPtr->utf8Atom)) {
|
||||
@@ -136,7 +134,22 @@ TkSelGetSelection(
|
||||
if (type) {
|
||||
string = [pb stringForType:type];
|
||||
}
|
||||
result = proc(clientData, interp, string ? [string UTF8String] : "");
|
||||
if (string) {
|
||||
|
||||
/*
|
||||
* Encode the string using the encoding which is used in Tcl
|
||||
* when TCL_UTF_MAX = 3. This replaces each UTF-16 surrogate with
|
||||
* a 3-byte sequence generated using the UTF-8 algorithm. (Even
|
||||
* though UTF-8 does not allow encoding surrogates, the algorithm
|
||||
* does produce a 3-byte sequence.)
|
||||
*/
|
||||
|
||||
char *bytes = NSStringToTclUni(string, NULL);
|
||||
result = proc(clientData, interp, bytes);
|
||||
if (bytes) {
|
||||
ckfree(bytes);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%s selection doesn't exist or form \"%s\" not defined",
|
||||
@@ -177,6 +190,7 @@ XSetSelectionOwner(
|
||||
clipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL;
|
||||
if (!dispPtr->clipboardActive) {
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
|
||||
changeCount = [pb declareTypes:[NSArray array] owner:NSApp];
|
||||
}
|
||||
}
|
||||
@@ -188,8 +202,8 @@ XSetSelectionOwner(
|
||||
*
|
||||
* TkMacOSXSelDeadWindow --
|
||||
*
|
||||
* This function is invoked just before a TkWindow is deleted. It
|
||||
* performs selection-related cleanup.
|
||||
* This function is invoked just before a TkWindow is deleted. It performs
|
||||
* selection-related cleanup.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
|
||||
@@ -17,11 +17,32 @@
|
||||
#include "tkMacOSXPrivate.h"
|
||||
#include "tkColor.h"
|
||||
|
||||
/*
|
||||
* The colorType specifies how the color value should be interpreted. For the
|
||||
* unique rgbColor entry, the RGB values are generated from the pixel value of
|
||||
* an XColor. The ttkBackground and semantic types are dynamic, meaning
|
||||
* that they change when dark mode is enabled on OSX 10.13 and later.
|
||||
*/
|
||||
|
||||
enum colorType {
|
||||
clearColor, /* There should be only one of these. */
|
||||
rgbColor, /* There should be only one of these. */
|
||||
appearance, /* There should be only one of these. */
|
||||
HIBrush, /* The value is a HITheme brush color table index. */
|
||||
HIText, /* The value is a HITheme text color table index. */
|
||||
HIBackground, /* The value is a HITheme background color table index. */
|
||||
ttkBackground, /* The value can be used as a parameter.*/
|
||||
semantic, /* The value can be used as a parameter.*/
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
struct SystemColorMapEntry {
|
||||
const char *name;
|
||||
ThemeBrush brush;
|
||||
ThemeTextColor textColor;
|
||||
ThemeBackgroundKind background;
|
||||
enum colorType type;
|
||||
long value;
|
||||
}; /* unsigned char pixelCode; */
|
||||
|
||||
/*
|
||||
@@ -32,157 +53,178 @@ struct SystemColorMapEntry {
|
||||
|
||||
#define MIN_PIXELCODE 30
|
||||
static const struct SystemColorMapEntry systemColorMap[] = {
|
||||
{ "Transparent", 0, 0, 0 }, /* 30: TRANSPARENT_PIXEL */
|
||||
{ "Highlight", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 31: HIGHLIGHT_PIXEL */
|
||||
{ "HighlightSecondary", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 32: HIGHLIGHT_SECONDARY_PIXEL */
|
||||
{ "HighlightText", kThemeBrushBlack, 0, 0 }, /* 33: HIGHLIGHT_TEXT_PIXEL */
|
||||
{ "HighlightAlternate", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 34: HIGHLIGHT_ALTERNATE_PIXEL */
|
||||
{ "ButtonText", 0, kThemeTextColorPushButtonActive, 0 }, /* 35: CONTROL_TEXT_PIXEL */
|
||||
{ "PrimaryHighlightColor", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 36 */
|
||||
{ "ButtonFace", kThemeBrushButtonFaceActive, 0, 0 }, /* 37: CONTROL_BODY_PIXEL */
|
||||
{ "SecondaryHighlightColor", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 38 */
|
||||
{ "ButtonFrame", kThemeBrushButtonFrameActive, 0, 0 }, /* 39: CONTROL_FRAME_PIXEL */
|
||||
{ "AlternatePrimaryHighlightColor", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 40 */
|
||||
{ "WindowBody", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 41: WINDOW_BODY_PIXEL */
|
||||
{ "SheetBackground", kThemeBrushSheetBackground, 0, 0 }, /* 42 */
|
||||
{ "MenuActive", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 43: MENU_ACTIVE_PIXEL */
|
||||
{ "Black", kThemeBrushBlack, 0, 0 }, /* 44 */
|
||||
{ "MenuActiveText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 45: MENU_ACTIVE_TEXT_PIXEL */
|
||||
{ "White", kThemeBrushWhite, 0, 0 }, /* 46 */
|
||||
{ "Menu", kThemeBrushMenuBackground, 0, 0 }, /* 47: MENU_BACKGROUND_PIXEL */
|
||||
{ "DialogBackgroundActive", kThemeBrushDialogBackgroundActive, 0, 0 }, /* 48 */
|
||||
{ "MenuDisabled", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 49: MENU_DISABLED_PIXEL */
|
||||
{ "DialogBackgroundInactive", kThemeBrushDialogBackgroundInactive, 0, 0 }, /* 50 */
|
||||
{ "MenuText", 0, kThemeTextColorMenuItemActive, 0 }, /* 51: MENU_TEXT_PIXEL */
|
||||
{ "AppearanceColor", 0, 0, 0 }, /* 52: APPEARANCE_PIXEL */
|
||||
{ "AlertBackgroundActive", kThemeBrushAlertBackgroundActive, 0, 0 }, /* 53 */
|
||||
{ "AlertBackgroundInactive", kThemeBrushAlertBackgroundInactive, 0, 0 }, /* 54 */
|
||||
{ "ModelessDialogBackgroundActive", kThemeBrushModelessDialogBackgroundActive, 0, 0 }, /* 55 */
|
||||
{ "ModelessDialogBackgroundInactive", kThemeBrushModelessDialogBackgroundInactive, 0, 0 }, /* 56 */
|
||||
{ "UtilityWindowBackgroundActive", kThemeBrushUtilityWindowBackgroundActive, 0, 0 }, /* 57 */
|
||||
{ "UtilityWindowBackgroundInactive", kThemeBrushUtilityWindowBackgroundInactive, 0, 0 }, /* 58 */
|
||||
{ "ListViewSortColumnBackground", kThemeBrushListViewSortColumnBackground, 0, 0 }, /* 59 */
|
||||
{ "ListViewBackground", kThemeBrushListViewBackground, 0, 0 }, /* 60 */
|
||||
{ "IconLabelBackground", kThemeBrushIconLabelBackground, 0, 0 }, /* 61 */
|
||||
{ "ListViewSeparator", kThemeBrushListViewSeparator, 0, 0 }, /* 62 */
|
||||
{ "ChasingArrows", kThemeBrushChasingArrows, 0, 0 }, /* 63 */
|
||||
{ "DragHilite", kThemeBrushDragHilite, 0, 0 }, /* 64 */
|
||||
{ "DocumentWindowBackground", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 65 */
|
||||
{ "FinderWindowBackground", kThemeBrushFinderWindowBackground, 0, 0 }, /* 66 */
|
||||
{ "ScrollBarDelimiterActive", kThemeBrushScrollBarDelimiterActive, 0, 0 }, /* 67 */
|
||||
{ "ScrollBarDelimiterInactive", kThemeBrushScrollBarDelimiterInactive, 0, 0 }, /* 68 */
|
||||
{ "FocusHighlight", kThemeBrushFocusHighlight, 0, 0 }, /* 69 */
|
||||
{ "PopupArrowActive", kThemeBrushPopupArrowActive, 0, 0 }, /* 70 */
|
||||
{ "PopupArrowPressed", kThemeBrushPopupArrowPressed, 0, 0 }, /* 71 */
|
||||
{ "PopupArrowInactive", kThemeBrushPopupArrowInactive, 0, 0 }, /* 72 */
|
||||
{ "AppleGuideCoachmark", kThemeBrushAppleGuideCoachmark, 0, 0 }, /* 73 */
|
||||
{ "IconLabelBackgroundSelected", kThemeBrushIconLabelBackgroundSelected, 0, 0 }, /* 74 */
|
||||
{ "StaticAreaFill", kThemeBrushStaticAreaFill, 0, 0 }, /* 75 */
|
||||
{ "ActiveAreaFill", kThemeBrushActiveAreaFill, 0, 0 }, /* 76 */
|
||||
{ "ButtonFrameActive", kThemeBrushButtonFrameActive, 0, 0 }, /* 77 */
|
||||
{ "ButtonFrameInactive", kThemeBrushButtonFrameInactive, 0, 0 }, /* 78 */
|
||||
{ "ButtonFaceActive", kThemeBrushButtonFaceActive, 0, 0 }, /* 79 */
|
||||
{ "ButtonFaceInactive", kThemeBrushButtonFaceInactive, 0, 0 }, /* 80 */
|
||||
{ "ButtonFacePressed", kThemeBrushButtonFacePressed, 0, 0 }, /* 81 */
|
||||
{ "ButtonActiveDarkShadow", kThemeBrushButtonActiveDarkShadow, 0, 0 }, /* 82 */
|
||||
{ "ButtonActiveDarkHighlight", kThemeBrushButtonActiveDarkHighlight, 0, 0 }, /* 83 */
|
||||
{ "ButtonActiveLightShadow", kThemeBrushButtonActiveLightShadow, 0, 0 }, /* 84 */
|
||||
{ "ButtonActiveLightHighlight", kThemeBrushButtonActiveLightHighlight, 0, 0 }, /* 85 */
|
||||
{ "ButtonInactiveDarkShadow", kThemeBrushButtonInactiveDarkShadow, 0, 0 }, /* 86 */
|
||||
{ "ButtonInactiveDarkHighlight", kThemeBrushButtonInactiveDarkHighlight, 0, 0 }, /* 87 */
|
||||
{ "ButtonInactiveLightShadow", kThemeBrushButtonInactiveLightShadow, 0, 0 }, /* 88 */
|
||||
{ "ButtonInactiveLightHighlight", kThemeBrushButtonInactiveLightHighlight, 0, 0 }, /* 89 */
|
||||
{ "ButtonPressedDarkShadow", kThemeBrushButtonPressedDarkShadow, 0, 0 }, /* 90 */
|
||||
{ "ButtonPressedDarkHighlight", kThemeBrushButtonPressedDarkHighlight, 0, 0 }, /* 91 */
|
||||
{ "ButtonPressedLightShadow", kThemeBrushButtonPressedLightShadow, 0, 0 }, /* 92 */
|
||||
{ "ButtonPressedLightHighlight", kThemeBrushButtonPressedLightHighlight, 0, 0 }, /* 93 */
|
||||
{ "BevelActiveLight", kThemeBrushBevelActiveLight, 0, 0 }, /* 94 */
|
||||
{ "BevelActiveDark", kThemeBrushBevelActiveDark, 0, 0 }, /* 95 */
|
||||
{ "BevelInactiveLight", kThemeBrushBevelInactiveLight, 0, 0 }, /* 96 */
|
||||
{ "BevelInactiveDark", kThemeBrushBevelInactiveDark, 0, 0 }, /* 97 */
|
||||
{ "NotificationWindowBackground", kThemeBrushNotificationWindowBackground, 0, 0 }, /* 98 */
|
||||
{ "MovableModalBackground", kThemeBrushMovableModalBackground, 0, 0 }, /* 99 */
|
||||
{ "SheetBackgroundOpaque", kThemeBrushSheetBackgroundOpaque, 0, 0 }, /* 100 */
|
||||
{ "DrawerBackground", kThemeBrushDrawerBackground, 0, 0 }, /* 101 */
|
||||
{ "ToolbarBackground", kThemeBrushToolbarBackground, 0, 0 }, /* 102 */
|
||||
{ "SheetBackgroundTransparent", kThemeBrushSheetBackgroundTransparent, 0, 0 }, /* 103 */
|
||||
{ "MenuBackground", kThemeBrushMenuBackground, 0, 0 }, /* 104 */
|
||||
{ "Pixel", 0, 0, 0 }, /* 105: PIXEL_MAGIC */
|
||||
{ "MenuBackgroundSelected", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 106 */
|
||||
{ "ListViewOddRowBackground", kThemeBrushListViewOddRowBackground, 0, 0 }, /* 107 */
|
||||
{ "ListViewEvenRowBackground", kThemeBrushListViewEvenRowBackground, 0, 0 }, /* 108 */
|
||||
{ "ListViewColumnDivider", kThemeBrushListViewColumnDivider, 0, 0 }, /* 109 */
|
||||
{ "BlackText", 0, kThemeTextColorBlack, 0 }, /* 110 */
|
||||
{ "DialogActiveText", 0, kThemeTextColorDialogActive, 0 }, /* 111 */
|
||||
{ "DialogInactiveText", 0, kThemeTextColorDialogInactive, 0 }, /* 112 */
|
||||
{ "AlertActiveText", 0, kThemeTextColorAlertActive, 0 }, /* 113 */
|
||||
{ "AlertInactiveText", 0, kThemeTextColorAlertInactive, 0 }, /* 114 */
|
||||
{ "ModelessDialogActiveText", 0, kThemeTextColorModelessDialogActive, 0 }, /* 115 */
|
||||
{ "ModelessDialogInactiveText", 0, kThemeTextColorModelessDialogInactive, 0 }, /* 116 */
|
||||
{ "WindowHeaderActiveText", 0, kThemeTextColorWindowHeaderActive, 0 }, /* 117 */
|
||||
{ "WindowHeaderInactiveText", 0, kThemeTextColorWindowHeaderInactive, 0 }, /* 118 */
|
||||
{ "PlacardActiveText", 0, kThemeTextColorPlacardActive, 0 }, /* 119 */
|
||||
{ "PlacardInactiveText", 0, kThemeTextColorPlacardInactive, 0 }, /* 120 */
|
||||
{ "PlacardPressedText", 0, kThemeTextColorPlacardPressed, 0 }, /* 121 */
|
||||
{ "PushButtonActiveText", 0, kThemeTextColorPushButtonActive, 0 }, /* 122 */
|
||||
{ "PushButtonInactiveText", 0, kThemeTextColorPushButtonInactive, 0 }, /* 123 */
|
||||
{ "PushButtonPressedText", 0, kThemeTextColorPushButtonPressed, 0 }, /* 124 */
|
||||
{ "BevelButtonActiveText", 0, kThemeTextColorBevelButtonActive, 0 }, /* 125 */
|
||||
{ "BevelButtonInactiveText", 0, kThemeTextColorBevelButtonInactive, 0 }, /* 126 */
|
||||
{ "BevelButtonPressedText", 0, kThemeTextColorBevelButtonPressed, 0 }, /* 127 */
|
||||
{ "PopupButtonActiveText", 0, kThemeTextColorPopupButtonActive, 0 }, /* 128 */
|
||||
{ "PopupButtonInactiveText", 0, kThemeTextColorPopupButtonInactive, 0 }, /* 129 */
|
||||
{ "PopupButtonPressedText", 0, kThemeTextColorPopupButtonPressed, 0 }, /* 130 */
|
||||
{ "IconLabelText", 0, kThemeTextColorIconLabel, 0 }, /* 131 */
|
||||
{ "ListViewText", 0, kThemeTextColorListView, 0 }, /* 132 */
|
||||
{ "DocumentWindowTitleActiveText", 0, kThemeTextColorDocumentWindowTitleActive, 0 }, /* 133 */
|
||||
{ "DocumentWindowTitleInactiveText", 0, kThemeTextColorDocumentWindowTitleInactive, 0 }, /* 134 */
|
||||
{ "MovableModalWindowTitleActiveText", 0, kThemeTextColorMovableModalWindowTitleActive, 0 }, /* 135 */
|
||||
{ "MovableModalWindowTitleInactiveText",0, kThemeTextColorMovableModalWindowTitleInactive, 0 }, /* 136 */
|
||||
{ "UtilityWindowTitleActiveText", 0, kThemeTextColorUtilityWindowTitleActive, 0 }, /* 137 */
|
||||
{ "UtilityWindowTitleInactiveText", 0, kThemeTextColorUtilityWindowTitleInactive, 0 }, /* 138 */
|
||||
{ "PopupWindowTitleActiveText", 0, kThemeTextColorPopupWindowTitleActive, 0 }, /* 139 */
|
||||
{ "PopupWindowTitleInactiveText", 0, kThemeTextColorPopupWindowTitleInactive, 0 }, /* 140 */
|
||||
{ "RootMenuActiveText", 0, kThemeTextColorRootMenuActive, 0 }, /* 141 */
|
||||
{ "RootMenuSelectedText", 0, kThemeTextColorRootMenuSelected, 0 }, /* 142 */
|
||||
{ "RootMenuDisabledText", 0, kThemeTextColorRootMenuDisabled, 0 }, /* 143 */
|
||||
{ "MenuItemActiveText", 0, kThemeTextColorMenuItemActive, 0 }, /* 144 */
|
||||
{ "MenuItemSelectedText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 145 */
|
||||
{ "MenuItemDisabledText", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 146 */
|
||||
{ "PopupLabelActiveText", 0, kThemeTextColorPopupLabelActive, 0 }, /* 147 */
|
||||
{ "PopupLabelInactiveText", 0, kThemeTextColorPopupLabelInactive, 0 }, /* 148 */
|
||||
{ "TabFrontActiveText", 0, kThemeTextColorTabFrontActive, 0 }, /* 149 */
|
||||
{ "TabNonFrontActiveText", 0, kThemeTextColorTabNonFrontActive, 0 }, /* 150 */
|
||||
{ "TabNonFrontPressedText", 0, kThemeTextColorTabNonFrontPressed, 0 }, /* 151 */
|
||||
{ "TabFrontInactiveText", 0, kThemeTextColorTabFrontInactive, 0 }, /* 152 */
|
||||
{ "TabNonFrontInactiveText", 0, kThemeTextColorTabNonFrontInactive, 0 }, /* 153 */
|
||||
{ "IconLabelSelectedText", 0, kThemeTextColorIconLabelSelected, 0 }, /* 154 */
|
||||
{ "BevelButtonStickyActiveText", 0, kThemeTextColorBevelButtonStickyActive, 0 }, /* 155 */
|
||||
{ "BevelButtonStickyInactiveText", 0, kThemeTextColorBevelButtonStickyInactive, 0 }, /* 156 */
|
||||
{ "NotificationText", 0, kThemeTextColorNotification, 0 }, /* 157 */
|
||||
{ "SystemDetailText", 0, kThemeTextColorSystemDetail, 0 }, /* 158 */
|
||||
{ "WhiteText", 0, kThemeTextColorWhite, 0 }, /* 159 */
|
||||
{ "TabPaneBackground", 0, 0, kThemeBackgroundTabPane }, /* 160 */
|
||||
{ "PlacardBackground", 0, 0, kThemeBackgroundPlacard }, /* 161 */
|
||||
{ "WindowHeaderBackground", 0, 0, kThemeBackgroundWindowHeader }, /* 162 */
|
||||
{ "ListViewWindowHeaderBackground", 0, 0, kThemeBackgroundListViewWindowHeader }, /* 163 */
|
||||
{ "SecondaryGroupBoxBackground", 0, 0, kThemeBackgroundSecondaryGroupBox }, /* 164 */
|
||||
{ "MetalBackground", 0, 0, kThemeBackgroundMetal }, /* 165 */
|
||||
{ NULL, 0, 0, 0 }
|
||||
{ "Transparent", clearColor, 0 }, /* 30: TRANSPARENT_PIXEL */
|
||||
{ "Highlight", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 31 */
|
||||
{ "HighlightSecondary", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 32 */
|
||||
{ "HighlightText", HIBrush, kThemeBrushBlack }, /* 33 */
|
||||
{ "HighlightAlternate", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 34 */
|
||||
{ "ButtonText", HIText, kThemeTextColorPushButtonActive }, /* 35 */
|
||||
{ "PrimaryHighlightColor", HIBrush, kThemeBrushPrimaryHighlightColor }, /* 36 */
|
||||
{ "ButtonFace", HIBrush, kThemeBrushButtonFaceActive }, /* 37 */
|
||||
{ "SecondaryHighlightColor", HIBrush, kThemeBrushSecondaryHighlightColor }, /* 38 */
|
||||
{ "ButtonFrame", HIBrush, kThemeBrushButtonFrameActive }, /* 39 */
|
||||
{ "AlternatePrimaryHighlightColor", HIBrush, kThemeBrushAlternatePrimaryHighlightColor }, /* 40 */
|
||||
{ "WindowBody", HIBrush, kThemeBrushDocumentWindowBackground }, /* 41 */
|
||||
{ "SheetBackground", HIBrush, kThemeBrushSheetBackground }, /* 42 */
|
||||
{ "MenuActive", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 43 */
|
||||
{ "Black", HIBrush, kThemeBrushBlack }, /* 44 */
|
||||
{ "MenuActiveText", HIText, kThemeTextColorMenuItemSelected }, /* 45 */
|
||||
{ "White", HIBrush, kThemeBrushWhite }, /* 46 */
|
||||
{ "Menu", HIBrush, kThemeBrushMenuBackground }, /* 47 */
|
||||
{ "DialogBackgroundActive", HIBrush, kThemeBrushDialogBackgroundActive }, /* 48 */
|
||||
{ "MenuDisabled", HIText, kThemeTextColorMenuItemDisabled }, /* 49 */
|
||||
{ "DialogBackgroundInactive", HIBrush, kThemeBrushDialogBackgroundInactive }, /* 50 */
|
||||
{ "MenuText", HIText, kThemeTextColorMenuItemActive }, /* 51 */
|
||||
{ "AppearanceColor", appearance, 0 }, /* 52: APPEARANCE_PIXEL */
|
||||
{ "AlertBackgroundActive", HIBrush, kThemeBrushAlertBackgroundActive }, /* 53 */
|
||||
{ "AlertBackgroundInactive", HIBrush, kThemeBrushAlertBackgroundInactive }, /* 54 */
|
||||
{ "ModelessDialogBackgroundActive", HIBrush, kThemeBrushModelessDialogBackgroundActive }, /* 55 */
|
||||
{ "ModelessDialogBackgroundInactive", HIBrush, kThemeBrushModelessDialogBackgroundInactive }, /* 56 */
|
||||
{ "UtilityWindowBackgroundActive", HIBrush, kThemeBrushUtilityWindowBackgroundActive }, /* 57 */
|
||||
{ "UtilityWindowBackgroundInactive", HIBrush, kThemeBrushUtilityWindowBackgroundInactive }, /* 58 */
|
||||
{ "ListViewSortColumnBackground", HIBrush, kThemeBrushListViewSortColumnBackground }, /* 59 */
|
||||
{ "ListViewBackground", HIBrush, kThemeBrushListViewBackground }, /* 60 */
|
||||
{ "IconLabelBackground", HIBrush, kThemeBrushIconLabelBackground }, /* 61 */
|
||||
{ "ListViewSeparator", HIBrush, kThemeBrushListViewSeparator }, /* 62 */
|
||||
{ "ChasingArrows", HIBrush, kThemeBrushChasingArrows }, /* 63 */
|
||||
{ "DragHilite", HIBrush, kThemeBrushDragHilite }, /* 64 */
|
||||
{ "DocumentWindowBackground", HIBrush, kThemeBrushDocumentWindowBackground }, /* 65 */
|
||||
{ "FinderWindowBackground", HIBrush, kThemeBrushFinderWindowBackground }, /* 66 */
|
||||
{ "ScrollBarDelimiterActive", HIBrush, kThemeBrushScrollBarDelimiterActive }, /* 67 */
|
||||
{ "ScrollBarDelimiterInactive", HIBrush, kThemeBrushScrollBarDelimiterInactive }, /* 68 */
|
||||
{ "FocusHighlight", HIBrush, kThemeBrushFocusHighlight }, /* 69 */
|
||||
{ "PopupArrowActive", HIBrush, kThemeBrushPopupArrowActive }, /* 70 */
|
||||
{ "PopupArrowPressed", HIBrush, kThemeBrushPopupArrowPressed }, /* 71 */
|
||||
{ "PopupArrowInactive", HIBrush, kThemeBrushPopupArrowInactive }, /* 72 */
|
||||
{ "AppleGuideCoachmark", HIBrush, kThemeBrushAppleGuideCoachmark }, /* 73 */
|
||||
{ "IconLabelBackgroundSelected", HIBrush, kThemeBrushIconLabelBackgroundSelected }, /* 74 */
|
||||
{ "StaticAreaFill", HIBrush, kThemeBrushStaticAreaFill }, /* 75 */
|
||||
{ "ActiveAreaFill", HIBrush, kThemeBrushActiveAreaFill }, /* 76 */
|
||||
{ "ButtonFrameActive", HIBrush, kThemeBrushButtonFrameActive }, /* 77 */
|
||||
{ "ButtonFrameInactive", HIBrush, kThemeBrushButtonFrameInactive }, /* 78 */
|
||||
{ "ButtonFaceActive", HIBrush, kThemeBrushButtonFaceActive }, /* 79 */
|
||||
{ "ButtonFaceInactive", HIBrush, kThemeBrushButtonFaceInactive }, /* 80 */
|
||||
{ "ButtonFacePressed", HIBrush, kThemeBrushButtonFacePressed }, /* 81 */
|
||||
{ "ButtonActiveDarkShadow", HIBrush, kThemeBrushButtonActiveDarkShadow }, /* 82 */
|
||||
{ "ButtonActiveDarkHighlight", HIBrush, kThemeBrushButtonActiveDarkHighlight }, /* 83 */
|
||||
{ "ButtonActiveLightShadow", HIBrush, kThemeBrushButtonActiveLightShadow }, /* 84 */
|
||||
{ "ButtonActiveLightHighlight", HIBrush, kThemeBrushButtonActiveLightHighlight }, /* 85 */
|
||||
{ "ButtonInactiveDarkShadow", HIBrush, kThemeBrushButtonInactiveDarkShadow }, /* 86 */
|
||||
{ "ButtonInactiveDarkHighlight", HIBrush, kThemeBrushButtonInactiveDarkHighlight }, /* 87 */
|
||||
{ "ButtonInactiveLightShadow", HIBrush, kThemeBrushButtonInactiveLightShadow }, /* 88 */
|
||||
{ "ButtonInactiveLightHighlight", HIBrush, kThemeBrushButtonInactiveLightHighlight }, /* 89 */
|
||||
{ "ButtonPressedDarkShadow", HIBrush, kThemeBrushButtonPressedDarkShadow }, /* 90 */
|
||||
{ "ButtonPressedDarkHighlight", HIBrush, kThemeBrushButtonPressedDarkHighlight }, /* 91 */
|
||||
{ "ButtonPressedLightShadow", HIBrush, kThemeBrushButtonPressedLightShadow }, /* 92 */
|
||||
{ "ButtonPressedLightHighlight", HIBrush, kThemeBrushButtonPressedLightHighlight }, /* 93 */
|
||||
{ "BevelActiveLight", HIBrush, kThemeBrushBevelActiveLight }, /* 94 */
|
||||
{ "BevelActiveDark", HIBrush, kThemeBrushBevelActiveDark }, /* 95 */
|
||||
{ "BevelInactiveLight", HIBrush, kThemeBrushBevelInactiveLight }, /* 96 */
|
||||
{ "BevelInactiveDark", HIBrush, kThemeBrushBevelInactiveDark }, /* 97 */
|
||||
{ "NotificationWindowBackground", HIBrush, kThemeBrushNotificationWindowBackground }, /* 98 */
|
||||
{ "MovableModalBackground", HIBrush, kThemeBrushMovableModalBackground }, /* 99 */
|
||||
{ "SheetBackgroundOpaque", HIBrush, kThemeBrushSheetBackgroundOpaque }, /* 100 */
|
||||
{ "DrawerBackground", HIBrush, kThemeBrushDrawerBackground }, /* 101 */
|
||||
{ "ToolbarBackground", HIBrush, kThemeBrushToolbarBackground }, /* 102 */
|
||||
{ "SheetBackgroundTransparent", HIBrush, kThemeBrushSheetBackgroundTransparent }, /* 103 */
|
||||
{ "MenuBackground", HIBrush, kThemeBrushMenuBackground }, /* 104 */
|
||||
{ "Pixel", rgbColor, 0 }, /* 105: PIXEL_MAGIC */
|
||||
{ "MenuBackgroundSelected", HIBrush, kThemeBrushMenuBackgroundSelected }, /* 106 */
|
||||
{ "ListViewOddRowBackground", HIBrush, kThemeBrushListViewOddRowBackground }, /* 107 */
|
||||
{ "ListViewEvenRowBackground", HIBrush, kThemeBrushListViewEvenRowBackground }, /* 108 */
|
||||
{ "ListViewColumnDivider", HIBrush, kThemeBrushListViewColumnDivider }, /* 109 */
|
||||
{ "BlackText", HIText, kThemeTextColorBlack }, /* 110 */
|
||||
{ "DialogActiveText", HIText, kThemeTextColorDialogActive }, /* 111 */
|
||||
{ "DialogInactiveText", HIText, kThemeTextColorDialogInactive }, /* 112 */
|
||||
{ "AlertActiveText", HIText, kThemeTextColorAlertActive }, /* 113 */
|
||||
{ "AlertInactiveText", HIText, kThemeTextColorAlertInactive }, /* 114 */
|
||||
{ "ModelessDialogActiveText", HIText, kThemeTextColorModelessDialogActive }, /* 115 */
|
||||
{ "ModelessDialogInactiveText", HIText, kThemeTextColorModelessDialogInactive }, /* 116 */
|
||||
{ "WindowHeaderActiveText", HIText, kThemeTextColorWindowHeaderActive }, /* 117 */
|
||||
{ "WindowHeaderInactiveText", HIText, kThemeTextColorWindowHeaderInactive }, /* 118 */
|
||||
{ "PlacardActiveText", HIText, kThemeTextColorPlacardActive }, /* 119 */
|
||||
{ "PlacardInactiveText", HIText, kThemeTextColorPlacardInactive }, /* 120 */
|
||||
{ "PlacardPressedText", HIText, kThemeTextColorPlacardPressed }, /* 121 */
|
||||
{ "PushButtonActiveText", HIText, kThemeTextColorPushButtonActive }, /* 122 */
|
||||
{ "PushButtonInactiveText", HIText, kThemeTextColorPushButtonInactive }, /* 123 */
|
||||
{ "PushButtonPressedText", HIText, kThemeTextColorPushButtonPressed }, /* 124 */
|
||||
{ "BevelButtonActiveText", HIText, kThemeTextColorBevelButtonActive }, /* 125 */
|
||||
{ "BevelButtonInactiveText", HIText, kThemeTextColorBevelButtonInactive }, /* 126 */
|
||||
{ "BevelButtonPressedText", HIText, kThemeTextColorBevelButtonPressed }, /* 127 */
|
||||
{ "PopupButtonActiveText", HIText, kThemeTextColorPopupButtonActive }, /* 128 */
|
||||
{ "PopupButtonInactiveText", HIText, kThemeTextColorPopupButtonInactive }, /* 129 */
|
||||
{ "PopupButtonPressedText", HIText, kThemeTextColorPopupButtonPressed }, /* 130 */
|
||||
{ "IconLabelText", HIText, kThemeTextColorIconLabel }, /* 131 */
|
||||
{ "ListViewText", HIText, kThemeTextColorListView }, /* 132 */
|
||||
{ "DocumentWindowTitleActiveText", HIText, kThemeTextColorDocumentWindowTitleActive }, /* 133 */
|
||||
{ "DocumentWindowTitleInactiveText", HIText, kThemeTextColorDocumentWindowTitleInactive }, /* 134 */
|
||||
{ "MovableModalWindowTitleActiveText", HIText, kThemeTextColorMovableModalWindowTitleActive }, /* 135 */
|
||||
{ "MovableModalWindowTitleInactiveText",HIText, kThemeTextColorMovableModalWindowTitleInactive }, /* 136 */
|
||||
{ "UtilityWindowTitleActiveText", HIText, kThemeTextColorUtilityWindowTitleActive }, /* 137 */
|
||||
{ "UtilityWindowTitleInactiveText", HIText, kThemeTextColorUtilityWindowTitleInactive }, /* 138 */
|
||||
{ "PopupWindowTitleActiveText", HIText, kThemeTextColorPopupWindowTitleActive }, /* 139 */
|
||||
{ "PopupWindowTitleInactiveText", HIText, kThemeTextColorPopupWindowTitleInactive }, /* 140 */
|
||||
{ "RootMenuActiveText", HIText, kThemeTextColorRootMenuActive }, /* 141 */
|
||||
{ "RootMenuSelectedText", HIText, kThemeTextColorRootMenuSelected }, /* 142 */
|
||||
{ "RootMenuDisabledText", HIText, kThemeTextColorRootMenuDisabled }, /* 143 */
|
||||
{ "MenuItemActiveText", HIText, kThemeTextColorMenuItemActive }, /* 144 */
|
||||
{ "MenuItemSelectedText", HIText, kThemeTextColorMenuItemSelected }, /* 145 */
|
||||
{ "MenuItemDisabledText", HIText, kThemeTextColorMenuItemDisabled }, /* 146 */
|
||||
{ "PopupLabelActiveText", HIText, kThemeTextColorPopupLabelActive }, /* 147 */
|
||||
{ "PopupLabelInactiveText", HIText, kThemeTextColorPopupLabelInactive }, /* 148 */
|
||||
{ "TabFrontActiveText", HIText, kThemeTextColorTabFrontActive }, /* 149 */
|
||||
{ "TabNonFrontActiveText", HIText, kThemeTextColorTabNonFrontActive }, /* 150 */
|
||||
{ "TabNonFrontPressedText", HIText, kThemeTextColorTabNonFrontPressed }, /* 151 */
|
||||
{ "TabFrontInactiveText", HIText, kThemeTextColorTabFrontInactive }, /* 152 */
|
||||
{ "TabNonFrontInactiveText", HIText, kThemeTextColorTabNonFrontInactive }, /* 153 */
|
||||
{ "IconLabelSelectedText", HIText, kThemeTextColorIconLabelSelected }, /* 154 */
|
||||
{ "BevelButtonStickyActiveText", HIText, kThemeTextColorBevelButtonStickyActive }, /* 155 */
|
||||
{ "BevelButtonStickyInactiveText", HIText, kThemeTextColorBevelButtonStickyInactive }, /* 156 */
|
||||
{ "NotificationText", HIText, kThemeTextColorNotification }, /* 157 */
|
||||
{ "SystemDetailText", HIText, kThemeTextColorSystemDetail }, /* 158 */
|
||||
{ "WhiteText", HIText, kThemeTextColorWhite }, /* 159 */
|
||||
{ "TabPaneBackground", HIBackground, kThemeBackgroundTabPane }, /* 160 */
|
||||
{ "PlacardBackground", HIBackground, kThemeBackgroundPlacard }, /* 161 */
|
||||
{ "WindowHeaderBackground", HIBackground, kThemeBackgroundWindowHeader }, /* 162 */
|
||||
{ "ListViewWindowHeaderBackground", HIBackground, kThemeBackgroundListViewWindowHeader }, /* 163 */
|
||||
{ "SecondaryGroupBoxBackground", HIBackground, kThemeBackgroundSecondaryGroupBox }, /* 164 */
|
||||
{ "MetalBackground", HIBackground, kThemeBackgroundMetal }, /* 165 */
|
||||
|
||||
/*
|
||||
* Colors based on "semantic" NSColors.
|
||||
*/
|
||||
|
||||
{ "WindowBackgroundColor", ttkBackground, 0 }, /* 166 */
|
||||
{ "WindowBackgroundColor1", ttkBackground, 1 }, /* 167 */
|
||||
{ "WindowBackgroundColor2", ttkBackground, 2 }, /* 168 */
|
||||
{ "WindowBackgroundColor3", ttkBackground, 3 }, /* 169 */
|
||||
{ "WindowBackgroundColor4", ttkBackground, 4 }, /* 170 */
|
||||
{ "WindowBackgroundColor5", ttkBackground, 5 }, /* 171 */
|
||||
{ "WindowBackgroundColor6", ttkBackground, 6 }, /* 172 */
|
||||
{ "WindowBackgroundColor7", ttkBackground, 7 }, /* 173 */
|
||||
{ "TextColor", semantic, 0 }, /* 174 */
|
||||
{ "SelectedTextColor", semantic, 1 }, /* 175 */
|
||||
{ "LabelColor", semantic, 2 }, /* 176 */
|
||||
{ "ControlTextColor", semantic, 3 }, /* 177 */
|
||||
{ "DisabledControlTextColor", semantic, 4 }, /* 178 */
|
||||
{ "SelectedTabTextColor", semantic, 5 }, /* 179 */
|
||||
{ "TextBackgroundColor", semantic, 6 }, /* 180 */
|
||||
{ "SelectedTextBackgroundColor", semantic, 7 }, /* 181 */
|
||||
{ "ControlAccentColor", semantic, 8 }, /* 182 */
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
#define MAX_PIXELCODE 165
|
||||
#define FIRST_SEMANTIC_COLOR 166
|
||||
#define MAX_PIXELCODE 182
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* GetThemeFromPixelCode --
|
||||
* GetEntryFromPixelCode --
|
||||
*
|
||||
* When given a pixel code corresponding to a theme system color,
|
||||
* set one of brush, textColor or background to the corresponding
|
||||
* Appearance Mgr theme constant.
|
||||
* Extract a SystemColorMapEntry from the table.
|
||||
*
|
||||
* Results:
|
||||
* Returns false if not a real pixel, true otherwise.
|
||||
* Returns false if the code is out of bounds.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
@@ -190,36 +232,28 @@ static const struct SystemColorMapEntry systemColorMap[] = {
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
GetThemeFromPixelCode(
|
||||
static bool
|
||||
GetEntryFromPixelCode(
|
||||
unsigned char code,
|
||||
ThemeBrush *brush,
|
||||
ThemeTextColor *textColor,
|
||||
ThemeBackgroundKind *background)
|
||||
struct SystemColorMapEntry *entry)
|
||||
{
|
||||
if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) {
|
||||
*brush = systemColorMap[code - MIN_PIXELCODE].brush;
|
||||
*textColor = systemColorMap[code - MIN_PIXELCODE].textColor;
|
||||
*background = systemColorMap[code - MIN_PIXELCODE].background;
|
||||
} else {
|
||||
*brush = 0;
|
||||
*textColor = 0;
|
||||
*background = 0;
|
||||
}
|
||||
if (!*brush && !*textColor && !*background && code != PIXEL_MAGIC &&
|
||||
code != TRANSPARENT_PIXEL) {
|
||||
return false;
|
||||
} else {
|
||||
*entry = systemColorMap[code - MIN_PIXELCODE];
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* GetThemeColor --
|
||||
* SetCGColorComponents --
|
||||
*
|
||||
* Get RGB color for a given system color or pixel value.
|
||||
* Set the components of a CGColorRef from an XColor pixel value and a
|
||||
* system color map entry. The pixel value is only used in the case where
|
||||
* the color is of type rgbColor. In that case the normalized XColor RGB
|
||||
* values are copied into the CGColorRef.
|
||||
*
|
||||
* Results:
|
||||
* OSStatus
|
||||
@@ -230,60 +264,217 @@ GetThemeFromPixelCode(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static NSColorSpace* deviceRGB = NULL;
|
||||
static CGFloat blueAccentRGBA[4] = {0, 122.0 / 255, 1.0, 1.0};
|
||||
static CGFloat windowBackground[4] =
|
||||
{236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};
|
||||
|
||||
static OSStatus
|
||||
GetThemeColor(
|
||||
SetCGColorComponents(
|
||||
struct SystemColorMapEntry entry,
|
||||
unsigned long pixel,
|
||||
ThemeBrush brush,
|
||||
ThemeTextColor textColor,
|
||||
ThemeBackgroundKind background,
|
||||
CGColorRef *c)
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
NSColor *bgColor, *color = nil;
|
||||
CGFloat rgba[4] = {0, 0, 0, 1};
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
|
||||
NSInteger colorVariant;
|
||||
static CGFloat graphiteAccentRGBA[4] =
|
||||
{152.0 / 255, 152.0 / 255, 152.0 / 255, 1.0};
|
||||
#endif
|
||||
|
||||
if (brush) {
|
||||
err = ChkErr(HIThemeBrushCreateCGColor, brush, c);
|
||||
/*} else if (textColor) {
|
||||
err = ChkErr(GetThemeTextColor, textColor, 32, true, c);*/
|
||||
} else {
|
||||
CGFloat rgba[4] = {0, 0, 0, 1};
|
||||
|
||||
switch ((pixel >> 24) & 0xff) {
|
||||
case PIXEL_MAGIC: {
|
||||
unsigned short red, green, blue;
|
||||
red = (pixel >> 16) & 0xff;
|
||||
green = (pixel >> 8) & 0xff;
|
||||
blue = (pixel ) & 0xff;
|
||||
red |= red << 8;
|
||||
green |= green << 8;
|
||||
blue |= blue << 8;
|
||||
rgba[0] = red / 65535.0;
|
||||
rgba[1] = green / 65535.0;
|
||||
rgba[2] = blue / 65535.0;
|
||||
break;
|
||||
}
|
||||
case TRANSPARENT_PIXEL:
|
||||
rgba[3] = 0.0;
|
||||
break;
|
||||
}
|
||||
|
||||
static CGColorSpaceRef deviceRGBSpace = NULL;
|
||||
if (!deviceRGBSpace) {
|
||||
deviceRGBSpace = CGColorSpaceCreateDeviceRGB();
|
||||
}
|
||||
*c = CGColorCreate(deviceRGBSpace, rgba );
|
||||
if (!deviceRGB) {
|
||||
deviceRGB = [NSColorSpace deviceRGBColorSpace];
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called before our autorelease pool is set up,
|
||||
* so it needs its own pool.
|
||||
*/
|
||||
|
||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||
|
||||
switch (entry.type) {
|
||||
case HIBrush:
|
||||
err = ChkErr(HIThemeBrushCreateCGColor, entry.value, c);
|
||||
return err;
|
||||
case rgbColor:
|
||||
rgba[0] = ((pixel >> 16) & 0xff) / 255.0;
|
||||
rgba[1] = ((pixel >> 8) & 0xff) / 255.0;
|
||||
rgba[2] = ((pixel ) & 0xff) / 255.0;
|
||||
break;
|
||||
case ttkBackground:
|
||||
|
||||
/*
|
||||
* Prior to OSX 10.14, getComponents returns black when applied to
|
||||
* windowBackGroundColor.
|
||||
*/
|
||||
|
||||
if ([NSApp macMinorVersion] < 14) {
|
||||
for (int i=0; i<3; i++) {
|
||||
rgba[i] = windowBackground[i];
|
||||
}
|
||||
} else {
|
||||
bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace:
|
||||
deviceRGB];
|
||||
[bgColor getComponents: rgba];
|
||||
}
|
||||
if (rgba[0] + rgba[1] + rgba[2] < 1.5) {
|
||||
for (int i=0; i<3; i++) {
|
||||
rgba[i] += entry.value*8.0 / 255.0;
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<3; i++) {
|
||||
rgba[i] -= entry.value*8.0 / 255.0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case semantic:
|
||||
switch (entry.value) {
|
||||
case 0:
|
||||
color = [[NSColor textColor] colorUsingColorSpace: deviceRGB];
|
||||
break;
|
||||
case 1:
|
||||
color = [[NSColor selectedTextColor] colorUsingColorSpace: deviceRGB];
|
||||
break;
|
||||
case 2:
|
||||
if ([NSApp macMinorVersion] > 9) {
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090
|
||||
color = [[NSColor labelColor] colorUsingColorSpace: deviceRGB];
|
||||
#endif
|
||||
} else {
|
||||
color = [[NSColor textColor] colorUsingColorSpace: deviceRGB];
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
color = [[NSColor controlTextColor] colorUsingColorSpace:
|
||||
deviceRGB];
|
||||
break;
|
||||
case 4:
|
||||
color = [[NSColor disabledControlTextColor] colorUsingColorSpace:
|
||||
deviceRGB];
|
||||
break;
|
||||
case 5:
|
||||
if ([NSApp macMinorVersion] > 6) {
|
||||
color = [[NSColor whiteColor] colorUsingColorSpace:
|
||||
deviceRGB];
|
||||
} else {
|
||||
color = [[NSColor blackColor] colorUsingColorSpace:
|
||||
deviceRGB];
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
color = [[NSColor textBackgroundColor] colorUsingColorSpace:
|
||||
deviceRGB];
|
||||
break;
|
||||
case 7:
|
||||
color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpace:
|
||||
deviceRGB];
|
||||
break;
|
||||
case 8:
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
|
||||
if (@available(macOS 10.14, *)) {
|
||||
color = [[NSColor controlAccentColor] colorUsingColorSpace:
|
||||
deviceRGB];
|
||||
} else {
|
||||
color = [NSColor colorWithColorSpace: deviceRGB
|
||||
components: blueAccentRGBA
|
||||
count: 4];
|
||||
}
|
||||
#else
|
||||
colorVariant = [[NSUserDefaults standardUserDefaults]
|
||||
integerForKey:@"AppleAquaColorVariant"];
|
||||
if (colorVariant == 6) {
|
||||
color = [NSColor colorWithColorSpace: deviceRGB
|
||||
components: graphiteAccentRGBA
|
||||
count: 4];
|
||||
} else {
|
||||
color = [NSColor colorWithColorSpace: deviceRGB
|
||||
components: blueAccentRGBA
|
||||
count: 4];
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
||||
if ([NSApp macMinorVersion] >= 10) {
|
||||
color = [[NSColor labelColor] colorUsingColorSpace:
|
||||
deviceRGB];
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
color = [[NSColor textColor] colorUsingColorSpace: deviceRGB];
|
||||
break;
|
||||
}
|
||||
[color getComponents: rgba];
|
||||
break;
|
||||
case clearColor:
|
||||
rgba[3] = 0.0;
|
||||
break;
|
||||
|
||||
/*
|
||||
* There are no HITheme functions which convert Text or background colors
|
||||
* to CGColors. (GetThemeTextColor has been removed, and it was never
|
||||
* possible with backgrounds.) If we get one of these we return black.
|
||||
*/
|
||||
|
||||
case HIText:
|
||||
case HIBackground:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*c = CGColorCreate(deviceRGB.CGColorSpace, rgba);
|
||||
[pool drain];
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkMacOSXInDarkMode --
|
||||
*
|
||||
* Tests whether the given window's NSView has a DarkAqua Appearance.
|
||||
*
|
||||
* Results:
|
||||
* Returns true if the NSView is in DarkMode, false if not.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MODULE_SCOPE Bool
|
||||
TkMacOSXInDarkMode(Tk_Window tkwin)
|
||||
{
|
||||
int result = false;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
|
||||
if ([NSApp macMinorVersion] >= 14) {
|
||||
static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua";
|
||||
TkWindow *winPtr = (TkWindow*) tkwin;
|
||||
NSView *view = TkMacOSXDrawableView(winPtr->privatePtr);
|
||||
result = (view &&
|
||||
[view.effectiveAppearance.name isEqualToString:darkAqua]);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkSetMacColor --
|
||||
*
|
||||
* Creates a CGColorRef from a X style pixel value.
|
||||
* Sets the components of a CGColorRef from an XColor pixel value.
|
||||
* The high order byte of the pixel value is used as an index into
|
||||
* the system color table, and then SetCGColorComponents is called
|
||||
* with the table entry and the pixel value.
|
||||
*
|
||||
* Results:
|
||||
* Returns false if not a real pixel, true otherwise.
|
||||
* Returns false if the high order byte is not a valid index, true
|
||||
* otherwise.
|
||||
*
|
||||
* Side effects:
|
||||
* The variable macColor is set to a new CGColorRef, the caller is
|
||||
@@ -299,14 +490,10 @@ TkSetMacColor(
|
||||
{
|
||||
CGColorRef *color = (CGColorRef*)macColor;
|
||||
OSStatus err = -1;
|
||||
ThemeBrush brush;
|
||||
ThemeTextColor textColor;
|
||||
ThemeBackgroundKind background;
|
||||
struct SystemColorMapEntry entry;
|
||||
|
||||
if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, &textColor,
|
||||
&background)) {
|
||||
err = ChkErr(GetThemeColor, pixel, brush, textColor, background,
|
||||
color);
|
||||
if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) {
|
||||
err = ChkErr(SetCGColorComponents, entry, pixel, color);
|
||||
}
|
||||
return (err == noErr);
|
||||
}
|
||||
@@ -321,7 +508,7 @@ TkSetMacColor(
|
||||
* Results:
|
||||
* None resp. retained CGColorRef for CopyCachedColor()
|
||||
*
|
||||
* Side effects:
|
||||
* Side effects:M
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -450,6 +637,7 @@ TkMacOSXGetNSColor(
|
||||
if (cgColor) {
|
||||
NSColorSpace *colorSpace = [[NSColorSpace alloc]
|
||||
initWithCGColorSpace:CGColorGetColorSpace(cgColor)];
|
||||
|
||||
nsColor = [NSColor colorWithColorSpace:colorSpace
|
||||
components:CGColorGetComponents(cgColor)
|
||||
count:CGColorGetNumberOfComponents(cgColor)];
|
||||
@@ -484,48 +672,56 @@ TkMacOSXSetColorInContext(
|
||||
unsigned long pixel,
|
||||
CGContextRef context)
|
||||
{
|
||||
OSStatus err = -1;
|
||||
CGColorRef cgColor = CopyCachedColor(gc, pixel);
|
||||
ThemeBrush brush;
|
||||
ThemeTextColor textColor;
|
||||
ThemeBackgroundKind background;
|
||||
OSStatus err = noErr;
|
||||
CGColorRef cgColor = nil;
|
||||
struct SystemColorMapEntry entry;
|
||||
CGRect rect;
|
||||
int code = (pixel >> 24) & 0xff;
|
||||
HIThemeBackgroundDrawInfo info = {0, kThemeStateActive, 0};;
|
||||
static CGColorSpaceRef deviceRGBSpace = NULL;
|
||||
|
||||
if (!cgColor && GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush,
|
||||
&textColor, &background)) {
|
||||
if (brush) {
|
||||
err = ChkErr(HIThemeSetFill, brush, NULL, context,
|
||||
if (!deviceRGBSpace) {
|
||||
deviceRGBSpace = CGColorSpaceCreateDeviceRGB();
|
||||
}
|
||||
if (code < FIRST_SEMANTIC_COLOR) {
|
||||
cgColor = CopyCachedColor(gc, pixel);
|
||||
}
|
||||
if (!cgColor && GetEntryFromPixelCode(code, &entry)) {
|
||||
switch (entry.type) {
|
||||
case HIBrush:
|
||||
err = ChkErr(HIThemeSetFill, entry.value, NULL, context,
|
||||
kHIThemeOrientationNormal);
|
||||
if (err == noErr) {
|
||||
err = ChkErr(HIThemeSetStroke, brush, NULL, context,
|
||||
err = ChkErr(HIThemeSetStroke, entry.value, NULL, context,
|
||||
kHIThemeOrientationNormal);
|
||||
}
|
||||
} else if (textColor) {
|
||||
err = ChkErr(HIThemeSetTextFill, textColor, NULL, context,
|
||||
break;
|
||||
case HIText:
|
||||
err = ChkErr(HIThemeSetTextFill, entry.value, NULL, context,
|
||||
kHIThemeOrientationNormal);
|
||||
} else if (background) {
|
||||
CGRect rect = CGContextGetClipBoundingBox(context);
|
||||
HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive,
|
||||
background };
|
||||
|
||||
break;
|
||||
case HIBackground:
|
||||
info.kind = entry.value;
|
||||
rect = CGContextGetClipBoundingBox(context);
|
||||
err = ChkErr(HIThemeApplyBackground, &rect, &info,
|
||||
context, kHIThemeOrientationNormal);
|
||||
break;
|
||||
default:
|
||||
err = ChkErr(SetCGColorComponents, entry, pixel, &cgColor);
|
||||
if (err == noErr) {
|
||||
SetCachedColor(gc, pixel, cgColor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (err == noErr) {
|
||||
return;
|
||||
}
|
||||
err = ChkErr(GetThemeColor, pixel, brush, textColor, background,
|
||||
&cgColor);
|
||||
if (err == noErr) {
|
||||
SetCachedColor(gc, pixel, cgColor);
|
||||
}
|
||||
} else if (!cgColor) {
|
||||
TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel);
|
||||
}
|
||||
if (cgColor) {
|
||||
CGContextSetFillColorWithColor(context, cgColor);
|
||||
CGContextSetStrokeColorWithColor(context, cgColor);
|
||||
CGColorRelease(cgColor);
|
||||
}
|
||||
if (err != noErr) {
|
||||
TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -549,7 +745,7 @@ TkMacOSXSetColorInContext(
|
||||
TkColor *
|
||||
TkpGetColor(
|
||||
Tk_Window tkwin, /* Window in which color will be used. */
|
||||
Tk_Uid name) /* Name of color to allocated (in form
|
||||
Tk_Uid name) /* Name of color to be allocated (in form
|
||||
* suitable for passing to XParseColor). */
|
||||
{
|
||||
Display *display = tkwin != None ? Tk_Display(tkwin) : NULL;
|
||||
@@ -561,22 +757,21 @@ TkpGetColor(
|
||||
* Check to see if this is a system color. Otherwise, XParseColor
|
||||
* will do all the work.
|
||||
*/
|
||||
|
||||
if (strncasecmp(name, "system", 6) == 0) {
|
||||
Tcl_Obj *strPtr = Tcl_NewStringObj(name+6, -1);
|
||||
int idx, result;
|
||||
|
||||
result = Tcl_GetIndexFromObjStruct(NULL, strPtr, systemColorMap,
|
||||
sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx);
|
||||
sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx);
|
||||
Tcl_DecrRefCount(strPtr);
|
||||
if (result == TCL_OK) {
|
||||
OSStatus err;
|
||||
CGColorRef c;
|
||||
unsigned char pixelCode = idx + MIN_PIXELCODE;
|
||||
ThemeBrush brush = systemColorMap[idx].brush;
|
||||
ThemeTextColor textColor = systemColorMap[idx].textColor;
|
||||
ThemeBackgroundKind background = systemColorMap[idx].background;
|
||||
struct SystemColorMapEntry entry = systemColorMap[idx];
|
||||
|
||||
err = ChkErr(GetThemeColor, 0, brush, textColor, background, &c);
|
||||
err = ChkErr(SetCGColorComponents, entry, 0, &c);
|
||||
if (err == noErr) {
|
||||
const size_t n = CGColorGetNumberOfComponents(c);
|
||||
const CGFloat *rgba = CGColorGetComponents(c);
|
||||
@@ -591,12 +786,12 @@ TkpGetColor(
|
||||
color.red = color.green = color.blue = rgba[0] * 65535.0;
|
||||
break;
|
||||
default:
|
||||
Tcl_Panic("CGColor with %d components", (int) n);
|
||||
Tcl_Panic("CGColor with %d components", (int) n);
|
||||
}
|
||||
color.pixel = ((((((pixelCode << 8)
|
||||
| ((color.red >> 8) & 0xff)) << 8)
|
||||
| ((color.green >> 8) & 0xff)) << 8)
|
||||
| ((color.blue >> 8) & 0xff));
|
||||
| ((color.red >> 8) & 0xff)) << 8)
|
||||
| ((color.green >> 8) & 0xff)) << 8)
|
||||
| ((color.blue >> 8) & 0xff));
|
||||
CGColorRelease(c);
|
||||
goto validXColor;
|
||||
}
|
||||
|
||||
@@ -79,22 +79,8 @@
|
||||
#define NSInformationalAlertStyle NSAlertStyleInformational
|
||||
#define NSCriticalAlertStyle NSAlertStyleCritical
|
||||
#define NSCenterTextAlignment NSTextAlignmentCenter
|
||||
#define NSDeviceIndependentModifierFlagsMask NSEventModifierFlagDeviceIndependentFlagsMask
|
||||
#define NSCommandKeyMask NSEventModifierFlagCommand
|
||||
#define NSShiftKeyMask NSEventModifierFlagShift
|
||||
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
|
||||
#define NSAlternateKeyMask NSEventModifierFlagOption
|
||||
#define NSControlKeyMask NSEventModifierFlagControl
|
||||
#define NSNumericPadKeyMask NSEventModifierFlagNumericPad
|
||||
#define NSFunctionKeyMask NSEventModifierFlagFunction
|
||||
#define NSKeyUp NSEventTypeKeyUp
|
||||
#define NSKeyDown NSEventTypeKeyDown
|
||||
#define NSFlagsChanged NSEventTypeFlagsChanged
|
||||
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
|
||||
#define NSShiftKeyMask NSEventModifierFlagShift
|
||||
#define NSAnyEventMask NSEventMaskAny
|
||||
#define NSApplicationDefinedMask NSEventMaskApplicationDefined
|
||||
#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground
|
||||
#define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow
|
||||
#define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel
|
||||
#define NSDocModalWindowMask NSWindowStyleMaskDocModalWindow
|
||||
|
||||
@@ -185,7 +185,7 @@ static const struct CursorName cursorNames[] = {
|
||||
* Declarations of static variables used in this file.
|
||||
*/
|
||||
|
||||
static TkMacOSXCursor * gCurrentCursor = NULL;
|
||||
static TkMacOSXCursor *gCurrentCursor = NULL;
|
||||
/* A pointer to the current cursor. */
|
||||
static int gResizeOverride = false;
|
||||
/* A boolean indicating whether we should use
|
||||
@@ -194,7 +194,7 @@ static int gTkOwnsCursor = true;/* A boolean indicating whether Tk owns the
|
||||
* cursor. If not (for instance, in the case
|
||||
* where a Tk window is embedded in another
|
||||
* app's window, and the cursor is out of the
|
||||
* tk window, we will not attempt to adjust
|
||||
* Tk window, we will not attempt to adjust
|
||||
* the cursor. */
|
||||
|
||||
/*
|
||||
@@ -278,6 +278,7 @@ FindCursorByName(
|
||||
kCGColorSpaceGenericGray);
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
|
||||
bitmap, pix*pix/8, NULL);
|
||||
|
||||
if (provider) {
|
||||
img = CGImageCreate(pix, pix, 1, 1, pix/8, colorspace,
|
||||
kCGBitmapByteOrderDefault, provider, decodeWB, 0,
|
||||
@@ -299,14 +300,21 @@ FindCursorByName(
|
||||
initWithCGImage:maskedImg];
|
||||
CFRelease(maskedImg);
|
||||
}
|
||||
if (mask) { CFRelease(mask); }
|
||||
if (img) { CFRelease(img); }
|
||||
if (colorspace) { CFRelease(colorspace); }
|
||||
if (mask) {
|
||||
CFRelease(mask);
|
||||
}
|
||||
if (img) {
|
||||
CFRelease(img);
|
||||
}
|
||||
if (colorspace) {
|
||||
CFRelease(colorspace);
|
||||
}
|
||||
if (bitmapImageRep) {
|
||||
image = [[NSImage alloc] initWithSize:NSMakeSize(pix, pix)];
|
||||
[image addRepresentation:bitmapImageRep];
|
||||
[bitmapImageRep release];
|
||||
}
|
||||
|
||||
uint16_t *hotSpotData = (uint16_t*)(bitmap + 2*pix*pix/8);
|
||||
hotSpot.y = CFSwapInt16BigToHost(*hotSpotData++);
|
||||
hotSpot.x = CFSwapInt16BigToHost(*hotSpotData);
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
/*
|
||||
* The definitions below provide symbolic names for the default colors.
|
||||
* NORMAL_BG - Normal background color.
|
||||
* NORMAL_FG - Normal foreground color.
|
||||
* ACTIVE_BG - Background color when widget is active.
|
||||
* ACTIVE_FG - Foreground color when widget is active.
|
||||
* SELECT_BG - Background color for selected text.
|
||||
* SELECT_FG - Foreground color for selected text.
|
||||
* TROUGH - Background color for troughs in scales and scrollbars.
|
||||
@@ -33,12 +35,14 @@
|
||||
|
||||
#define BLACK "Black"
|
||||
#define WHITE "White"
|
||||
#define NORMAL_BG "systemWindowBody"
|
||||
#define ACTIVE_BG "systemButtonFacePressed"
|
||||
#define ACTIVE_FG "systemPushButtonPressedText"
|
||||
#define SELECT_BG "systemHighlight"
|
||||
#define SELECT_FG None
|
||||
#define INACTIVE_SELECT_BG "systemHighlightSecondary"
|
||||
#define NORMAL_BG "systemWindowBackgroundColor"
|
||||
#define TEXT_BG "systemTextBackgroundColor"
|
||||
#define NORMAL_FG "systemTextColor"
|
||||
#define ACTIVE_BG "systemWindowBackgroundColor"
|
||||
#define ACTIVE_FG "systemTextColor"
|
||||
#define SELECT_BG "systemSelectedTextBackgroundColor"
|
||||
#define SELECT_FG "systemSelectedTextColor"
|
||||
#define INACTIVE_SELECT_BG "systemSelectedTextBackgroundColor"
|
||||
#define TROUGH "#c3c3c3"
|
||||
#define INDICATOR "#b03060"
|
||||
#define DISABLED "#a3a3a3"
|
||||
@@ -50,11 +54,10 @@
|
||||
#define DEF_BUTTON_ANCHOR "center"
|
||||
#define DEF_BUTTON_ACTIVE_BG_COLOR ACTIVE_BG
|
||||
#define DEF_BUTTON_ACTIVE_BG_MONO BLACK
|
||||
#define DEF_BUTTON_ACTIVE_FG_COLOR ACTIVE_FG
|
||||
#define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR
|
||||
#define DEF_BUTTON_ACTIVE_FG_COLOR WHITE
|
||||
#define DEF_CHKRAD_ACTIVE_FG_COLOR ACTIVE_FG
|
||||
#define DEF_BUTTON_ACTIVE_FG_MONO WHITE
|
||||
/* #define DEF_BUTTON_BG_COLOR "systemButtonFace"*/
|
||||
#define DEF_BUTTON_BG_COLOR WHITE
|
||||
#define DEF_BUTTON_BG_COLOR NORMAL_BG
|
||||
#define DEF_BUTTON_BG_MONO WHITE
|
||||
#define DEF_BUTTON_BITMAP ""
|
||||
#define DEF_BUTTON_BORDER_WIDTH "2"
|
||||
@@ -64,7 +67,7 @@
|
||||
#define DEF_BUTTON_DEFAULT "disabled"
|
||||
#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED
|
||||
#define DEF_BUTTON_DISABLED_FG_MONO ""
|
||||
#define DEF_BUTTON_FG "systemButtonText"
|
||||
#define DEF_BUTTON_FG NORMAL_FG
|
||||
#define DEF_CHKRAD_FG DEF_BUTTON_FG
|
||||
#define DEF_BUTTON_FONT "TkDefaultFont"
|
||||
#define DEF_BUTTON_HEIGHT "0"
|
||||
@@ -78,7 +81,7 @@
|
||||
//#else
|
||||
#define DEF_BUTTON_HIGHLIGHT_WIDTH "1"
|
||||
//#endif
|
||||
#define DEF_BUTTON_IMAGE ((char *) NULL)
|
||||
#define DEF_BUTTON_IMAGE NULL
|
||||
#define DEF_BUTTON_INDICATOR "1"
|
||||
#define DEF_BUTTON_JUSTIFY "center"
|
||||
#define DEF_BUTTON_OFF_VALUE "0"
|
||||
@@ -105,10 +108,10 @@
|
||||
#define DEF_BUTTON_REPEAT_INTERVAL "0"
|
||||
#define DEF_BUTTON_SELECT_COLOR INDICATOR
|
||||
#define DEF_BUTTON_SELECT_MONO BLACK
|
||||
#define DEF_BUTTON_SELECT_IMAGE ((char *) NULL)
|
||||
#define DEF_BUTTON_SELECT_IMAGE NULL
|
||||
#define DEF_BUTTON_STATE "normal"
|
||||
#define DEF_LABEL_TAKE_FOCUS "0"
|
||||
#define DEF_BUTTON_TAKE_FOCUS ((char *) NULL)
|
||||
#define DEF_BUTTON_TAKE_FOCUS NULL
|
||||
#define DEF_BUTTON_TEXT ""
|
||||
#define DEF_BUTTON_TEXT_VARIABLE ""
|
||||
#define DEF_BUTTON_UNDERLINE "-1"
|
||||
@@ -146,7 +149,7 @@
|
||||
#define DEF_CANVAS_SELECT_BD_MONO "0"
|
||||
#define DEF_CANVAS_SELECT_FG_COLOR SELECT_FG
|
||||
#define DEF_CANVAS_SELECT_FG_MONO WHITE
|
||||
#define DEF_CANVAS_TAKE_FOCUS ((char *) NULL)
|
||||
#define DEF_CANVAS_TAKE_FOCUS NULL
|
||||
#define DEF_CANVAS_WIDTH "10c"
|
||||
#define DEF_CANVAS_X_SCROLL_CMD ""
|
||||
#define DEF_CANVAS_X_SCROLL_INCREMENT "0"
|
||||
@@ -169,7 +172,7 @@
|
||||
#define MAC_OSX_ENTRY_RELIEF TK_RELIEF_SUNKEN
|
||||
#define MAC_OSX_ENTRY_SELECT_RELIEF TK_RELIEF_FLAT
|
||||
|
||||
#define DEF_ENTRY_BG_COLOR NORMAL_BG
|
||||
#define DEF_ENTRY_BG_COLOR TEXT_BG
|
||||
#define DEF_ENTRY_BG_MONO WHITE
|
||||
#define DEF_ENTRY_BORDER_WIDTH "2"
|
||||
#define DEF_ENTRY_CURSOR "xterm"
|
||||
@@ -178,23 +181,20 @@
|
||||
#define DEF_ENTRY_DISABLED_FG DISABLED
|
||||
#define DEF_ENTRY_EXPORT_SELECTION "1"
|
||||
#define DEF_ENTRY_FONT "TkTextFont"
|
||||
#define DEF_ENTRY_FG BLACK
|
||||
#define DEF_ENTRY_FG NORMAL_FG
|
||||
#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG
|
||||
#define DEF_ENTRY_HIGHLIGHT BLACK
|
||||
/* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */
|
||||
#define DEF_ENTRY_HIGHLIGHT_WIDTH "3"
|
||||
#define DEF_ENTRY_INSERT_BG BLACK
|
||||
#define DEF_ENTRY_INSERT_BG NORMAL_FG
|
||||
#define DEF_ENTRY_INSERT_BD_COLOR "0"
|
||||
#define DEF_ENTRY_INSERT_BD_MONO "0"
|
||||
#define DEF_ENTRY_INSERT_OFF_TIME "300"
|
||||
#define DEF_ENTRY_INSERT_ON_TIME "600"
|
||||
/* #define DEF_ENTRY_INSERT_WIDTH "2" */
|
||||
#define DEF_ENTRY_INSERT_WIDTH "1"
|
||||
#define DEF_ENTRY_JUSTIFY "left"
|
||||
#define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG
|
||||
#define DEF_ENTRY_READONLY_BG_MONO WHITE
|
||||
#define DEF_ENTRY_RELIEF "sunken"
|
||||
/* #define DEF_ENTRY_RELIEF "solid" */
|
||||
#define DEF_ENTRY_SCROLL_COMMAND ""
|
||||
#define DEF_ENTRY_SELECT_COLOR SELECT_BG
|
||||
#define DEF_ENTRY_SELECT_MONO BLACK
|
||||
@@ -202,9 +202,9 @@
|
||||
#define DEF_ENTRY_SELECT_BD_MONO "0"
|
||||
#define DEF_ENTRY_SELECT_FG_COLOR SELECT_FG
|
||||
#define DEF_ENTRY_SELECT_FG_MONO WHITE
|
||||
#define DEF_ENTRY_SHOW ((char *) NULL)
|
||||
#define DEF_ENTRY_SHOW NULL
|
||||
#define DEF_ENTRY_STATE "normal"
|
||||
#define DEF_ENTRY_TAKE_FOCUS ((char *) NULL)
|
||||
#define DEF_ENTRY_TAKE_FOCUS NULL
|
||||
#define DEF_ENTRY_TEXT_VARIABLE ""
|
||||
#define DEF_ENTRY_WIDTH "20"
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
#define DEF_LABELFRAME_BORDER_WIDTH "2"
|
||||
#define DEF_LABELFRAME_CLASS "Labelframe"
|
||||
#define DEF_LABELFRAME_RELIEF "groove"
|
||||
#define DEF_LABELFRAME_FG "systemButtonText"
|
||||
#define DEF_LABELFRAME_FG NORMAL_FG
|
||||
#define DEF_LABELFRAME_FONT "TkDefaultFont"
|
||||
#define DEF_LABELFRAME_TEXT ""
|
||||
#define DEF_LABELFRAME_LABELANCHOR "nw"
|
||||
@@ -247,14 +247,14 @@
|
||||
*/
|
||||
|
||||
#define DEF_LISTBOX_ACTIVE_STYLE "dotbox"
|
||||
#define DEF_LISTBOX_BG_COLOR WHITE
|
||||
#define DEF_LISTBOX_BG_COLOR TEXT_BG
|
||||
#define DEF_LISTBOX_BG_MONO WHITE
|
||||
#define DEF_LISTBOX_BORDER_WIDTH "1"
|
||||
#define DEF_LISTBOX_CURSOR ""
|
||||
#define DEF_LISTBOX_DISABLED_FG DISABLED
|
||||
#define DEF_LISTBOX_EXPORT_SELECTION "1"
|
||||
#define DEF_LISTBOX_FONT "TkTextFont"
|
||||
#define DEF_LISTBOX_FG BLACK
|
||||
#define DEF_LISTBOX_FG NORMAL_FG
|
||||
#define DEF_LISTBOX_HEIGHT "10"
|
||||
#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG
|
||||
#define DEF_LISTBOX_HIGHLIGHT BLACK
|
||||
@@ -271,36 +271,36 @@
|
||||
#define DEF_LISTBOX_SELECT_MODE "browse"
|
||||
#define DEF_LISTBOX_SET_GRID "0"
|
||||
#define DEF_LISTBOX_STATE "normal"
|
||||
#define DEF_LISTBOX_TAKE_FOCUS ((char *) NULL)
|
||||
#define DEF_LISTBOX_TAKE_FOCUS NULL
|
||||
#define DEF_LISTBOX_WIDTH "20"
|
||||
|
||||
/*
|
||||
* Defaults for individual entries of menus:
|
||||
*/
|
||||
|
||||
#define DEF_MENU_ENTRY_ACTIVE_BG ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_ACTIVE_FG ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_ACCELERATOR ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_BG ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_BITMAP None
|
||||
#define DEF_MENU_ENTRY_ACTIVE_BG NULL
|
||||
#define DEF_MENU_ENTRY_ACTIVE_FG NULL
|
||||
#define DEF_MENU_ENTRY_ACCELERATOR NULL
|
||||
#define DEF_MENU_ENTRY_BG NULL
|
||||
#define DEF_MENU_ENTRY_BITMAP NULL
|
||||
#define DEF_MENU_ENTRY_COLUMN_BREAK "0"
|
||||
#define DEF_MENU_ENTRY_COMMAND ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_COMMAND NULL
|
||||
#define DEF_MENU_ENTRY_COMPOUND "none"
|
||||
#define DEF_MENU_ENTRY_FG ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_FONT ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_FG NULL
|
||||
#define DEF_MENU_ENTRY_FONT NULL
|
||||
#define DEF_MENU_ENTRY_HIDE_MARGIN "0"
|
||||
#define DEF_MENU_ENTRY_IMAGE ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_IMAGE NULL
|
||||
#define DEF_MENU_ENTRY_INDICATOR "1"
|
||||
#define DEF_MENU_ENTRY_LABEL ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_MENU ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_LABEL NULL
|
||||
#define DEF_MENU_ENTRY_MENU NULL
|
||||
#define DEF_MENU_ENTRY_OFF_VALUE "0"
|
||||
#define DEF_MENU_ENTRY_ON_VALUE "1"
|
||||
#define DEF_MENU_ENTRY_SELECT_IMAGE ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_SELECT_IMAGE NULL
|
||||
#define DEF_MENU_ENTRY_STATE "normal"
|
||||
#define DEF_MENU_ENTRY_VALUE ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_CHECK_VARIABLE ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_VALUE NULL
|
||||
#define DEF_MENU_ENTRY_CHECK_VARIABLE NULL
|
||||
#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton"
|
||||
#define DEF_MENU_ENTRY_SELECT ((char *) NULL)
|
||||
#define DEF_MENU_ENTRY_SELECT NULL
|
||||
#define DEF_MENU_ENTRY_UNDERLINE "-1"
|
||||
|
||||
/*
|
||||
@@ -326,7 +326,7 @@
|
||||
#define DEF_MENU_SELECT_MONO BLACK
|
||||
#define DEF_MENU_TAKE_FOCUS "0"
|
||||
#define DEF_MENU_TEAROFF "0"
|
||||
#define DEF_MENU_TEAROFF_CMD ((char *) NULL)
|
||||
#define DEF_MENU_TEAROFF_CMD NULL
|
||||
#define DEF_MENU_TITLE ""
|
||||
#define DEF_MENU_TYPE "normal"
|
||||
|
||||
@@ -334,32 +334,32 @@
|
||||
* Defaults for menubuttons:
|
||||
*/
|
||||
|
||||
#define DEF_MENUBUTTON_ANCHOR "center"
|
||||
#define DEF_MENUBUTTON_ANCHOR "w"
|
||||
#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG
|
||||
#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK
|
||||
#define DEF_MENUBUTTON_ACTIVE_BG_MONO WHITE
|
||||
#define DEF_MENUBUTTON_ACTIVE_FG_COLOR ACTIVE_FG
|
||||
#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE
|
||||
#define DEF_MENUBUTTON_ACTIVE_FG_MONO BLACK
|
||||
#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG
|
||||
#define DEF_MENUBUTTON_BG_MONO WHITE
|
||||
#define DEF_MENUBUTTON_BITMAP ""
|
||||
#define DEF_MENUBUTTON_BORDER_WIDTH "2"
|
||||
#define DEF_MENUBUTTON_BORDER_WIDTH "0"
|
||||
#define DEF_MENUBUTTON_CURSOR ""
|
||||
#define DEF_MENUBUTTON_DIRECTION "below"
|
||||
#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED
|
||||
#define DEF_MENUBUTTON_DISABLED_FG_MONO ""
|
||||
#define DEF_MENUBUTTON_FONT "TkDefaultFont"
|
||||
#define DEF_MENUBUTTON_FG BLACK
|
||||
#define DEF_MENUBUTTON_FG NORMAL_FG
|
||||
#define DEF_MENUBUTTON_HEIGHT "0"
|
||||
#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR
|
||||
#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO
|
||||
#define DEF_MENUBUTTON_HIGHLIGHT BLACK
|
||||
#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0"
|
||||
#define DEF_MENUBUTTON_IMAGE ((char *) NULL)
|
||||
#define DEF_MENUBUTTON_IMAGE NULL
|
||||
#define DEF_MENUBUTTON_INDICATOR "1"
|
||||
#define DEF_MENUBUTTON_JUSTIFY "left"
|
||||
#define DEF_MENUBUTTON_MENU ""
|
||||
#define DEF_MENUBUTTON_PADX "4"
|
||||
#define DEF_MENUBUTTON_PADY "3"
|
||||
#define DEF_MENUBUTTON_PADX "0"
|
||||
#define DEF_MENUBUTTON_PADY "0"
|
||||
#define DEF_MENUBUTTON_RELIEF "flat"
|
||||
#define DEF_MENUBUTTON_STATE "normal"
|
||||
#define DEF_MENUBUTTON_TAKE_FOCUS "0"
|
||||
@@ -379,7 +379,7 @@
|
||||
#define DEF_MESSAGE_BG_MONO WHITE
|
||||
#define DEF_MESSAGE_BORDER_WIDTH "1"
|
||||
#define DEF_MESSAGE_CURSOR ""
|
||||
#define DEF_MESSAGE_FG BLACK
|
||||
#define DEF_MESSAGE_FG NORMAL_FG
|
||||
#define DEF_MESSAGE_FONT "TkDefaultFont"
|
||||
#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG
|
||||
#define DEF_MESSAGE_HIGHLIGHT BLACK
|
||||
@@ -443,7 +443,7 @@
|
||||
#define DEF_SCALE_CURSOR ""
|
||||
#define DEF_SCALE_DIGITS "0"
|
||||
#define DEF_SCALE_FONT "TkDefaultFont"
|
||||
#define DEF_SCALE_FG_COLOR BLACK
|
||||
#define DEF_SCALE_FG_COLOR NORMAL_FG
|
||||
#define DEF_SCALE_FG_MONO BLACK
|
||||
#define DEF_SCALE_FROM "0"
|
||||
#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR
|
||||
@@ -463,7 +463,7 @@
|
||||
#define DEF_SCALE_SLIDER_LENGTH "30"
|
||||
#define DEF_SCALE_SLIDER_RELIEF "raised"
|
||||
#define DEF_SCALE_STATE "normal"
|
||||
#define DEF_SCALE_TAKE_FOCUS ((char *) NULL)
|
||||
#define DEF_SCALE_TAKE_FOCUS NULL
|
||||
#define DEF_SCALE_TICK_INTERVAL "0"
|
||||
#define DEF_SCALE_TO "100"
|
||||
#define DEF_SCALE_VARIABLE ""
|
||||
@@ -490,7 +490,7 @@
|
||||
#define DEF_SCROLLBAR_RELIEF "flat"
|
||||
#define DEF_SCROLLBAR_REPEAT_DELAY "300"
|
||||
#define DEF_SCROLLBAR_REPEAT_INTERVAL "100"
|
||||
#define DEF_SCROLLBAR_TAKE_FOCUS ((char *) NULL)
|
||||
#define DEF_SCROLLBAR_TAKE_FOCUS NULL
|
||||
#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH
|
||||
#define DEF_SCROLLBAR_TROUGH_MONO WHITE
|
||||
#define DEF_SCROLLBAR_WIDTH "15"
|
||||
@@ -500,19 +500,19 @@
|
||||
*/
|
||||
|
||||
#define DEF_TEXT_AUTO_SEPARATORS "1"
|
||||
#define DEF_TEXT_BG_COLOR NORMAL_BG
|
||||
#define DEF_TEXT_BG_COLOR TEXT_BG
|
||||
#define DEF_TEXT_BG_MONO WHITE
|
||||
#define DEF_TEXT_BLOCK_CURSOR "0"
|
||||
#define DEF_TEXT_BORDER_WIDTH "0"
|
||||
#define DEF_TEXT_CURSOR "xterm"
|
||||
#define DEF_TEXT_FG BLACK
|
||||
#define DEF_TEXT_FG NORMAL_FG
|
||||
#define DEF_TEXT_EXPORT_SELECTION "1"
|
||||
#define DEF_TEXT_FONT "TkFixedFont"
|
||||
#define DEF_TEXT_HEIGHT "24"
|
||||
#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG
|
||||
#define DEF_TEXT_HIGHLIGHT BLACK
|
||||
#define DEF_TEXT_HIGHLIGHT_WIDTH "3"
|
||||
#define DEF_TEXT_INSERT_BG BLACK
|
||||
#define DEF_TEXT_INSERT_BG NORMAL_FG
|
||||
#define DEF_TEXT_INSERT_BD_COLOR "0"
|
||||
#define DEF_TEXT_INSERT_BD_MONO "0"
|
||||
#define DEF_TEXT_INSERT_OFF_TIME "300"
|
||||
@@ -538,7 +538,7 @@
|
||||
#define DEF_TEXT_STATE "normal"
|
||||
#define DEF_TEXT_TABS ""
|
||||
#define DEF_TEXT_TABSTYLE "tabular"
|
||||
#define DEF_TEXT_TAKE_FOCUS ((char *) NULL)
|
||||
#define DEF_TEXT_TAKE_FOCUS NULL
|
||||
#define DEF_TEXT_UNDO "0"
|
||||
#define DEF_TEXT_WIDTH "80"
|
||||
#define DEF_TEXT_WRAP "char"
|
||||
@@ -551,6 +551,14 @@
|
||||
|
||||
#define DEF_CANVTEXT_FONT "TkDefaultFont"
|
||||
|
||||
/*
|
||||
* Defaults for canvas items
|
||||
* (arcs, bitmaps, lines, polygons, rectangles, and ovals):
|
||||
*/
|
||||
|
||||
#define DEF_CANVBMAP_FG NORMAL_FG
|
||||
#define DEF_CANVITEM_OUTLINE NORMAL_FG
|
||||
|
||||
/*
|
||||
* Defaults for toplevels (most of the defaults for frames also apply
|
||||
* to toplevels):
|
||||
|
||||
@@ -22,31 +22,39 @@
|
||||
#else
|
||||
#define modalOK NSModalResponseOK
|
||||
#define modalCancel NSModalResponseCancel
|
||||
#endif
|
||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1090
|
||||
#define modalOther -1
|
||||
#define modalError -2
|
||||
|
||||
/*Vars for filtering in "open file" and "save file" dialogs.*/
|
||||
/*
|
||||
* Vars for filtering in "open file" and "save file" dialogs.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
bool doFileTypes; // show the accessory view which displays the filter menu
|
||||
bool preselectFilter; // a filter was selected by the typevariable
|
||||
bool userHasSelectedFilter; // The user has changed the filter in the accessory view
|
||||
|
||||
NSMutableArray *fileTypeNames; // array of names, e.g. "Text document"
|
||||
NSMutableArray *fileTypeExtensions; // array of allowed extensions per name, e.g. "txt", "doc"
|
||||
NSMutableArray *fileTypeLabels; // displayed string, e.g. "Text document (.txt, .doc)"
|
||||
NSMutableArray *fileTypeAllowsAll; // boolean if the all pattern (*.*) is included
|
||||
|
||||
NSMutableArray *allowedExtensions; // set of all allowed extensions
|
||||
bool allowedExtensionsAllowAll; // set of all allowed extensions includes *.*
|
||||
|
||||
NSUInteger fileTypeIndex; // index of currently selected filter
|
||||
bool doFileTypes; /* Show the accessory view which
|
||||
* displays the filter menu */
|
||||
bool preselectFilter; /* A filter was selected by the
|
||||
* typevariable. */
|
||||
bool userHasSelectedFilter; /* The user has changed the filter in
|
||||
* the accessory view. */
|
||||
NSMutableArray *fileTypeNames; /* Array of names, e.g. "Text
|
||||
* document". */
|
||||
NSMutableArray *fileTypeExtensions; /* Array of allowed extensions per
|
||||
* name, e.g. "txt", "doc". */
|
||||
NSMutableArray *fileTypeLabels; /* Displayed string, e.g. "Text
|
||||
* document (.txt, .doc)". */
|
||||
NSMutableArray *fileTypeAllowsAll; /* Boolean if the all pattern (*.*) is
|
||||
* included. */
|
||||
NSMutableArray *allowedExtensions; /* Set of all allowed extensions. */
|
||||
bool allowedExtensionsAllowAll; /* Set of all allowed extensions
|
||||
* includes *.* */
|
||||
NSUInteger fileTypeIndex; /* Index of currently selected
|
||||
* filter. */
|
||||
} filepanelFilterInfo;
|
||||
|
||||
filepanelFilterInfo filterInfo;
|
||||
|
||||
NSOpenPanel *openpanel;
|
||||
NSSavePanel *savepanel;
|
||||
static filepanelFilterInfo filterInfo;
|
||||
static NSOpenPanel *openpanel;
|
||||
static NSSavePanel *savepanel;
|
||||
|
||||
static const char *const colorOptionStrings[] = {
|
||||
"-initialcolor", "-parent", "-title", NULL
|
||||
@@ -166,10 +174,15 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {
|
||||
};
|
||||
|
||||
/*
|
||||
* Construct a file URL from directory and filename. Either may
|
||||
* be nil. If both are nil, returns nil.
|
||||
* Construct a file URL from directory and filename. Either may be nil. If both
|
||||
* are nil, returns nil.
|
||||
*/
|
||||
static NSURL *getFileURL(NSString *directory, NSString *filename) {
|
||||
|
||||
static NSURL *
|
||||
getFileURL(
|
||||
NSString *directory,
|
||||
NSString *filename)
|
||||
{
|
||||
NSURL *url = nil;
|
||||
if (directory) {
|
||||
url = [NSURL fileURLWithPath:directory isDirectory:YES];
|
||||
@@ -182,12 +195,20 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) {
|
||||
|
||||
#pragma mark TKApplication(TKDialog)
|
||||
|
||||
@interface NSColorPanel(TKDialog)
|
||||
- (void) _setUseModalAppearance: (BOOL) flag;
|
||||
@end
|
||||
|
||||
@implementation TKApplication(TKDialog)
|
||||
|
||||
- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url {
|
||||
}
|
||||
|
||||
- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError {
|
||||
*outError = nil;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) tkFilePanelDidEnd: (NSSavePanel *) panel
|
||||
returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
|
||||
{
|
||||
@@ -233,7 +254,6 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode
|
||||
contextInfo: (void *) contextInfo
|
||||
{
|
||||
@@ -276,12 +296,18 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) {
|
||||
|
||||
if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) {
|
||||
[openpanel setAllowsOtherFileTypes:YES];
|
||||
/* setAllowsOtherFileTypes might have no effect; it's inherited from the
|
||||
* NSSavePanel, where it has the effect that it does not append an extension
|
||||
* Setting the allowed file types to nil allows selecting any file */
|
||||
|
||||
/*
|
||||
* setAllowsOtherFileTypes might have no effect; it's inherited from
|
||||
* the NSSavePanel, where it has the effect that it does not append an
|
||||
* extension. Setting the allowed file types to nil allows selecting
|
||||
* any file.
|
||||
*/
|
||||
|
||||
[openpanel setAllowedFileTypes:nil];
|
||||
} else {
|
||||
NSMutableArray *allowedtypes = [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
|
||||
NSMutableArray *allowedtypes =
|
||||
[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
|
||||
[openpanel setAllowedFileTypes:allowedtypes];
|
||||
[openpanel setAllowsOtherFileTypes:NO];
|
||||
}
|
||||
@@ -297,7 +323,8 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) {
|
||||
[savepanel setAllowsOtherFileTypes:YES];
|
||||
[savepanel setAllowedFileTypes:nil];
|
||||
} else {
|
||||
NSMutableArray *allowedtypes = [filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
|
||||
NSMutableArray *allowedtypes =
|
||||
[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex];
|
||||
[savepanel setAllowedFileTypes:allowedtypes];
|
||||
[savepanel setAllowsOtherFileTypes:NO];
|
||||
}
|
||||
@@ -309,6 +336,30 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) {
|
||||
|
||||
#pragma mark -
|
||||
|
||||
static NSInteger showOpenSavePanel(
|
||||
NSSavePanel *panel,
|
||||
NSWindow *parent,
|
||||
FilePanelCallbackInfo *callbackInfo)
|
||||
{
|
||||
NSInteger modalReturnCode;
|
||||
|
||||
if (parent && ![parent attachedSheet] && [NSApp macMinorVersion] < 15) {
|
||||
[panel beginSheetModalForWindow:parent
|
||||
completionHandler:^(NSInteger returnCode) {
|
||||
[NSApp tkFilePanelDidEnd:panel
|
||||
returnCode:returnCode
|
||||
contextInfo:callbackInfo ];
|
||||
}];
|
||||
modalReturnCode = callbackInfo->cmdObj ? modalOther :
|
||||
[NSApp runModalForWindow:panel];
|
||||
} else {
|
||||
modalReturnCode = [panel runModal];
|
||||
[NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
|
||||
contextInfo:callbackInfo];
|
||||
}
|
||||
return modalReturnCode;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -388,6 +439,7 @@ Tk_ChooseColorObjCmd(
|
||||
[colorPanel _setUseModalAppearance:YES];
|
||||
if (title) {
|
||||
NSString *s = [[NSString alloc] initWithUTF8String:title];
|
||||
|
||||
[colorPanel setTitle:s];
|
||||
[s release];
|
||||
}
|
||||
@@ -419,9 +471,17 @@ end:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* dissect the -filetype nested lists and store the information
|
||||
* in the filterInfo structure */
|
||||
int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVariablePtr) {
|
||||
/*
|
||||
* Dissect the -filetype nested lists and store the information in the
|
||||
* filterInfo structure.
|
||||
*/
|
||||
|
||||
static int
|
||||
parseFileFilters(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *fileTypesPtr,
|
||||
Tcl_Obj *typeVariablePtr)
|
||||
{
|
||||
|
||||
if (!fileTypesPtr) {
|
||||
filterInfo.doFileTypes = false;
|
||||
@@ -429,6 +489,7 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar
|
||||
}
|
||||
|
||||
FileFilterList fl;
|
||||
|
||||
TkInitFileFilters(&fl);
|
||||
if (TkGetFileFilters(interp, &fl, fileTypesPtr, 0) != TCL_OK) {
|
||||
TkFreeFileFilters(&fl);
|
||||
@@ -449,11 +510,12 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar
|
||||
if (filterInfo.doFileTypes) {
|
||||
for (FileFilter *filterPtr = fl.filters; filterPtr;
|
||||
filterPtr = filterPtr->next) {
|
||||
NSString * name = [[NSString alloc] initWithUTF8String: filterPtr -> name];
|
||||
NSString *name = [[NSString alloc] initWithUTF8String: filterPtr->name];
|
||||
|
||||
[filterInfo.fileTypeNames addObject:name];
|
||||
[name release];
|
||||
NSMutableArray * clauseextensions = [NSMutableArray array];
|
||||
NSMutableArray * displayextensions = [NSMutableArray array];
|
||||
NSMutableArray *clauseextensions = [NSMutableArray array];
|
||||
NSMutableArray *displayextensions = [NSMutableArray array];
|
||||
bool allowsAll = NO;
|
||||
|
||||
for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr;
|
||||
@@ -464,7 +526,7 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar
|
||||
const char *str = globPtr->pattern;
|
||||
while (*str && (*str == '*' || *str == '.')) {
|
||||
str++;
|
||||
}
|
||||
}
|
||||
if (*str) {
|
||||
NSString *extension = [[NSString alloc] initWithUTF8String:str];
|
||||
if (![filterInfo.allowedExtensions containsObject:extension]) {
|
||||
@@ -476,7 +538,10 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar
|
||||
|
||||
[extension release];
|
||||
} else {
|
||||
// it is the all pattern (*, .* or *.*)
|
||||
/*
|
||||
* It is the all pattern (*, .* or *.*)
|
||||
*/
|
||||
|
||||
allowsAll = YES;
|
||||
filterInfo.allowedExtensionsAllowAll = YES;
|
||||
[displayextensions addObject:@"*"];
|
||||
@@ -486,27 +551,39 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar
|
||||
[filterInfo.fileTypeExtensions addObject:clauseextensions];
|
||||
[filterInfo.fileTypeAllowsAll addObject:[NSNumber numberWithBool:allowsAll]];
|
||||
|
||||
NSMutableString * label = [[NSMutableString alloc] initWithString:name];
|
||||
NSMutableString *label = [[NSMutableString alloc] initWithString:name];
|
||||
[label appendString:@" ("];
|
||||
[label appendString:[displayextensions componentsJoinedByString:@", "]];
|
||||
[label appendString:@")"];
|
||||
[filterInfo.fileTypeLabels addObject:label];
|
||||
[label release];
|
||||
|
||||
}
|
||||
|
||||
/* Check if the typevariable exists and matches one of the names */
|
||||
/*
|
||||
* Check if the typevariable exists and matches one of the names.
|
||||
*/
|
||||
|
||||
filterInfo.preselectFilter = false;
|
||||
filterInfo.userHasSelectedFilter = false;
|
||||
if (typeVariablePtr) {
|
||||
/* extract the variable content as a NSString */
|
||||
Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp, typeVariablePtr, NULL, TCL_GLOBAL_ONLY);
|
||||
/*
|
||||
* Extract the variable content as a NSString.
|
||||
*/
|
||||
|
||||
Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp,
|
||||
typeVariablePtr, NULL, TCL_GLOBAL_ONLY);
|
||||
|
||||
/*
|
||||
* Check that the typevariable exists.
|
||||
*/
|
||||
|
||||
/* check that the typevariable exists */
|
||||
if (selectedFileTypeObj != NULL) {
|
||||
const char *selectedFileType = Tcl_GetString(selectedFileTypeObj);
|
||||
NSString *selectedFileTypeStr = [[NSString alloc] initWithUTF8String:selectedFileType];
|
||||
NSUInteger index = [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr];
|
||||
const char *selectedFileType =
|
||||
Tcl_GetString(selectedFileTypeObj);
|
||||
NSString *selectedFileTypeStr =
|
||||
[[NSString alloc] initWithUTF8String:selectedFileType];
|
||||
NSUInteger index =
|
||||
[filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr];
|
||||
|
||||
if (index != NSNotFound) {
|
||||
filterInfo.fileTypeIndex = index;
|
||||
@@ -521,17 +598,24 @@ int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVar
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
bool filterCompatible(NSString *extension, int filterIndex) {
|
||||
NSMutableArray *allowedExtensions = [filterInfo.fileTypeExtensions objectAtIndex: filterIndex];
|
||||
static bool
|
||||
filterCompatible(
|
||||
NSString *extension,
|
||||
int filterIndex)
|
||||
{
|
||||
NSMutableArray *allowedExtensions =
|
||||
[filterInfo.fileTypeExtensions objectAtIndex: filterIndex];
|
||||
|
||||
/*
|
||||
* If this contains the all pattern, accept any extension.
|
||||
*/
|
||||
|
||||
/* If this contains the all pattern, accept any extension */
|
||||
if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterIndex] boolValue]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return [allowedExtensions containsObject: extension];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -570,6 +654,8 @@ Tk_GetOpenFileObjCmd(
|
||||
NSInteger modalReturnCode = modalError;
|
||||
BOOL parentIsKey = NO;
|
||||
|
||||
[openpanel setDelegate:NSApp];
|
||||
|
||||
for (i = 1; i < objc; i += 2) {
|
||||
if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings,
|
||||
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
|
||||
@@ -631,22 +717,24 @@ Tk_GetOpenFileObjCmd(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (title) {
|
||||
[openpanel setTitle:title];
|
||||
|
||||
/* From OSX 10.11, the title string is silently ignored in the open panel.
|
||||
* Prepend the title to the message in this case
|
||||
* NOTE should be conditional on OSX version, but
|
||||
* -mmacosx-version-min does not revert this behaviour*/
|
||||
/*
|
||||
* From OSX 10.11, the title string is silently ignored in the open
|
||||
* panel. Prepend the title to the message in this case.
|
||||
*/
|
||||
|
||||
if (message) {
|
||||
NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message];
|
||||
[message release];
|
||||
[title release];
|
||||
message = fullmessage;
|
||||
} else {
|
||||
message = title;
|
||||
if ([NSApp macMinorVersion] > 10) {
|
||||
if (message) {
|
||||
NSString *fullmessage =
|
||||
[[NSString alloc] initWithFormat:@"%@\n%@", title, message];
|
||||
[message release];
|
||||
[title release];
|
||||
message = fullmessage;
|
||||
} else {
|
||||
message = title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,117 +750,124 @@ Tk_GetOpenFileObjCmd(
|
||||
}
|
||||
|
||||
if (filterInfo.doFileTypes) {
|
||||
NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
|
||||
NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)];
|
||||
NSTextField *label = [[NSTextField alloc]
|
||||
initWithFrame:NSMakeRect(0, 0, 60, 22)];
|
||||
NSPopUpButton *popupButton = [[NSPopUpButton alloc]
|
||||
initWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO];
|
||||
NSView *accessoryView = [[NSView alloc]
|
||||
initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
|
||||
|
||||
[label setEditable:NO];
|
||||
[label setStringValue:@"Filter:"];
|
||||
[label setBordered:NO];
|
||||
[label setBezeled:NO];
|
||||
[label setDrawsBackground:NO];
|
||||
|
||||
NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 240, 22.0) pullsDown:NO];
|
||||
[popupButton addItemsWithTitles:filterInfo.fileTypeLabels];
|
||||
[popupButton setAction:@selector(selectFormat:)];
|
||||
|
||||
[accessoryView addSubview:label];
|
||||
[accessoryView addSubview:popupButton];
|
||||
|
||||
if (filterInfo.preselectFilter) {
|
||||
/* A specific filter was selected from the typevariable. Select it and
|
||||
* open the accessory view */
|
||||
|
||||
/*
|
||||
* A specific filter was selected from the typevariable. Select it
|
||||
* and open the accessory view.
|
||||
*/
|
||||
|
||||
[popupButton selectItemAtIndex:filterInfo.fileTypeIndex];
|
||||
/* on OSX > 10.11, the optons are not visible by default. Ergo allow all file types
|
||||
|
||||
/*
|
||||
* On OSX > 10.11, the options are not visible by default. Ergo
|
||||
* allow all file types
|
||||
[openpanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]];
|
||||
*/
|
||||
|
||||
[openpanel setAllowedFileTypes:filterInfo.allowedExtensions];
|
||||
} else {
|
||||
[openpanel setAllowedFileTypes:filterInfo.allowedExtensions];
|
||||
}
|
||||
|
||||
if (filterInfo.allowedExtensionsAllowAll) {
|
||||
[openpanel setAllowsOtherFileTypes:YES];
|
||||
} else {
|
||||
[openpanel setAllowsOtherFileTypes:NO];
|
||||
}
|
||||
|
||||
[openpanel setAccessoryView:accessoryView];
|
||||
} else {
|
||||
/* No filters are given. Allow picking all files */
|
||||
/*
|
||||
* No filters are given. Allow picking all files.
|
||||
*/
|
||||
|
||||
[openpanel setAllowsOtherFileTypes:YES];
|
||||
}
|
||||
|
||||
if (cmdObj) {
|
||||
callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
|
||||
if (Tcl_IsShared(cmdObj)) {
|
||||
cmdObj = Tcl_DuplicateObj(cmdObj);
|
||||
}
|
||||
Tcl_IncrRefCount(cmdObj);
|
||||
}
|
||||
|
||||
callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
|
||||
callbackInfo->cmdObj = cmdObj;
|
||||
callbackInfo->interp = interp;
|
||||
callbackInfo->multiple = multiple;
|
||||
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
|
||||
if (haveParentOption && parent && ![parent attachedSheet]) {
|
||||
parentIsKey = [parent isKeyWindow];
|
||||
if (directory || filename ) {
|
||||
NSURL * fileURL = getFileURL(directory, filename);
|
||||
[openpanel setDirectoryURL:fileURL];
|
||||
}
|
||||
if (directory || filename) {
|
||||
NSURL *fileURL = getFileURL(directory, filename);
|
||||
|
||||
[openpanel beginSheetModalForWindow:parent
|
||||
completionHandler:^(NSInteger returnCode)
|
||||
{ [NSApp tkFilePanelDidEnd:openpanel
|
||||
returnCode:returnCode
|
||||
contextInfo:callbackInfo ]; } ];
|
||||
modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:openpanel];
|
||||
} else {
|
||||
if (directory || filename ) {
|
||||
NSURL * fileURL = getFileURL(directory, filename);
|
||||
[openpanel setDirectoryURL:fileURL];
|
||||
}
|
||||
|
||||
modalReturnCode = [openpanel runModal];
|
||||
[NSApp tkFilePanelDidEnd:openpanel returnCode:modalReturnCode
|
||||
contextInfo:callbackInfo];
|
||||
[openpanel setDirectoryURL:fileURL];
|
||||
}
|
||||
if (haveParentOption) {
|
||||
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
|
||||
parentIsKey = parent && [parent isKeyWindow];
|
||||
} else {
|
||||
parent = nil;
|
||||
parentIsKey = False;
|
||||
}
|
||||
modalReturnCode = showOpenSavePanel(openpanel, parent, callbackInfo);
|
||||
result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
|
||||
if (parentIsKey) {
|
||||
[parent makeKeyWindow];
|
||||
}
|
||||
|
||||
if ((typeVariablePtr && (modalReturnCode == NSOKButton)) &&
|
||||
filterInfo.doFileTypes) {
|
||||
if ((typeVariablePtr && (modalReturnCode == NSOKButton))
|
||||
&& filterInfo.doFileTypes) {
|
||||
/*
|
||||
* The -typevariable must be set to the selected file type, if the dialog was not cancelled
|
||||
* The -typevariable must be set to the selected file type, if the
|
||||
* dialog was not cancelled.
|
||||
*/
|
||||
|
||||
NSUInteger selectedFilterIndex = filterInfo.fileTypeIndex;
|
||||
NSString *selectedFilter = NULL;
|
||||
|
||||
if (filterInfo.userHasSelectedFilter) {
|
||||
selectedFilterIndex = filterInfo.fileTypeIndex;
|
||||
selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
|
||||
} else {
|
||||
/* Difficult case: the user has not touched the filter settings, but we must
|
||||
* return something in the typevariable. First check if the preselected type is compatible
|
||||
* with the selected file, otherwise choose the first compatible type from the list,
|
||||
* finally fall back to the empty string */
|
||||
/*
|
||||
* Difficult case: the user has not touched the filter settings,
|
||||
* but we must return something in the typevariable. First check if
|
||||
* the preselected type is compatible with the selected file,
|
||||
* otherwise choose the first compatible type from the list,
|
||||
* finally fall back to the empty string.
|
||||
*/
|
||||
|
||||
NSURL *selectedFile;
|
||||
NSString *extension;
|
||||
if (multiple) {
|
||||
// Use the first file in the case of multiple selection
|
||||
// Anyway it is not overly useful here
|
||||
/*
|
||||
* Use the first file in the case of multiple selection.
|
||||
* Anyway it is not overly useful here.
|
||||
*/
|
||||
selectedFile = [[openpanel URLs] objectAtIndex:0];
|
||||
} else {
|
||||
selectedFile = [openpanel URL];
|
||||
}
|
||||
|
||||
NSString *extension = [selectedFile pathExtension];
|
||||
extension = [selectedFile pathExtension];
|
||||
|
||||
if (filterInfo.preselectFilter &&
|
||||
filterCompatible(extension, filterInfo.fileTypeIndex)) {
|
||||
filterCompatible(extension, filterInfo.fileTypeIndex)) {
|
||||
selectedFilterIndex = filterInfo.fileTypeIndex; // The preselection from the typevariable
|
||||
selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
|
||||
} else {
|
||||
// scan the list
|
||||
NSUInteger i;
|
||||
|
||||
for (i = 0; i < [filterInfo.fileTypeNames count]; i++) {
|
||||
if (filterCompatible(extension, i)) {
|
||||
selectedFilterIndex = i;
|
||||
@@ -784,19 +879,15 @@ Tk_GetOpenFileObjCmd(
|
||||
} else {
|
||||
selectedFilter = @"";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
|
||||
Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY);
|
||||
Tcl_NewStringObj([selectedFilter UTF8String], -1),
|
||||
TCL_GLOBAL_ONLY);
|
||||
}
|
||||
|
||||
|
||||
end:
|
||||
end:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -811,6 +902,7 @@ Tk_GetOpenFileObjCmd(
|
||||
*
|
||||
* Side effects:
|
||||
* See user documentation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -832,10 +924,12 @@ Tk_GetSaveFileObjCmd(
|
||||
NSString *directory = nil, *filename = nil, *defaultType = nil;
|
||||
NSString *message = nil, *title = nil;
|
||||
NSWindow *parent;
|
||||
savepanel = [NSSavePanel savePanel];
|
||||
savepanel = [NSSavePanel savePanel];
|
||||
NSInteger modalReturnCode = modalError;
|
||||
BOOL parentIsKey = NO;
|
||||
|
||||
[savepanel setDelegate:NSApp];
|
||||
|
||||
for (i = 1; i < objc; i += 2) {
|
||||
if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings,
|
||||
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
|
||||
@@ -910,13 +1004,17 @@ Tk_GetSaveFileObjCmd(
|
||||
if (title) {
|
||||
[savepanel setTitle:title];
|
||||
|
||||
/* From OSX 10.11, the title string is silently ignored, if the save panel is a sheet.
|
||||
* Prepend the title to the message in this case
|
||||
* NOTE should be conditional on OSX version, but
|
||||
* -mmacosx-version-min does not revert this behaviour*/
|
||||
/*
|
||||
* From OSX 10.11, the title string is silently ignored, if the save
|
||||
* panel is a sheet. Prepend the title to the message in this case.
|
||||
* NOTE: should be conditional on OSX version, but -mmacosx-version-min
|
||||
* does not revert this behaviour.
|
||||
*/
|
||||
|
||||
if (haveParentOption) {
|
||||
if (message) {
|
||||
NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message];
|
||||
NSString *fullmessage =
|
||||
[[NSString alloc] initWithFormat:@"%@\n%@",title,message];
|
||||
[message release];
|
||||
[title release];
|
||||
message = fullmessage;
|
||||
@@ -936,15 +1034,20 @@ Tk_GetSaveFileObjCmd(
|
||||
}
|
||||
|
||||
if (filterInfo.doFileTypes) {
|
||||
NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
|
||||
NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)];
|
||||
NSView *accessoryView = [[NSView alloc]
|
||||
initWithFrame:NSMakeRect(0.0, 0.0, 300, 32.0)];
|
||||
NSTextField *label = [[NSTextField alloc]
|
||||
initWithFrame:NSMakeRect(0, 0, 60, 22)];
|
||||
|
||||
[label setEditable:NO];
|
||||
[label setStringValue:NSLocalizedString(@"Format:", nil)];
|
||||
[label setBordered:NO];
|
||||
[label setBezeled:NO];
|
||||
[label setDrawsBackground:NO];
|
||||
|
||||
NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO];
|
||||
NSPopUpButton *popupButton = [[NSPopUpButton alloc]
|
||||
initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO];
|
||||
|
||||
[popupButton addItemsWithTitles:filterInfo.fileTypeLabels];
|
||||
[popupButton selectItemAtIndex:filterInfo.fileTypeIndex];
|
||||
[popupButton setAction:@selector(saveFormat:)];
|
||||
@@ -957,10 +1060,14 @@ Tk_GetSaveFileObjCmd(
|
||||
[savepanel setAllowedFileTypes:[filterInfo.fileTypeExtensions objectAtIndex:filterInfo.fileTypeIndex]];
|
||||
[savepanel setAllowsOtherFileTypes:filterInfo.allowedExtensionsAllowAll];
|
||||
} else if (defaultType) {
|
||||
/* If no filetypes are given, defaultextension is an alternative way
|
||||
* to specify the attached extension. Just propose this extension,
|
||||
* but don't display an accessory view */
|
||||
/*
|
||||
* If no filetypes are given, defaultextension is an alternative way to
|
||||
* specify the attached extension. Just propose this extension, but
|
||||
* don't display an accessory view.
|
||||
*/
|
||||
|
||||
NSMutableArray *AllowedFileTypes = [NSMutableArray array];
|
||||
|
||||
[AllowedFileTypes addObject:defaultType];
|
||||
[savepanel setAllowedFileTypes:AllowedFileTypes];
|
||||
[savepanel setAllowsOtherFileTypes:YES];
|
||||
@@ -970,62 +1077,56 @@ Tk_GetSaveFileObjCmd(
|
||||
[savepanel setExtensionHidden:NO];
|
||||
|
||||
if (cmdObj) {
|
||||
callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
|
||||
if (Tcl_IsShared(cmdObj)) {
|
||||
cmdObj = Tcl_DuplicateObj(cmdObj);
|
||||
}
|
||||
Tcl_IncrRefCount(cmdObj);
|
||||
}
|
||||
callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
|
||||
callbackInfo->cmdObj = cmdObj;
|
||||
callbackInfo->interp = interp;
|
||||
callbackInfo->multiple = 0;
|
||||
|
||||
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
|
||||
if (haveParentOption && parent && ![parent attachedSheet]) {
|
||||
parentIsKey = [parent isKeyWindow];
|
||||
if (directory) {
|
||||
[savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
|
||||
}
|
||||
/*check for file name, otherwise set to empty string; crashes with uncaught exception if set to nil*/
|
||||
if (filename) {
|
||||
[savepanel setNameFieldStringValue:filename];
|
||||
} else {
|
||||
[savepanel setNameFieldStringValue:@""];
|
||||
}
|
||||
[savepanel beginSheetModalForWindow:parent
|
||||
completionHandler:^(NSInteger returnCode)
|
||||
{ [NSApp tkFilePanelDidEnd:savepanel
|
||||
returnCode:returnCode
|
||||
contextInfo:callbackInfo ]; } ];
|
||||
modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:savepanel];
|
||||
} else {
|
||||
if (directory) {
|
||||
[savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
|
||||
}
|
||||
/*check for file name, otherwise set to empty string; crashes with uncaught exception if set to nil*/
|
||||
if (filename) {
|
||||
[savepanel setNameFieldStringValue:filename];
|
||||
} else {
|
||||
[savepanel setNameFieldStringValue:@""];
|
||||
}
|
||||
modalReturnCode = [savepanel runModal];
|
||||
[NSApp tkFilePanelDidEnd:savepanel returnCode:modalReturnCode
|
||||
contextInfo:callbackInfo];
|
||||
if (directory) {
|
||||
[savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for file name and set to the empty string if nil. This prevents a crash
|
||||
* with an uncaught exception.
|
||||
*/
|
||||
|
||||
if (filename) {
|
||||
[savepanel setNameFieldStringValue:filename];
|
||||
} else {
|
||||
[savepanel setNameFieldStringValue:@""];
|
||||
}
|
||||
if (haveParentOption) {
|
||||
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
|
||||
parentIsKey = parent && [parent isKeyWindow];
|
||||
} else {
|
||||
parent = nil;
|
||||
parentIsKey = False;
|
||||
}
|
||||
modalReturnCode = showOpenSavePanel(savepanel, parent, callbackInfo);
|
||||
result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
|
||||
if (parentIsKey) {
|
||||
[parent makeKeyWindow];
|
||||
}
|
||||
|
||||
if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && filterInfo.doFileTypes) {
|
||||
if (typeVariablePtr && (modalReturnCode == NSOKButton)
|
||||
&& filterInfo.doFileTypes) {
|
||||
/*
|
||||
* The -typevariable must be set to the selected file type, if the dialog was not cancelled
|
||||
* The -typevariable must be set to the selected file type, if the
|
||||
* dialog was not cancelled.
|
||||
*/
|
||||
NSString * selectedFilter = [filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex];
|
||||
Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
|
||||
Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY);
|
||||
}
|
||||
|
||||
NSString *selectedFilter =
|
||||
[filterInfo.fileTypeNames objectAtIndex:filterInfo.fileTypeIndex];
|
||||
Tcl_ObjSetVar2(interp, typeVariablePtr, NULL,
|
||||
Tcl_NewStringObj([selectedFilter UTF8String], -1),
|
||||
TCL_GLOBAL_ONLY);
|
||||
}
|
||||
|
||||
end:
|
||||
return result;
|
||||
@@ -1070,6 +1171,8 @@ Tk_ChooseDirectoryObjCmd(
|
||||
NSInteger modalReturnCode = modalError;
|
||||
BOOL parentIsKey = NO;
|
||||
|
||||
[panel setDelegate:NSApp];
|
||||
|
||||
for (i = 1; i < objc; i += 2) {
|
||||
if (Tcl_GetIndexFromObjStruct(interp, objv[i], chooseOptionStrings,
|
||||
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
|
||||
@@ -1125,35 +1228,34 @@ Tk_ChooseDirectoryObjCmd(
|
||||
[panel setCanChooseDirectories:YES];
|
||||
[panel setCanCreateDirectories:!mustexist];
|
||||
if (cmdObj) {
|
||||
callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
|
||||
if (Tcl_IsShared(cmdObj)) {
|
||||
cmdObj = Tcl_DuplicateObj(cmdObj);
|
||||
}
|
||||
Tcl_IncrRefCount(cmdObj);
|
||||
}
|
||||
callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
|
||||
callbackInfo->cmdObj = cmdObj;
|
||||
callbackInfo->interp = interp;
|
||||
callbackInfo->multiple = 0;
|
||||
/*check for directory value, set to root if not specified; otherwise crashes with exception because of nil string parameter*/
|
||||
|
||||
/*
|
||||
* Check for directory value, set to root if not specified; otherwise
|
||||
* crashes with exception because of nil string parameter.
|
||||
*/
|
||||
|
||||
if (!directory) {
|
||||
directory = @"/";
|
||||
}
|
||||
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
|
||||
if (haveParentOption && parent && ![parent attachedSheet]) {
|
||||
parentIsKey = [parent isKeyWindow];
|
||||
[panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
|
||||
[panel beginSheetModalForWindow:parent
|
||||
completionHandler:^(NSInteger returnCode)
|
||||
{ [NSApp tkFilePanelDidEnd:panel
|
||||
returnCode:returnCode
|
||||
contextInfo:callbackInfo ]; } ];
|
||||
modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel];
|
||||
[panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
|
||||
if (haveParentOption) {
|
||||
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
|
||||
parentIsKey = parent && [parent isKeyWindow];
|
||||
} else {
|
||||
[panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
|
||||
modalReturnCode = [panel runModal];
|
||||
[NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
|
||||
contextInfo:callbackInfo];
|
||||
parent = nil;
|
||||
parentIsKey = False;
|
||||
}
|
||||
modalReturnCode = showOpenSavePanel(panel, parent, callbackInfo);
|
||||
result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
|
||||
if (parentIsKey) {
|
||||
[parent makeKeyWindow];
|
||||
@@ -1198,18 +1300,19 @@ TkAboutDlg(void)
|
||||
NSString *year = [dateFormatter stringFromDate:[NSDate date]];
|
||||
|
||||
[dateFormatter release];
|
||||
|
||||
|
||||
/*
|
||||
* This replaces the old about dialog with a standard alert that displays
|
||||
* correctly on 10.14.
|
||||
*/
|
||||
|
||||
|
||||
NSString *version = @"Tcl " TCL_PATCH_LEVEL " & Tk " TCL_PATCH_LEVEL;
|
||||
NSString *url = @"www.tcl-lang.org";
|
||||
NSString *url = @"www.tcl-lang.org";
|
||||
NSTextView *credits = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,300,300)];
|
||||
NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
|
||||
NSDictionary *textAttributes = [NSDictionary dictionaryWithObject:font
|
||||
forKey:NSFontAttributeName];
|
||||
|
||||
[credits insertText: [[NSAttributedString alloc]
|
||||
initWithString:[NSString stringWithFormat: @"\n"
|
||||
"Tcl and Tk are distributed under a modified BSD license: "
|
||||
@@ -1223,11 +1326,13 @@ TkAboutDlg(void)
|
||||
"%1$C 1998-2000 Jim Ingham & Ray Johnson\n\n"
|
||||
"%1$C 1998-2000 Scriptics Inc.\n\n"
|
||||
"%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year]
|
||||
attributes:textAttributes]
|
||||
replacementRange:NSMakeRange(0,0)];
|
||||
attributes:textAttributes]
|
||||
replacementRange:NSMakeRange(0,0)];
|
||||
[credits setDrawsBackground:NO];
|
||||
[credits setEditable:NO];
|
||||
NSAlert *about = [[NSAlert alloc] init];
|
||||
|
||||
NSAlert *about = [[NSAlert alloc] init];
|
||||
|
||||
[[about window] setTitle:@"About Tcl & Tk"];
|
||||
[about setMessageText: version];
|
||||
[about setInformativeText:url];
|
||||
@@ -1382,7 +1487,8 @@ Tk_MessageBoxObjCmd(
|
||||
*/
|
||||
|
||||
if (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1],
|
||||
alertButtonStrings, sizeof(char *), "-default value", TCL_EXACT, &index) != TCL_OK) {
|
||||
alertButtonStrings, sizeof(char *), "-default value",
|
||||
TCL_EXACT, &index) != TCL_OK) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -1403,7 +1509,7 @@ Tk_MessageBoxObjCmd(
|
||||
[alert setAlertStyle:alertStyles[iconIndex]];
|
||||
i = 0;
|
||||
while (i < 3 && alertButtonNames[typeIndex][i]) {
|
||||
[alert addButtonWithTitle:(NSString*)alertButtonNames[typeIndex][i++]];
|
||||
[alert addButtonWithTitle:(NSString*) alertButtonNames[typeIndex][i++]];
|
||||
}
|
||||
buttons = [alert buttons];
|
||||
for (NSButton *b in buttons) {
|
||||
@@ -1418,24 +1524,25 @@ Tk_MessageBoxObjCmd(
|
||||
[[buttons objectAtIndex: defaultNativeButtonIndex-1]
|
||||
setKeyEquivalent: @"\r"];
|
||||
if (cmdObj) {
|
||||
callbackInfo = ckalloc(sizeof(AlertCallbackInfo));
|
||||
if (Tcl_IsShared(cmdObj)) {
|
||||
cmdObj = Tcl_DuplicateObj(cmdObj);
|
||||
}
|
||||
Tcl_IncrRefCount(cmdObj);
|
||||
}
|
||||
callbackInfo = ckalloc(sizeof(AlertCallbackInfo));
|
||||
callbackInfo->cmdObj = cmdObj;
|
||||
callbackInfo->interp = interp;
|
||||
callbackInfo->typeIndex = typeIndex;
|
||||
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
|
||||
if (haveParentOption && parent && ![parent attachedSheet]) {
|
||||
parentIsKey = [parent isKeyWindow];
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > 1090
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
|
||||
[alert beginSheetModalForWindow:parent
|
||||
completionHandler:^(NSModalResponse returnCode)
|
||||
{ [NSApp tkAlertDidEnd:alert
|
||||
returnCode:returnCode
|
||||
contextInfo:callbackInfo ]; } ];
|
||||
completionHandler:^(NSModalResponse returnCode) {
|
||||
[NSApp tkAlertDidEnd:alert
|
||||
returnCode:returnCode
|
||||
contextInfo:callbackInfo];
|
||||
}];
|
||||
#else
|
||||
[alert beginSheetModalForWindow:parent
|
||||
modalDelegate:NSApp
|
||||
@@ -1443,7 +1550,7 @@ Tk_MessageBoxObjCmd(
|
||||
contextInfo:callbackInfo];
|
||||
#endif
|
||||
modalReturnCode = cmdObj ? 0 :
|
||||
[NSApp runModalForWindow:[alert window]];
|
||||
[alert runModal];
|
||||
} else {
|
||||
modalReturnCode = [alert runModal];
|
||||
[NSApp tkAlertDidEnd:alert returnCode:modalReturnCode
|
||||
@@ -1475,7 +1582,10 @@ typedef struct FontchooserData {
|
||||
Tk_Window parent;
|
||||
} FontchooserData;
|
||||
|
||||
enum FontchooserEvent { FontchooserClosed, FontchooserSelection };
|
||||
enum FontchooserEvent {
|
||||
FontchooserClosed,
|
||||
FontchooserSelection
|
||||
};
|
||||
|
||||
static void FontchooserEvent(int kind);
|
||||
static Tcl_Obj * FontchooserCget(FontchooserData *fcdPtr,
|
||||
@@ -1567,8 +1677,8 @@ enum FontchooserOption {
|
||||
*
|
||||
* FontchooserEvent --
|
||||
*
|
||||
* This processes events generated by user interaction with the
|
||||
* font panel.
|
||||
* This processes events generated by user interaction with the font
|
||||
* panel.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -1627,9 +1737,8 @@ FontchooserEvent(
|
||||
*
|
||||
* FontchooserCget --
|
||||
*
|
||||
* Helper for the FontchooserConfigure command to return the
|
||||
* current value of any of the options (which may be NULL in
|
||||
* the structure)
|
||||
* Helper for the FontchooserConfigure command to return the current value
|
||||
* of any of the options (which may be NULL in the structure).
|
||||
*
|
||||
* Results:
|
||||
* Tcl object of option value.
|
||||
@@ -1692,8 +1801,8 @@ FontchooserCget(
|
||||
*
|
||||
* FontchooserConfigureCmd --
|
||||
*
|
||||
* Implementation of the 'tk fontchooser configure' ensemble command.
|
||||
* See the user documentation for what it does.
|
||||
* Implementation of the 'tk fontchooser configure' ensemble command. See
|
||||
* the user documentation for what it does.
|
||||
*
|
||||
* Results:
|
||||
* See the user documentation.
|
||||
@@ -1826,7 +1935,8 @@ FontchooserConfigureCmd(
|
||||
[fm setSelectedAttributes:fontPanelFontAttributes
|
||||
isMultiple:NO];
|
||||
if ([fp isVisible]) {
|
||||
TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL);
|
||||
TkSendVirtualEvent(fcdPtr->parent,
|
||||
"TkFontchooserFontChanged", NULL);
|
||||
}
|
||||
break;
|
||||
case FontchooserCmd:
|
||||
@@ -1854,9 +1964,9 @@ FontchooserConfigureCmd(
|
||||
*
|
||||
* FontchooserShowCmd --
|
||||
*
|
||||
* Implements the 'tk fontchooser show' ensemble command. The
|
||||
* per-interp configuration data for the dialog is held in an interp
|
||||
* associated structure.
|
||||
* Implements the 'tk fontchooser show' ensemble command. The per-interp
|
||||
* configuration data for the dialog is held in an interp associated
|
||||
* structure.
|
||||
*
|
||||
* Results:
|
||||
* See the user documentation.
|
||||
@@ -1882,8 +1992,10 @@ FontchooserShowCmd(
|
||||
Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask,
|
||||
FontchooserParentEventHandler, fcdPtr);
|
||||
}
|
||||
|
||||
NSFontManager *fm = [NSFontManager sharedFontManager];
|
||||
NSFontPanel *fp = [fm fontPanel:YES];
|
||||
|
||||
if ([fp delegate] != NSApp) {
|
||||
[fp setDelegate:NSApp];
|
||||
}
|
||||
@@ -1901,8 +2013,8 @@ FontchooserShowCmd(
|
||||
*
|
||||
* FontchooserHideCmd --
|
||||
*
|
||||
* Implementation of the 'tk fontchooser hide' ensemble. See the
|
||||
* user documentation for details.
|
||||
* Implementation of the 'tk fontchooser hide' ensemble. See the user
|
||||
* documentation for details.
|
||||
*
|
||||
* Results:
|
||||
* See the user documentation.
|
||||
@@ -1921,6 +2033,7 @@ FontchooserHideCmd(
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
NSFontPanel *fp = [[NSFontManager sharedFontManager] fontPanel:NO];
|
||||
|
||||
if ([fp isVisible]) {
|
||||
[fp orderOut:NSApp];
|
||||
}
|
||||
@@ -1954,7 +2067,7 @@ FontchooserParentEventHandler(
|
||||
if (eventPtr->type == DestroyNotify) {
|
||||
Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask,
|
||||
FontchooserParentEventHandler, fcdPtr);
|
||||
fcdPtr->parent = None;
|
||||
fcdPtr->parent = NULL;
|
||||
FontchooserHideCmd(NULL, NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
@@ -2001,8 +2114,8 @@ DeleteFontchooserData(
|
||||
*
|
||||
* TkInitFontchooser --
|
||||
*
|
||||
* Associate the font chooser configuration data with the Tcl
|
||||
* interpreter. There is one font chooser per interp.
|
||||
* Associate the font chooser configuration data with the Tcl interpreter.
|
||||
* There is one font chooser per interp.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -272,7 +272,14 @@ TkpUseWindow(
|
||||
}
|
||||
|
||||
usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, (Window) parent);
|
||||
if (usePtr != NULL && !(usePtr->flags & TK_CONTAINER)) {
|
||||
if (usePtr == NULL) {
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"couldn't create child of window \"%s\"", string));
|
||||
Tcl_SetErrorCode(interp, "TK", "EMBED", "NO_TARGET", NULL);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
} else if (!(usePtr->flags & TK_CONTAINER)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"window \"%s\" doesn't have -container option set",
|
||||
usePtr->pathName));
|
||||
@@ -281,15 +288,9 @@ TkpUseWindow(
|
||||
}
|
||||
|
||||
/*
|
||||
* The code below can probably be simplified given we have already
|
||||
* discovered 'usePtr' above.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Save information about the container and the embedded window in a
|
||||
* Container structure. Currently, there must already be an existing
|
||||
* Container structure, since we only allow the case where both container
|
||||
* and embedded app. are in the same process.
|
||||
* Since we do not allow embedding into windows belonging to a different
|
||||
* process, we know that a container will exist showing the parent window
|
||||
* as the parent. This loop finds that container.
|
||||
*/
|
||||
|
||||
for (containerPtr = firstContainerPtr; containerPtr != NULL;
|
||||
@@ -312,16 +313,6 @@ TkpUseWindow(
|
||||
}
|
||||
|
||||
macWin->winPtr = winPtr;
|
||||
winPtr->privatePtr = macWin;
|
||||
|
||||
/*
|
||||
* The grafPtr will be NULL for a Tk in Tk embedded window. It is none of
|
||||
* our business what it is for a Tk not in Tk embedded window, but we will
|
||||
* initialize it to NULL, and let the registerWinProc set it. In any case,
|
||||
* you must always use TkMacOSXGetDrawablePort to get the portPtr. It will
|
||||
* correctly find the container's port.
|
||||
*/
|
||||
|
||||
macWin->view = nil;
|
||||
macWin->context = NULL;
|
||||
macWin->size = CGSizeZero;
|
||||
@@ -333,6 +324,7 @@ TkpUseWindow(
|
||||
macWin->toplevel = macWin;
|
||||
macWin->toplevel->referenceCount++;
|
||||
|
||||
winPtr->privatePtr = macWin;
|
||||
winPtr->flags |= TK_EMBEDDED;
|
||||
|
||||
/*
|
||||
@@ -341,64 +333,28 @@ TkpUseWindow(
|
||||
*/
|
||||
|
||||
macWin->flags |= TK_EMBEDDED;
|
||||
macWin->xOff = parent->winPtr->privatePtr->xOff +
|
||||
parent->winPtr->changes.border_width +
|
||||
winPtr->changes.x;
|
||||
macWin->yOff = parent->winPtr->privatePtr->yOff +
|
||||
parent->winPtr->changes.border_width +
|
||||
winPtr->changes.y;
|
||||
|
||||
/*
|
||||
* Now check whether it is embedded in another Tk widget. If not (the
|
||||
* first case below) we see if there is an in-process embedding handler
|
||||
* registered, and if so, let that fill in the rest of the macWin.
|
||||
* Finish filling up the container structure with the embedded window's
|
||||
* information.
|
||||
*/
|
||||
|
||||
if (containerPtr == NULL) {
|
||||
/*
|
||||
* If someone has registered an in-process embedding handler, then
|
||||
* see if it can handle this window...
|
||||
*/
|
||||
containerPtr->embedded = (Window) macWin;
|
||||
containerPtr->embeddedPtr = macWin->winPtr;
|
||||
|
||||
if (tkMacOSXEmbedHandler == NULL ||
|
||||
tkMacOSXEmbedHandler->registerWinProc((long) parent,
|
||||
(Tk_Window) winPtr) != TCL_OK) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"The window ID %s does not correspond to a valid Tk Window",
|
||||
string));
|
||||
Tcl_SetErrorCode(interp, "TK", "EMBED", "HANDLE", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*
|
||||
* Create an event handler to clean up the Container structure when
|
||||
* tkwin is eventually deleted.
|
||||
*/
|
||||
|
||||
containerPtr = ckalloc(sizeof(Container));
|
||||
|
||||
containerPtr->parentPtr = NULL;
|
||||
containerPtr->embedded = (Window) macWin;
|
||||
containerPtr->embeddedPtr = macWin->winPtr;
|
||||
containerPtr->nextPtr = firstContainerPtr;
|
||||
firstContainerPtr = containerPtr;
|
||||
} else {
|
||||
/*
|
||||
* The window is embedded in another Tk window.
|
||||
*/
|
||||
|
||||
macWin->xOff = parent->winPtr->privatePtr->xOff +
|
||||
parent->winPtr->changes.border_width +
|
||||
winPtr->changes.x;
|
||||
macWin->yOff = parent->winPtr->privatePtr->yOff +
|
||||
parent->winPtr->changes.border_width +
|
||||
winPtr->changes.y;
|
||||
|
||||
/*
|
||||
* Finish filling up the container structure with the embedded
|
||||
* window's information.
|
||||
*/
|
||||
|
||||
containerPtr->embedded = (Window) macWin;
|
||||
containerPtr->embeddedPtr = macWin->winPtr;
|
||||
|
||||
/*
|
||||
* Create an event handler to clean up the Container structure when
|
||||
* tkwin is eventually deleted.
|
||||
*/
|
||||
|
||||
Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
|
||||
winPtr);
|
||||
}
|
||||
Tk_CreateEventHandler(tkwin, StructureNotifyMask,
|
||||
EmbeddedEventProc, winPtr);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -494,7 +450,7 @@ TkMacOSXContainerId(
|
||||
}
|
||||
}
|
||||
Tcl_Panic("TkMacOSXContainerId couldn't find window");
|
||||
return None;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -530,8 +486,8 @@ TkMacOSXGetHostToplevel(
|
||||
* TODO: Here we should handle out of process embedding.
|
||||
*/
|
||||
|
||||
if (contWinPtr == NULL) {
|
||||
return None;
|
||||
if (!contWinPtr) {
|
||||
return NULL;
|
||||
}
|
||||
return TkMacOSXGetHostToplevel(contWinPtr);
|
||||
}
|
||||
@@ -542,9 +498,7 @@ TkMacOSXGetHostToplevel(
|
||||
* TkpClaimFocus --
|
||||
*
|
||||
* This procedure is invoked when someone asks for the input focus to be
|
||||
* put on a window in an embedded application, but the application
|
||||
* doesn't currently have the focus. It requests the input focus from the
|
||||
* container application.
|
||||
* put on a window in an embedded application.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -583,7 +537,7 @@ TkpClaimFocus(
|
||||
event.xfocus.window = containerPtr->parent;
|
||||
event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
|
||||
event.xfocus.detail = force;
|
||||
Tk_QueueWindowEvent(&event,TCL_QUEUE_TAIL);
|
||||
Tk_HandleEvent(&event);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -614,6 +568,7 @@ TkpTestembedCmd(
|
||||
Container *containerPtr;
|
||||
Tcl_DString dString;
|
||||
char buffer[50];
|
||||
Tcl_Interp *embeddedInterp = NULL, *parentInterp = NULL;
|
||||
|
||||
if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "all") == 0)) {
|
||||
all = 1;
|
||||
@@ -623,30 +578,54 @@ TkpTestembedCmd(
|
||||
Tcl_DStringInit(&dString);
|
||||
for (containerPtr = firstContainerPtr; containerPtr != NULL;
|
||||
containerPtr = containerPtr->nextPtr) {
|
||||
if (containerPtr->embeddedPtr != NULL) {
|
||||
embeddedInterp = containerPtr->embeddedPtr->mainPtr->interp;
|
||||
}
|
||||
if (containerPtr->parentPtr != NULL) {
|
||||
parentInterp = containerPtr->parentPtr->mainPtr->interp;
|
||||
}
|
||||
if (embeddedInterp != interp && parentInterp != interp) {
|
||||
continue;
|
||||
}
|
||||
Tcl_DStringStartSublist(&dString);
|
||||
|
||||
/*
|
||||
* Parent id
|
||||
*/
|
||||
|
||||
if (containerPtr->parent == None) {
|
||||
Tcl_DStringAppendElement(&dString, "");
|
||||
} else if (all) {
|
||||
sprintf(buffer, "0x%x", (int) containerPtr->parent);
|
||||
sprintf(buffer, "0x%lx", containerPtr->parent);
|
||||
Tcl_DStringAppendElement(&dString, buffer);
|
||||
} else {
|
||||
Tcl_DStringAppendElement(&dString, "XXX");
|
||||
}
|
||||
if (containerPtr->parentPtr == NULL) {
|
||||
|
||||
/*
|
||||
* Parent pathName
|
||||
*/
|
||||
|
||||
if (containerPtr->parentPtr == NULL ||
|
||||
parentInterp != interp) {
|
||||
Tcl_DStringAppendElement(&dString, "");
|
||||
} else {
|
||||
Tcl_DStringAppendElement(&dString,
|
||||
containerPtr->parentPtr->pathName);
|
||||
}
|
||||
if (containerPtr->embedded == None) {
|
||||
Tcl_DStringAppendElement(&dString, "");
|
||||
} else if (all) {
|
||||
sprintf(buffer, "0x%x", (int) containerPtr->embedded);
|
||||
Tcl_DStringAppendElement(&dString, buffer);
|
||||
} else {
|
||||
Tcl_DStringAppendElement(&dString, "XXX");
|
||||
}
|
||||
if (containerPtr->embeddedPtr == NULL) {
|
||||
|
||||
/*
|
||||
* On X11 embedded is a wrapper, which does not exist on macOS.
|
||||
*/
|
||||
|
||||
Tcl_DStringAppendElement(&dString, "");
|
||||
|
||||
/*
|
||||
* Embedded window pathName
|
||||
*/
|
||||
|
||||
if (containerPtr->embeddedPtr == NULL ||
|
||||
embeddedInterp != interp) {
|
||||
Tcl_DStringAppendElement(&dString, "");
|
||||
} else {
|
||||
Tcl_DStringAppendElement(&dString,
|
||||
@@ -803,6 +782,7 @@ ContainerEventProc(
|
||||
/*
|
||||
* When the interpreter is being dismantled this can be nil.
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -868,7 +848,9 @@ ContainerEventProc(
|
||||
eventPtr->xmaprequest.window);
|
||||
} else if (eventPtr->type == DestroyNotify) {
|
||||
/*
|
||||
* The embedded application is gone. Destroy the container window.
|
||||
* It is not clear whether the container should be destroyed
|
||||
* when an embedded window is destroyed. See ticket [67384bce7d].
|
||||
* Here we are following unix, by destroying the container.
|
||||
*/
|
||||
|
||||
Tk_DestroyWindow((Tk_Window) winPtr);
|
||||
@@ -904,6 +886,14 @@ EmbedStructureProc(
|
||||
Tk_ErrorHandler errHandler;
|
||||
|
||||
if (eventPtr->type == ConfigureNotify) {
|
||||
|
||||
/*
|
||||
* Send a ConfigureNotify to the embedded application.
|
||||
*/
|
||||
|
||||
if (containerPtr->embeddedPtr != None) {
|
||||
TkDoConfigureNotify(containerPtr->embeddedPtr);
|
||||
}
|
||||
if (containerPtr->embedded != None) {
|
||||
/*
|
||||
* Ignore errors, since the embedded application could have
|
||||
@@ -1052,11 +1042,10 @@ EmbedGeometryRequest(
|
||||
/*
|
||||
* Forward the requested size into our geometry management hierarchy via
|
||||
* the container window. We need to send a Configure event back to the
|
||||
* embedded application if we decide not to honor its request; to make
|
||||
* this happen, process all idle event handlers synchronously here (so
|
||||
* that the geometry managers have had a chance to do whatever they want
|
||||
* to do), and if the window's size didn't change then generate a
|
||||
* configure event.
|
||||
* embedded application if we decide not to honor its request; to make this
|
||||
* happen, process all idle event handlers synchronously here (so that the
|
||||
* geometry managers have had a chance to do whatever they want to do), and
|
||||
* if the window's size didn't change then generate a configure event.
|
||||
*/
|
||||
|
||||
Tk_GeometryRequest((Tk_Window) winPtr, width, height);
|
||||
@@ -1078,8 +1067,8 @@ EmbedGeometryRequest(
|
||||
* application of its current size and location. This procedure is called
|
||||
* when the embedded application made a geometry request that we did not
|
||||
* grant, so that the embedded application knows that its geometry didn't
|
||||
* change after all. It is a response to ConfigureRequest events, which
|
||||
* we do not currently synthesize on the Mac
|
||||
* change after all. It is a response to ConfigureRequest events, which we
|
||||
* do not currently synthesize on the Mac
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -1139,8 +1128,8 @@ EmbedWindowDeleted(
|
||||
containerPtr->parentPtr->flags & TK_BOTH_HALVES) {
|
||||
XEvent event;
|
||||
|
||||
event.xany.serial =
|
||||
LastKnownRequestProcessed(Tk_Display(containerPtr->parentPtr));
|
||||
event.xany.serial = LastKnownRequestProcessed(
|
||||
Tk_Display(containerPtr->parentPtr));
|
||||
event.xany.send_event = False;
|
||||
event.xany.display = Tk_Display(containerPtr->parentPtr);
|
||||
|
||||
|
||||
@@ -123,11 +123,18 @@ TkpDrawEntryBorderAndFocus(
|
||||
if (isSpinbox) {
|
||||
int incDecWidth;
|
||||
|
||||
oldWidth = Tk_Width(tkwin);
|
||||
/*
|
||||
* If native spinbox buttons are going to be drawn, then temporarily
|
||||
* change the width of the widget so that the same code can be used
|
||||
* for drawing the Entry portion of the Spinbox as is used to draw
|
||||
* an ordinary Entry. The width must be restored before returning.
|
||||
*/
|
||||
|
||||
ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH,
|
||||
&incDecWidth);
|
||||
Tk_Width(tkwin) -= incDecWidth + 1;
|
||||
oldWidth = Tk_Width(tkwin);
|
||||
if (ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH,
|
||||
&incDecWidth) != 0) {
|
||||
Tk_Width(tkwin) -= incDecWidth + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -149,6 +156,15 @@ TkpDrawEntryBorderAndFocus(
|
||||
bounds.size.width = Tk_Width(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
|
||||
bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
|
||||
if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) {
|
||||
|
||||
/*
|
||||
* No graphics context is available. If the widget is a Spinbox, we
|
||||
* must restore its width before returning 0. (Ticket [273b6a4996].)
|
||||
*/
|
||||
|
||||
if (isSpinbox) {
|
||||
Tk_Width(tkwin) = oldWidth;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation);
|
||||
@@ -171,10 +187,10 @@ TkpDrawEntryBorderAndFocus(
|
||||
* have to implement it.
|
||||
*
|
||||
* Results:
|
||||
* 1 if it has drawn the border, 0 if not.
|
||||
* 1 if it has drawn the buttons, 0 if not.
|
||||
*
|
||||
* Side effects:
|
||||
* May draw the entry border into pixmap.
|
||||
* May draw the buttons into pixmap.
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
@@ -243,9 +259,9 @@ TkpDrawSpinboxButtons(
|
||||
*/
|
||||
|
||||
bgGC = Tk_GCForColor(sbPtr->entry.highlightBgColorPtr, d);
|
||||
rects[0].x = bounds.origin.x;
|
||||
rects[0].x = Tk_Width(tkwin) - incDecWidth - 1;
|
||||
rects[0].y = 0;
|
||||
rects[0].width = Tk_Width(tkwin);
|
||||
rects[0].width = incDecWidth + 1;
|
||||
rects[0].height = Tk_Height(tkwin);
|
||||
XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1);
|
||||
|
||||
|
||||
@@ -114,21 +114,16 @@ enum {
|
||||
*
|
||||
* This routine is a stub called by XSync, which is called during the Tk
|
||||
* update command. The language specification does not require that the
|
||||
* update command be synchronous but many of the tests assume that is the
|
||||
* case. It is not naturally the case on macOS since many idle tasks are
|
||||
* run inside of the drawRect method of a window's contentView, and that
|
||||
* method will not be called until after this function returns. To make
|
||||
* the tests work, we attempt to force this to be synchronous by waiting
|
||||
* until drawRect has been called for each window. The mechanism we use
|
||||
* for this is to have drawRect post an ApplicationDefined NSEvent on the
|
||||
* AppKit event queue when it finishes drawing, and wait for it here.
|
||||
* update command be synchronous but many of the tests implicitly assume
|
||||
* that it is. It is definitely asynchronous on macOS since many idle
|
||||
* tasks are run inside of the drawRect method of a window's contentView,
|
||||
* which will not be called until after this function returns.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Calls the drawRect method of the contentView of each visible
|
||||
* window.
|
||||
* Side effects: Processes all pending idle events then calls the display
|
||||
* method of each visible window.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -136,15 +131,12 @@ enum {
|
||||
MODULE_SCOPE void
|
||||
TkMacOSXFlushWindows(void)
|
||||
{
|
||||
NSArray *macWindows = [NSApp orderedWindows];
|
||||
if ([NSApp simulateDrawing]) {
|
||||
[NSApp setSimulateDrawing:NO];
|
||||
if (Tk_GetNumMainWindows() == 0) {
|
||||
return;
|
||||
}
|
||||
for (NSWindow *w in macWindows) {
|
||||
if (TkMacOSXGetXWindow(w)) {
|
||||
[w displayIfNeeded];
|
||||
}
|
||||
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
|
||||
for (NSWindow *w in [NSApp orderedWindows]) {
|
||||
[w display];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* tkMacOSXFont.c --
|
||||
*
|
||||
* Contains the Macintosh implementation of the platform-independant
|
||||
* font package interface.
|
||||
* Contains the Macintosh implementation of the platform-independent font
|
||||
* package interface.
|
||||
*
|
||||
* Copyright 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de
|
||||
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
|
||||
@@ -32,9 +32,8 @@
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
TkFont font; /* Stuff used by generic font package. Must
|
||||
* be first in structure. */
|
||||
|
||||
TkFont font; /* Stuff used by generic font package. Must be
|
||||
* first in structure. */
|
||||
NSFont *nsFont;
|
||||
NSDictionary *nsAttributes;
|
||||
} MacFont;
|
||||
@@ -83,27 +82,167 @@ static int antialiasedTextEnabled = -1;
|
||||
static NSCharacterSet *whitespaceCharacterSet = nil;
|
||||
static NSCharacterSet *lineendingCharacterSet = nil;
|
||||
|
||||
static void GetTkFontAttributesForNSFont(NSFont *nsFont,
|
||||
TkFontAttributes *faPtr);
|
||||
static NSFont *FindNSFont(const char *familyName, NSFontTraitMask traits,
|
||||
NSInteger weight, CGFloat size, int fallbackToDefault);
|
||||
static void InitFont(NSFont *nsFont, const TkFontAttributes *reqFaPtr,
|
||||
MacFont * fontPtr);
|
||||
static int CreateNamedSystemFont(Tcl_Interp *interp, Tk_Window tkwin,
|
||||
const char* name, TkFontAttributes *faPtr);
|
||||
static void DrawCharsInContext(Display *display, Drawable drawable, GC gc,
|
||||
Tk_Font tkfont, const char *source, int numBytes, int rangeStart,
|
||||
int rangeLength, int x, int y, double angle);
|
||||
|
||||
@interface NSFont(TKFont)
|
||||
- (NSFont *) bestMatchingFontForCharacters: (const UTF16Char *) characters
|
||||
length: (NSUInteger) length attributes: (NSDictionary *) attributes
|
||||
actualCoveredLength: (NSUInteger *) coveredLength;
|
||||
@end
|
||||
static void GetTkFontAttributesForNSFont(NSFont *nsFont,
|
||||
TkFontAttributes *faPtr);
|
||||
static NSFont * FindNSFont(const char *familyName,
|
||||
NSFontTraitMask traits, NSInteger weight,
|
||||
CGFloat size, int fallbackToDefault);
|
||||
static void InitFont(NSFont *nsFont,
|
||||
const TkFontAttributes *reqFaPtr,
|
||||
MacFont *fontPtr);
|
||||
static int CreateNamedSystemFont(Tcl_Interp *interp,
|
||||
Tk_Window tkwin, const char *name,
|
||||
TkFontAttributes *faPtr);
|
||||
static void DrawCharsInContext(Display *display, Drawable drawable,
|
||||
GC gc, Tk_Font tkfont, const char *source,
|
||||
int numBytes, int rangeStart, int rangeLength,
|
||||
int x, int y, double angle);
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Font Helpers:
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclUniToNSString --
|
||||
*
|
||||
* When Tcl is compiled with TCL_UTF_MAX = 3 (the default for 8.6) it cannot
|
||||
* deal directly with UTF-8 encoded non-BMP characters, since their UTF-8
|
||||
* encoding requires 4 bytes.
|
||||
*
|
||||
* As a workaround, these versions of Tcl encode non-BMP characters as a string
|
||||
* of length 6 in which the high and low UTF-16 surrogates have been encoded
|
||||
* using the UTF-8 algorithm. The UTF-8 encoding does not allow encoding
|
||||
* surrogates, so these 6-byte strings are not valid UTF-8, and hence Apple's
|
||||
* NString class will refuse to instantiate an NSString from the 6-byte
|
||||
* encoding. This function allows creating an NSString from a C-string which
|
||||
* has been encoded using this scheme.
|
||||
*
|
||||
* Results:
|
||||
* An NSString, which may be nil.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MODULE_SCOPE NSString*
|
||||
TclUniToNSString(
|
||||
const char *source,
|
||||
int numBytes)
|
||||
{
|
||||
NSString *string = [[NSString alloc] initWithBytesNoCopy:(void *)source
|
||||
length:numBytes
|
||||
encoding:NSUTF8StringEncoding
|
||||
freeWhenDone:NO];
|
||||
if (!string) {
|
||||
const unichar *characters = ckalloc(numBytes*sizeof(unichar));
|
||||
const char *in = source;
|
||||
unichar *out = (unichar *) characters;
|
||||
while (in < source + numBytes) {
|
||||
in += Tcl_UtfToUniChar(in, out++);
|
||||
}
|
||||
string = [[NSString alloc] initWithCharacters:characters
|
||||
length:(out - characters)];
|
||||
ckfree(characters);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* TclUniAtIndex --
|
||||
*
|
||||
* Write a sequence of bytes up to length 6 which is an encoding of a UTF-16
|
||||
* character in an NSString. Also record the unicode code point of the character.
|
||||
* this may be a non-BMP character constructed by reading two surrogates from
|
||||
* the NSString.
|
||||
*
|
||||
* Results:
|
||||
* Returns the number of bytes written.
|
||||
*
|
||||
* Side effects:
|
||||
* Bytes are written to the char array referenced by the pointer uni and
|
||||
* the unicode code point is written to the integer referenced by the
|
||||
* pointer code.
|
||||
*
|
||||
*/
|
||||
|
||||
MODULE_SCOPE int
|
||||
TclUniAtIndex(
|
||||
NSString *string,
|
||||
int index,
|
||||
char *uni,
|
||||
unsigned int *code)
|
||||
{
|
||||
char *ptr = uni;
|
||||
UniChar uniChar = [string characterAtIndex: index];
|
||||
if (CFStringIsSurrogateHighCharacter(uniChar)) {
|
||||
UniChar lowChar = [string characterAtIndex: ++index];
|
||||
*code = CFStringGetLongCharacterForSurrogatePair(
|
||||
uniChar, lowChar);
|
||||
ptr += Tcl_UniCharToUtf(uniChar, ptr);
|
||||
ptr += Tcl_UniCharToUtf(lowChar, ptr);
|
||||
return ptr - uni;
|
||||
} else {
|
||||
*code = (int) uniChar;
|
||||
[[string substringWithRange: NSMakeRange(index, 1)]
|
||||
getCString: uni
|
||||
maxLength: XMaxTransChars
|
||||
encoding: NSUTF8StringEncoding];
|
||||
return strlen(uni);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* NSStringToTclUni --
|
||||
*
|
||||
* Encodes the unicode string represented by an NSString object with the
|
||||
* internal encoding that Tcl uses when TCL_UTF_MAX = 3. This encoding
|
||||
* is similar to UTF-8 except that non-BMP characters are encoded as two
|
||||
* successive 3-byte sequences which are constructed from UTF-16 surrogates
|
||||
* by applying the UTF-8 algorithm. Even though the UTF-8 encoding does not
|
||||
* allow encoding surrogates, the algorithm does produce a well-defined
|
||||
* 3-byte sequence.
|
||||
*
|
||||
* Results:
|
||||
* Returns a pointer to a null-terminated byte array which encodes the
|
||||
* NSString.
|
||||
*
|
||||
* Side effects:
|
||||
* Memory is allocated to hold the byte array, which must be freed with
|
||||
* ckalloc. If the pointer numBytes is not NULL the number of non-null
|
||||
* bytes written to the array is stored in the integer it references.
|
||||
*/
|
||||
|
||||
MODULE_SCOPE char*
|
||||
NSStringToTclUni(
|
||||
NSString *string,
|
||||
int *numBytes)
|
||||
{
|
||||
unsigned int code;
|
||||
int i;
|
||||
char *ptr, *bytes = ckalloc(6*[string length] + 1);
|
||||
|
||||
ptr = bytes;
|
||||
if (ptr) {
|
||||
for (i = 0; i < [string length]; i++) {
|
||||
ptr += TclUniAtIndex(string, i, ptr, &code);
|
||||
if (code > 0xffff){
|
||||
i++;
|
||||
}
|
||||
}
|
||||
*ptr = '\0';
|
||||
}
|
||||
if (numBytes) {
|
||||
*numBytes = ptr - bytes;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
#define GetNSFontTraitsFromTkFontAttributes(faPtr) \
|
||||
((faPtr)->weight == TK_FW_BOLD ? NSBoldFontMask : NSUnboldFontMask) | \
|
||||
((faPtr)->slant == TK_FS_ITALIC ? NSItalicFontMask : NSUnitalicFontMask)
|
||||
@@ -131,11 +270,11 @@ GetTkFontAttributesForNSFont(
|
||||
{
|
||||
NSFontTraitMask traits = [[NSFontManager sharedFontManager]
|
||||
traitsOfFont:nsFont];
|
||||
|
||||
faPtr->family = Tk_GetUid([[nsFont familyName] UTF8String]);
|
||||
faPtr->size = [nsFont pointSize];
|
||||
faPtr->weight = (traits & NSBoldFontMask ? TK_FW_BOLD : TK_FW_NORMAL);
|
||||
faPtr->slant = (traits & NSItalicFontMask ? TK_FS_ITALIC : TK_FS_ROMAN);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -179,6 +318,18 @@ FindNSFont(
|
||||
size = [defaultFont pointSize];
|
||||
}
|
||||
nsFont = [fm fontWithFamily:family traits:traits weight:weight size:size];
|
||||
|
||||
/*
|
||||
* A second bug in NSFontManager that Apple created for the Catalina OS
|
||||
* causes requests as above to sometimes return fonts with additional
|
||||
* traits that were not requested, even though fonts without those unwanted
|
||||
* traits exist on the system. See bug [90d555e088]. As a workaround
|
||||
* we ask the font manager to remove any unrequested traits.
|
||||
*/
|
||||
|
||||
if (nsFont) {
|
||||
nsFont = [fm convertFont:nsFont toNotHaveTrait:~traits];
|
||||
}
|
||||
if (!nsFont) {
|
||||
NSArray *availableFamilies = [fm availableFontFamilies];
|
||||
NSString *caseFamily = nil;
|
||||
@@ -238,7 +389,7 @@ InitFont(
|
||||
int ascent, descent/*, dontAA*/;
|
||||
static const UniChar ch[] = {'.', 'W', ' ', 0xc4, 0xc1, 0xc2, 0xc3, 0xc7};
|
||||
/* ., W, Space, Auml, Aacute, Acirc, Atilde, Ccedilla */
|
||||
#define nCh (sizeof(ch) / sizeof(UniChar))
|
||||
#define nCh (sizeof(ch) / sizeof(UniChar))
|
||||
CGGlyph glyphs[nCh];
|
||||
CGRect boundingRects[nCh];
|
||||
|
||||
@@ -250,7 +401,11 @@ InitFont(
|
||||
TkInitFontAttributes(faPtr);
|
||||
}
|
||||
fontPtr->nsFont = nsFont;
|
||||
// some don't like antialiasing on fixed-width even if bigger than limit
|
||||
|
||||
/*
|
||||
* Some don't like antialiasing on fixed-width even if bigger than limit
|
||||
*/
|
||||
|
||||
// dontAA = [nsFont isFixedPitch] && fontPtr->font.fa.size <= 10;
|
||||
if (antialiasedTextEnabled >= 0/* || dontAA*/) {
|
||||
renderingMode = (antialiasedTextEnabled == 0/* || dontAA*/) ?
|
||||
@@ -300,7 +455,7 @@ InitFont(
|
||||
NSLigatureAttributeName,
|
||||
[NSNumber numberWithDouble:kern], NSKernAttributeName, nil];
|
||||
fontPtr->nsAttributes = [nsAttributes retain];
|
||||
#undef nCh
|
||||
#undef nCh
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -342,7 +497,7 @@ CreateNamedSystemFont(
|
||||
*
|
||||
* This procedure is called when an application is created. It
|
||||
* initializes all the structures that are used by the
|
||||
* platform-dependant code on a per application basis.
|
||||
* platform-dependent code on a per application basis.
|
||||
* Note that this is called before TkpInit() !
|
||||
*
|
||||
* Results:
|
||||
@@ -364,10 +519,14 @@ TkpFontPkgInit(
|
||||
NSFont *nsFont;
|
||||
TkFontAttributes fa;
|
||||
NSMutableCharacterSet *cs;
|
||||
/* Since we called before TkpInit, we need our own autorelease pool. */
|
||||
/*
|
||||
* Since we called before TkpInit, we need our own autorelease pool.
|
||||
*/
|
||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||
|
||||
/* force this for now */
|
||||
/*
|
||||
* Force this for now.
|
||||
*/
|
||||
if (!mainPtr->winPtr->mainPtr) {
|
||||
mainPtr->winPtr->mainPtr = mainPtr;
|
||||
}
|
||||
@@ -389,10 +548,25 @@ TkpFontPkgInit(
|
||||
systemFont++;
|
||||
}
|
||||
TkInitFontAttributes(&fa);
|
||||
#if 0
|
||||
|
||||
/*
|
||||
* In macOS 10.15.1 Apple introduced a bug in NSFontManager which caused
|
||||
* it to not recognize the familyName ".SF NSMono" which is the familyName
|
||||
* of the default fixed pitch system fault on that system. See bug [855049e799].
|
||||
* As a workaround we call [NSFont userFixedPitchFontOfSize:11] instead.
|
||||
* This returns a user font in the "Menlo" family.
|
||||
*/
|
||||
|
||||
nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL);
|
||||
#else
|
||||
nsFont = [NSFont userFixedPitchFontOfSize:11];
|
||||
#endif
|
||||
if (nsFont) {
|
||||
GetTkFontAttributesForNSFont(nsFont, &fa);
|
||||
#if 0
|
||||
CFRelease(nsFont);
|
||||
#endif
|
||||
} else {
|
||||
fa.family = Tk_GetUid("Monaco");
|
||||
fa.size = 11;
|
||||
@@ -419,17 +593,17 @@ TkpFontPkgInit(
|
||||
* Map a platform-specific native font name to a TkFont.
|
||||
*
|
||||
* Results:
|
||||
* The return value is a pointer to a TkFont that represents the
|
||||
* native font. If a native font by the given name could not be
|
||||
* found, the return value is NULL.
|
||||
* The return value is a pointer to a TkFont that represents the native
|
||||
* font. If a native font by the given name could not be found, the return
|
||||
* value is NULL.
|
||||
*
|
||||
* Every call to this procedure returns a new TkFont structure, even
|
||||
* if the name has already been seen before. The caller should call
|
||||
* Every call to this procedure returns a new TkFont structure, even if
|
||||
* the name has already been seen before. The caller should call
|
||||
* TkpDeleteFont() when the font is no longer needed.
|
||||
*
|
||||
* The caller is responsible for initializing the memory associated
|
||||
* with the generic TkFont when this function returns and releasing
|
||||
* the contents of the generics TkFont before calling TkpDeleteFont().
|
||||
* The caller is responsible for initializing the memory associated with
|
||||
* the generic TkFont when this function returns and releasing the
|
||||
* contents of the generics TkFont before calling TkpDeleteFont().
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
@@ -455,8 +629,8 @@ TkpGetNativeFont(
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
ctFont = CTFontCreateUIFontForLanguage(HIThemeGetUIFontType(
|
||||
themeFontId), 0, NULL);
|
||||
ctFont = CTFontCreateUIFontForLanguage(
|
||||
HIThemeGetUIFontType(themeFontId), 0, NULL);
|
||||
if (ctFont) {
|
||||
fontPtr = ckalloc(sizeof(MacFont));
|
||||
InitFont((NSFont*) ctFont, NULL, fontPtr);
|
||||
@@ -474,19 +648,18 @@ TkpGetNativeFont(
|
||||
* closest matching attributes.
|
||||
*
|
||||
* Results:
|
||||
* The return value is a pointer to a TkFont that represents the font
|
||||
* with the desired attributes. If a font with the desired attributes
|
||||
* could not be constructed, some other font will be substituted
|
||||
* automatically.
|
||||
* The return value is a pointer to a TkFont that represents the font with
|
||||
* the desired attributes. If a font with the desired attributes could not
|
||||
* be constructed, some other font will be substituted automatically.
|
||||
*
|
||||
* Every call to this procedure returns a new TkFont structure, even
|
||||
* if the specified attributes have already been seen before. The
|
||||
* caller should call TkpDeleteFont() to free the platform- specific
|
||||
* data when the font is no longer needed.
|
||||
* Every call to this procedure returns a new TkFont structure, even if
|
||||
* the specified attributes have already been seen before. The caller
|
||||
* should call TkpDeleteFont() to free the platform- specific data when
|
||||
* the font is no longer needed.
|
||||
*
|
||||
* The caller is responsible for initializing the memory associated
|
||||
* with the generic TkFont when this function returns and releasing
|
||||
* the contents of the generic TkFont before calling TkpDeleteFont().
|
||||
* The caller is responsible for initializing the memory associated with
|
||||
* the generic TkFont when this function returns and releasing the
|
||||
* contents of the generic TkFont before calling TkpDeleteFont().
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
@@ -498,16 +671,16 @@ TkFont *
|
||||
TkpGetFontFromAttributes(
|
||||
TkFont *tkFontPtr, /* If non-NULL, store the information in this
|
||||
* existing TkFont structure, rather than
|
||||
* allocating a new structure to hold the
|
||||
* font; the existing contents of the font
|
||||
* will be released. If NULL, a new TkFont
|
||||
* structure is allocated. */
|
||||
* allocating a new structure to hold the font;
|
||||
* the existing contents of the font will be
|
||||
* released. If NULL, a new TkFont structure is
|
||||
* allocated. */
|
||||
Tk_Window tkwin, /* For display where font will be used. */
|
||||
const TkFontAttributes *faPtr)
|
||||
/* Set of attributes to match. */
|
||||
{
|
||||
MacFont *fontPtr;
|
||||
int points = (int)(TkFontGetPoints(tkwin, faPtr->size) + 0.5);
|
||||
int points = (int) (TkFontGetPoints(tkwin, faPtr->size) + 0.5);
|
||||
NSFontTraitMask traits = GetNSFontTraitsFromTkFontAttributes(faPtr);
|
||||
NSInteger weight = (faPtr->weight == TK_FW_BOLD ? 9 : 5);
|
||||
NSFont *nsFont;
|
||||
@@ -544,9 +717,9 @@ TkpGetFontFromAttributes(
|
||||
* TkpDeleteFont --
|
||||
*
|
||||
* Called to release a font allocated by TkpGetNativeFont() or
|
||||
* TkpGetFontFromAttributes(). The caller should have already
|
||||
* released the fields of the TkFont that are used exclusively by the
|
||||
* generic TkFont code.
|
||||
* TkpGetFontFromAttributes(). The caller should have already released the
|
||||
* fields of the TkFont that are used exclusively by the generic TkFont
|
||||
* code.
|
||||
*
|
||||
* Results:
|
||||
* TkFont is deallocated.
|
||||
@@ -573,8 +746,8 @@ TkpDeleteFont(
|
||||
*
|
||||
* TkpGetFontFamilies --
|
||||
*
|
||||
* Return information about the font families that are available on
|
||||
* the display of the given window.
|
||||
* Return information about the font families that are available on the
|
||||
* display of the given window.
|
||||
*
|
||||
* Results:
|
||||
* Modifies interp's result object to hold a list of all the available
|
||||
@@ -606,12 +779,12 @@ TkpGetFontFamilies(
|
||||
*
|
||||
* TkpGetSubFonts --
|
||||
*
|
||||
* A function used by the testing package for querying the actual
|
||||
* screen fonts that make up a font object.
|
||||
* A function used by the testing package for querying the actual screen
|
||||
* fonts that make up a font object.
|
||||
*
|
||||
* Results:
|
||||
* Modifies interp's result object to hold a list containing the names
|
||||
* of the screen fonts that make up the given font object.
|
||||
* Modifies interp's result object to hold a list containing the names of
|
||||
* the screen fonts that make up the given font object.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
@@ -648,8 +821,8 @@ TkpGetSubFonts(
|
||||
*
|
||||
* TkpGetFontAttrsForChar --
|
||||
*
|
||||
* Retrieve the font attributes of the actual font used to render a
|
||||
* given character.
|
||||
* Retrieve the font attributes of the actual font used to render a given
|
||||
* character.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -751,10 +924,9 @@ Tk_MeasureChars(
|
||||
* all the characters on the line for context.
|
||||
*
|
||||
* Results:
|
||||
* The return value is the number of bytes from source that
|
||||
* fit into the span that extends from 0 to maxLength. *lengthPtr is
|
||||
* filled with the x-coordinate of the right edge of the last
|
||||
* character that did fit.
|
||||
* The return value is the number of bytes from source that fit into the
|
||||
* span that extends from 0 to maxLength. *lengthPtr is filled with the
|
||||
* x-coordinate of the right edge of the last character that did fit.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
@@ -780,11 +952,11 @@ TkpMeasureCharsInContext(
|
||||
* TK_PARTIAL_OK means include the last char
|
||||
* which only partially fits on this line.
|
||||
* TK_WHOLE_WORDS means stop on a word
|
||||
* boundary, if possible. TK_AT_LEAST_ONE
|
||||
* means return at least one character even
|
||||
* if no characters fit. If TK_WHOLE_WORDS
|
||||
* and TK_AT_LEAST_ONE are set and the first
|
||||
* word doesn't fit, we return at least one
|
||||
* boundary, if possible. TK_AT_LEAST_ONE means
|
||||
* return at least one character even if no
|
||||
* characters fit. If TK_WHOLE_WORDS and
|
||||
* TK_AT_LEAST_ONE are set and the first word
|
||||
* doesn't fit, we return at least one
|
||||
* character or whatever characters fit into
|
||||
* maxLength. TK_ISOLATE_END means that the
|
||||
* last character should not be considered in
|
||||
@@ -814,8 +986,7 @@ TkpMeasureCharsInContext(
|
||||
if (maxLength > 32767) {
|
||||
maxLength = 32767;
|
||||
}
|
||||
string = [[NSString alloc] initWithBytesNoCopy:(void*)source
|
||||
length:numBytes encoding:NSUTF8StringEncoding freeWhenDone:NO];
|
||||
string = TclUniToNSString((const char *)source, numBytes);
|
||||
if (!string) {
|
||||
length = 0;
|
||||
fit = rangeLength;
|
||||
@@ -870,14 +1041,13 @@ TkpMeasureCharsInContext(
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no line breakpoint in the source string between
|
||||
* its start and the index position that fits in maxWidth, then
|
||||
* If there is no line breakpoint in the source string between its
|
||||
* start and the index position that fits in maxWidth, then
|
||||
* CTTypesetterSuggestLineBreak() returns that very last index.
|
||||
* However if the TK_WHOLE_WORDS flag is set, we want to break
|
||||
* at a word boundary. In this situation, unless TK_AT_LEAST_ONE
|
||||
* is set, we must report that zero chars actually fit (in other
|
||||
* words the smallest word of the source string is still larger
|
||||
* than maxWidth).
|
||||
* However if the TK_WHOLE_WORDS flag is set, we want to break at a
|
||||
* word boundary. In this situation, unless TK_AT_LEAST_ONE is set, we
|
||||
* must report that zero chars actually fit (in other words the
|
||||
* smallest word of the source string is still larger than maxWidth).
|
||||
*/
|
||||
|
||||
if ((index >= start) && (index < len) &&
|
||||
@@ -909,9 +1079,12 @@ TkpMeasureCharsInContext(
|
||||
CFRelease(line);
|
||||
}
|
||||
|
||||
/* The call to CTTypesetterSuggestClusterBreak above will always
|
||||
return at least one character regardless of whether it exceeded
|
||||
it or not. Clean that up now. */
|
||||
/*
|
||||
* The call to CTTypesetterSuggestClusterBreak above will always return
|
||||
* at least one character regardless of whether it exceeded it or not.
|
||||
* Clean that up now.
|
||||
*/
|
||||
|
||||
while (width > maxWidth && !(flags & TK_PARTIAL_OK)
|
||||
&& index > start+(flags & TK_AT_LEAST_ONE)) {
|
||||
range.length = --index;
|
||||
@@ -952,7 +1125,7 @@ done:
|
||||
* actual implementation in TkpDrawCharsInContext().
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Information gets drawn on the screen.
|
||||
@@ -970,8 +1143,8 @@ Tk_DrawChars(
|
||||
const char *source, /* UTF-8 string to be displayed. Need not be
|
||||
* '\0' terminated. All Tk meta-characters
|
||||
* (tabs, control characters, and newlines)
|
||||
* should be stripped out of the string that
|
||||
* is passed to this function. If they are not
|
||||
* should be stripped out of the string that is
|
||||
* passed to this function. If they are not
|
||||
* stripped out, they will be displayed as
|
||||
* regular printing characters. */
|
||||
int numBytes, /* Number of bytes in string. */
|
||||
@@ -992,8 +1165,8 @@ TkDrawAngledChars(
|
||||
const char *source, /* UTF-8 string to be displayed. Need not be
|
||||
* '\0' terminated. All Tk meta-characters
|
||||
* (tabs, control characters, and newlines)
|
||||
* should be stripped out of the string that
|
||||
* is passed to this function. If they are not
|
||||
* should be stripped out of the string that is
|
||||
* passed to this function. If they are not
|
||||
* stripped out, they will be displayed as
|
||||
* regular printing characters. */
|
||||
int numBytes, /* Number of bytes in string. */
|
||||
@@ -1035,8 +1208,8 @@ TkpDrawCharsInContext(
|
||||
const char * source, /* UTF-8 string to be displayed. Need not be
|
||||
* '\0' terminated. All Tk meta-characters
|
||||
* (tabs, control characters, and newlines)
|
||||
* should be stripped out of the string that
|
||||
* is passed to this function. If they are not
|
||||
* should be stripped out of the string that is
|
||||
* passed to this function. If they are not
|
||||
* stripped out, they will be displayed as
|
||||
* regular printing characters. */
|
||||
int numBytes, /* Number of bytes in string. */
|
||||
@@ -1060,8 +1233,8 @@ DrawCharsInContext(
|
||||
const char * source, /* UTF-8 string to be displayed. Need not be
|
||||
* '\0' terminated. All Tk meta-characters
|
||||
* (tabs, control characters, and newlines)
|
||||
* should be stripped out of the string that
|
||||
* is passed to this function. If they are not
|
||||
* should be stripped out of the string that is
|
||||
* passed to this function. If they are not
|
||||
* stripped out, they will be displayed as
|
||||
* regular printing characters. */
|
||||
int numBytes, /* Number of bytes in string. */
|
||||
@@ -1092,8 +1265,7 @@ DrawCharsInContext(
|
||||
!TkMacOSXSetupDrawingContext(drawable, gc, 1, &drawingContext)) {
|
||||
return;
|
||||
}
|
||||
string = [[NSString alloc] initWithBytesNoCopy:(void*)source
|
||||
length:numBytes encoding:NSUTF8StringEncoding freeWhenDone:NO];
|
||||
string = TclUniToNSString((const char *)source, numBytes);
|
||||
if (!string) {
|
||||
return;
|
||||
}
|
||||
@@ -1125,6 +1297,7 @@ DrawCharsInContext(
|
||||
len = Tcl_NumUtfChars(source, rangeStart + rangeLength);
|
||||
if (start > 0) {
|
||||
CGRect clipRect = CGRectInfinite, startBounds;
|
||||
|
||||
line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start));
|
||||
startBounds = CTLineGetImageBounds(line, context);
|
||||
CFRelease(line);
|
||||
@@ -1247,9 +1420,10 @@ TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
|
||||
NSUnderlineStyleAttributeName];
|
||||
id strikethrough = [nsAttributes objectForKey:
|
||||
NSStrikethroughStyleAttributeName];
|
||||
|
||||
objv[i++] = Tcl_NewStringObj(familyName, -1);
|
||||
objv[i++] = Tcl_NewIntObj([nsFont pointSize]);
|
||||
#define S(s) Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1))
|
||||
#define S(s) Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1))
|
||||
objv[i++] = (traits & NSBoldFontMask) ? S(bold) : S(normal);
|
||||
objv[i++] = (traits & NSItalicFontMask) ? S(italic) : S(roman);
|
||||
if ([underline respondsToSelector:@selector(intValue)] &&
|
||||
@@ -1273,8 +1447,9 @@ TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
|
||||
* TkMacOSXUseAntialiasedText --
|
||||
*
|
||||
* Enables or disables application-wide use of antialiased text (where
|
||||
* available). Sets up a linked Tcl global variable to allow
|
||||
* disabling of antialiased text from tcl.
|
||||
* available). Sets up a linked Tcl global variable to allow disabling of
|
||||
* antialiased text from Tcl.
|
||||
*
|
||||
* The possible values for this variable are:
|
||||
*
|
||||
* -1 - Use system default as configurable in "System Prefs" -> "General".
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* tkMacOSXFont.h --
|
||||
*
|
||||
* Contains the Macintosh implementation of the platform-independant
|
||||
* Contains the Macintosh implementation of the platform-independent
|
||||
* font package interface.
|
||||
*
|
||||
* Copyright (c) 1990-1994 The Regents of the University of California.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/*
|
||||
* tkMacOSXHLEvents.c --
|
||||
*
|
||||
* Implements high level event support for the Macintosh. Currently, the
|
||||
* only event that really does anything is the Quit event.
|
||||
* Implements high level event support for the Macintosh.
|
||||
*
|
||||
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
||||
* Copyright 2001-2009, Apple Inc.
|
||||
* Copyright (c) 2001-2009, Apple Inc.
|
||||
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
|
||||
* Copyright (c) 2015 Marc Culler
|
||||
* Copyright (c) 2015-2019 Marc Culler
|
||||
* Copyright (c) 2019 Kevin Walzer/WordTech Communications LLC.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
@@ -29,16 +29,35 @@ typedef struct KillEvent {
|
||||
* AppleEvent */
|
||||
} KillEvent;
|
||||
|
||||
/*
|
||||
* When processing an AppleEvent as an idle task, a pointer to one
|
||||
* of these structs is passed as the clientData.
|
||||
*/
|
||||
|
||||
typedef struct AppleEventInfo {
|
||||
Tcl_Interp *interp;
|
||||
const char *procedure;
|
||||
Tcl_DString command;
|
||||
NSAppleEventDescriptor *replyEvent; /* Only used for DoScriptText. */
|
||||
} AppleEventInfo;
|
||||
|
||||
/*
|
||||
* Static functions used only in this file.
|
||||
*/
|
||||
|
||||
static void tkMacOSXProcessFiles(NSAppleEventDescriptor* event,
|
||||
NSAppleEventDescriptor* replyEvent,
|
||||
Tcl_Interp *interp,
|
||||
const char* procedure);
|
||||
static int MissedAnyParameters(const AppleEvent *theEvent);
|
||||
static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
|
||||
static void ProcessAppleEvent(ClientData clientData);
|
||||
|
||||
/*
|
||||
* Names of the procedures which can be used to process AppleEvents.
|
||||
*/
|
||||
|
||||
static const char *openDocumentProc = "::tk::mac::OpenDocument";
|
||||
static const char *launchURLProc = "::tk::mac::LaunchURL";
|
||||
static const char *printDocProc = "::tk::mac::PrintDocument";
|
||||
static const char *scriptFileProc = "::tk::mac::DoScriptFile";
|
||||
static const char *scriptTextProc = "::tk::mac::DoScriptText";
|
||||
|
||||
#pragma mark TKApplication(TKHLEvents)
|
||||
|
||||
@@ -78,9 +97,7 @@ static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
|
||||
- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event
|
||||
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
|
||||
{
|
||||
Tcl_Interp *interp = _eventInterp;
|
||||
|
||||
if (interp &&
|
||||
if (_eventInterp &&
|
||||
Tcl_FindCommand(_eventInterp, "::tk::mac::OpenApplication", NULL, 0)){
|
||||
int code = Tcl_EvalEx(_eventInterp, "::tk::mac::OpenApplication",
|
||||
-1, TCL_EVAL_GLOBAL);
|
||||
@@ -93,12 +110,7 @@ static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
|
||||
- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
|
||||
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
|
||||
ProcessSerialNumber thePSN = {0, kCurrentProcess};
|
||||
SetFrontProcess(&thePSN);
|
||||
#else
|
||||
[[NSApplication sharedApplication] activateIgnoringOtherApps: YES];
|
||||
#endif
|
||||
[NSApp activateIgnoringOtherApps: YES];
|
||||
if (_eventInterp && Tcl_FindCommand(_eventInterp,
|
||||
"::tk::mac::ReopenApplication", NULL, 0)) {
|
||||
int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ReopenApplication",
|
||||
@@ -124,160 +136,6 @@ static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
|
||||
|
||||
- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event
|
||||
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
|
||||
{
|
||||
tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::OpenDocument");
|
||||
}
|
||||
|
||||
- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
|
||||
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
|
||||
{
|
||||
tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::PrintDocument");
|
||||
}
|
||||
|
||||
- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
|
||||
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
|
||||
{
|
||||
OSStatus err;
|
||||
const AEDesc *theDesc = nil;
|
||||
DescType type = 0, initialType = 0;
|
||||
Size actual;
|
||||
int tclErr = -1;
|
||||
char URLBuffer[1 + URL_MAX_LENGTH];
|
||||
char errString[128];
|
||||
char typeString[5];
|
||||
|
||||
/*
|
||||
* The DoScript event receives one parameter that should be text data or a
|
||||
* fileURL.
|
||||
*/
|
||||
|
||||
theDesc = [event aeDesc];
|
||||
if (theDesc == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType,
|
||||
NULL, 0, NULL);
|
||||
if (err != noErr) {
|
||||
sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", (int)err);
|
||||
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
|
||||
errString, strlen(errString));
|
||||
return;
|
||||
}
|
||||
|
||||
if (MissedAnyParameters((AppleEvent*)theDesc)) {
|
||||
sprintf(errString, "AEDoScriptHandler: extra parameters");
|
||||
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
|
||||
errString, strlen(errString));
|
||||
return;
|
||||
}
|
||||
|
||||
if (initialType == typeFileURL || initialType == typeAlias) {
|
||||
/*
|
||||
* The descriptor can be coerced to a file url. Source the file, or
|
||||
* pass the path as a string argument to ::tk::mac::DoScriptFile if
|
||||
* that procedure exists.
|
||||
*/
|
||||
err = AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type,
|
||||
(Ptr) URLBuffer, URL_MAX_LENGTH, &actual);
|
||||
if (err == noErr && actual > 0){
|
||||
URLBuffer[actual] = '\0';
|
||||
NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer];
|
||||
NSURL *fileURL = [NSURL URLWithString:urlString];
|
||||
Tcl_DString command;
|
||||
Tcl_DStringInit(&command);
|
||||
if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptFile", NULL, 0)){
|
||||
Tcl_DStringAppend(&command, "::tk::mac::DoScriptFile", -1);
|
||||
} else {
|
||||
Tcl_DStringAppend(&command, "source", -1);
|
||||
}
|
||||
Tcl_DStringAppendElement(&command, [[fileURL path] UTF8String]);
|
||||
tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
|
||||
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
|
||||
}
|
||||
} else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
|
||||
NULL, 0, &actual)) {
|
||||
if (actual > 0) {
|
||||
/*
|
||||
* The descriptor can be coerced to UTF8 text. Evaluate as Tcl, or
|
||||
* or pass the text as a string argument to ::tk::mac::DoScriptText
|
||||
* if that procedure exists.
|
||||
*/
|
||||
char *data = ckalloc(actual + 1);
|
||||
if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
|
||||
data, actual, NULL)) {
|
||||
if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptText", NULL, 0)){
|
||||
Tcl_DString command;
|
||||
Tcl_DStringInit(&command);
|
||||
Tcl_DStringAppend(&command, "::tk::mac::DoScriptText", -1);
|
||||
Tcl_DStringAppendElement(&command, data);
|
||||
tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
|
||||
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
|
||||
} else {
|
||||
tclErr = Tcl_EvalEx(_eventInterp, data, actual, TCL_EVAL_GLOBAL);
|
||||
}
|
||||
}
|
||||
ckfree(data);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* The descriptor can not be coerced to a fileURL or UTF8 text.
|
||||
*/
|
||||
for (int i = 0; i < 4; i++) {
|
||||
typeString[i] = ((char*)&initialType)[3-i];
|
||||
}
|
||||
typeString[4] = '\0';
|
||||
sprintf(errString, "AEDoScriptHandler: invalid script type '%s', "
|
||||
"must be coercable to 'furl' or 'utf8'", typeString);
|
||||
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, errString,
|
||||
strlen(errString));
|
||||
}
|
||||
/*
|
||||
* If we ran some Tcl code, put the result in the reply.
|
||||
*/
|
||||
if (tclErr >= 0) {
|
||||
int reslen;
|
||||
const char *result =
|
||||
Tcl_GetStringFromObj(Tcl_GetObjResult(_eventInterp), &reslen);
|
||||
if (tclErr == TCL_OK) {
|
||||
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyDirectObject, typeChar,
|
||||
result, reslen);
|
||||
} else {
|
||||
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
|
||||
result, reslen);
|
||||
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorNumber, typeSInt32,
|
||||
(Ptr) &tclErr,sizeof(int));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkMacOSXProcessFiles --
|
||||
*
|
||||
* Extract a list of fileURLs from an AppleEvent and call the specified
|
||||
* procedure with the file paths as arguments.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The event is handled by running the procedure.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
tkMacOSXProcessFiles(
|
||||
NSAppleEventDescriptor* event,
|
||||
NSAppleEventDescriptor* replyEvent,
|
||||
Tcl_Interp *interp,
|
||||
const char* procedure)
|
||||
{
|
||||
Tcl_Encoding utf8;
|
||||
const AEDesc *fileSpecDesc = nil;
|
||||
@@ -288,14 +146,13 @@ tkMacOSXProcessFiles(
|
||||
Size actual;
|
||||
long count, index;
|
||||
AEKeyword keyword;
|
||||
Tcl_DString command, pathName;
|
||||
int code;
|
||||
Tcl_DString pathName;
|
||||
|
||||
/*
|
||||
* Do nothing if we don't have an interpreter or the procedure doesn't exist.
|
||||
* Do nothing if we don't have an interpreter.
|
||||
*/
|
||||
|
||||
if (!interp || !Tcl_FindCommand(interp, procedure, NULL, 0)) {
|
||||
if (!_eventInterp) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -325,12 +182,14 @@ tkMacOSXProcessFiles(
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a Tcl command which calls the procedure, passing the
|
||||
* paths contained in the AppleEvent as arguments.
|
||||
* Construct a Tcl expression which calls the ::tk::mac::OpenDocument
|
||||
* procedure, passing the paths contained in the AppleEvent as arguments.
|
||||
*/
|
||||
|
||||
Tcl_DStringInit(&command);
|
||||
Tcl_DStringAppend(&command, procedure, -1);
|
||||
AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
|
||||
Tcl_DString *openCommand = &AEInfo->command;
|
||||
Tcl_DStringInit(openCommand);
|
||||
Tcl_DStringAppend(openCommand, openDocumentProc, -1);
|
||||
utf8 = Tcl_GetEncoding(NULL, "utf-8");
|
||||
|
||||
for (index = 1; index <= count; index++) {
|
||||
@@ -347,23 +206,203 @@ tkMacOSXProcessFiles(
|
||||
continue;
|
||||
}
|
||||
Tcl_ExternalToUtfDString(utf8, [[fileURL path] UTF8String], -1, &pathName);
|
||||
Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
|
||||
Tcl_DStringAppendElement(openCommand, Tcl_DStringValue(&pathName));
|
||||
Tcl_DStringFree(&pathName);
|
||||
}
|
||||
|
||||
Tcl_FreeEncoding(utf8);
|
||||
AEDisposeDesc(&contents);
|
||||
AEInfo->interp = _eventInterp;
|
||||
AEInfo->procedure = openDocumentProc;
|
||||
AEInfo->replyEvent = nil;
|
||||
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
|
||||
}
|
||||
|
||||
- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
|
||||
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
|
||||
{
|
||||
NSString* file = [[event paramDescriptorForKeyword:keyDirectObject]
|
||||
stringValue];
|
||||
const char *printFile = [file UTF8String];
|
||||
AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
|
||||
Tcl_DString *printCommand = &AEInfo->command;
|
||||
Tcl_DStringInit(printCommand);
|
||||
Tcl_DStringAppend(printCommand, printDocProc, -1);
|
||||
Tcl_DStringAppendElement(printCommand, printFile);
|
||||
AEInfo->interp = _eventInterp;
|
||||
AEInfo->procedure = printDocProc;
|
||||
AEInfo->replyEvent = nil;
|
||||
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
|
||||
}
|
||||
|
||||
- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
|
||||
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
|
||||
{
|
||||
OSStatus err;
|
||||
const AEDesc *theDesc = nil;
|
||||
DescType type = 0, initialType = 0;
|
||||
Size actual;
|
||||
char URLBuffer[1 + URL_MAX_LENGTH];
|
||||
char errString[128];
|
||||
|
||||
/*
|
||||
* Handle the event by evaluating the Tcl expression we constructed.
|
||||
* The DoScript event receives one parameter that should be text data or a
|
||||
* fileURL.
|
||||
*/
|
||||
|
||||
code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
|
||||
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
|
||||
if (code != TCL_OK) {
|
||||
Tcl_BackgroundException(interp, code);
|
||||
theDesc = [event aeDesc];
|
||||
if (theDesc == nil) {
|
||||
return;
|
||||
}
|
||||
Tcl_DStringFree(&command);
|
||||
|
||||
err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType,
|
||||
NULL, 0, NULL);
|
||||
if (err != noErr) {
|
||||
sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", (int)err);
|
||||
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString,
|
||||
typeChar, errString, strlen(errString));
|
||||
return;
|
||||
}
|
||||
|
||||
if (MissedAnyParameters((AppleEvent*)theDesc)) {
|
||||
sprintf(errString, "AEDoScriptHandler: extra parameters");
|
||||
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString,
|
||||
typeChar,errString, strlen(errString));
|
||||
return;
|
||||
}
|
||||
|
||||
if (initialType == typeFileURL || initialType == typeAlias) {
|
||||
|
||||
/*
|
||||
* This descriptor can be coerced to a file url. Construct a Tcl
|
||||
* expression which passes the file path as a string argument to
|
||||
* ::tk::mac::DoScriptFile.
|
||||
*/
|
||||
|
||||
if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type,
|
||||
(Ptr) URLBuffer, URL_MAX_LENGTH, &actual)) {
|
||||
if (actual > 0) {
|
||||
URLBuffer[actual] = '\0';
|
||||
NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer];
|
||||
NSURL *fileURL = [NSURL URLWithString:urlString];
|
||||
AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
|
||||
Tcl_DString *scriptFileCommand = &AEInfo->command;
|
||||
Tcl_DStringInit(scriptFileCommand);
|
||||
Tcl_DStringAppend(scriptFileCommand, scriptFileProc, -1);
|
||||
Tcl_DStringAppendElement(scriptFileCommand, [[fileURL path] UTF8String]);
|
||||
AEInfo->interp = _eventInterp;
|
||||
AEInfo->procedure = scriptFileProc;
|
||||
AEInfo->replyEvent = nil;
|
||||
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
|
||||
}
|
||||
}
|
||||
} else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
|
||||
NULL, 0, &actual)) {
|
||||
/*
|
||||
* The descriptor cannot be coerced to a file URL but can be coerced to
|
||||
* text. Construct a Tcl expression which passes the text as a string
|
||||
* argument to ::tk::mac::DoScriptText.
|
||||
*/
|
||||
|
||||
if (actual > 0) {
|
||||
char *data = ckalloc(actual + 1);
|
||||
if (noErr == AEGetParamPtr(theDesc, keyDirectObject,
|
||||
typeUTF8Text, &type,
|
||||
data, actual, NULL)) {
|
||||
AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
|
||||
Tcl_DString *scriptTextCommand = &AEInfo->command;
|
||||
Tcl_DStringInit(scriptTextCommand);
|
||||
Tcl_DStringAppend(scriptTextCommand, scriptTextProc, -1);
|
||||
Tcl_DStringAppendElement(scriptTextCommand, data);
|
||||
AEInfo->interp = _eventInterp;
|
||||
AEInfo->procedure = scriptTextProc;
|
||||
if (Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
|
||||
AEInfo->replyEvent = replyEvent;
|
||||
ProcessAppleEvent((ClientData)AEInfo);
|
||||
} else {
|
||||
AEInfo->replyEvent = nil;
|
||||
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleURLEvent:(NSAppleEventDescriptor*)event
|
||||
withReplyEvent:(NSAppleEventDescriptor*)replyEvent
|
||||
{
|
||||
NSString* url = [[event paramDescriptorForKeyword:keyDirectObject]
|
||||
stringValue];
|
||||
const char *cURL=[url UTF8String];
|
||||
AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
|
||||
Tcl_DString *launchCommand = &AEInfo->command;
|
||||
Tcl_DStringInit(launchCommand);
|
||||
Tcl_DStringAppend(launchCommand, launchURLProc, -1);
|
||||
Tcl_DStringAppendElement(launchCommand, cURL);
|
||||
AEInfo->interp = _eventInterp;
|
||||
AEInfo->procedure = launchURLProc;
|
||||
AEInfo->replyEvent = nil;
|
||||
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* ProcessAppleEvent --
|
||||
*
|
||||
* Usually used as an idle task which evaluates a Tcl expression generated
|
||||
* from an AppleEvent. If the AppleEventInfo passed as the client data
|
||||
* has a non-null replyEvent, the result of evaluating the expression will
|
||||
* be added to the reply. This must not be done when this function is
|
||||
* called as an idle task, but is done when handling DoScriptText events
|
||||
* when this function is called directly.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The expression will be evaluated and the clientData will be freed.
|
||||
* The replyEvent may be modified to contain the result of evaluating
|
||||
* a Tcl expression.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void ProcessAppleEvent(
|
||||
ClientData clientData)
|
||||
{
|
||||
int code;
|
||||
AppleEventInfo *AEInfo = (AppleEventInfo*) clientData;
|
||||
if (!AEInfo->interp ||
|
||||
!Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
|
||||
return;
|
||||
}
|
||||
code = Tcl_EvalEx(AEInfo->interp, Tcl_DStringValue(&AEInfo->command),
|
||||
Tcl_DStringLength(&AEInfo->command), TCL_EVAL_GLOBAL);
|
||||
if (code != TCL_OK) {
|
||||
Tcl_BackgroundException(AEInfo->interp, code);
|
||||
}
|
||||
|
||||
if (AEInfo->replyEvent && code >= 0) {
|
||||
int reslen;
|
||||
const char *result = Tcl_GetStringFromObj(Tcl_GetObjResult(AEInfo->interp),
|
||||
&reslen);
|
||||
if (code == TCL_OK) {
|
||||
AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
|
||||
keyDirectObject, typeChar, result, reslen);
|
||||
} else {
|
||||
AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
|
||||
keyErrorString, typeChar, result, reslen);
|
||||
AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
|
||||
keyErrorNumber, typeSInt32, (Ptr) &code, sizeof(int));
|
||||
}
|
||||
}
|
||||
Tcl_DStringFree(&AEInfo->command);
|
||||
ckfree(clientData);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -414,12 +453,17 @@ TkMacOSXInitAppleEvents(
|
||||
forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
|
||||
|
||||
[aeManager setEventHandler:NSApp
|
||||
andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:)
|
||||
andSelector:@selector(handlePrintDocumentsEvent:withReplyEvent:)
|
||||
forEventClass:kCoreEventClass andEventID:kAEPrintDocuments];
|
||||
|
||||
[aeManager setEventHandler:NSApp
|
||||
andSelector:@selector(handleDoScriptEvent:withReplyEvent:)
|
||||
forEventClass:kAEMiscStandards andEventID:kAEDoScript];
|
||||
|
||||
[aeManager setEventHandler:NSApp
|
||||
andSelector:@selector(handleURLEvent:withReplyEvent:)
|
||||
forEventClass:kInternetEventClass andEventID:kAEGetURL];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ _XInitImageFuncPtrs(
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -81,27 +81,37 @@ TkMacOSXCreateCGImageWithXImage(
|
||||
data = memcpy(ckalloc(len), image->data + image->xoffset, len);
|
||||
}
|
||||
if (data) {
|
||||
provider = CGDataProviderCreateWithData(data, data, len, releaseData);
|
||||
provider = CGDataProviderCreateWithData(data, data, len,
|
||||
releaseData);
|
||||
}
|
||||
if (provider) {
|
||||
img = CGImageMaskCreate(image->width, image->height, bitsPerComponent,
|
||||
bitsPerPixel, image->bytes_per_line, provider, decode, 0);
|
||||
img = CGImageMaskCreate(image->width, image->height,
|
||||
bitsPerComponent, bitsPerPixel, image->bytes_per_line,
|
||||
provider, decode, 0);
|
||||
}
|
||||
} else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
|
||||
|
||||
} else if ((image->format == ZPixmap) && (image->bits_per_pixel == 32)) {
|
||||
/*
|
||||
* Color image
|
||||
*/
|
||||
|
||||
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
|
||||
|
||||
if (image->width == 0 && image->height == 0) {
|
||||
/*
|
||||
* CGCreateImage complains on early macOS releases.
|
||||
*/
|
||||
|
||||
return NULL;
|
||||
}
|
||||
bitsPerComponent = 8;
|
||||
bitsPerPixel = 32;
|
||||
bitmapInfo = (image->byte_order == MSBFirst ?
|
||||
kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big);
|
||||
kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big);
|
||||
bitmapInfo |= kCGImageAlphaLast;
|
||||
data = memcpy(ckalloc(len), image->data + image->xoffset, len);
|
||||
if (data) {
|
||||
provider = CGDataProviderCreateWithData(data, data, len, releaseData);
|
||||
provider = CGDataProviderCreateWithData(data, data, len,
|
||||
releaseData);
|
||||
}
|
||||
if (provider) {
|
||||
img = CGImageCreate(image->width, image->height, bitsPerComponent,
|
||||
@@ -118,7 +128,6 @@ TkMacOSXCreateCGImageWithXImage(
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -170,15 +179,14 @@ XGetImage(
|
||||
|
||||
if (win && has_retina == unknown) {
|
||||
#ifdef __clang__
|
||||
has_retina = [win respondsToSelector:@selector(backingScaleFactor)]?
|
||||
yes : no;
|
||||
has_retina = [win respondsToSelector:@selector(backingScaleFactor)] ?
|
||||
yes : no;
|
||||
#else
|
||||
has_retina = no;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (has_retina == yes) {
|
||||
|
||||
/*
|
||||
* We only allow scale factors 1 or 2, as Apple currently does.
|
||||
*/
|
||||
@@ -196,7 +204,7 @@ XGetImage(
|
||||
}
|
||||
|
||||
bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable,
|
||||
x, y, width, height);
|
||||
x, y, width, height);
|
||||
if (!bitmap_rep) {
|
||||
TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
|
||||
return NULL;
|
||||
@@ -205,12 +213,12 @@ XGetImage(
|
||||
size = [bitmap_rep bytesPerPlane];
|
||||
bytes_per_row = [bitmap_rep bytesPerRow];
|
||||
bitmap = ckalloc(size);
|
||||
if (!bitmap ||
|
||||
(bitmap_fmt != 0 && bitmap_fmt != 1) ||
|
||||
[bitmap_rep samplesPerPixel] != 4 ||
|
||||
[bitmap_rep isPlanar] != 0 ||
|
||||
bytes_per_row < 4 * scaled_width ||
|
||||
size != bytes_per_row*scaled_height ) {
|
||||
if (!bitmap
|
||||
|| (bitmap_fmt != 0 && bitmap_fmt != 1)
|
||||
|| [bitmap_rep samplesPerPixel] != 4
|
||||
|| [bitmap_rep isPlanar] != 0
|
||||
|| bytes_per_row < 4 * scaled_width
|
||||
|| size != bytes_per_row * scaled_height) {
|
||||
TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
|
||||
CFRelease(bitmap_rep);
|
||||
return NULL;
|
||||
@@ -219,8 +227,8 @@ XGetImage(
|
||||
CFRelease(bitmap_rep);
|
||||
|
||||
/*
|
||||
* When Apple extracts a bitmap from an NSView, it may be in
|
||||
* either BGRA or ABGR format. For an XImage we need RGBA.
|
||||
* When Apple extracts a bitmap from an NSView, it may be in either
|
||||
* BGRA or ABGR format. For an XImage we need RGBA.
|
||||
*/
|
||||
|
||||
struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr;
|
||||
@@ -239,16 +247,16 @@ XGetImage(
|
||||
}
|
||||
}
|
||||
imagePtr = XCreateImage(display, NULL, depth, format, offset,
|
||||
(char*)bitmap, scaled_width, scaled_height,
|
||||
bitmap_pad, bytes_per_row);
|
||||
(char*) bitmap, scaled_width, scaled_height,
|
||||
bitmap_pad, bytes_per_row);
|
||||
if (scalefactor == 2) {
|
||||
imagePtr->pixelpower = 1;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* There are some calls to XGetImage in the generic Tk
|
||||
* code which pass an XYPixmap rather than a ZPixmap.
|
||||
* XYPixmaps should be handled here.
|
||||
* There are some calls to XGetImage in the generic Tk code which pass
|
||||
* an XYPixmap rather than a ZPixmap. XYPixmaps should be handled
|
||||
* here.
|
||||
*/
|
||||
TkMacOSXDbgMsg("XGetImage does not handle XYPixmaps at the moment.");
|
||||
}
|
||||
@@ -314,40 +322,40 @@ ImageGetPixel(
|
||||
+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);
|
||||
|
||||
switch (image->bits_per_pixel) {
|
||||
case 32: {
|
||||
r = (*((unsigned int*) srcPtr) >> 16) & 0xff;
|
||||
g = (*((unsigned int*) srcPtr) >> 8) & 0xff;
|
||||
b = (*((unsigned int*) srcPtr) ) & 0xff;
|
||||
/*if (image->byte_order == LSBFirst) {
|
||||
r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0];
|
||||
} else {
|
||||
r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3];
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
|
||||
g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
|
||||
b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
|
||||
break;
|
||||
case 8:
|
||||
r = (*srcPtr << 2) & 0xc0;
|
||||
g = (*srcPtr << 4) & 0xc0;
|
||||
b = (*srcPtr << 6) & 0xc0;
|
||||
r |= r >> 2 | r >> 4 | r >> 6;
|
||||
g |= g >> 2 | g >> 4 | g >> 6;
|
||||
b |= b >> 2 | b >> 4 | b >> 6;
|
||||
break;
|
||||
case 4: {
|
||||
unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);
|
||||
r = (c & 0x04) ? 0xff : 0;
|
||||
g = (c & 0x02) ? 0xff : 0;
|
||||
b = (c & 0x01) ? 0xff : 0;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
|
||||
break;
|
||||
case 32:
|
||||
r = (*((unsigned int*) srcPtr) >> 16) & 0xff;
|
||||
g = (*((unsigned int*) srcPtr) >> 8) & 0xff;
|
||||
b = (*((unsigned int*) srcPtr) ) & 0xff;
|
||||
/*if (image->byte_order == LSBFirst) {
|
||||
r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0];
|
||||
} else {
|
||||
r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3];
|
||||
}*/
|
||||
break;
|
||||
case 16:
|
||||
r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
|
||||
g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
|
||||
b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
|
||||
break;
|
||||
case 8:
|
||||
r = (*srcPtr << 2) & 0xc0;
|
||||
g = (*srcPtr << 4) & 0xc0;
|
||||
b = (*srcPtr << 6) & 0xc0;
|
||||
r |= r >> 2 | r >> 4 | r >> 6;
|
||||
g |= g >> 2 | g >> 4 | g >> 6;
|
||||
b |= b >> 2 | b >> 4 | b >> 6;
|
||||
break;
|
||||
case 4: {
|
||||
unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);
|
||||
|
||||
r = (c & 0x04) ? 0xff : 0;
|
||||
g = (c & 0x02) ? 0xff : 0;
|
||||
b = (c & 0x01) ? 0xff : 0;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b;
|
||||
@@ -380,6 +388,7 @@ ImagePutPixel(
|
||||
unsigned char *dstPtr = ((unsigned char*) image->data)
|
||||
+ (y * image->bytes_per_line)
|
||||
+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);
|
||||
|
||||
if (image->bits_per_pixel == 32) {
|
||||
*((unsigned int*) dstPtr) = pixel;
|
||||
} else {
|
||||
@@ -411,7 +420,7 @@ ImagePutPixel(
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -442,6 +451,7 @@ XCreateImage(
|
||||
int bytes_per_line)
|
||||
{
|
||||
XImage *ximage;
|
||||
|
||||
display->request++;
|
||||
ximage = ckalloc(sizeof(XImage));
|
||||
|
||||
@@ -452,9 +462,12 @@ XCreateImage(
|
||||
ximage->format = format;
|
||||
ximage->data = data;
|
||||
ximage->obdata = NULL;
|
||||
/* The default pixelpower is 0. This must be explicitly set to 1 in the
|
||||
|
||||
/*
|
||||
* The default pixelpower is 0. This must be explicitly set to 1 in the
|
||||
* case of an XImage extracted from a Retina display.
|
||||
*/
|
||||
|
||||
ximage->pixelpower = 0;
|
||||
|
||||
if (format == ZPixmap) {
|
||||
@@ -467,7 +480,10 @@ XCreateImage(
|
||||
if (bitmap_pad) {
|
||||
ximage->bitmap_pad = bitmap_pad;
|
||||
} else {
|
||||
/* Use 16 byte alignment for best Quartz perfomance */
|
||||
/*
|
||||
* Use 16 byte alignment for best Quartz perfomance.
|
||||
*/
|
||||
|
||||
ximage->bitmap_pad = 128;
|
||||
}
|
||||
if (bytes_per_line) {
|
||||
@@ -500,11 +516,11 @@ XCreateImage(
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkPutImage --
|
||||
* TkPutImage, XPutImage --
|
||||
*
|
||||
* Copies a rectangular subimage of an XImage into a drawable.
|
||||
* Currently this is only called by TkImgPhotoDisplay, using
|
||||
* a Window as the drawable.
|
||||
* Copies a rectangular subimage of an XImage into a drawable. Currently
|
||||
* this is only called by TkImgPhotoDisplay, using a Window as the
|
||||
* drawable.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -516,9 +532,7 @@ XCreateImage(
|
||||
*/
|
||||
|
||||
int
|
||||
TkPutImage(
|
||||
unsigned long *colors, /* Unused on Macintosh. */
|
||||
int ncolors, /* Unused on Macintosh. */
|
||||
XPutImage(
|
||||
Display* display, /* Display. */
|
||||
Drawable drawable, /* Drawable to place image on. */
|
||||
GC gc, /* GC to use. */
|
||||
@@ -550,13 +564,15 @@ TkPutImage(
|
||||
}
|
||||
if (img) {
|
||||
|
||||
/* If the XImage has big pixels, the source is rescaled to reflect
|
||||
/*
|
||||
* If the XImage has big pixels, the source is rescaled to reflect
|
||||
* the actual pixel dimensions. This is not currently used, but
|
||||
* could arise if the image were copied from a retina monitor and
|
||||
* redrawn on an ordinary monitor.
|
||||
*/
|
||||
|
||||
int pp = image->pixelpower;
|
||||
|
||||
bounds = CGRectMake(0, 0, image->width, image->height);
|
||||
srcRect = CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp);
|
||||
dstRect = CGRectMake(dest_x, dest_y, width, height);
|
||||
@@ -573,6 +589,23 @@ TkPutImage(
|
||||
TkMacOSXRestoreDrawingContext(&dc);
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
TkPutImage(
|
||||
unsigned long *colors, /* Array of pixel values used by this image.
|
||||
* May be NULL. */
|
||||
int ncolors, /* Number of colors used, or 0. */
|
||||
Display *display,
|
||||
Drawable d, /* Destination drawable. */
|
||||
GC gc,
|
||||
XImage *image, /* Source image. */
|
||||
int src_x, int src_y, /* Offset of subimage. */
|
||||
int dest_x, int dest_y, /* Position of subimage origin in drawable. */
|
||||
unsigned int width, unsigned int height)
|
||||
/* Dimensions of subimage. */
|
||||
{
|
||||
return XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
@@ -30,24 +30,10 @@ static char scriptPath[PATH_MAX + 1] = "";
|
||||
|
||||
#pragma mark TKApplication(TKInit)
|
||||
|
||||
@interface TKApplication(TKKeyboard)
|
||||
- (void) keyboardChanged: (NSNotification *) notification;
|
||||
@end
|
||||
|
||||
#define TKApplication_NSApplicationDelegate <NSApplicationDelegate>
|
||||
@interface TKApplication(TKWindowEvent) TKApplication_NSApplicationDelegate
|
||||
- (void) _setupWindowNotifications;
|
||||
@end
|
||||
|
||||
@interface TKApplication(TKMenus)
|
||||
- (void) _setupMenus;
|
||||
@end
|
||||
|
||||
@implementation TKApplication
|
||||
@synthesize poolLock = _poolLock;
|
||||
@synthesize macMinorVersion = _macMinorVersion;
|
||||
@synthesize isDrawing = _isDrawing;
|
||||
@synthesize simulateDrawing = _simulateDrawing;
|
||||
@end
|
||||
|
||||
/*
|
||||
@@ -59,7 +45,7 @@ static char scriptPath[PATH_MAX + 1] = "";
|
||||
@implementation TKApplication(TKInit)
|
||||
- (void) _resetAutoreleasePool
|
||||
{
|
||||
if([self poolLock] == 0) {
|
||||
if ([self poolLock] == 0) {
|
||||
[_mainPool drain];
|
||||
_mainPool = [NSAutoreleasePool new];
|
||||
} else {
|
||||
@@ -116,7 +102,6 @@ static char scriptPath[PATH_MAX + 1] = "";
|
||||
_defaultMainMenu = nil;
|
||||
[self _setupMenus];
|
||||
|
||||
|
||||
/*
|
||||
* Initialize event processing.
|
||||
*/
|
||||
@@ -132,11 +117,27 @@ static char scriptPath[PATH_MAX + 1] = "";
|
||||
-(void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||
{
|
||||
/*
|
||||
* It is not safe to force activation of the NSApp until this
|
||||
* method is called. Activating too early can cause the menu
|
||||
* bar to be unresponsive.
|
||||
* It is not safe to force activation of the NSApp until this method is
|
||||
* called. Activating too early can cause the menu bar to be unresponsive.
|
||||
* The call to activateIgnoringOtherApps was moved here to avoid this.
|
||||
* However, with the release of macOS 10.15 (Catalina) this was no longer
|
||||
* sufficient. (See ticket bf93d098d7.) Apparently apps were being
|
||||
* activated automatically, and this was sometimes being done too early.
|
||||
* As a workaround we deactivate and then reactivate the app, even though
|
||||
* Apple says that "Normally, you shouldn’t invoke this method".
|
||||
*/
|
||||
|
||||
[NSApp deactivate];
|
||||
[NSApp activateIgnoringOtherApps: YES];
|
||||
|
||||
/*
|
||||
* Process events to ensure that the root window is fully initialized. See
|
||||
* ticket 56a1823c73.
|
||||
*/
|
||||
|
||||
[NSApp _lockAutoreleasePool];
|
||||
while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
|
||||
[NSApp _unlockAutoreleasePool];
|
||||
}
|
||||
|
||||
- (void) _setup: (Tcl_Interp *) interp
|
||||
@@ -156,7 +157,7 @@ static char scriptPath[PATH_MAX + 1] = "";
|
||||
* Record the OS version we are running on.
|
||||
*/
|
||||
int minorVersion;
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
|
||||
Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion);
|
||||
#else
|
||||
NSOperatingSystemVersion systemVersion;
|
||||
@@ -166,15 +167,15 @@ static char scriptPath[PATH_MAX + 1] = "";
|
||||
[NSApp setMacMinorVersion: minorVersion];
|
||||
|
||||
/*
|
||||
* We are not drawing yet.
|
||||
* We are not drawing right now.
|
||||
*/
|
||||
|
||||
[NSApp setIsDrawing:NO];
|
||||
[NSApp setSimulateDrawing:NO];
|
||||
|
||||
/*
|
||||
* Be our own delegate.
|
||||
*/
|
||||
|
||||
[self setDelegate:self];
|
||||
|
||||
/*
|
||||
@@ -187,6 +188,7 @@ static char scriptPath[PATH_MAX + 1] = "";
|
||||
* If no icon has been set from an Info.plist file, use the Wish icon from
|
||||
* the Tk framework.
|
||||
*/
|
||||
|
||||
NSString *iconFile = [[NSBundle mainBundle] objectForInfoDictionaryKey:
|
||||
@"CFBundleIconFile"];
|
||||
if (!iconFile) {
|
||||
@@ -315,8 +317,8 @@ TkpInit(
|
||||
}
|
||||
|
||||
/*
|
||||
* Instantiate our NSApplication object. This needs to be
|
||||
* done before we check whether to open a console window.
|
||||
* Instantiate our NSApplication object. This needs to be done before
|
||||
* we check whether to open a console window.
|
||||
*/
|
||||
|
||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
||||
@@ -330,8 +332,44 @@ TkpInit(
|
||||
[TKApplication sharedApplication];
|
||||
[pool drain];
|
||||
[NSApp _setup:interp];
|
||||
|
||||
/*
|
||||
* WARNING: The finishLaunching method runs asynchronously, apparently
|
||||
* in a separate thread. This creates a race between the
|
||||
* initialization of the NSApplication and the initialization of Tk.
|
||||
* If Tk wins the race bad things happen with the root window (see
|
||||
* below). If the NSApplication wins then an AppleEvent created during
|
||||
* launch, e.g. by dropping a file icon on the application icon, will
|
||||
* be delivered before the procedure meant to to handle the AppleEvent
|
||||
* has been defined. This is now handled by processing the AppleEvent
|
||||
* as an idle task. See tkMacOSXHLEvents.c.
|
||||
*/
|
||||
|
||||
[NSApp finishLaunching];
|
||||
|
||||
/*
|
||||
* Create a Tk event source based on the Appkit event queue.
|
||||
*/
|
||||
|
||||
Tk_MacOSXSetupTkNotifier();
|
||||
|
||||
/*
|
||||
* If Tk initialization wins the race, the root window is mapped before
|
||||
* the NSApplication is initialized. This can cause bad things to
|
||||
* happen. The root window can open off screen with no way to make it
|
||||
* appear on screen until the app icon is clicked. This will happen if
|
||||
* a Tk application opens a modal window in its startup script (see
|
||||
* ticket 56a1823c73). In other cases, an empty root window can open
|
||||
* on screen and remain visible for a noticeable amount of time while
|
||||
* the Tk initialization finishes (see ticket d1989fb7cf). The call
|
||||
* below forces Tk to block until the Appkit event queue has been
|
||||
* created. This seems to be sufficient to ensure that the
|
||||
* NSApplication initialization wins the race, avoiding these bad
|
||||
* window behaviors.
|
||||
*/
|
||||
|
||||
Tcl_DoOneEvent(TCL_WINDOW_EVENTS | TCL_DONT_WAIT);
|
||||
|
||||
/*
|
||||
* If we don't have a TTY and stdin is a special character file of
|
||||
* length 0, (e.g. /dev/null, which is what Finder sets when double
|
||||
@@ -347,8 +385,8 @@ TkpInit(
|
||||
Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR));
|
||||
|
||||
/*
|
||||
* Only show the console if we don't have a startup script
|
||||
* and tcl_interactive hasn't been set already.
|
||||
* Only show the console if we don't have a startup script and
|
||||
* tcl_interactive hasn't been set already.
|
||||
*/
|
||||
|
||||
if (Tcl_GetStartupScript(NULL) == NULL) {
|
||||
@@ -365,9 +403,14 @@ TkpInit(
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Initialize the NSServices object here. Apple's docs say to do this
|
||||
* in applicationDidFinishLaunching, but the Tcl interpreter is not
|
||||
* initialized until this function call.
|
||||
*/
|
||||
|
||||
Tk_MacOSXSetupTkNotifier();
|
||||
TkMacOSXServices_Init(interp);
|
||||
}
|
||||
|
||||
if (tkLibPath[0] != '\0') {
|
||||
Tcl_SetVar2(interp, "tk_library", NULL, tkLibPath, TCL_GLOBAL_ONLY);
|
||||
@@ -382,7 +425,7 @@ TkpInit(
|
||||
TkMacOSXStandardAboutPanelObjCmd, NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "::tk::mac::iconBitmap",
|
||||
TkMacOSXIconBitmapObjCmd, NULL, NULL);
|
||||
|
||||
Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath", TkMacOSXGetAppPath, NULL, NULL);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -422,7 +465,58 @@ TkpGetAppName(
|
||||
}
|
||||
Tcl_DStringAppend(namePtr, name, -1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkMacOSXGetAppPath --
|
||||
*
|
||||
* Returns the path of the Wish application bundle.
|
||||
*
|
||||
* Results:
|
||||
* Returns the application path.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
int TkMacOSXGetAppPath(
|
||||
ClientData cd,
|
||||
Tcl_Interp *ip,
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
|
||||
CFURLRef mainBundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());
|
||||
|
||||
|
||||
/*
|
||||
* Convert the URL reference into a string reference.
|
||||
*/
|
||||
|
||||
CFStringRef appPath = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);
|
||||
|
||||
/*
|
||||
* Get the system encoding method.
|
||||
*/
|
||||
|
||||
CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
|
||||
|
||||
/*
|
||||
* Convert the string reference into a C string.
|
||||
*/
|
||||
|
||||
char *path = (char *) CFStringGetCStringPtr(appPath, encodingMethod);
|
||||
|
||||
Tcl_SetResult(ip, path, NULL);
|
||||
|
||||
CFRelease(mainBundleURL);
|
||||
CFRelease(appPath);
|
||||
return TCL_OK;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
@@ -71,6 +71,7 @@ struct TkWindowPrivate {
|
||||
* gone. */
|
||||
struct TkWindowPrivate *toplevel;
|
||||
/* Pointer to the toplevel datastruct. */
|
||||
CGFloat fillRGBA[4]; /* Background used by the ttk FillElement */
|
||||
int flags; /* Various state see defines below. */
|
||||
};
|
||||
typedef struct TkWindowPrivate MacDrawable;
|
||||
@@ -86,6 +87,7 @@ typedef struct TkWindowPrivate MacDrawable;
|
||||
#define TK_IS_PIXMAP 0x10
|
||||
#define TK_IS_BW_PIXMAP 0x20
|
||||
#define TK_DO_NOT_DRAW 0x40
|
||||
#define TTK_HAS_CONTRASTING_BG 0x80
|
||||
|
||||
/*
|
||||
* I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags
|
||||
@@ -200,7 +202,8 @@ MODULE_SCOPE void TkpReleaseRegion(TkRegion r);
|
||||
MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
|
||||
MODULE_SCOPE Bool TkpAppIsDrawing(void);
|
||||
MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin);
|
||||
MODULE_SCOPE void TkTestSimulateDrawing(Bool);
|
||||
MODULE_SCOPE Bool TkTestLogDisplay(void);
|
||||
MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin);
|
||||
|
||||
/*
|
||||
* Include the stubbed internal platform-specific API.
|
||||
@@ -209,3 +212,12 @@ MODULE_SCOPE void TkTestSimulateDrawing(Bool);
|
||||
#include "tkIntPlatDecls.h"
|
||||
|
||||
#endif /* _TKMACINT */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 79
|
||||
* coding: utf-8
|
||||
* End:
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -180,13 +180,13 @@ InitKeyMaps(void)
|
||||
for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
|
||||
hPtr = Tcl_CreateHashEntry(&keycodeTable, INT2PTR(kPtr->keycode),
|
||||
&dummy);
|
||||
Tcl_SetHashValue(hPtr, kPtr->keysym);
|
||||
Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym));
|
||||
}
|
||||
Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
|
||||
for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
|
||||
hPtr = Tcl_CreateHashEntry(&vkeyTable, INT2PTR(kPtr->keycode),
|
||||
&dummy);
|
||||
Tcl_SetHashValue(hPtr, kPtr->keysym);
|
||||
Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym));
|
||||
}
|
||||
initialized = 1;
|
||||
}
|
||||
@@ -443,8 +443,11 @@ TkpGetString(
|
||||
* result. */
|
||||
{
|
||||
(void) winPtr; /*unused*/
|
||||
int ch;
|
||||
|
||||
Tcl_DStringInit(dsPtr);
|
||||
return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, -1);
|
||||
return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars,
|
||||
TkUtfToUniChar(eventPtr->xkey.trans_chars, &ch));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -717,7 +720,7 @@ TkpSetKeycodeAndState(
|
||||
}
|
||||
|
||||
if (keysym <= LATIN1_MAX) {
|
||||
int done = Tcl_UniCharToUtf(keysym, eventPtr->xkey.trans_chars);
|
||||
int done = TkUniCharToUtf(keysym, eventPtr->xkey.trans_chars);
|
||||
|
||||
eventPtr->xkey.trans_chars[done] = 0;
|
||||
} else {
|
||||
@@ -803,7 +806,7 @@ TkpGetKeySym(
|
||||
/* If nbytes has been set, it's not a function key, but a regular key that
|
||||
has been translated in tkMacOSXKeyEvent.c; just use that. */
|
||||
if (eventPtr->xkey.nbytes) {
|
||||
return eventPtr->xkey.keycode & 0xFFFF;
|
||||
return eventPtr->xkey.keycode;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -110,6 +110,11 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
|
||||
#pragma mark TKMenu
|
||||
|
||||
/*
|
||||
* This interface is not declared in tkMacOSXPrivate.h because it requires
|
||||
* tkMenu.h.
|
||||
*/
|
||||
|
||||
@interface TKMenu(TKMenuPrivate)
|
||||
- (id) initWithTkMenu: (TkMenu *) tkMenu;
|
||||
- (TkMenu *) tkMenu;
|
||||
@@ -117,10 +122,6 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
- (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index;
|
||||
@end
|
||||
|
||||
#define TKMenu_NSMenuDelegate <NSMenuDelegate>
|
||||
@interface TKMenu(TKMenuDelegate) TKMenu_NSMenuDelegate
|
||||
@end
|
||||
|
||||
@implementation TKMenu
|
||||
- (void) setSpecial: (NSUInteger) special
|
||||
{
|
||||
@@ -192,10 +193,10 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
- (void) insertItem: (NSMenuItem *) newItem atIndex: (NSInteger) index
|
||||
{
|
||||
if (_tkMenu && index >= 0) {
|
||||
if ((NSUInteger)index <= _tkOffset) {
|
||||
if ((NSUInteger) index <= _tkOffset) {
|
||||
_tkOffset++;
|
||||
} else {
|
||||
NSAssert((NSUInteger)index >= _tkItemCount + _tkOffset,
|
||||
NSAssert((NSUInteger) index >= _tkItemCount + _tkOffset,
|
||||
@"Cannot insert in the middle of Tk menu");
|
||||
}
|
||||
}
|
||||
@@ -205,9 +206,9 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
- (void) removeItemAtIndex: (NSInteger) index
|
||||
{
|
||||
if (_tkMenu && index >= 0) {
|
||||
if ((NSUInteger)index < _tkOffset) {
|
||||
if ((NSUInteger) index < _tkOffset) {
|
||||
_tkOffset--;
|
||||
} else if ((NSUInteger)index < _tkItemCount + _tkOffset) {
|
||||
} else if ((NSUInteger) index < _tkItemCount + _tkOffset) {
|
||||
_tkItemCount--;
|
||||
}
|
||||
}
|
||||
@@ -220,20 +221,22 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
action:@selector(tkMenuItemInvoke:) keyEquivalent:@""];
|
||||
|
||||
[menuItem setTarget:self];
|
||||
[menuItem setTag:(NSInteger)mePtr];
|
||||
[menuItem setTag:(NSInteger) mePtr];
|
||||
return menuItem;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation TKMenu(TKMenuActions)
|
||||
// target methods
|
||||
|
||||
- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
|
||||
{
|
||||
return [menuItem isEnabled];
|
||||
}
|
||||
|
||||
// Workaround for bug 3572016; leaves menu items enabled during modal dialog.
|
||||
/*
|
||||
* Workaround for bug 3572016; leave menu items enabled during modal dialog.
|
||||
*/
|
||||
|
||||
- (BOOL)worksWhenModal
|
||||
{
|
||||
return YES;
|
||||
@@ -243,22 +246,25 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
{
|
||||
/*
|
||||
* With the delegate matching key equivalents, when a menu action is sent
|
||||
* in response to a key equivalent, sender is the whole menu and not the
|
||||
* the specific menu item, use this to ignore key equivalents for our
|
||||
* in response to a key equivalent, the sender is the whole menu and not the
|
||||
* specific menu item. We use this to ignore key equivalents for Tk
|
||||
* menus (as Tk handles them directly via bindings).
|
||||
*/
|
||||
|
||||
if ([sender isKindOfClass:[NSMenuItem class]]) {
|
||||
NSMenuItem *menuItem = (NSMenuItem *)sender;
|
||||
TkMenu *menuPtr = (TkMenu *)_tkMenu;
|
||||
TkMenuEntry *mePtr = (TkMenuEntry *)[menuItem tag];
|
||||
NSMenuItem *menuItem = (NSMenuItem *) sender;
|
||||
TkMenu *menuPtr = (TkMenu *) _tkMenu;
|
||||
TkMenuEntry *mePtr = (TkMenuEntry *) [menuItem tag];
|
||||
|
||||
if (menuPtr && mePtr) {
|
||||
Tcl_Interp *interp = menuPtr->interp;
|
||||
/*Add time for errors to fire if necessary. This is sub-optimal
|
||||
*but avoids issues with Tcl/Cocoa event loop integration.
|
||||
|
||||
/*
|
||||
* Add time for errors to fire if necessary. This is sub-optimal
|
||||
* but avoids issues with Tcl/Cocoa event loop integration.
|
||||
*/
|
||||
Tcl_Sleep(100);
|
||||
|
||||
//Tcl_Sleep(100);
|
||||
Tcl_Preserve(interp);
|
||||
Tcl_Preserve(menuPtr);
|
||||
|
||||
@@ -277,40 +283,55 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
@end
|
||||
|
||||
@implementation TKMenu(TKMenuDelegate)
|
||||
#define keyEquivModifiersMatch(km, m) (( \
|
||||
((km) & NSCommandKeyMask) != ((m) & NSCommandKeyMask) || \
|
||||
((km) & NSAlternateKeyMask) != ((m) & NSAlternateKeyMask) || \
|
||||
((km) & NSControlKeyMask) != ((m) & NSControlKeyMask) || \
|
||||
(((km) & NSShiftKeyMask) != ((m) & NSShiftKeyMask) && \
|
||||
((m) & NSFunctionKeyMask))) ? NO : YES)
|
||||
|
||||
- (BOOL) menuHasKeyEquivalent: (NSMenu *) menu forEvent: (NSEvent *) event
|
||||
target: (id *) target action: (SEL *) action
|
||||
{
|
||||
/*Use lowercaseString to keep "shift" from firing twice if bound to different procedure.*/
|
||||
/*
|
||||
* Use lowercaseString when comparing keyEquivalents since the notion of
|
||||
* a shifted upper case letter does not make much sense.
|
||||
*/
|
||||
|
||||
NSString *key = [[event charactersIgnoringModifiers] lowercaseString];
|
||||
NSUInteger modifiers = [event modifierFlags] &
|
||||
NSDeviceIndependentModifierFlagsMask;
|
||||
|
||||
if (modifiers == (NSCommandKeyMask | NSShiftKeyMask) &&
|
||||
[key compare:@"?"] == NSOrderedSame) {
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* Command-Shift-? has not been allowed as a keyboard equivalent since
|
||||
* the first aqua port, for some mysterious reason.
|
||||
*/
|
||||
|
||||
// For command key, take input manager's word so things
|
||||
// like dvorak / qwerty layout work.
|
||||
if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) {
|
||||
key = [event characters];
|
||||
return NO;
|
||||
} else if (modifiers == (NSControlKeyMask | NSShiftKeyMask) &&
|
||||
[event keyCode] == 48) {
|
||||
/*
|
||||
* Starting with OSX 10.12 Control-Tab and Control-Shift-Tab are used
|
||||
* to select window tabs. But for some even more mysterious reason the
|
||||
* Control-Shift-Tab event has character 0x19 = NSBackTabCharacter
|
||||
* rather than 0x09 = NSTabCharacter. At the same time, the
|
||||
* keyEquivalent must be \0x09 in order for it to be displayed
|
||||
* correctly in the menu. This makes it impossible for the standard
|
||||
* "Select Previous Tab" to work correctly, unless we intervene.
|
||||
*/
|
||||
|
||||
key = @"\t";
|
||||
} else if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) {
|
||||
/*
|
||||
* If the command modifier is set, use the full character string so
|
||||
* things like the dvorak / qwerty layout will work.
|
||||
*/
|
||||
|
||||
key = [event characters];
|
||||
}
|
||||
|
||||
NSArray *itemArray = [self itemArray];
|
||||
|
||||
for (NSMenuItem *item in itemArray) {
|
||||
if ([item isEnabled] && [[item keyEquivalent] compare:key] ==
|
||||
NSOrderedSame) {
|
||||
if ([item isEnabled] &&
|
||||
[[item keyEquivalent] compare:key] == NSOrderedSame) {
|
||||
NSUInteger keyEquivModifiers = [item keyEquivalentModifierMask];
|
||||
|
||||
if (keyEquivModifiersMatch(keyEquivModifiers, modifiers)) {
|
||||
if (keyEquivModifiers == modifiers) {
|
||||
*target = [item target];
|
||||
*action = [item action];
|
||||
return YES;
|
||||
@@ -367,10 +388,6 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
|
||||
#pragma mark TKApplication(TKMenu)
|
||||
|
||||
@interface NSApplication(TKMenu)
|
||||
- (void) setAppleMenu: (NSMenu *) menu;
|
||||
@end
|
||||
|
||||
@implementation TKApplication(TKMenu)
|
||||
|
||||
- (void) menuBeginTracking: (NSNotification *) notification
|
||||
@@ -611,6 +628,10 @@ TkpConfigureMenuEntry(
|
||||
&imageHeight);
|
||||
image = TkMacOSXGetNSImageWithBitmap(mePtr->menuPtr->display, bitmap,
|
||||
gc, imageWidth, imageHeight);
|
||||
if (gc->foreground == defaultFg) {
|
||||
// Use a semantic foreground color by default
|
||||
[image setTemplate:YES];
|
||||
}
|
||||
}
|
||||
[menuItem setImage:image];
|
||||
if ((!image || mePtr->compound != COMPOUND_NONE) && mePtr->labelPtr &&
|
||||
@@ -633,7 +654,7 @@ TkpConfigureMenuEntry(
|
||||
gc->foreground!=defaultFg? gc->foreground:gc->background);
|
||||
|
||||
attributes = [[attributes mutableCopy] autorelease];
|
||||
[(NSMutableDictionary *)attributes setObject:color
|
||||
[(NSMutableDictionary *) attributes setObject:color
|
||||
forKey:NSForegroundColorAttributeName];
|
||||
}
|
||||
if (attributes) {
|
||||
@@ -673,21 +694,31 @@ TkpConfigureMenuEntry(
|
||||
[submenu setTitle:title];
|
||||
|
||||
if ([menuItem isEnabled]) {
|
||||
/* This menuItem might have been previously disabled (XXX:
|
||||
track this), which would have disabled entries; we must
|
||||
re-enable the entries here. */
|
||||
int i = 0;
|
||||
NSArray *itemArray = [submenu itemArray];
|
||||
for (NSMenuItem *item in itemArray) {
|
||||
TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
|
||||
/* Work around an apparent bug where itemArray can have
|
||||
more items than the menu's entries[] array. */
|
||||
if (i >= menuRefPtr->menuPtr->numEntries) break;
|
||||
[item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This menuItem might have been previously disabled (XXX:
|
||||
* track this), which would have disabled entries; we must
|
||||
* re-enable the entries here.
|
||||
*/
|
||||
|
||||
int i = 0;
|
||||
NSArray *itemArray = [submenu itemArray];
|
||||
|
||||
for (NSMenuItem *item in itemArray) {
|
||||
TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
|
||||
|
||||
/*
|
||||
* Work around an apparent bug where itemArray can have
|
||||
* more items than the menu's entries[] array.
|
||||
*/
|
||||
|
||||
if (i >= (int) menuRefPtr->menuPtr->numEntries) {
|
||||
break;
|
||||
}
|
||||
[item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -738,10 +769,13 @@ TkpDestroyMenuEntry(
|
||||
*
|
||||
* TkpPostMenu --
|
||||
*
|
||||
* Posts a menu on the screen
|
||||
* Posts a menu on the screen. If entry is < 0 then the menu is drawn so
|
||||
* its top left corner is located at the point with screen coordinates
|
||||
* (x,y). Otherwise the top left corner of the specified entry is located
|
||||
* at that point.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
* Returns a standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* The menu is posted and handled.
|
||||
@@ -753,54 +787,174 @@ int
|
||||
TkpPostMenu(
|
||||
Tcl_Interp *interp, /* The interpreter this menu lives in */
|
||||
TkMenu *menuPtr, /* The menu we are posting */
|
||||
int x, /* The global x-coordinate of the top, left-
|
||||
* hand corner of where the menu is supposed
|
||||
* to be posted. */
|
||||
int y) /* The global y-coordinate */
|
||||
int x, int y, /* The screen coordinates where the top left
|
||||
* corner of the menu, or of the specified
|
||||
* entry, will be located. */
|
||||
int index)
|
||||
{
|
||||
|
||||
|
||||
/* Get the object that holds this Tk Window.*/
|
||||
Tk_Window root;
|
||||
root = Tk_MainWindow(interp);
|
||||
if (root == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Drawable d = Tk_WindowId(root);
|
||||
NSView *rootview = TkMacOSXGetRootControl(d);
|
||||
NSWindow *win = [rootview window];
|
||||
int result;
|
||||
Tk_Window realWin = menuPtr->tkwin;
|
||||
TkWindow *realWinPtr;
|
||||
NSView *realWinView;
|
||||
|
||||
while (1) {
|
||||
if (realWin == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*
|
||||
* Fix for bug 07cfc9f03e: use the view for the parent real (non-menu)
|
||||
* toplevel window, rather than always using the root window.
|
||||
* This allows menus to appear on a separate monitor than the root
|
||||
* window, and to use the appearance of their parent real window
|
||||
* rather than the appearance of the root window.
|
||||
*/
|
||||
realWinPtr = (TkWindow*) realWin;
|
||||
realWinView = TkMacOSXDrawableView(realWinPtr->privatePtr);
|
||||
if (realWinView != nil) {
|
||||
break;
|
||||
}
|
||||
realWin = Tk_Parent(realWin);
|
||||
}
|
||||
NSWindow *win = [realWinView window];
|
||||
NSView *view = [win contentView];
|
||||
NSMenu *menu = (NSMenu *) menuPtr->platformData;
|
||||
NSInteger itemIndex = index;
|
||||
NSInteger numItems = [menu numberOfItems];
|
||||
NSMenuItem *item = nil;
|
||||
NSPoint location = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);
|
||||
|
||||
inPostMenu = 1;
|
||||
|
||||
result = TkPreprocessMenu(menuPtr);
|
||||
if (result != TCL_OK) {
|
||||
inPostMenu = 0;
|
||||
return result;
|
||||
}
|
||||
if (itemIndex >= numItems) {
|
||||
itemIndex = numItems - 1;
|
||||
}
|
||||
if (itemIndex >= 0) {
|
||||
item = [menu itemAtIndex:itemIndex];
|
||||
}
|
||||
|
||||
int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
|
||||
NSView *view = [win contentView];
|
||||
NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1);
|
||||
/*
|
||||
* The post commands could have deleted the menu, which means we are dead
|
||||
* and should go away.
|
||||
*/
|
||||
|
||||
frame.origin = [view convertPoint:
|
||||
[win tkConvertPointFromScreen:frame.origin] fromView:nil];
|
||||
if (menuPtr->tkwin == NULL) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
NSMenu *menu = (NSMenu *) menuPtr->platformData;
|
||||
NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc]
|
||||
initTextCell:@"" pullsDown:NO];
|
||||
|
||||
[popUpButtonCell setAltersStateOfSelectedItem:NO];
|
||||
[popUpButtonCell setMenu:menu];
|
||||
[popUpButtonCell selectItem:nil];
|
||||
[popUpButtonCell performClickWithFrame:frame inView:view];
|
||||
[popUpButtonCell release];
|
||||
Tcl_SetServiceMode(oldMode);
|
||||
[menu popUpMenuPositioningItem:item
|
||||
atLocation:[win tkConvertPointFromScreen:location]
|
||||
inView:view];
|
||||
inPostMenu = 0;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkpPostTearoffMenu --
|
||||
*
|
||||
* Tearoff menus are not supported on the Mac. This placeholder function,
|
||||
* which is simply a copy of the unix function, posts a completely useless
|
||||
* window with a black background on the screen. If entry is < 0 then the
|
||||
* window is positioned so that its top left corner is located at the
|
||||
* point with screen coordinates (x, y). Otherwise the window position is
|
||||
* offset so that top left corner of the specified entry would be located
|
||||
* at that point, if there actually were a menu.
|
||||
*
|
||||
* Mac menus steal all mouse or keyboard input from the application until
|
||||
* the menu is dismissed, with or without a selection, by a mouse or key
|
||||
* event. Posting a Mac menu in a regression test will cause the test to
|
||||
* halt waiting for user input. This is why the TkpPostMenu function is
|
||||
* not being used as the placeholder.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* A useless window is posted.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TkpPostTearoffMenu(
|
||||
Tcl_Interp *interp, /* The interpreter this menu lives in */
|
||||
TkMenu *menuPtr, /* The menu we are posting */
|
||||
int x, int y, int index) /* The screen coordinates where the top left
|
||||
* corner of the menu, or of the specified
|
||||
* entry, will be located. */
|
||||
{
|
||||
int vRootX, vRootY, vRootWidth, vRootHeight;
|
||||
int result;
|
||||
|
||||
if (index >= (int) menuPtr->numEntries) {
|
||||
index = menuPtr->numEntries - 1;
|
||||
}
|
||||
if (index >= 0) {
|
||||
y -= menuPtr->entries[index]->y;
|
||||
}
|
||||
|
||||
TkActivateMenuEntry(menuPtr, -1);
|
||||
TkRecomputeMenu(menuPtr);
|
||||
result = TkPostCommand(menuPtr);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* The post commands could have deleted the menu, which means we are dead
|
||||
* and should go away.
|
||||
*/
|
||||
|
||||
if (menuPtr->tkwin == NULL) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust the position of the menu if necessary to keep it visible on the
|
||||
* screen. There are two special tricks to make this work right:
|
||||
*
|
||||
* 1. If a virtual root window manager is being used then the coordinates
|
||||
* are in the virtual root window of menuPtr's parent; since the menu
|
||||
* uses override-redirect mode it will be in the *real* root window for
|
||||
* the screen, so we have to map the coordinates from the virtual root
|
||||
* (if any) to the real root. Can't get the virtual root from the menu
|
||||
* itself (it will never be seen by the wm) so use its parent instead
|
||||
* (it would be better to have an an option that names a window to use
|
||||
* for this...).
|
||||
* 2. The menu may not have been mapped yet, so its current size might be
|
||||
* the default 1x1. To compute how much space it needs, use its
|
||||
* requested size, not its actual size.
|
||||
*/
|
||||
|
||||
Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
|
||||
&vRootWidth, &vRootHeight);
|
||||
vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
|
||||
if (x > vRootX + vRootWidth) {
|
||||
x = vRootX + vRootWidth;
|
||||
}
|
||||
if (x < vRootX) {
|
||||
x = vRootX;
|
||||
}
|
||||
vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
|
||||
if (y > vRootY + vRootHeight) {
|
||||
y = vRootY + vRootHeight;
|
||||
}
|
||||
if (y < vRootY) {
|
||||
y = vRootY;
|
||||
}
|
||||
Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
|
||||
if (!Tk_IsMapped(menuPtr->tkwin)) {
|
||||
Tk_MapWindow(menuPtr->tkwin);
|
||||
}
|
||||
TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -835,12 +989,12 @@ TkpSetWindowMenuBar(
|
||||
*
|
||||
* TkpSetMainMenubar --
|
||||
*
|
||||
* Puts the menu associated with a window into the menubar. Should only
|
||||
* be called when the window is in front.
|
||||
* Puts the menu associated with a window into the menubar. Should only be
|
||||
* called when the window is in front.
|
||||
*
|
||||
* This is a no-op on all other platforms. On OS X it is a no-op when
|
||||
* passed a NULL menuName or a nonexistent menuName, with an exception
|
||||
* for the first call in a new interpreter. In that special case, passing a
|
||||
* passed a NULL menuName or a nonexistent menuName, with an exception for
|
||||
* the first call in a new interpreter. In that special case, passing a
|
||||
* NULL menuName installs the default menu.
|
||||
*
|
||||
* Results:
|
||||
@@ -860,15 +1014,32 @@ TkpSetMainMenubar(
|
||||
{
|
||||
static Tcl_Interp *currentInterp = NULL;
|
||||
TKMenu *menu = nil;
|
||||
TkWindow *winPtr = (TkWindow *) tkwin;
|
||||
|
||||
/*
|
||||
* We will be called when an embedded window receives an ActivationNotify
|
||||
* event, but we should not change the menubar in that case.
|
||||
*/
|
||||
|
||||
if (Tk_IsEmbedded(winPtr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (menuName) {
|
||||
TkWindow *winPtr = (TkWindow *) tkwin;
|
||||
Tk_Window menubar = NULL;
|
||||
|
||||
if (winPtr->wmInfoPtr && winPtr->wmInfoPtr->menuPtr &&
|
||||
winPtr->wmInfoPtr->menuPtr->masterMenuPtr &&
|
||||
winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin &&
|
||||
!strcmp(menuName, Tk_PathName(
|
||||
winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin))) {
|
||||
if (winPtr->wmInfoPtr &&
|
||||
winPtr->wmInfoPtr->menuPtr &&
|
||||
winPtr->wmInfoPtr->menuPtr->masterMenuPtr) {
|
||||
menubar = winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to find the NSMenu directly. If that fails, ask Tk to find
|
||||
* it.
|
||||
*/
|
||||
|
||||
if (menubar != NULL && strcmp(menuName, Tk_PathName(menubar)) == 0) {
|
||||
menu = (TKMenu *) winPtr->wmInfoPtr->menuPtr->platformData;
|
||||
} else {
|
||||
TkMenuReferences *menuRefPtr = TkFindMenuReferences(interp,
|
||||
@@ -880,6 +1051,12 @@ TkpSetMainMenubar(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we couldn't find a menu, do nothing unless the window belongs to a
|
||||
* different application. In that case, install the default menubar.
|
||||
*/
|
||||
|
||||
if (menu || interp != currentInterp) {
|
||||
[NSApp tkSetMainMenu:menu];
|
||||
}
|
||||
@@ -892,8 +1069,8 @@ TkpSetMainMenubar(
|
||||
* CheckForSpecialMenu --
|
||||
*
|
||||
* Given a menu, check to see whether or not it is a cascade in a menubar
|
||||
* with one of the special names .apple, .help or .window If it is, the
|
||||
* entry that points to this menu will be marked.
|
||||
* with one of the special names ".apple", ".help" or ".window". If it is,
|
||||
* the entry that points to this menu will be marked.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -1070,26 +1247,32 @@ void
|
||||
TkpComputeStandardMenuGeometry(
|
||||
TkMenu *menuPtr) /* Structure describing menu. */
|
||||
{
|
||||
NSSize menuSize;
|
||||
Tk_Font tkfont, menuFont;
|
||||
Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
|
||||
int modifierCharWidth, menuModifierCharWidth;
|
||||
int x, y, modifierWidth, labelWidth, indicatorSpace;
|
||||
int windowWidth, windowHeight, accelWidth;
|
||||
int i, j, lastColumnBreak, maxWidth;
|
||||
int i, maxWidth;
|
||||
int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
|
||||
TkMenuEntry *mePtr, *columnEntryPtr;
|
||||
TkMenuEntry *mePtr;
|
||||
int haveAccel = 0;
|
||||
|
||||
if (menuPtr->tkwin == NULL) {
|
||||
/*
|
||||
* Do nothing if this menu is a clone.
|
||||
*/
|
||||
|
||||
if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) {
|
||||
return;
|
||||
}
|
||||
|
||||
menuSize = [(NSMenu *) menuPtr->platformData size];
|
||||
Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
|
||||
&borderWidth);
|
||||
Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
|
||||
&activeBorderWidth);
|
||||
x = y = borderWidth;
|
||||
windowHeight = maxWidth = lastColumnBreak = 0;
|
||||
windowHeight = maxWidth = 0;
|
||||
maxIndicatorSpace = 0;
|
||||
|
||||
/*
|
||||
@@ -1097,16 +1280,16 @@ TkpComputeStandardMenuGeometry(
|
||||
* want to do it intelligently. We are going to precalculate them and pass
|
||||
* them down to all of the measuring and drawing routines. We will measure
|
||||
* the font metrics of the menu once. If an entry does not have its own
|
||||
* font set, then we give the geometry/drawing routines the menu's font
|
||||
* and metrics. If an entry has its own font, we will measure that font
|
||||
* and give all of the geometry/drawing the entry's font and metrics.
|
||||
* font set, then we give the geometry/drawing routines the menu's font and
|
||||
* metrics. If an entry has its own font, we will measure that font and
|
||||
* give all of the geometry/drawing the entry's font and metrics.
|
||||
*/
|
||||
|
||||
menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
|
||||
Tk_GetFontMetrics(menuFont, &menuMetrics);
|
||||
menuModifierCharWidth = ModifierCharWidth(menuFont);
|
||||
|
||||
for (i = 0; i < menuPtr->numEntries; i++) {
|
||||
for (i = 0; i < (int) menuPtr->numEntries; i++) {
|
||||
mePtr = menuPtr->entries[i];
|
||||
if (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) {
|
||||
haveAccel = 1;
|
||||
@@ -1114,8 +1297,11 @@ TkpComputeStandardMenuGeometry(
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < menuPtr->numEntries; i++) {
|
||||
for (i = 0; i < (int) menuPtr->numEntries; i++) {
|
||||
mePtr = menuPtr->entries[i];
|
||||
if (mePtr->type == TEAROFF_ENTRY) {
|
||||
continue;
|
||||
}
|
||||
if (mePtr->fontPtr == NULL) {
|
||||
tkfont = menuFont;
|
||||
fmPtr = &menuMetrics;
|
||||
@@ -1126,26 +1312,8 @@ TkpComputeStandardMenuGeometry(
|
||||
fmPtr = &entryMetrics;
|
||||
modifierCharWidth = ModifierCharWidth(tkfont);
|
||||
}
|
||||
|
||||
if ((i > 0) && mePtr->columnBreak) {
|
||||
if (maxIndicatorSpace != 0) {
|
||||
maxIndicatorSpace += 2;
|
||||
}
|
||||
for (j = lastColumnBreak; j < i; j++) {
|
||||
columnEntryPtr = menuPtr->entries[j];
|
||||
columnEntryPtr->indicatorSpace = maxIndicatorSpace;
|
||||
columnEntryPtr->width = maxIndicatorSpace + maxWidth
|
||||
+ 2 * activeBorderWidth;
|
||||
columnEntryPtr->x = x;
|
||||
columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
|
||||
}
|
||||
x += maxIndicatorSpace + maxWidth + 2 * activeBorderWidth;
|
||||
maxWidth = maxIndicatorSpace = 0;
|
||||
lastColumnBreak = i;
|
||||
y = borderWidth;
|
||||
}
|
||||
accelWidth = modifierWidth = indicatorSpace = 0;
|
||||
if (mePtr->type == SEPARATOR_ENTRY || mePtr->type == TEAROFF_ENTRY) {
|
||||
if (mePtr->type == SEPARATOR_ENTRY) {
|
||||
mePtr->height = menuSeparatorHeight;
|
||||
} else {
|
||||
/*
|
||||
@@ -1163,12 +1331,14 @@ TkpComputeStandardMenuGeometry(
|
||||
if (mePtr->image) {
|
||||
Tk_SizeOfImage(mePtr->image, &width, &height);
|
||||
haveImage = 1;
|
||||
height += 2; /* tweak */
|
||||
} else if (mePtr->bitmapPtr) {
|
||||
Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin,
|
||||
mePtr->bitmapPtr);
|
||||
|
||||
Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
|
||||
haveImage = 1;
|
||||
height += 2; /* tweak */
|
||||
}
|
||||
if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
|
||||
NSAttributedString *attrTitle = [menuItem attributedTitle];
|
||||
@@ -1180,11 +1350,8 @@ TkpComputeStandardMenuGeometry(
|
||||
size = [[menuItem title] sizeWithAttributes:
|
||||
TkMacOSXNSFontAttributesForFont(tkfont)];
|
||||
}
|
||||
size.width += menuTextLeadingEdgeMargin +
|
||||
menuTextTrailingEdgeMargin;
|
||||
if (size.height < fmPtr->linespace) {
|
||||
size.height = fmPtr->linespace;
|
||||
}
|
||||
size.width += menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;
|
||||
size.height -= 1; /* tweak */
|
||||
if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
|
||||
int margin = width + menuIconTrailingEdgeMargin;
|
||||
|
||||
@@ -1200,9 +1367,11 @@ TkpComputeStandardMenuGeometry(
|
||||
height = size.height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* image only. */
|
||||
}
|
||||
labelWidth = width + menuItemExtraWidth;
|
||||
mePtr->height = height + menuItemExtraHeight;
|
||||
|
||||
if (mePtr->type == CASCADE_ENTRY) {
|
||||
modifierWidth = modifierCharWidth;
|
||||
} else if (mePtr->accelLength == 0) {
|
||||
@@ -1233,30 +1402,18 @@ TkpComputeStandardMenuGeometry(
|
||||
if (entryWidth > maxWidth) {
|
||||
maxWidth = entryWidth;
|
||||
}
|
||||
menuPtr->entries[i]->width = entryWidth;
|
||||
mePtr->height += 2 * activeBorderWidth;
|
||||
}
|
||||
mePtr->x = x;
|
||||
mePtr->y = y;
|
||||
y += menuPtr->entries[i]->height + borderWidth;
|
||||
if (y > windowHeight) {
|
||||
windowHeight = y;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
|
||||
columnEntryPtr = menuPtr->entries[j];
|
||||
columnEntryPtr->indicatorSpace = maxIndicatorSpace;
|
||||
columnEntryPtr->width = maxIndicatorSpace + maxWidth
|
||||
+ 2 * activeBorderWidth;
|
||||
columnEntryPtr->x = x;
|
||||
columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN;
|
||||
}
|
||||
windowWidth = x + maxIndicatorSpace + maxWidth
|
||||
+ 2 * activeBorderWidth + borderWidth;
|
||||
windowHeight += borderWidth;
|
||||
|
||||
windowWidth = menuSize.width;
|
||||
if (windowWidth <= 0) {
|
||||
windowWidth = 1;
|
||||
}
|
||||
windowHeight = menuSize.height;
|
||||
if (windowHeight <= 0) {
|
||||
windowHeight = 1;
|
||||
}
|
||||
@@ -1290,7 +1447,7 @@ GenerateMenuSelectEvent(
|
||||
if (menuPtr) {
|
||||
int index = [menu tkIndexOfItem:menuItem];
|
||||
|
||||
if (index < 0 || index >= menuPtr->numEntries ||
|
||||
if (index < 0 || index >= (int) menuPtr->numEntries ||
|
||||
(menuPtr->entries[index])->state == ENTRY_DISABLED) {
|
||||
TkActivateMenuEntry(menuPtr, -1);
|
||||
} else {
|
||||
@@ -1369,7 +1526,7 @@ RecursivelyClearActiveMenu(
|
||||
int i;
|
||||
|
||||
TkActivateMenuEntry(menuPtr, -1);
|
||||
for (i = 0; i < menuPtr->numEntries; i++) {
|
||||
for (i = 0; i < (int) menuPtr->numEntries; i++) {
|
||||
TkMenuEntry *mePtr = menuPtr->entries[i];
|
||||
|
||||
if (mePtr->type == CASCADE_ENTRY
|
||||
@@ -1404,7 +1561,10 @@ TkMacOSXClearMenubarActive(void)
|
||||
if (mainMenu && [mainMenu isKindOfClass:[TKMenu class]]) {
|
||||
TkMenu *menuPtr = [(TKMenu *) mainMenu tkMenu];
|
||||
|
||||
if (menuPtr && menuPtr->numEntries && menuPtr->entries) {
|
||||
if (menuPtr &&
|
||||
!(menuPtr->menuFlags & MENU_DELETION_PENDING) &&
|
||||
menuPtr->numEntries > 0 &&
|
||||
menuPtr->entries != NULL) {
|
||||
RecursivelyClearActiveMenu(menuPtr);
|
||||
}
|
||||
}
|
||||
@@ -1464,10 +1624,10 @@ TkpMenuInit(void)
|
||||
#undef observe
|
||||
|
||||
[NSMenuItem setUsesUserKeyEquivalents:NO];
|
||||
tkColPtr = TkpGetColor(None, DEF_MENU_BG_COLOR);
|
||||
tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);
|
||||
defaultBg = tkColPtr->color.pixel;
|
||||
ckfree(tkColPtr);
|
||||
tkColPtr = TkpGetColor(None, DEF_MENU_FG);
|
||||
tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);
|
||||
defaultFg = tkColPtr->color.pixel;
|
||||
ckfree(tkColPtr);
|
||||
|
||||
@@ -1658,7 +1818,7 @@ TkMacOSXPreprocessMenu(void)
|
||||
* TkMacOSXUseID --
|
||||
*
|
||||
* Take the ID out of the available list for new menus. Used by the
|
||||
* default menu bar's menus so that they do not get created at the tk
|
||||
* default menu bar's menus so that they do not get created at the Tk
|
||||
* level. See TkMacOSXGetNewMenuID for more information.
|
||||
*
|
||||
* Results:
|
||||
@@ -1683,8 +1843,7 @@ TkMacOSXUseMenuID(
|
||||
*
|
||||
* TkMacOSXDispatchMenuEvent --
|
||||
*
|
||||
* Given a menu id and an item, dispatches the command associated with
|
||||
* it.
|
||||
* Given a menu id and an item, dispatches the command associated with it.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -1734,9 +1893,10 @@ TkMacOSXHandleTearoffMenu(void)
|
||||
*
|
||||
* TkMacOSXSetHelpMenuItemCount --
|
||||
*
|
||||
* Has to be called after the first call to InsertMenu. Sets up the
|
||||
* global variable for the number of items in the unmodified help menu.
|
||||
* NB. Nobody uses this any more, since you can get the number of system
|
||||
* Has to be called after the first call to InsertMenu. Sets up the global
|
||||
* variable for the number of items in the unmodified help menu.
|
||||
*
|
||||
* NB: Nobody uses this any more, since you can get the number of system
|
||||
* help items from HMGetHelpMenu trivially. But it is in the stubs
|
||||
* table...
|
||||
*
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* tkMacOSXMenubutton.c --
|
||||
*
|
||||
* This file implements the Macintosh specific portion of the
|
||||
* menubutton widget.
|
||||
* This file implements the Macintosh specific portion of the menubutton
|
||||
* widget.
|
||||
*
|
||||
* Copyright (c) 1996 by Sun Microsystems, Inc.
|
||||
* Copyright 2001, Apple Computer, Inc.
|
||||
@@ -32,7 +32,6 @@ typedef struct {
|
||||
int hasImageOrBitmap;
|
||||
} DrawParams;
|
||||
|
||||
|
||||
/*
|
||||
* Declaration of Mac specific button structure.
|
||||
*/
|
||||
@@ -47,18 +46,27 @@ typedef struct MacMenuButton {
|
||||
} MacMenuButton;
|
||||
|
||||
/*
|
||||
* Forward declarations for procedures defined later in this file:
|
||||
* Forward declarations for static functions defined later in this file:
|
||||
*/
|
||||
|
||||
static void MenuButtonEventProc(ClientData clientData, XEvent *eventPtr);
|
||||
static void MenuButtonBackgroundDrawCB ( MacMenuButton *ptr, SInt16 depth, Boolean isColorDev);
|
||||
static void MenuButtonContentDrawCB ( ThemeButtonKind kind, const HIThemeButtonDrawInfo * info, MacMenuButton *ptr, SInt16 depth, Boolean isColorDev);
|
||||
static void MenuButtonEventProc ( ClientData clientData, XEvent *eventPtr);
|
||||
static void TkMacOSXComputeMenuButtonParams (TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo* drawinfo);
|
||||
static int TkMacOSXComputeMenuButtonDrawParams (TkMenuButton * butPtr, DrawParams * dpPtr);
|
||||
static void TkMacOSXDrawMenuButton (MacMenuButton *butPtr,
|
||||
GC gc, Pixmap pixmap);
|
||||
static void DrawMenuButtonImageAndText(TkMenuButton* butPtr);
|
||||
static void MenuButtonEventProc(ClientData clientData,
|
||||
XEvent *eventPtr);
|
||||
static void MenuButtonBackgroundDrawCB(MacMenuButton *ptr,
|
||||
SInt16 depth, Boolean isColorDev);
|
||||
static void MenuButtonContentDrawCB(ThemeButtonKind kind,
|
||||
const HIThemeButtonDrawInfo *info,
|
||||
MacMenuButton *ptr, SInt16 depth,
|
||||
Boolean isColorDev);
|
||||
static void MenuButtonEventProc(ClientData clientData,
|
||||
XEvent *eventPtr);
|
||||
static void TkMacOSXComputeMenuButtonParams(TkMenuButton *butPtr,
|
||||
ThemeButtonKind *btnkind,
|
||||
HIThemeButtonDrawInfo *drawinfo);
|
||||
static void TkMacOSXComputeMenuButtonDrawParams(
|
||||
TkMenuButton *butPtr, DrawParams *dpPtr);
|
||||
static void TkMacOSXDrawMenuButton(MacMenuButton *butPtr, GC gc,
|
||||
Pixmap pixmap);
|
||||
static void DrawMenuButtonImageAndText(TkMenuButton *butPtr);
|
||||
|
||||
/*
|
||||
* The structure below defines menubutton class behavior by means of
|
||||
@@ -70,11 +78,45 @@ Tk_ClassProcs tkpMenubuttonClass = {
|
||||
TkMenuButtonWorldChanged, /* worldChangedProc */
|
||||
};
|
||||
|
||||
/*
|
||||
* We use Apple's Pop-Up Button widget to represent the Tk Menubutton.
|
||||
* However, we do not use the NSPopUpButton class for this control. Instead we
|
||||
* render the Pop-Up Button using the HITheme library. This imposes some
|
||||
* constraints on what can be done. The HITheme renderer allows only specific
|
||||
* dimensions for the button.
|
||||
*
|
||||
* The HITheme library allows drawing a Pop-Up Button with an arbitrary bounds
|
||||
* rectangle. However the button is always drawn as a rounded box which is 22
|
||||
* pixels high. If the bounds rectangle is less than 22 pixels high, the
|
||||
* button is drawn at the top of the rectangle and the bottom of the button is
|
||||
* clipped away. So we set a minimum height of 22 pixels for a Menubutton. If
|
||||
* the bounds rectangle is more than 22 pixels high, then the button is drawn
|
||||
* centered vertically in the bounds rectangle.
|
||||
*
|
||||
* The content rectangle of the button is inset by 14 pixels on the left and 28
|
||||
* pixels on the right. The rightmost part of the button contains the blue
|
||||
* double-arrow symbol which is 28 pixels wide.
|
||||
*
|
||||
* To maintain compatibility with code that runs on multiple operating systems,
|
||||
* the width and height of the content rectangle includes the borderWidth, the
|
||||
* highlightWidth and the padX and padY dimensions of the Menubutton. However,
|
||||
* to be consistent with the standard Apple appearance, the content is always
|
||||
* be drawn at the left side of the content rectangle. All of the excess space
|
||||
* appears on the right side of the content, and the anchor property is
|
||||
* ignored. The easiest way to comply with Apple's Human Interface Guidelines
|
||||
* would be to set bd = highlightthickness = padx = 0 and to specify an
|
||||
* explicit width for the button. Apple also recommends using the same width
|
||||
* for all Pop-Up Buttons in a given window.
|
||||
*/
|
||||
|
||||
#define LEFT_INSET 8
|
||||
#define RIGHT_INSET 28
|
||||
#define MIN_HEIGHT 22
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkpCreateMenuButton --
|
||||
* TkpCreateMenuButton --
|
||||
*
|
||||
* Allocate a new TkMenuButton structure.
|
||||
*
|
||||
@@ -93,13 +135,11 @@ TkpCreateMenuButton(
|
||||
{
|
||||
MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton));
|
||||
|
||||
Tk_CreateEventHandler(tkwin, ActivateMask,
|
||||
MenuButtonEventProc, (ClientData) mbPtr);
|
||||
Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc, mbPtr);
|
||||
mbPtr->flags = FIRST_DRAW;
|
||||
mbPtr->btnkind = kThemePopupButton;
|
||||
bzero(&mbPtr->drawinfo, sizeof(mbPtr->drawinfo));
|
||||
bzero(&mbPtr->lastdrawinfo, sizeof(mbPtr->lastdrawinfo));
|
||||
|
||||
return (TkMenuButton *) mbPtr;
|
||||
}
|
||||
|
||||
@@ -114,8 +154,7 @@ TkpCreateMenuButton(
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Commands are output to X to display the menubutton in its
|
||||
* current mode.
|
||||
* Commands are output to X to display the menubutton in its current mode.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -124,11 +163,11 @@ void
|
||||
TkpDisplayMenuButton(
|
||||
ClientData clientData) /* Information about widget. */
|
||||
{
|
||||
MacMenuButton *mbPtr = (MacMenuButton *)clientData;
|
||||
TkMenuButton *butPtr = (TkMenuButton *) clientData;
|
||||
Tk_Window tkwin = butPtr->tkwin;
|
||||
MacMenuButton *mbPtr = clientData;
|
||||
TkMenuButton *butPtr = clientData;
|
||||
Tk_Window tkwin = butPtr->tkwin;
|
||||
Pixmap pixmap;
|
||||
DrawParams* dpPtr = &mbPtr->drawParams;
|
||||
DrawParams *dpPtr = &mbPtr->drawParams;
|
||||
|
||||
butPtr->flags &= ~REDRAW_PENDING;
|
||||
if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
|
||||
@@ -140,22 +179,27 @@ TkpDisplayMenuButton(
|
||||
TkMacOSXComputeMenuButtonDrawParams(butPtr, dpPtr);
|
||||
|
||||
/*
|
||||
* set up clipping region. Make sure the we are using the port
|
||||
* for this button, or we will set the wrong window's clip.
|
||||
* Set up clipping region. Make sure the we are using the port for this
|
||||
* button, or we will set the wrong window's clip.
|
||||
*/
|
||||
|
||||
TkMacOSXSetUpClippingRgn(pixmap);
|
||||
|
||||
/* Draw the native portion of the buttons. */
|
||||
/*
|
||||
* Draw the native portion of the buttons.
|
||||
*/
|
||||
|
||||
TkMacOSXDrawMenuButton(mbPtr, dpPtr->gc, pixmap);
|
||||
|
||||
/* Draw highlight border, if needed. */
|
||||
/*
|
||||
* Draw highlight border, if needed.
|
||||
*/
|
||||
|
||||
if (butPtr->highlightWidth < 3) {
|
||||
if ((butPtr->flags & GOT_FOCUS)) {
|
||||
Tk_Draw3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,
|
||||
Tk_Width(tkwin), Tk_Height(tkwin),
|
||||
butPtr->highlightWidth, TK_RELIEF_SOLID);
|
||||
}
|
||||
if (butPtr->flags & GOT_FOCUS) {
|
||||
GC gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);
|
||||
TkMacOSXDrawSolidBorder(tkwin, gc, 0, butPtr->highlightWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,13 +208,14 @@ TkpDisplayMenuButton(
|
||||
*
|
||||
* TkpDestroyMenuButton --
|
||||
*
|
||||
* Free data structures associated with the menubutton control.
|
||||
* Free data structures associated with the menubutton control. This is a
|
||||
* no-op on the Mac.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Restores the default control state.
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -204,15 +249,12 @@ TkpComputeMenuButtonGeometry(butPtr)
|
||||
register TkMenuButton *butPtr; /* Widget record for menu button. */
|
||||
{
|
||||
int width, height, avgWidth, haveImage = 0, haveText = 0;
|
||||
MacMenuButton *mbPtr = (MacMenuButton*)butPtr;
|
||||
int txtWidth, txtHeight;
|
||||
Tk_FontMetrics fm;
|
||||
DrawParams drawParams;
|
||||
int paddingx = 0;
|
||||
int paddingy = 0;
|
||||
int highlightWidth = butPtr->highlightWidth > 0 ? butPtr->highlightWidth : 0;
|
||||
|
||||
/*
|
||||
* First figure out the size of the contents of the button.
|
||||
* First compute the size of the contents of the button.
|
||||
*/
|
||||
|
||||
width = 0;
|
||||
@@ -221,8 +263,6 @@ TkpComputeMenuButtonGeometry(butPtr)
|
||||
txtHeight = 0;
|
||||
avgWidth = 0;
|
||||
|
||||
TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
|
||||
|
||||
if (butPtr->image != NULL) {
|
||||
Tk_SizeOfImage(butPtr->image, &width, &height);
|
||||
haveImage = 1;
|
||||
@@ -231,58 +271,55 @@ TkpComputeMenuButtonGeometry(butPtr)
|
||||
haveImage = 1;
|
||||
}
|
||||
|
||||
if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) {
|
||||
if (butPtr->text && strlen(butPtr->text) > 0) {
|
||||
haveText = 1;
|
||||
Tk_FreeTextLayout(butPtr->textLayout);
|
||||
butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
|
||||
butPtr->text, -1, butPtr->wrapLength,
|
||||
butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
|
||||
|
||||
txtWidth = butPtr->textWidth;
|
||||
txtHeight = butPtr->textHeight;
|
||||
avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
|
||||
Tk_GetFontMetrics(butPtr->tkfont, &fm);
|
||||
haveText = (txtWidth != 0 && txtHeight != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the button is compound (ie, it shows both an image and text),
|
||||
* the new geometry is a combination of the image and text geometry.
|
||||
* We only honor the compound bit if the button has both text and an
|
||||
* image, because otherwise it is not really a compound button.
|
||||
* If the button is compound (ie, it shows both an image and text), the new
|
||||
* geometry is a combination of the image and text geometry. We only honor
|
||||
* the compound bit if the button has both text and an image, because
|
||||
* otherwise it is not really a compound button.
|
||||
*/
|
||||
|
||||
if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
|
||||
if (haveImage && haveText) {
|
||||
switch ((enum compound) butPtr->compound) {
|
||||
case COMPOUND_TOP:
|
||||
case COMPOUND_BOTTOM: {
|
||||
/*
|
||||
* Image is above or below text
|
||||
*/
|
||||
case COMPOUND_TOP:
|
||||
case COMPOUND_BOTTOM:
|
||||
/*
|
||||
* Image is above or below text
|
||||
*/
|
||||
|
||||
height += txtHeight + butPtr->padY;
|
||||
width = (width > txtWidth ? width : txtWidth);
|
||||
break;
|
||||
}
|
||||
case COMPOUND_LEFT:
|
||||
case COMPOUND_RIGHT: {
|
||||
/*
|
||||
* Image is left or right of text
|
||||
*/
|
||||
height += txtHeight + butPtr->padY;
|
||||
width = (width > txtWidth ? width : txtWidth);
|
||||
break;
|
||||
case COMPOUND_LEFT:
|
||||
case COMPOUND_RIGHT:
|
||||
/*
|
||||
* Image is left or right of text
|
||||
*/
|
||||
|
||||
width += txtWidth + butPtr->padX;
|
||||
height = (height > txtHeight ? height : txtHeight);
|
||||
break;
|
||||
}
|
||||
case COMPOUND_CENTER: {
|
||||
/*
|
||||
* Image and text are superimposed
|
||||
*/
|
||||
width += txtWidth + butPtr->padX;
|
||||
height = (height > txtHeight ? height : txtHeight);
|
||||
break;
|
||||
case COMPOUND_CENTER:
|
||||
/*
|
||||
* Image and text are superimposed
|
||||
*/
|
||||
|
||||
width = (width > txtWidth ? width : txtWidth);
|
||||
height = (height > txtHeight ? height : txtHeight);
|
||||
break;
|
||||
}
|
||||
case COMPOUND_NONE: {break;}
|
||||
width = (width > txtWidth ? width : txtWidth);
|
||||
height = (height > txtHeight ? height : txtHeight);
|
||||
break;
|
||||
case COMPOUND_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
if (butPtr->width > 0) {
|
||||
@@ -293,76 +330,29 @@ TkpComputeMenuButtonGeometry(butPtr)
|
||||
}
|
||||
|
||||
} else {
|
||||
if (haveImage) {
|
||||
if (haveImage) { /* Image only */
|
||||
if (butPtr->width > 0) {
|
||||
width = butPtr->width;
|
||||
}
|
||||
if (butPtr->height > 0) {
|
||||
height = butPtr->height;
|
||||
}
|
||||
} else {
|
||||
} else { /* Text only */
|
||||
width = txtWidth;
|
||||
height = txtHeight;
|
||||
if (butPtr->width > 0) {
|
||||
width = butPtr->width * avgWidth;
|
||||
width = butPtr->width * avgWidth + 2*butPtr->padX;
|
||||
}
|
||||
if (butPtr->height > 0) {
|
||||
height = butPtr->height * fm.linespace;
|
||||
height = butPtr->height * fm.linespace + 2*butPtr->padY;
|
||||
}
|
||||
}
|
||||
}
|
||||
width += 2 * butPtr->padX - 2;
|
||||
height += 2 * butPtr->padY - 2;
|
||||
|
||||
/*Add padding for button arrows.*/
|
||||
width += 22;
|
||||
|
||||
/*
|
||||
* Now figure out the size of the border decorations for the button.
|
||||
*/
|
||||
|
||||
if (butPtr->highlightWidth < 0) {
|
||||
butPtr->highlightWidth = 0;
|
||||
}
|
||||
butPtr->inset = 0;
|
||||
butPtr->inset += butPtr->highlightWidth;
|
||||
|
||||
TkMacOSXComputeMenuButtonDrawParams(butPtr,&drawParams);
|
||||
|
||||
HIRect tmpRect;
|
||||
HIRect contBounds;
|
||||
|
||||
tmpRect = CGRectMake(0, 0, width, height);
|
||||
|
||||
HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);
|
||||
|
||||
|
||||
|
||||
/* If the content region has a minimum height, match it. */
|
||||
if (height < contBounds.size.height) {
|
||||
height = contBounds.size.height;
|
||||
}
|
||||
|
||||
/* If the content region has a minimum width, match it. */
|
||||
if (width < contBounds.size.width) {
|
||||
width = contBounds.size.width;
|
||||
}
|
||||
|
||||
/* Pad to fill difference between content bounds and button bounds. */
|
||||
paddingx = tmpRect.origin.x - contBounds.origin.x;
|
||||
paddingy = tmpRect.origin.y - contBounds.origin.y;
|
||||
|
||||
if (paddingx > 0) {
|
||||
width += paddingx;
|
||||
}
|
||||
if (paddingy > 0) {
|
||||
height += paddingy;
|
||||
}
|
||||
|
||||
width += butPtr->inset*2;
|
||||
height += butPtr->inset*2;
|
||||
|
||||
|
||||
butPtr->inset = highlightWidth + butPtr->borderWidth;
|
||||
width += LEFT_INSET + RIGHT_INSET + 2*butPtr->inset;
|
||||
height += 2*butPtr->inset;
|
||||
height = height < MIN_HEIGHT ? MIN_HEIGHT : height;
|
||||
Tk_GeometryRequest(butPtr->tkwin, width, height);
|
||||
Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
|
||||
}
|
||||
@@ -384,32 +374,24 @@ TkpComputeMenuButtonGeometry(butPtr)
|
||||
*/
|
||||
void
|
||||
DrawMenuButtonImageAndText(
|
||||
TkMenuButton* butPtr)
|
||||
TkMenuButton *butPtr)
|
||||
{
|
||||
MacMenuButton *mbPtr = (MacMenuButton*)butPtr;
|
||||
Tk_Window tkwin = butPtr->tkwin;
|
||||
Pixmap pixmap;
|
||||
int haveImage = 0;
|
||||
int haveText = 0;
|
||||
int imageWidth = 0;
|
||||
int imageHeight = 0;
|
||||
int imageXOffset = 0;
|
||||
int imageYOffset = 0;
|
||||
int textXOffset = 0;
|
||||
int textYOffset = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int fullWidth = 0;
|
||||
int fullHeight = 0;
|
||||
int pressed;
|
||||
MacMenuButton *mbPtr = (MacMenuButton *) butPtr;
|
||||
Tk_Window tkwin = butPtr->tkwin;
|
||||
Pixmap pixmap;
|
||||
int haveImage = 0, haveText = 0;
|
||||
int imageWidth = 0, imageHeight = 0;
|
||||
int imageXOffset = 0, imageYOffset = 0;
|
||||
int textXOffset = 0, textYOffset = 0;
|
||||
int width = 0, height = 0;
|
||||
int fullWidth = 0, fullHeight = 0;
|
||||
|
||||
if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DrawParams* dpPtr = &mbPtr->drawParams;
|
||||
pixmap = (Pixmap)Tk_WindowId(tkwin);
|
||||
|
||||
DrawParams *dpPtr = &mbPtr->drawParams;
|
||||
pixmap = (Pixmap) Tk_WindowId(tkwin);
|
||||
|
||||
if (butPtr->image != None) {
|
||||
Tk_SizeOfImage(butPtr->image, &width, &height);
|
||||
@@ -419,86 +401,80 @@ DrawMenuButtonImageAndText(
|
||||
haveImage = 1;
|
||||
}
|
||||
|
||||
imageWidth = width;
|
||||
imageWidth = width;
|
||||
imageHeight = height;
|
||||
|
||||
if (mbPtr->drawinfo.state == kThemeStatePressed) {
|
||||
/* Offset bitmaps by a bit when the button is pressed. */
|
||||
pressed = 1;
|
||||
}
|
||||
haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
|
||||
if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
|
||||
int x = 0, y = 0;
|
||||
|
||||
haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
|
||||
if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
textXOffset = 0;
|
||||
textYOffset = 0;
|
||||
fullWidth = 0;
|
||||
fullHeight = 0;
|
||||
|
||||
switch ((enum compound) butPtr->compound) {
|
||||
case COMPOUND_TOP:
|
||||
case COMPOUND_BOTTOM: {
|
||||
/* Image is above or below text */
|
||||
if (butPtr->compound == COMPOUND_TOP) {
|
||||
textYOffset = height + butPtr->padY;
|
||||
} else {
|
||||
imageYOffset = butPtr->textHeight + butPtr->padY;
|
||||
}
|
||||
fullHeight = height + butPtr->textHeight + butPtr->padY;
|
||||
fullWidth = (width > butPtr->textWidth ? width :
|
||||
butPtr->textWidth);
|
||||
textXOffset = (fullWidth - butPtr->textWidth)/2;
|
||||
imageXOffset = (fullWidth - width)/2;
|
||||
break;
|
||||
}
|
||||
case COMPOUND_LEFT:
|
||||
case COMPOUND_RIGHT: {
|
||||
/*
|
||||
* Image is left or right of text
|
||||
*/
|
||||
case COMPOUND_TOP:
|
||||
case COMPOUND_BOTTOM:
|
||||
/*
|
||||
* Image is above or below text.
|
||||
*/
|
||||
|
||||
if (butPtr->compound == COMPOUND_LEFT) {
|
||||
textXOffset = width + butPtr->padX - 2;
|
||||
} else {
|
||||
imageXOffset = butPtr->textWidth + butPtr->padX;
|
||||
}
|
||||
fullWidth = butPtr->textWidth + butPtr->padX + width;
|
||||
fullHeight = (height > butPtr->textHeight ? height :
|
||||
butPtr->textHeight);
|
||||
textYOffset = (fullHeight - butPtr->textHeight)/2;
|
||||
imageYOffset = (fullHeight - height)/2;
|
||||
break;
|
||||
}
|
||||
case COMPOUND_CENTER: {
|
||||
/*
|
||||
* Image and text are superimposed
|
||||
*/
|
||||
if (butPtr->compound == COMPOUND_TOP) {
|
||||
textYOffset = height + butPtr->padY;
|
||||
} else {
|
||||
imageYOffset = butPtr->textHeight + butPtr->padY;
|
||||
}
|
||||
fullHeight = height + butPtr->textHeight + butPtr->padY;
|
||||
fullWidth = (width > butPtr->textWidth ?
|
||||
width : butPtr->textWidth);
|
||||
textXOffset = (fullWidth - butPtr->textWidth)/2;
|
||||
imageXOffset = (fullWidth - width)/2;
|
||||
break;
|
||||
case COMPOUND_LEFT:
|
||||
case COMPOUND_RIGHT:
|
||||
/*
|
||||
* Image is left or right of text
|
||||
*/
|
||||
|
||||
fullWidth = (width > butPtr->textWidth ? width :
|
||||
butPtr->textWidth);
|
||||
fullHeight = (height > butPtr->textHeight ? height :
|
||||
butPtr->textHeight);
|
||||
textXOffset = (fullWidth - butPtr->textWidth)/2;
|
||||
imageXOffset = (fullWidth - width)/2;
|
||||
textYOffset = (fullHeight - butPtr->textHeight)/2;
|
||||
imageYOffset = (fullHeight - height)/2;
|
||||
break;
|
||||
}
|
||||
case COMPOUND_NONE: {break;}
|
||||
if (butPtr->compound == COMPOUND_LEFT) {
|
||||
textXOffset = width + butPtr->padX - 2;
|
||||
} else {
|
||||
imageXOffset = butPtr->textWidth + butPtr->padX;
|
||||
}
|
||||
fullWidth = butPtr->textWidth + butPtr->padX + width;
|
||||
fullHeight = (height > butPtr->textHeight ? height :
|
||||
butPtr->textHeight);
|
||||
textYOffset = (fullHeight - butPtr->textHeight)/2;
|
||||
imageYOffset = (fullHeight - height)/2;
|
||||
break;
|
||||
case COMPOUND_CENTER:
|
||||
/*
|
||||
* Image and text are superimposed
|
||||
*/
|
||||
|
||||
fullWidth = (width > butPtr->textWidth ? width : butPtr->textWidth);
|
||||
fullHeight = (height > butPtr->textHeight ? height :
|
||||
butPtr->textHeight);
|
||||
textXOffset = (fullWidth - butPtr->textWidth) / 2;
|
||||
imageXOffset = (fullWidth - width) / 2;
|
||||
textYOffset = (fullHeight - butPtr->textHeight) / 2;
|
||||
imageYOffset = (fullHeight - height) / 2;
|
||||
break;
|
||||
case COMPOUND_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
TkComputeAnchor(butPtr->anchor, tkwin,
|
||||
butPtr->padX + butPtr->borderWidth,
|
||||
butPtr->padY + butPtr->borderWidth,
|
||||
butPtr->padX + butPtr->inset, butPtr->padY + butPtr->inset,
|
||||
fullWidth, fullHeight, &x, &y);
|
||||
imageXOffset += x;
|
||||
imageXOffset = LEFT_INSET;
|
||||
imageYOffset += y;
|
||||
textYOffset -= 1;
|
||||
|
||||
if (butPtr->image != NULL) {
|
||||
Tk_RedrawImage(butPtr->image, 0, 0, width,
|
||||
height, pixmap, imageXOffset, imageYOffset);
|
||||
Tk_RedrawImage(butPtr->image, 0, 0, width,
|
||||
height, pixmap, imageXOffset, imageYOffset);
|
||||
} else {
|
||||
XSetClipOrigin(butPtr->display, dpPtr->gc,
|
||||
imageXOffset, imageYOffset);
|
||||
@@ -512,56 +488,49 @@ DrawMenuButtonImageAndText(
|
||||
dpPtr->gc, butPtr->textLayout,
|
||||
x + textXOffset, y + textYOffset, 0, -1);
|
||||
Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc,
|
||||
butPtr->textLayout,
|
||||
x + textXOffset, y + textYOffset,
|
||||
butPtr->textLayout, x + textXOffset, y + textYOffset,
|
||||
butPtr->underline);
|
||||
} else {
|
||||
int x, y;
|
||||
|
||||
if (haveImage) {
|
||||
int x = 0;
|
||||
int y;
|
||||
TkComputeAnchor(butPtr->anchor, tkwin,
|
||||
butPtr->padX + butPtr->borderWidth,
|
||||
butPtr->padY + butPtr->borderWidth,
|
||||
width, height, &x, &y);
|
||||
imageXOffset += x;
|
||||
imageYOffset += y;
|
||||
|
||||
if (butPtr->image != NULL) {
|
||||
Tk_RedrawImage(butPtr->image, 0, 0, width, height,
|
||||
pixmap, imageXOffset, imageYOffset);
|
||||
imageXOffset = LEFT_INSET;
|
||||
imageYOffset += y;
|
||||
if (butPtr->image != NULL) {
|
||||
Tk_RedrawImage(butPtr->image, 0, 0, width, height,
|
||||
pixmap, imageXOffset, imageYOffset);
|
||||
} else {
|
||||
XSetClipOrigin(butPtr->display, dpPtr->gc, x, y);
|
||||
XCopyPlane(butPtr->display, butPtr->bitmap,
|
||||
pixmap, dpPtr->gc,
|
||||
0, 0, (unsigned int) width,
|
||||
(unsigned int) height,
|
||||
imageXOffset, imageYOffset, 1);
|
||||
pixmap, dpPtr->gc,
|
||||
0, 0, (unsigned int) width,
|
||||
(unsigned int) height,
|
||||
imageXOffset, imageYOffset, 1);
|
||||
XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
|
||||
}
|
||||
} else {
|
||||
/*Move x back by eight pixels to give the menubutton arrows room.*/
|
||||
int x = 0;
|
||||
int y;
|
||||
textXOffset = 8;
|
||||
textXOffset = LEFT_INSET;
|
||||
TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
|
||||
butPtr->textWidth, butPtr->textHeight, &x, &y);
|
||||
butPtr->textWidth, butPtr->textHeight, &x, &y);
|
||||
Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc,
|
||||
butPtr->textLayout, x - textXOffset, y, 0, -1);
|
||||
butPtr->textLayout, textXOffset, y, 0, -1);
|
||||
y += butPtr->textHeight/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
*
|
||||
* TkMacOSXDrawMenuButton --
|
||||
*
|
||||
* This function draws the tk menubutton using Mac controls
|
||||
* In addition, this code may apply custom colors passed
|
||||
* in the TkMenubutton.
|
||||
* This function draws the tk menubutton using Mac controls. In
|
||||
* addition, this code may apply custom colors passed in the
|
||||
* TkMenubutton.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -571,45 +540,39 @@ DrawMenuButtonImageAndText(
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
TkMacOSXDrawMenuButton(
|
||||
MacMenuButton *mbPtr, /* Mac menubutton. */
|
||||
GC gc, /* The GC we are drawing into - needed for
|
||||
* the bevel button */
|
||||
Pixmap pixmap) /* The pixmap we are drawing into - needed
|
||||
* for the bevel button */
|
||||
|
||||
GC gc, /* The GC we are drawing into - needed for the bevel
|
||||
* button */
|
||||
Pixmap pixmap) /* The pixmap we are drawing into - needed for the
|
||||
* bevel button */
|
||||
{
|
||||
TkMenuButton * butPtr = ( TkMenuButton *)mbPtr;
|
||||
TkWindow * winPtr;
|
||||
HIRect cntrRect;
|
||||
TkMenuButton *butPtr = (TkMenuButton *) mbPtr;
|
||||
TkWindow *winPtr = (TkWindow *) butPtr->tkwin;
|
||||
HIRect cntrRect;
|
||||
TkMacOSXDrawingContext dc;
|
||||
DrawParams* dpPtr = &mbPtr->drawParams;
|
||||
DrawParams *dpPtr = &mbPtr->drawParams;
|
||||
int useNewerHITools = 1;
|
||||
|
||||
winPtr = (TkWindow *)butPtr->tkwin;
|
||||
|
||||
TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
|
||||
|
||||
cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff, Tk_Width(butPtr->tkwin),Tk_Height(butPtr->tkwin));
|
||||
|
||||
cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset);
|
||||
|
||||
cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,
|
||||
Tk_Width(butPtr->tkwin), Tk_Height(butPtr->tkwin));
|
||||
|
||||
if (useNewerHITools == 1) {
|
||||
HIRect contHIRec;
|
||||
static HIThemeButtonDrawInfo hiinfo;
|
||||
|
||||
MenuButtonBackgroundDrawCB((MacMenuButton*) mbPtr, 32, true);
|
||||
|
||||
MenuButtonBackgroundDrawCB(mbPtr, 32, true);
|
||||
if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
hiinfo.version = 0;
|
||||
hiinfo.state = mbPtr->drawinfo.state;
|
||||
hiinfo.kind = mbPtr->btnkind;
|
||||
hiinfo.kind = mbPtr->btnkind;
|
||||
hiinfo.value = mbPtr->drawinfo.value;
|
||||
hiinfo.adornment = mbPtr->drawinfo.adornment;
|
||||
hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();
|
||||
@@ -617,17 +580,26 @@ TkMacOSXDrawMenuButton(
|
||||
hiinfo.animation.time.start = hiinfo.animation.time.current;
|
||||
}
|
||||
|
||||
HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, &contHIRec);
|
||||
/*
|
||||
* To avoid menubuttons with white text on a white background, we
|
||||
* always set the state to inactive in Dark Mode. It isn't perfect but
|
||||
* it is usable. Using a ttk::menubutton would be a better choice,
|
||||
* however.
|
||||
*/
|
||||
|
||||
if (TkMacOSXInDarkMode(butPtr->tkwin)) {
|
||||
hiinfo.state = kThemeStateInactive;
|
||||
}
|
||||
|
||||
HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
|
||||
kHIThemeOrientationNormal, &contHIRec);
|
||||
TkMacOSXRestoreDrawingContext(&dc);
|
||||
|
||||
MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo, (MacMenuButton *)mbPtr, 32, true);
|
||||
MenuButtonContentDrawCB(mbPtr->btnkind, &mbPtr->drawinfo,
|
||||
mbPtr, 32, true);
|
||||
} else {
|
||||
if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
TkMacOSXRestoreDrawingContext(&dc);
|
||||
}
|
||||
mbPtr->lastdrawinfo = mbPtr->drawinfo;
|
||||
@@ -638,33 +610,34 @@ TkMacOSXDrawMenuButton(
|
||||
*
|
||||
* MenuButtonBackgroundDrawCB --
|
||||
*
|
||||
* This function draws the background that
|
||||
* lies under checkboxes and radiobuttons.
|
||||
* This function draws the background that lies under checkboxes and
|
||||
* radiobuttons.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The background gets updated to the current color.
|
||||
* The background gets updated to the current color.
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
MenuButtonBackgroundDrawCB (
|
||||
MacMenuButton *ptr,
|
||||
SInt16 depth,
|
||||
Boolean isColorDev)
|
||||
{
|
||||
TkMenuButton* butPtr = (TkMenuButton*)ptr;
|
||||
Tk_Window tkwin = butPtr->tkwin;
|
||||
TkMenuButton* butPtr = (TkMenuButton *) ptr;
|
||||
Tk_Window tkwin = butPtr->tkwin;
|
||||
Pixmap pixmap;
|
||||
|
||||
if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
|
||||
return;
|
||||
}
|
||||
pixmap = (Pixmap)Tk_WindowId(tkwin);
|
||||
|
||||
pixmap = (Pixmap) Tk_WindowId(tkwin);
|
||||
Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0,
|
||||
Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
|
||||
Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -672,16 +645,17 @@ MenuButtonBackgroundDrawCB (
|
||||
*
|
||||
* MenuButtonContentDrawCB --
|
||||
*
|
||||
* This function draws the label and image for the button.
|
||||
* This function draws the label and image for the button.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The content of the button gets updated.
|
||||
* The content of the button gets updated.
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
MenuButtonContentDrawCB (
|
||||
ThemeButtonKind kind,
|
||||
@@ -690,14 +664,13 @@ MenuButtonContentDrawCB (
|
||||
SInt16 depth,
|
||||
Boolean isColorDev)
|
||||
{
|
||||
TkMenuButton *butPtr = (TkMenuButton *)ptr;
|
||||
Tk_Window tkwin = butPtr->tkwin;
|
||||
TkMenuButton *butPtr = (TkMenuButton *) ptr;
|
||||
Tk_Window tkwin = butPtr->tkwin;
|
||||
|
||||
if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DrawMenuButtonImageAndText( butPtr);
|
||||
DrawMenuButtonImageAndText(butPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -705,8 +678,8 @@ MenuButtonContentDrawCB (
|
||||
*
|
||||
* MenuButtonEventProc --
|
||||
*
|
||||
* This procedure is invoked by the Tk dispatcher for various
|
||||
* events on buttons.
|
||||
* This procedure is invoked by the Tk dispatcher for various events on
|
||||
* buttons.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -722,8 +695,8 @@ MenuButtonEventProc(
|
||||
ClientData clientData, /* Information about window. */
|
||||
XEvent *eventPtr) /* Information about event. */
|
||||
{
|
||||
TkMenuButton *buttonPtr = (TkMenuButton *) clientData;
|
||||
MacMenuButton *mbPtr = (MacMenuButton *) clientData;
|
||||
TkMenuButton *buttonPtr = clientData;
|
||||
MacMenuButton *mbPtr = clientData;
|
||||
|
||||
if (eventPtr->type == ActivateNotify
|
||||
|| eventPtr->type == DeactivateNotify) {
|
||||
@@ -747,9 +720,9 @@ MenuButtonEventProc(
|
||||
*
|
||||
* TkMacOSXComputeMenuButtonParams --
|
||||
*
|
||||
* This procedure computes the various parameters used
|
||||
* when creating a Carbon Appearance control.
|
||||
* These are determined by the various tk button parameters
|
||||
* This procedure computes the various parameters used when creating a
|
||||
* Carbon Appearance control. These are determined by the various Tk
|
||||
* button parameters
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -761,19 +734,18 @@ MenuButtonEventProc(
|
||||
*/
|
||||
|
||||
static void
|
||||
TkMacOSXComputeMenuButtonParams(TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo *drawinfo)
|
||||
TkMacOSXComputeMenuButtonParams(
|
||||
TkMenuButton *butPtr,
|
||||
ThemeButtonKind *btnkind,
|
||||
HIThemeButtonDrawInfo *drawinfo)
|
||||
{
|
||||
MacMenuButton *mbPtr = (MacMenuButton *)butPtr;
|
||||
MacMenuButton *mbPtr = (MacMenuButton *) butPtr;
|
||||
|
||||
if (butPtr->image || butPtr->bitmap) {
|
||||
if (butPtr->image || butPtr->bitmap || butPtr->text) {
|
||||
/* TODO: allow for Small and Mini menubuttons. */
|
||||
*btnkind = kThemePopupButton;
|
||||
} else {
|
||||
if (!butPtr->text || !*butPtr->text) {
|
||||
*btnkind = kThemeArrowButton;
|
||||
} else {
|
||||
*btnkind = kThemePopupButton;
|
||||
}
|
||||
} else { /* This should never happen. */
|
||||
*btnkind = kThemeArrowButton;
|
||||
}
|
||||
|
||||
drawinfo->value = kThemeButtonOff;
|
||||
@@ -812,24 +784,25 @@ TkMacOSXComputeMenuButtonParams(TkMenuButton * butPtr, ThemeButtonKind* btnkind,
|
||||
*
|
||||
* TkMacOSXComputeMenuButtonDrawParams --
|
||||
*
|
||||
* This procedure computes the various parameters used
|
||||
* when drawing a button
|
||||
* These are determined by the various tk button parameters
|
||||
* This procedure selects an appropriate drawing context for drawing a
|
||||
* menubutton.
|
||||
*
|
||||
* Results:
|
||||
* 1 if control will be used, 0 otherwise.
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Sets the button draw parameters
|
||||
* Sets the button draw parameters.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr)
|
||||
static void
|
||||
TkMacOSXComputeMenuButtonDrawParams(
|
||||
TkMenuButton *butPtr,
|
||||
DrawParams *dpPtr)
|
||||
{
|
||||
dpPtr->hasImageOrBitmap = ((butPtr->image != NULL)
|
||||
|| (butPtr->bitmap != None));
|
||||
dpPtr->hasImageOrBitmap =
|
||||
((butPtr->image != NULL) || (butPtr->bitmap != None));
|
||||
dpPtr->border = butPtr->normalBorder;
|
||||
if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
|
||||
dpPtr->gc = butPtr->disabledGC;
|
||||
@@ -839,10 +812,8 @@ TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr)
|
||||
} else {
|
||||
dpPtr->gc = butPtr->normalTextGC;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
static void GenerateEditEvent(const char *name);
|
||||
static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
|
||||
|
||||
|
||||
#pragma mark TKApplication(TKMenus)
|
||||
|
||||
@@ -69,9 +70,8 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
|
||||
[NSMenuItem itemWithTitle:
|
||||
[NSString stringWithFormat:@"About %@", aboutName]
|
||||
action:@selector(orderFrontStandardAboutPanel:)] atIndex:0];
|
||||
|
||||
TKMenu *fileMenu = [TKMenu menuWithTitle:@"File" menuItems:
|
||||
[NSArray arrayWithObjects:
|
||||
_defaultFileMenuItems =
|
||||
[[NSArray arrayWithObjects:
|
||||
[NSMenuItem itemWithTitle:
|
||||
[NSString stringWithFormat:@"Source%C", 0x2026]
|
||||
action:@selector(tkSource:)],
|
||||
@@ -79,7 +79,10 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
|
||||
action:@selector(tkDemo:)],
|
||||
[NSMenuItem itemWithTitle:@"Close" action:@selector(performClose:)
|
||||
target:nil keyEquivalent:@"w"],
|
||||
nil]];
|
||||
nil] retain];
|
||||
_demoMenuItem = [_defaultFileMenuItems objectAtIndex:1];
|
||||
TKMenu *fileMenu = [TKMenu menuWithTitle:@"File"
|
||||
menuItems: _defaultFileMenuItems];
|
||||
TKMenu *editMenu = [TKMenu menuWithTitle:@"Edit" menuItems:
|
||||
[NSArray arrayWithObjects:
|
||||
[NSMenuItem itemWithTitle:@"Undo" action:@selector(undo:)
|
||||
@@ -97,29 +100,56 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
|
||||
target:nil],
|
||||
nil]];
|
||||
|
||||
_defaultWindowsMenuItems = [[NSArray arrayWithObjects:
|
||||
[NSMenuItem itemWithTitle:@"Minimize"
|
||||
action:@selector(performMiniaturize:) target:nil
|
||||
keyEquivalent:@"m"],
|
||||
[NSMenuItem itemWithTitle:@"Zoom" action:@selector(performZoom:)
|
||||
target:nil],
|
||||
[NSMenuItem separatorItem],
|
||||
_defaultWindowsMenuItems = [NSArray arrayWithObjects:
|
||||
[NSMenuItem itemWithTitle:@"Minimize"
|
||||
action:@selector(performMiniaturize:) target:nil
|
||||
keyEquivalent:@"m"],
|
||||
[NSMenuItem itemWithTitle:@"Zoom" action:@selector(performZoom:)
|
||||
target:nil],
|
||||
nil];
|
||||
|
||||
/*
|
||||
* On OS X 10.12 we get duplicate tab control items if we create them here.
|
||||
*/
|
||||
|
||||
if ([NSApp macMinorVersion] > 12) {
|
||||
_defaultWindowsMenuItems = [_defaultWindowsMenuItems
|
||||
arrayByAddingObjectsFromArray:
|
||||
[NSArray arrayWithObjects:
|
||||
[NSMenuItem separatorItem],
|
||||
[NSMenuItem itemWithTitle:@"Show Previous Tab"
|
||||
action:@selector(selectPreviousTab:)
|
||||
target:nil
|
||||
keyEquivalent:@"\t"
|
||||
keyEquivalentModifierMask:
|
||||
NSControlKeyMask|NSShiftKeyMask],
|
||||
[NSMenuItem itemWithTitle:@"Show Next Tab"
|
||||
action:@selector(selectNextTab:)
|
||||
target:nil
|
||||
keyEquivalent:@"\t"
|
||||
keyEquivalentModifierMask:NSControlKeyMask],
|
||||
[NSMenuItem itemWithTitle:@"Move Tab To New Window"
|
||||
action:@selector(moveTabToNewWindow:)
|
||||
target:nil],
|
||||
[NSMenuItem itemWithTitle:@"Merge All Windows"
|
||||
action:@selector(mergeAllWindows:)
|
||||
target:nil],
|
||||
[NSMenuItem separatorItem],
|
||||
nil]];
|
||||
}
|
||||
_defaultWindowsMenuItems = [_defaultWindowsMenuItems arrayByAddingObject:
|
||||
[NSMenuItem itemWithTitle:@"Bring All to Front"
|
||||
action:@selector(arrangeInFront:)],
|
||||
nil] retain];
|
||||
|
||||
action:@selector(arrangeInFront:)]];
|
||||
[_defaultWindowsMenuItems retain];
|
||||
TKMenu *windowsMenu = [TKMenu menuWithTitle:@"Window" menuItems:
|
||||
_defaultWindowsMenuItems];
|
||||
|
||||
_defaultWindowsMenuItems];
|
||||
_defaultHelpMenuItems = [[NSArray arrayWithObjects:
|
||||
[NSMenuItem itemWithTitle:
|
||||
[NSString stringWithFormat:@"%@ Help", applicationName]
|
||||
action:@selector(showHelp:) keyEquivalent:@"?"],
|
||||
nil] retain];
|
||||
|
||||
TKMenu *helpMenu = [TKMenu menuWithTitle:@"Help" menuItems:
|
||||
_defaultHelpMenuItems];
|
||||
|
||||
[self setServicesMenu:_servicesMenu];
|
||||
[self setWindowsMenu:windowsMenu];
|
||||
_defaultMainMenu = [[TKMenu menuWithTitle:@"" submenus:[NSArray
|
||||
@@ -138,6 +168,7 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
|
||||
[_defaultHelpMenuItems release];
|
||||
[_defaultWindowsMenuItems release];
|
||||
[_defaultApplicationMenuItems release];
|
||||
[_defaultFileMenuItems release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@@ -146,7 +177,6 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
|
||||
SEL action = [anItem action];
|
||||
|
||||
if (sel_isEqual(action, @selector(preferences:))) {
|
||||
|
||||
return (_eventInterp && Tcl_FindCommand(_eventInterp,
|
||||
"::tk::mac::ShowPreferences", NULL, 0));
|
||||
} else if (sel_isEqual(action, @selector(tkDemo:))) {
|
||||
@@ -232,6 +262,7 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
|
||||
if (path) {
|
||||
Tcl_IncrRefCount(path);
|
||||
|
||||
[_demoMenuItem setHidden:YES];
|
||||
int code = Tcl_FSEvalFileEx(_eventInterp, path, NULL);
|
||||
|
||||
if (code != TCL_OK) {
|
||||
|
||||
@@ -24,16 +24,19 @@ typedef struct {
|
||||
Point global;
|
||||
Point local;
|
||||
} MouseEventData;
|
||||
static Tk_Window captureWinPtr = NULL; /* Current capture window; may be
|
||||
* NULL. */
|
||||
|
||||
static int GenerateButtonEvent(MouseEventData *medPtr);
|
||||
static unsigned int ButtonModifiers2State(UInt32 buttonState,
|
||||
UInt32 keyModifiers);
|
||||
UInt32 keyModifiers);
|
||||
|
||||
#pragma mark TKApplication(TKMouseEvent)
|
||||
|
||||
enum {
|
||||
NSWindowWillMoveEventType = 20
|
||||
};
|
||||
|
||||
/*
|
||||
* In OS X 10.6 an NSEvent of type NSMouseMoved would always have a non-Nil
|
||||
* window attribute pointing to the active window. As of 10.8 this behavior
|
||||
@@ -47,14 +50,19 @@ enum {
|
||||
@implementation TKApplication(TKMouseEvent)
|
||||
- (NSEvent *) tkProcessMouseEvent: (NSEvent *) theEvent
|
||||
{
|
||||
NSWindow *eventWindow = [theEvent window];
|
||||
NSEventType eventType = [theEvent type];
|
||||
TkWindow *winPtr = NULL, *grabWinPtr;
|
||||
Tk_Window tkwin;
|
||||
NSPoint local, global;
|
||||
#if 0
|
||||
NSTrackingArea *trackingArea = nil;
|
||||
NSInteger eventNumber, clickCount, buttonNumber;
|
||||
#endif
|
||||
[NSEvent stopPeriodicEvents];
|
||||
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
|
||||
#endif
|
||||
NSWindow* eventWindow = [theEvent window];
|
||||
NSEventType eventType = [theEvent type];
|
||||
#if 0
|
||||
NSTrackingArea *trackingArea = nil;
|
||||
NSInteger eventNumber, clickCount, buttonNumber;
|
||||
#endif
|
||||
switch (eventType) {
|
||||
case NSMouseEntered:
|
||||
@@ -73,74 +81,152 @@ enum {
|
||||
case NSTabletPoint:
|
||||
case NSTabletProximity:
|
||||
case NSScrollWheel:
|
||||
break;
|
||||
break;
|
||||
default: /* Unrecognized mouse event. */
|
||||
return theEvent;
|
||||
}
|
||||
|
||||
/* Remember the window in case we need it next time. */
|
||||
if (eventWindow && eventWindow != _windowWithMouse) {
|
||||
if (_windowWithMouse) {
|
||||
[_windowWithMouse release];
|
||||
}
|
||||
_windowWithMouse = eventWindow;
|
||||
[_windowWithMouse retain];
|
||||
}
|
||||
/*
|
||||
* Compute the mouse position in Tk screen coordinates (global) and in the
|
||||
* Tk coordinates of its containing Tk Window (local). If a grab is in effect,
|
||||
* the local coordinates should be relative to the grab window.
|
||||
*/
|
||||
|
||||
/* Create an Xevent to add to the Tk queue. */
|
||||
NSPoint global, local = [theEvent locationInWindow];
|
||||
if (eventWindow) { /* local will be in window coordinates. */
|
||||
if (eventWindow) {
|
||||
local = [theEvent locationInWindow];
|
||||
global = [eventWindow tkConvertPointToScreen: local];
|
||||
tkwin = TkMacOSXGetCapture();
|
||||
if (tkwin) {
|
||||
winPtr = (TkWindow *) tkwin;
|
||||
eventWindow = TkMacOSXDrawableWindow(winPtr->window);
|
||||
if (eventWindow) {
|
||||
local = [eventWindow tkConvertPointFromScreen: global];
|
||||
} else {
|
||||
return theEvent;
|
||||
}
|
||||
}
|
||||
local.y = [eventWindow frame].size.height - local.y;
|
||||
global.y = tkMacOSXZeroScreenHeight - global.y;
|
||||
} else { /* local will be in screen coordinates. */
|
||||
if (_windowWithMouse ) {
|
||||
eventWindow = _windowWithMouse;
|
||||
global = local;
|
||||
local = [eventWindow tkConvertPointFromScreen: local];
|
||||
local.y = [eventWindow frame].size.height - local.y;
|
||||
global.y = tkMacOSXZeroScreenHeight - global.y;
|
||||
} else { /* We have no window. Use the screen???*/
|
||||
local.y = tkMacOSXZeroScreenHeight - local.y;
|
||||
global = local;
|
||||
global.y = TkMacOSXZeroScreenHeight() - global.y;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* If the event has no NSWindow, the location is in screen coordinates.
|
||||
*/
|
||||
|
||||
global = [theEvent locationInWindow];
|
||||
tkwin = TkMacOSXGetCapture();
|
||||
if (tkwin) {
|
||||
winPtr = (TkWindow *) tkwin;
|
||||
eventWindow = TkMacOSXDrawableWindow(winPtr->window);
|
||||
} else {
|
||||
eventWindow = [NSApp mainWindow];
|
||||
}
|
||||
if (!eventWindow) {
|
||||
return theEvent;
|
||||
}
|
||||
local = [eventWindow tkConvertPointFromScreen: global];
|
||||
local.y = [eventWindow frame].size.height - local.y;
|
||||
global.y = TkMacOSXZeroScreenHeight() - global.y;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we still don't have a window, try using the toplevel that
|
||||
* manages the NSWindow.
|
||||
*/
|
||||
|
||||
if (!tkwin) {
|
||||
winPtr = TkMacOSXGetTkWindow(eventWindow);
|
||||
tkwin = (Tk_Window) winPtr;
|
||||
}
|
||||
if (!tkwin) {
|
||||
|
||||
/*
|
||||
* We can't find a window for this event. We have to ignore it.
|
||||
*/
|
||||
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
TkMacOSXDbgMsg("tkwin == NULL");
|
||||
#endif
|
||||
return theEvent;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore the event if a local grab is in effect and the Tk event window is
|
||||
* not in the grabber's subtree.
|
||||
*/
|
||||
|
||||
grabWinPtr = winPtr->dispPtr->grabWinPtr;
|
||||
if (grabWinPtr && /* There is a grab in effect ... */
|
||||
!winPtr->dispPtr->grabFlags && /* and it is a local grab ... */
|
||||
grabWinPtr->mainPtr == winPtr->mainPtr){ /* in the same application. */
|
||||
Tk_Window tkwin2, tkEventWindow = Tk_CoordsToWindow(global.x, global.y, tkwin);
|
||||
if (!tkEventWindow) {
|
||||
return theEvent;
|
||||
}
|
||||
for (tkwin2 = tkEventWindow;
|
||||
!Tk_IsTopLevel(tkwin2);
|
||||
tkwin2 = Tk_Parent(tkwin2)) {
|
||||
if (tkwin2 == (Tk_Window) grabWinPtr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tkwin2 != (Tk_Window) grabWinPtr) {
|
||||
return theEvent;
|
||||
}
|
||||
}
|
||||
|
||||
Window window = TkMacOSXGetXWindow(eventWindow);
|
||||
Tk_Window tkwin = window ? Tk_IdToWindow(TkGetDisplayList()->display,
|
||||
window) : NULL;
|
||||
if (!tkwin) {
|
||||
tkwin = TkMacOSXGetCapture();
|
||||
}
|
||||
if (!tkwin) {
|
||||
return theEvent; /* Give up. No window for this event. */
|
||||
/*
|
||||
* Convert local from NSWindow flipped coordinates to the toplevel's
|
||||
* coordinates.
|
||||
*/
|
||||
|
||||
if (Tk_IsEmbedded(winPtr)) {
|
||||
TkWindow *contPtr = TkpGetOtherWindow(winPtr);
|
||||
if (Tk_IsTopLevel(contPtr)) {
|
||||
local.x -= contPtr->wmInfoPtr->xInParent;
|
||||
local.y -= contPtr->wmInfoPtr->yInParent;
|
||||
} else {
|
||||
TkWindow *topPtr = TkMacOSXGetHostToplevel(winPtr)->winPtr;
|
||||
local.x -= (topPtr->wmInfoPtr->xInParent + contPtr->changes.x);
|
||||
local.y -= (topPtr->wmInfoPtr->yInParent + contPtr->changes.y);
|
||||
}
|
||||
} else {
|
||||
local.x -= winPtr->wmInfoPtr->xInParent;
|
||||
local.y -= winPtr->wmInfoPtr->yInParent;
|
||||
}
|
||||
|
||||
TkWindow *winPtr = (TkWindow *) tkwin;
|
||||
local.x -= winPtr->wmInfoPtr->xInParent;
|
||||
local.y -= winPtr->wmInfoPtr->yInParent;
|
||||
/*
|
||||
* Use the toplevel coordinates to find the containing Tk window. Then
|
||||
* convert local into the coordinates of that window. (The converted
|
||||
* local coordinates are only needed for scrollwheel events.)
|
||||
*/
|
||||
|
||||
int win_x, win_y;
|
||||
tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y,
|
||||
&win_x, &win_y);
|
||||
tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
|
||||
local.x = win_x;
|
||||
local.y = win_y;
|
||||
|
||||
/*
|
||||
* Generate an XEvent for this mouse event.
|
||||
*/
|
||||
|
||||
unsigned int state = 0;
|
||||
NSInteger button = [theEvent buttonNumber];
|
||||
int button = [theEvent buttonNumber] + Button1;
|
||||
EventRef eventRef = (EventRef)[theEvent eventRef];
|
||||
UInt32 buttons;
|
||||
OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord,
|
||||
typeUInt32, NULL, sizeof(UInt32), NULL, &buttons);
|
||||
typeUInt32, NULL, sizeof(UInt32), NULL, &buttons);
|
||||
|
||||
if (err == noErr) {
|
||||
state |= (buttons & ((1<<5) - 1)) << 8;
|
||||
} else if (button < 5) {
|
||||
state |= (buttons & 0x1F) * Button1Mask;
|
||||
} else if (button <= Button5) {
|
||||
switch (eventType) {
|
||||
case NSLeftMouseDown:
|
||||
case NSRightMouseDown:
|
||||
case NSLeftMouseDragged:
|
||||
case NSRightMouseDragged:
|
||||
case NSOtherMouseDown:
|
||||
state |= 1 << (button + 8);
|
||||
state |= TkGetButtonMask(button);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -172,11 +258,22 @@ enum {
|
||||
}
|
||||
|
||||
if (eventType != NSScrollWheel) {
|
||||
|
||||
/*
|
||||
* For normal mouse events, Tk_UpdatePointer will send the XEvent.
|
||||
*/
|
||||
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state);
|
||||
TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d",
|
||||
tkwin, global.x, global.y, state);
|
||||
#endif
|
||||
Tk_UpdatePointer(tkwin, global.x, global.y, state);
|
||||
} else { /* handle scroll wheel event */
|
||||
} else {
|
||||
|
||||
/*
|
||||
* For scroll wheel events we need to send the XEvent here.
|
||||
*/
|
||||
|
||||
CGFloat delta;
|
||||
int coarseDelta;
|
||||
XEvent xEvent;
|
||||
@@ -193,7 +290,7 @@ enum {
|
||||
delta = [theEvent deltaY];
|
||||
if (delta != 0.0) {
|
||||
coarseDelta = (delta > -1.0 && delta < 1.0) ?
|
||||
(signbit(delta) ? -1 : 1) : lround(delta);
|
||||
(signbit(delta) ? -1 : 1) : lround(delta);
|
||||
xEvent.xbutton.state = state;
|
||||
xEvent.xkey.keycode = coarseDelta;
|
||||
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
|
||||
@@ -202,7 +299,7 @@ enum {
|
||||
delta = [theEvent deltaX];
|
||||
if (delta != 0.0) {
|
||||
coarseDelta = (delta > -1.0 && delta < 1.0) ?
|
||||
(signbit(delta) ? -1 : 1) : lround(delta);
|
||||
(signbit(delta) ? -1 : 1) : lround(delta);
|
||||
xEvent.xbutton.state = state | ShiftMask;
|
||||
xEvent.xkey.keycode = coarseDelta;
|
||||
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
|
||||
@@ -299,10 +396,10 @@ ButtonModifiers2State(
|
||||
unsigned int state;
|
||||
|
||||
/*
|
||||
* Tk supports at most 5 buttons.
|
||||
* Tk on OSX supports at most 5 buttons.
|
||||
*/
|
||||
|
||||
state = (buttonState & ((1<<5) - 1)) << 8;
|
||||
state = (buttonState & 0x1F) * Button1Mask;
|
||||
|
||||
if (keyModifiers & alphaLock) {
|
||||
state |= LockMask;
|
||||
@@ -385,7 +482,7 @@ XQueryPointer(
|
||||
}
|
||||
if (getGlobal) {
|
||||
*root_x_return = global.x;
|
||||
*root_y_return = tkMacOSXZeroScreenHeight - global.y;
|
||||
*root_y_return = TkMacOSXZeroScreenHeight() - global.y;
|
||||
}
|
||||
}
|
||||
if (mask_return) {
|
||||
@@ -437,7 +534,7 @@ TkGenerateButtonEventForXPointer(
|
||||
* TkGenerateButtonEvent --
|
||||
*
|
||||
* Given a global x & y position and the button key status this procedure
|
||||
* generates the appropiate X button event. It also handles the state
|
||||
* generates the appropriate X button event. It also handles the state
|
||||
* changes needed to implement implicit grabs.
|
||||
*
|
||||
* Results:
|
||||
@@ -469,7 +566,7 @@ TkGenerateButtonEvent(
|
||||
med.local = med.global;
|
||||
|
||||
if (win) {
|
||||
NSPoint local = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
|
||||
NSPoint local = NSMakePoint(x, TkMacOSXZeroScreenHeight() - y);
|
||||
|
||||
local = [win tkConvertPointFromScreen:local];
|
||||
local.y = [win frame].size.height - local.y;
|
||||
@@ -478,7 +575,7 @@ TkGenerateButtonEvent(
|
||||
local.y -= macWin->winPtr->wmInfoPtr->yInParent;
|
||||
}
|
||||
med.local.h = local.x;
|
||||
med.local.v = tkMacOSXZeroScreenHeight - local.y;
|
||||
med.local.v = TkMacOSXZeroScreenHeight() - local.y;
|
||||
}
|
||||
|
||||
return GenerateButtonEvent(&med);
|
||||
@@ -511,6 +608,7 @@ GenerateButtonEvent(
|
||||
TkDisplay *dispPtr;
|
||||
|
||||
#if UNUSED
|
||||
|
||||
/*
|
||||
* ButtonDown events will always occur in the front window. ButtonUp
|
||||
* events, however, may occur anywhere on the screen. ButtonUp events
|
||||
@@ -543,32 +641,95 @@ TkpWarpPointer(
|
||||
TkDisplay *dispPtr)
|
||||
{
|
||||
CGPoint pt;
|
||||
UInt32 buttonState;
|
||||
NSPoint loc;
|
||||
int wNum;
|
||||
|
||||
if (dispPtr->warpWindow) {
|
||||
int x, y;
|
||||
|
||||
TkWindow *winPtr = (TkWindow *) dispPtr->warpWindow;
|
||||
TkWindow *topPtr = winPtr->privatePtr->toplevel->winPtr;
|
||||
NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);
|
||||
wNum = [w windowNumber];
|
||||
Tk_GetRootCoords(dispPtr->warpWindow, &x, &y);
|
||||
pt.x = x + dispPtr->warpX;
|
||||
pt.y = y + dispPtr->warpY;
|
||||
loc.x = dispPtr->warpX;
|
||||
loc.y = Tk_Height(topPtr) - dispPtr->warpY;
|
||||
} else {
|
||||
pt.x = dispPtr->warpX;
|
||||
wNum = 0;
|
||||
pt.x = loc.x = dispPtr->warpX;
|
||||
pt.y = dispPtr->warpY;
|
||||
loc.y = TkMacOSXZeroScreenHeight() - pt.y;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell the OSX core to generate the events to make it happen.
|
||||
* Generate an NSEvent of type NSMouseMoved.
|
||||
*
|
||||
* It is not clear why this is necessary. For example, calling
|
||||
* event generate $w <Motion> -warp 1 -x $X -y $Y
|
||||
* will cause two <Motion> events to be added to the Tcl queue.
|
||||
*/
|
||||
|
||||
buttonState = [NSEvent pressedMouseButtons];
|
||||
CGEventType type = kCGEventMouseMoved;
|
||||
CGEventRef theEvent = CGEventCreateMouseEvent(NULL,
|
||||
type,
|
||||
pt,
|
||||
buttonState);
|
||||
CGWarpMouseCursorPosition(pt);
|
||||
CGEventPost(kCGHIDEventTap, theEvent);
|
||||
CFRelease(theEvent);
|
||||
NSEvent *warpEvent = [NSEvent mouseEventWithType:NSMouseMoved
|
||||
location:loc
|
||||
modifierFlags:0
|
||||
timestamp:GetCurrentEventTime()
|
||||
windowNumber:wNum
|
||||
context:nil
|
||||
eventNumber:0
|
||||
clickCount:1
|
||||
pressure:0.0];
|
||||
[NSApp postEvent:warpEvent atStart:NO];
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkpSetCapture --
|
||||
*
|
||||
* This function captures the mouse so that all future events will be
|
||||
* reported to this window, even if the mouse is outside the window. If
|
||||
* the specified window is NULL, then the mouse is released.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Sets the capture flag and captures the mouse.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TkpSetCapture(
|
||||
TkWindow *winPtr) /* Capture window, or NULL. */
|
||||
{
|
||||
while (winPtr && !Tk_IsTopLevel(winPtr)) {
|
||||
winPtr = winPtr->parentPtr;
|
||||
}
|
||||
[NSEvent stopPeriodicEvents];
|
||||
captureWinPtr = (Tk_Window) winPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkMacOSXGetCapture --
|
||||
*
|
||||
* Results:
|
||||
* Returns the current grab window
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tk_Window
|
||||
TkMacOSXGetCapture(void)
|
||||
{
|
||||
return captureWinPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -33,7 +33,7 @@ static void TkMacOSXEventsSetupProc(ClientData clientData, int flags);
|
||||
static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
|
||||
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
static char* Tk_EventName[39] = {
|
||||
static const char *Tk_EventName[39] = {
|
||||
"",
|
||||
"",
|
||||
"KeyPress", /*2*/
|
||||
@@ -84,7 +84,7 @@ InspectQueueRestrictProc(
|
||||
const char *name;
|
||||
long serial = ve->serial;
|
||||
long time = eventPtr->xkey.time;
|
||||
|
||||
|
||||
if (eventPtr->type == VirtualEvent) {
|
||||
name = ve->name;
|
||||
} else {
|
||||
@@ -113,11 +113,6 @@ void DebugPrintQueue(void)
|
||||
|
||||
#pragma mark TKApplication(TKNotify)
|
||||
|
||||
@interface NSApplication(TKNotify)
|
||||
/* We need to declare this hidden method. */
|
||||
- (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event;
|
||||
@end
|
||||
|
||||
@implementation TKApplication(TKNotify)
|
||||
/*
|
||||
* Earlier versions of Tk would override nextEventMatchingMask here, adding a
|
||||
@@ -140,14 +135,16 @@ void DebugPrintQueue(void)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Call super then check the pasteboard.
|
||||
* Since the contentView is the first responder for a Tk Window, it is
|
||||
* responsible for sending events up the responder chain. We also check the
|
||||
* pasteboard here.
|
||||
*/
|
||||
- (void) sendEvent: (NSEvent *) theEvent
|
||||
{
|
||||
[super sendEvent:theEvent];
|
||||
[NSApp tkCheckPasteboard];
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
fprintf(stderr, "Sending event of type %d\n", (int)[theEvent type]);
|
||||
fprintf(stderr, "Sending event of type %d\n", (int)[theEvent type]);
|
||||
DebugPrintQueue();
|
||||
#endif
|
||||
}
|
||||
@@ -193,8 +190,8 @@ GetRunLoopMode(NSModalSession modalSession)
|
||||
*
|
||||
* Tk_MacOSXSetupTkNotifier --
|
||||
*
|
||||
* This procedure is called during Tk initialization to create
|
||||
* the event source for TkAqua events.
|
||||
* This procedure is called during Tk initialization to create the event
|
||||
* source for TkAqua events.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -227,8 +224,7 @@ Tk_MacOSXSetupTkNotifier(void)
|
||||
"first [load] of TkAqua has to occur in the main thread!");
|
||||
}
|
||||
Tcl_CreateEventSource(TkMacOSXEventsSetupProc,
|
||||
TkMacOSXEventsCheckProc,
|
||||
NULL);
|
||||
TkMacOSXEventsCheckProc, NULL);
|
||||
TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
|
||||
Tcl_SetServiceMode(TCL_SERVICE_ALL);
|
||||
TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);
|
||||
@@ -261,8 +257,7 @@ TkMacOSXNotifyExitHandler(
|
||||
TSD_INIT();
|
||||
|
||||
Tcl_DeleteEventSource(TkMacOSXEventsSetupProc,
|
||||
TkMacOSXEventsCheckProc,
|
||||
NULL);
|
||||
TkMacOSXEventsCheckProc, NULL);
|
||||
tsdPtr->initialized = 0;
|
||||
}
|
||||
|
||||
@@ -271,19 +266,19 @@ TkMacOSXNotifyExitHandler(
|
||||
*
|
||||
* TkMacOSXEventsSetupProc --
|
||||
*
|
||||
* This procedure implements the setup part of the MacOSX event
|
||||
* source. It is invoked by Tcl_DoOneEvent before calling
|
||||
* TkMacOSXEventsProc to process all queued NSEvents. In our
|
||||
* case, all we need to do is to set the Tcl MaxBlockTime to
|
||||
* 0 before starting the loop to process all queued NSEvents.
|
||||
* This procedure implements the setup part of the MacOSX event source. It
|
||||
* is invoked by Tcl_DoOneEvent before calling TkMacOSXEventsProc to
|
||||
* process all queued NSEvents. In our case, all we need to do is to set
|
||||
* the Tcl MaxBlockTime to 0 before starting the loop to process all
|
||||
* queued NSEvents.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
* If NSEvents are queued, then the maximum block time will be set
|
||||
* to 0 to ensure that control returns immediately to Tcl.
|
||||
* If NSEvents are queued, then the maximum block time will be set to 0 to
|
||||
* ensure that control returns immediately to Tcl.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -293,20 +288,43 @@ TkMacOSXEventsSetupProc(
|
||||
ClientData clientData,
|
||||
int flags)
|
||||
{
|
||||
static Bool havePeriodicEvents = NO;
|
||||
NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
|
||||
/* runloopMode will be nil if we are in a Tcl event loop. */
|
||||
|
||||
/*
|
||||
* runloopMode will be nil if we are in a Tcl event loop.
|
||||
*/
|
||||
|
||||
if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
|
||||
static const Tcl_Time zeroBlockTime = { 0, 0 };
|
||||
[NSApp _resetAutoreleasePool];
|
||||
/* Call this with dequeue=NO -- just checking if the queue is empty. */
|
||||
NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:GetRunLoopMode(TkMacOSXGetModalSession())
|
||||
dequeue:NO];
|
||||
|
||||
/*
|
||||
* Call this with dequeue=NO -- just checking if the queue is empty.
|
||||
*/
|
||||
|
||||
NSEvent *currentEvent =
|
||||
[NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:GetRunLoopMode(TkMacOSXGetModalSession())
|
||||
dequeue:NO];
|
||||
if (currentEvent) {
|
||||
if (currentEvent.type > 0) {
|
||||
Tcl_SetMaxBlockTime(&zeroBlockTime);
|
||||
[NSEvent stopPeriodicEvents];
|
||||
havePeriodicEvents = NO;
|
||||
}
|
||||
} else if (!havePeriodicEvents){
|
||||
|
||||
/*
|
||||
* When the user is not generating events we schedule a "hearbeat"
|
||||
* event to fire every 0.1 seconds. This helps to make the vwait
|
||||
* command more responsive when there is no user input, e.g. when
|
||||
* running the test suite.
|
||||
*/
|
||||
|
||||
havePeriodicEvents = YES;
|
||||
[NSEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,15 +334,15 @@ TkMacOSXEventsSetupProc(
|
||||
*
|
||||
* TkMacOSXEventsCheckProc --
|
||||
*
|
||||
* This procedure loops through all NSEvents waiting in the
|
||||
* TKApplication event queue, generating X events from them.
|
||||
* This procedure loops through all NSEvents waiting in the TKApplication
|
||||
* event queue, generating X events from them.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* NSevents are used to generate X events, which are added to the
|
||||
* Tcl event queue.
|
||||
* NSevents are used to generate X events, which are added to the Tcl
|
||||
* event queue.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -334,38 +352,52 @@ TkMacOSXEventsCheckProc(
|
||||
int flags)
|
||||
{
|
||||
NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
|
||||
/* runloopMode will be nil if we are in a Tcl event loop. */
|
||||
|
||||
/*
|
||||
* runloopMode will be nil if we are in a Tcl event loop.
|
||||
*/
|
||||
|
||||
if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
|
||||
NSEvent *currentEvent = nil;
|
||||
NSEvent *testEvent = nil;
|
||||
NSModalSession modalSession;
|
||||
/* It is possible for the SetupProc to be called before this function
|
||||
|
||||
/*
|
||||
* It is possible for the SetupProc to be called before this function
|
||||
* returns. This happens, for example, when we process an event which
|
||||
* opens a modal window. To prevent premature release of our
|
||||
* application-wide autorelease pool by a nested call to the SetupProc,
|
||||
* we must lock it here.
|
||||
*/
|
||||
|
||||
[NSApp _lockAutoreleasePool];
|
||||
do {
|
||||
modalSession = TkMacOSXGetModalSession();
|
||||
testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:GetRunLoopMode(modalSession)
|
||||
dequeue:NO];
|
||||
/* We must not steal any events during LiveResize. */
|
||||
testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:GetRunLoopMode(modalSession)
|
||||
dequeue:NO];
|
||||
|
||||
/*
|
||||
* We must not steal any events during LiveResize.
|
||||
*/
|
||||
|
||||
if (testEvent && [[testEvent window] inLiveResize]) {
|
||||
break;
|
||||
}
|
||||
currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:GetRunLoopMode(modalSession)
|
||||
dequeue:YES];
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:GetRunLoopMode(modalSession)
|
||||
dequeue:YES];
|
||||
if (currentEvent) {
|
||||
/* Generate Xevents. */
|
||||
/*
|
||||
* Generate Xevents.
|
||||
*/
|
||||
|
||||
int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
|
||||
NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent];
|
||||
Tcl_SetServiceMode(oldServiceMode);
|
||||
if (processedEvent) { /* Should always be non-NULL. */
|
||||
if (processedEvent) {
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
TKLog(@" event: %@", currentEvent);
|
||||
#endif
|
||||
@@ -379,11 +411,14 @@ TkMacOSXEventsCheckProc(
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
/* Now we can unlock the pool. */
|
||||
|
||||
/*
|
||||
* Now we can unlock the pool.
|
||||
*/
|
||||
|
||||
[NSApp _unlockAutoreleasePool];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <math.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
@@ -110,12 +111,19 @@
|
||||
* no-op functions on the Macintosh.
|
||||
*/
|
||||
|
||||
#define XFlush(display)
|
||||
#define XFree(data) {if ((data) != NULL) ckfree(data);}
|
||||
#define XGrabServer(display)
|
||||
#define XNoOp(display) {display->request++;}
|
||||
#define XUngrabServer(display)
|
||||
#define XSynchronize(display, bool) {display->request++;}
|
||||
#undef XFlush
|
||||
#define XFlush(display) (0)
|
||||
#undef XFree
|
||||
#define XFree(data) (((data) != NULL) ? (ckfree(data),0) : 0)
|
||||
#undef XGrabServer
|
||||
#define XGrabServer(display) (0)
|
||||
#undef XNoOp
|
||||
#define XNoOp(display) (display->request++,0)
|
||||
#undef XUngrabServer
|
||||
#define XUngrabServer(display) (0)
|
||||
#undef XSynchronize
|
||||
#define XSynchronize(display, onoff) (display->request++,NULL)
|
||||
#undef XVisualIDFromVisual
|
||||
#define XVisualIDFromVisual(visual) (visual->visualid)
|
||||
|
||||
/*
|
||||
@@ -128,15 +136,15 @@
|
||||
#define TkpSync(display)
|
||||
|
||||
/*
|
||||
* The following macro returns the pixel value that corresponds to the
|
||||
* RGB values in the given XColor structure.
|
||||
* TkMacOSXGetCapture is a legacy function used on the Mac. When fixing
|
||||
* [943d5ebe51], TkpGetCapture was added to the Windows port. Both
|
||||
* are actually the same feature and should bear the same name. However,
|
||||
* in order to avoid potential backwards incompatibilities, renaming
|
||||
* TkMacOSXGetCapture into TkpGetCapture in *PlatDecls.h shall not be
|
||||
* done in a patch release, therefore use a define here.
|
||||
*/
|
||||
|
||||
#define PIXEL_MAGIC ((unsigned char) 0x69)
|
||||
#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \
|
||||
| (((p)->red >> 8) & 0xff)) << 8) \
|
||||
| (((p)->green >> 8) & 0xff)) << 8) \
|
||||
| (((p)->blue >> 8) & 0xff))
|
||||
#define TkpGetCapture TkMacOSXGetCapture
|
||||
|
||||
/*
|
||||
* This macro stores a representation of the window handle in a string.
|
||||
@@ -159,19 +167,20 @@
|
||||
*/
|
||||
|
||||
#define TRANSPARENT_PIXEL 30
|
||||
#define HIGHLIGHT_PIXEL 31
|
||||
#define HIGHLIGHT_SECONDARY_PIXEL 32
|
||||
#define HIGHLIGHT_TEXT_PIXEL 33
|
||||
#define HIGHLIGHT_ALTERNATE_PIXEL 34
|
||||
#define CONTROL_TEXT_PIXEL 35
|
||||
#define CONTROL_BODY_PIXEL 37
|
||||
#define CONTROL_FRAME_PIXEL 39
|
||||
#define WINDOW_BODY_PIXEL 41
|
||||
#define MENU_ACTIVE_PIXEL 43
|
||||
#define MENU_ACTIVE_TEXT_PIXEL 45
|
||||
#define MENU_BACKGROUND_PIXEL 47
|
||||
#define MENU_DISABLED_PIXEL 49
|
||||
#define MENU_TEXT_PIXEL 51
|
||||
#define APPEARANCE_PIXEL 52
|
||||
#define PIXEL_MAGIC ((unsigned char) 0x69)
|
||||
|
||||
/*
|
||||
* The following macro returns the pixel value that corresponds to the
|
||||
* 16-bit RGB values in the given XColor structure.
|
||||
* The format is: (PIXEL_MAGIC <<< 24) | (R << 16) | (G << 8) | B
|
||||
* where each of R, G and B is the high order byte of a 16-bit component.
|
||||
*/
|
||||
|
||||
#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \
|
||||
| (((p)->red >> 8) & 0xff)) << 8) \
|
||||
| (((p)->green >> 8) & 0xff)) << 8) \
|
||||
| (((p)->blue >> 8) & 0xff))
|
||||
|
||||
|
||||
#endif /* _TKMACPORT */
|
||||
|
||||
@@ -137,8 +137,6 @@ typedef struct TkMacOSXDrawingContext {
|
||||
* Variables internal to TkAqua.
|
||||
*/
|
||||
|
||||
MODULE_SCOPE CGFloat tkMacOSXZeroScreenHeight;
|
||||
MODULE_SCOPE CGFloat tkMacOSXZeroScreenTop;
|
||||
MODULE_SCOPE long tkMacOSXMacOSXVersion;
|
||||
|
||||
/*
|
||||
@@ -177,6 +175,8 @@ MODULE_SCOPE OSStatus TkMacOSHIShapeUnion(HIShapeRef inShape1,
|
||||
MODULE_SCOPE void * TkMacOSXGetNamedSymbol(const char *module,
|
||||
const char *symbol);
|
||||
MODULE_SCOPE void TkMacOSXDisplayChanged(Display *display);
|
||||
MODULE_SCOPE CGFloat TkMacOSXZeroScreenHeight();
|
||||
MODULE_SCOPE CGFloat TkMacOSXZeroScreenTop();
|
||||
MODULE_SCOPE int TkMacOSXUseAntialiasedText(Tcl_Interp *interp,
|
||||
int enable);
|
||||
MODULE_SCOPE int TkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable,
|
||||
@@ -233,6 +233,16 @@ MODULE_SCOPE int TkMacOSXStandardAboutPanelObjCmd(ClientData clientData,
|
||||
MODULE_SCOPE int TkMacOSXIconBitmapObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
MODULE_SCOPE void TkMacOSXDrawSolidBorder(Tk_Window tkwin, GC gc,
|
||||
int inset, int thickness);
|
||||
MODULE_SCOPE int TkMacOSXServices_Init(Tcl_Interp *interp);
|
||||
MODULE_SCOPE int TkMacOSXRegisterServiceWidgetObjCmd(ClientData clientData,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
MODULE_SCOPE NSString* TclUniToNSString(const char *source, int numBytes);
|
||||
MODULE_SCOPE int TclUniAtIndex(NSString *string, int index, char *uni,
|
||||
unsigned int *code);
|
||||
MODULE_SCOPE char* NSStringToTclUni(NSString *string, int *numBytes);
|
||||
|
||||
#pragma mark Private Objective-C Classes
|
||||
|
||||
@@ -250,28 +260,29 @@ VISIBILITY_HIDDEN
|
||||
- (BOOL)isSpecial:(NSUInteger)special;
|
||||
@end
|
||||
|
||||
@interface TKMenu(TKMenuDelegate) <NSMenuDelegate>
|
||||
@end
|
||||
|
||||
VISIBILITY_HIDDEN
|
||||
@interface TKApplication : NSApplication {
|
||||
@private
|
||||
Tcl_Interp *_eventInterp;
|
||||
NSMenu *_servicesMenu;
|
||||
TKMenu *_defaultMainMenu, *_defaultApplicationMenu;
|
||||
NSMenuItem *_demoMenuItem;
|
||||
NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
|
||||
NSArray *_defaultHelpMenuItems;
|
||||
NSWindow *_windowWithMouse;
|
||||
NSArray *_defaultHelpMenuItems, *_defaultFileMenuItems;
|
||||
NSAutoreleasePool *_mainPool;
|
||||
#ifdef __i386__
|
||||
/* The Objective C runtime used on i386 requires this. */
|
||||
int _poolLock;
|
||||
int _macMinorVersion;
|
||||
Bool _isDrawing;
|
||||
Bool _simulateDrawing;
|
||||
#endif
|
||||
}
|
||||
@property int poolLock;
|
||||
@property int macMinorVersion;
|
||||
@property Bool isDrawing;
|
||||
@property Bool simulateDrawing;
|
||||
|
||||
@end
|
||||
@interface TKApplication(TKInit)
|
||||
@@ -280,6 +291,24 @@ VISIBILITY_HIDDEN
|
||||
- (void)_lockAutoreleasePool;
|
||||
- (void)_unlockAutoreleasePool;
|
||||
@end
|
||||
@interface TKApplication(TKKeyboard)
|
||||
- (void) keyboardChanged: (NSNotification *) notification;
|
||||
@end
|
||||
@interface TKApplication(TKWindowEvent) <NSApplicationDelegate>
|
||||
- (void) _setupWindowNotifications;
|
||||
@end
|
||||
@interface TKApplication(TKDialog) <NSOpenSavePanelDelegate>
|
||||
@end
|
||||
@interface TKApplication(TKMenu)
|
||||
- (void)tkSetMainMenu:(TKMenu *)menu;
|
||||
@end
|
||||
@interface TKApplication(TKMenus)
|
||||
- (void) _setupMenus;
|
||||
@end
|
||||
@interface NSApplication(TKNotify)
|
||||
/* We need to declare this hidden method. */
|
||||
- (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event;
|
||||
@end
|
||||
@interface TKApplication(TKEvent)
|
||||
- (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;
|
||||
@end
|
||||
@@ -289,9 +318,6 @@ VISIBILITY_HIDDEN
|
||||
@interface TKApplication(TKKeyEvent)
|
||||
- (NSEvent *)tkProcessKeyEvent:(NSEvent *)theEvent;
|
||||
@end
|
||||
@interface TKApplication(TKMenu)
|
||||
- (void)tkSetMainMenu:(TKMenu *)menu;
|
||||
@end
|
||||
@interface TKApplication(TKClipboard)
|
||||
- (void)tkProvidePasteboard:(TkDisplay *)dispPtr;
|
||||
- (void)tkCheckPasteboard;
|
||||
@@ -313,18 +339,23 @@ VISIBILITY_HIDDEN
|
||||
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
|
||||
- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
|
||||
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
|
||||
- (void)handleURLEvent: (NSAppleEventDescriptor*)event
|
||||
withReplyEvent: (NSAppleEventDescriptor*)replyEvent;
|
||||
@end
|
||||
|
||||
VISIBILITY_HIDDEN
|
||||
@interface TKContentView : NSView <NSTextInput> {
|
||||
/*
|
||||
* Subclass TKContentView from NSTextInputClient to enable composition and
|
||||
* input from the Character Palette.
|
||||
*/
|
||||
|
||||
@interface TKContentView : NSView <NSTextInputClient>
|
||||
{
|
||||
@private
|
||||
/*Remove private API calls.*/
|
||||
#if 0
|
||||
id _savedSubviews;
|
||||
BOOL _subviewsSetAside;
|
||||
#endif
|
||||
NSString *privateWorkingText;
|
||||
Bool _needsRedisplay;
|
||||
}
|
||||
@property Bool needsRedisplay;
|
||||
@end
|
||||
|
||||
@interface TKContentView(TKKeyEvent)
|
||||
@@ -332,22 +363,27 @@ VISIBILITY_HIDDEN
|
||||
@end
|
||||
|
||||
@interface TKContentView(TKWindowEvent)
|
||||
- (void) drawRect: (NSRect) rect;
|
||||
- (void) generateExposeEvents: (HIShapeRef) shape;
|
||||
- (void) generateExposeEvents: (HIShapeRef) shape;
|
||||
- (void) tkToolbarButton: (id) sender;
|
||||
- (BOOL) isOpaque;
|
||||
- (BOOL) wantsDefaultClipping;
|
||||
- (BOOL) acceptsFirstResponder;
|
||||
- (void) keyDown: (NSEvent *) theEvent;
|
||||
@end
|
||||
|
||||
@interface NSWindow(TKWm)
|
||||
- (NSPoint) tkConvertPointToScreen:(NSPoint)point;
|
||||
- (NSPoint) tkConvertPointFromScreen:(NSPoint)point;
|
||||
@end
|
||||
|
||||
VISIBILITY_HIDDEN
|
||||
@interface TKWindow : NSWindow
|
||||
@end
|
||||
|
||||
@interface NSWindow(TKWm)
|
||||
- (NSPoint) tkConvertPointToScreen:(NSPoint)point;
|
||||
- (NSPoint) tkConvertPointFromScreen:(NSPoint)point;
|
||||
@interface TKWindow(TKWm)
|
||||
- (void) tkLayoutChanged;
|
||||
@end
|
||||
|
||||
@interface NSDrawerWindow : NSWindow
|
||||
{
|
||||
id _i1, _i2;
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma mark NSMenu & NSMenuItem Utilities
|
||||
@@ -378,4 +414,34 @@ VISIBILITY_HIDDEN
|
||||
keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask;
|
||||
@end
|
||||
|
||||
@interface NSColorPanel(TKDialog)
|
||||
- (void) _setUseModalAppearance: (BOOL) flag;
|
||||
@end
|
||||
|
||||
@interface NSFont(TKFont)
|
||||
- (NSFont *) bestMatchingFontForCharacters: (const UTF16Char *) characters
|
||||
length: (NSUInteger) length attributes: (NSDictionary *) attributes
|
||||
actualCoveredLength: (NSUInteger *) coveredLength;
|
||||
@end
|
||||
|
||||
/*
|
||||
* This method of NSApplication is not declared in NSApplication.h so we
|
||||
* declare it here to be a method of the TKMenu category.
|
||||
*/
|
||||
|
||||
@interface NSApplication(TKMenu)
|
||||
- (void) setAppleMenu: (NSMenu *) menu;
|
||||
@end
|
||||
|
||||
#endif /* _TKMACPRIV */
|
||||
|
||||
int TkMacOSXGetAppPath(ClientData cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]);
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 79
|
||||
* coding: utf-8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -54,13 +54,14 @@ TkCreateRegion(void)
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
TkDestroyRegion(
|
||||
TkRegion r)
|
||||
{
|
||||
if (r) {
|
||||
CFRelease(r);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -80,7 +81,7 @@ TkDestroyRegion(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
TkIntersectRegion(
|
||||
TkRegion sra,
|
||||
TkRegion srb,
|
||||
@@ -88,6 +89,7 @@ TkIntersectRegion(
|
||||
{
|
||||
ChkErr(HIShapeIntersect, (HIShapeRef) sra, (HIShapeRef) srb,
|
||||
(HIMutableShapeRef) dr_return);
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -107,7 +109,7 @@ TkIntersectRegion(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
TkSubtractRegion(
|
||||
TkRegion sra,
|
||||
TkRegion srb,
|
||||
@@ -115,6 +117,7 @@ TkSubtractRegion(
|
||||
{
|
||||
ChkErr(HIShapeDifference, (HIShapeRef) sra, (HIShapeRef) srb,
|
||||
(HIMutableShapeRef) dr_return);
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -134,7 +137,7 @@ TkSubtractRegion(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
TkUnionRectWithRegion(
|
||||
XRectangle* rectangle,
|
||||
TkRegion src_region,
|
||||
@@ -153,6 +156,7 @@ TkUnionRectWithRegion(
|
||||
(HIMutableShapeRef) dest_region_return);
|
||||
CFRelease(rectRgn);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -187,8 +191,8 @@ TkMacOSXIsEmptyRegion(
|
||||
* Xwindow documentation for more details.
|
||||
*
|
||||
* Results:
|
||||
* Returns RectanglePart or RectangleOut. Note that this is not a
|
||||
* complete implementation since it doesn't test for RectangleIn.
|
||||
* Returns RectanglePart or RectangleOut. Note that this is not a complete
|
||||
* implementation since it doesn't test for RectangleIn.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
@@ -204,13 +208,13 @@ TkRectInRegion(
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
{
|
||||
if ( TkMacOSXIsEmptyRegion(region) ) {
|
||||
return RectangleOut;
|
||||
}
|
||||
else {
|
||||
if (TkMacOSXIsEmptyRegion(region)) {
|
||||
return RectangleOut;
|
||||
} else {
|
||||
const CGRect r = CGRectMake(x, y, width, height);
|
||||
|
||||
return HIShapeIntersectsRect((HIShapeRef) region, &r) ?
|
||||
RectanglePart : RectangleOut;
|
||||
RectanglePart : RectangleOut;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,10 +235,10 @@ TkRectInRegion(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
TkClipBox(
|
||||
TkRegion r,
|
||||
XRectangle* rect_return)
|
||||
XRectangle *rect_return)
|
||||
{
|
||||
CGRect rect;
|
||||
|
||||
@@ -243,6 +247,7 @@ TkClipBox(
|
||||
rect_return->y = rect.origin.y;
|
||||
rect_return->width = rect.size.width;
|
||||
rect_return->height = rect.size.height;
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -51,10 +51,10 @@ static ControlActionUPP scaleActionProc = NULL; /* Pointer to func. */
|
||||
* Forward declarations for procedures defined later in this file:
|
||||
*/
|
||||
|
||||
static void MacScaleEventProc(ClientData clientData, XEvent *eventPtr);
|
||||
static pascal void ScaleActionProc(ControlRef theControl,
|
||||
ControlPartCode partCode);
|
||||
|
||||
static void MacScaleEventProc(ClientData clientData,
|
||||
XEvent *eventPtr);
|
||||
static pascal void ScaleActionProc(ControlRef theControl,
|
||||
ControlPartCode partCode);
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -84,7 +84,7 @@ TkpCreateScale(
|
||||
}
|
||||
|
||||
Tk_CreateEventHandler(tkwin, ButtonPressMask,
|
||||
MacScaleEventProc, (ClientData) macScalePtr);
|
||||
MacScaleEventProc, macScalePtr);
|
||||
|
||||
return (TkScale *) macScalePtr;
|
||||
}
|
||||
@@ -125,8 +125,8 @@ TkpDestroyScale(
|
||||
*
|
||||
* TkpDisplayScale --
|
||||
*
|
||||
* This procedure is invoked as an idle handler to redisplay
|
||||
* the contents of a scale widget.
|
||||
* This procedure is invoked as an idle handler to redisplay the contents
|
||||
* of a scale widget.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -141,12 +141,12 @@ void
|
||||
TkpDisplayScale(
|
||||
ClientData clientData) /* Widget record for scale. */
|
||||
{
|
||||
TkScale *scalePtr = (TkScale *) clientData;
|
||||
TkScale *scalePtr = clientData;
|
||||
Tk_Window tkwin = scalePtr->tkwin;
|
||||
Tcl_Interp *interp = scalePtr->interp;
|
||||
int result;
|
||||
char string[TCL_DOUBLE_SPACE];
|
||||
MacScale *macScalePtr = (MacScale *) clientData;
|
||||
MacScale *macScalePtr = clientData;
|
||||
Rect r;
|
||||
WindowRef windowRef;
|
||||
CGrafPtr destPort, savePort;
|
||||
@@ -168,9 +168,9 @@ TkpDisplayScale(
|
||||
* Invoke the scale's command if needed.
|
||||
*/
|
||||
|
||||
Tcl_Preserve((ClientData) scalePtr);
|
||||
Tcl_Preserve(scalePtr);
|
||||
if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
|
||||
Tcl_Preserve((ClientData) interp);
|
||||
Tcl_Preserve(interp);
|
||||
if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format,
|
||||
scalePtr->value) < 0) {
|
||||
string[TCL_DOUBLE_SPACE - 1] = '\0';
|
||||
@@ -185,19 +185,18 @@ TkpDisplayScale(
|
||||
Tcl_AddErrorInfo(interp, "\n (command executed by scale)");
|
||||
Tcl_BackgroundException(interp, result);
|
||||
}
|
||||
Tcl_Release((ClientData) interp);
|
||||
Tcl_Release(interp);
|
||||
}
|
||||
scalePtr->flags &= ~INVOKE_COMMAND;
|
||||
if (scalePtr->flags & SCALE_DELETED) {
|
||||
Tcl_Release((ClientData) scalePtr);
|
||||
Tcl_Release(scalePtr);
|
||||
return;
|
||||
}
|
||||
Tcl_Release((ClientData) scalePtr);
|
||||
Tcl_Release(scalePtr);
|
||||
|
||||
/*
|
||||
* Now handle the part of redisplay that is the same for
|
||||
* horizontal and vertical scales: border and traversal
|
||||
* highlight.
|
||||
* Now handle the part of redisplay that is the same for horizontal and
|
||||
* vertical scales: border and traversal highlight.
|
||||
*/
|
||||
|
||||
if (scalePtr->highlightWidth != 0) {
|
||||
@@ -229,7 +228,7 @@ TkpDisplayScale(
|
||||
#define MAC_OSX_SCROLL_WIDTH 10
|
||||
|
||||
if (scalePtr->orient == ORIENT_HORIZONTAL) {
|
||||
int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH)/2;
|
||||
int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2;
|
||||
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
@@ -240,7 +239,7 @@ TkpDisplayScale(
|
||||
r.right = macDraw->xOff+Tk_Width(tkwin) - scalePtr->inset;
|
||||
r.bottom = macDraw->yOff + offset + MAC_OSX_SCROLL_WIDTH/2;
|
||||
} else {
|
||||
int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH)/2;
|
||||
int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2;
|
||||
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
@@ -249,7 +248,7 @@ TkpDisplayScale(
|
||||
r.left = macDraw->xOff + offset;
|
||||
r.top = macDraw->yOff + scalePtr->inset;
|
||||
r.right = macDraw->xOff + offset + MAC_OSX_SCROLL_WIDTH/2;
|
||||
r.bottom = macDraw->yOff+Tk_Height(tkwin) - scalePtr->inset;
|
||||
r.bottom = macDraw->yOff + Tk_Height(tkwin) - scalePtr->inset;
|
||||
}
|
||||
|
||||
if (macScalePtr->scaleHandle == NULL) {
|
||||
@@ -273,7 +272,7 @@ TkpDisplayScale(
|
||||
|
||||
CreateSliderControl(windowRef, &r, initialValue, minValue, maxValue,
|
||||
kControlSliderPointsDownOrRight, numTicks, 1, scaleActionProc,
|
||||
&(macScalePtr->scaleHandle));
|
||||
&macScalePtr->scaleHandle);
|
||||
SetControlReference(macScalePtr->scaleHandle, (UInt32) scalePtr);
|
||||
|
||||
if (IsWindowActive(windowRef)) {
|
||||
@@ -290,8 +289,8 @@ TkpDisplayScale(
|
||||
* Finally draw the control.
|
||||
*/
|
||||
|
||||
SetControlVisibility(macScalePtr->scaleHandle,true,true);
|
||||
HiliteControl(macScalePtr->scaleHandle,0);
|
||||
SetControlVisibility(macScalePtr->scaleHandle, true, true);
|
||||
HiliteControl(macScalePtr->scaleHandle, 0);
|
||||
Draw1Control(macScalePtr->scaleHandle);
|
||||
|
||||
if (portChanged) {
|
||||
@@ -306,13 +305,12 @@ done:
|
||||
*
|
||||
* TkpScaleElement --
|
||||
*
|
||||
* Determine which part of a scale widget lies under a given
|
||||
* point.
|
||||
* Determine which part of a scale widget lies under a given point.
|
||||
*
|
||||
* Results:
|
||||
* The return value is either TROUGH1, SLIDER, TROUGH2, or
|
||||
* OTHER, depending on which of the scale's active elements
|
||||
* (if any) is under the point at (x,y).
|
||||
* The return value is either TROUGH1, SLIDER, TROUGH2, or OTHER,
|
||||
* depending on which of the scale's active elements (if any) is under the
|
||||
* point at (x,y).
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
@@ -357,22 +355,22 @@ TkpScaleElement(
|
||||
#endif
|
||||
|
||||
switch (part) {
|
||||
case inSlider:
|
||||
return SLIDER;
|
||||
case inInc:
|
||||
if (scalePtr->orient == ORIENT_VERTICAL) {
|
||||
return TROUGH1;
|
||||
} else {
|
||||
return TROUGH2;
|
||||
}
|
||||
case inDecr:
|
||||
if (scalePtr->orient == ORIENT_VERTICAL) {
|
||||
return TROUGH2;
|
||||
} else {
|
||||
return TROUGH1;
|
||||
}
|
||||
default:
|
||||
return OTHER;
|
||||
case inSlider:
|
||||
return SLIDER;
|
||||
case inInc:
|
||||
if (scalePtr->orient == ORIENT_VERTICAL) {
|
||||
return TROUGH1;
|
||||
} else {
|
||||
return TROUGH2;
|
||||
}
|
||||
case inDecr:
|
||||
if (scalePtr->orient == ORIENT_VERTICAL) {
|
||||
return TROUGH2;
|
||||
} else {
|
||||
return TROUGH1;
|
||||
}
|
||||
default:
|
||||
return OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,15 +379,15 @@ TkpScaleElement(
|
||||
*
|
||||
* MacScaleEventProc --
|
||||
*
|
||||
* This procedure is invoked by the Tk dispatcher for
|
||||
* ButtonPress events on scales.
|
||||
* This procedure is invoked by the Tk dispatcher for ButtonPress events
|
||||
* on scales.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* When the window gets deleted, internal structures get
|
||||
* cleaned up. When it gets exposed, it is redisplayed.
|
||||
* When the window gets deleted, internal structures get cleaned up. When
|
||||
* it gets exposed, it is redisplayed.
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
@@ -411,9 +409,9 @@ MacScaleEventProc(
|
||||
#endif
|
||||
|
||||
/*
|
||||
* To call Macintosh control routines we must have the port
|
||||
* set to the window containing the control. We will then test
|
||||
* which part of the control was hit and act accordingly.
|
||||
* To call Macintosh control routines we must have the port set to the
|
||||
* window containing the control. We will then test which part of the
|
||||
* control was hit and act accordingly.
|
||||
*/
|
||||
|
||||
destPort = TkMacOSXGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin));
|
||||
@@ -461,8 +459,8 @@ MacScaleEventProc(
|
||||
* ScaleActionProc --
|
||||
*
|
||||
* Callback procedure used by the Macintosh toolbox call
|
||||
* HandleControlClick. This call will update the display
|
||||
* while the scrollbar is being manipulated by the user.
|
||||
* HandleControlClick. This call will update the display while the
|
||||
* scrollbar is being manipulated by the user.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -486,9 +484,9 @@ ScaleActionProc(
|
||||
#endif
|
||||
value = GetControlValue(theControl);
|
||||
TkScaleSetValue(scalePtr, value, 1, 1);
|
||||
Tcl_Preserve((ClientData) scalePtr);
|
||||
Tcl_Preserve(scalePtr);
|
||||
TkMacOSXRunTclEventLoop();
|
||||
Tcl_Release((ClientData) scalePtr);
|
||||
Tcl_Release(scalePtr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
* Copyright 2001-2009, Apple Inc.
|
||||
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
|
||||
* Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC.
|
||||
* Copyright (c) 2018 Marc Culler
|
||||
* Copyright (c) 2018-2019 Marc Culler
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
@@ -17,28 +18,29 @@
|
||||
#include "tkScrollbar.h"
|
||||
#include "tkMacOSXPrivate.h"
|
||||
|
||||
|
||||
#define MIN_SCROLLBAR_VALUE 0
|
||||
|
||||
/*
|
||||
* Minimum slider length, in pixels (designed to make sure that the slider is
|
||||
* always easy to grab with the mouse).
|
||||
*/
|
||||
|
||||
#define MIN_SLIDER_LENGTH 5
|
||||
#define MIN_SLIDER_LENGTH 18
|
||||
#define MIN_GAP 4
|
||||
|
||||
/*
|
||||
* Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.
|
||||
*/
|
||||
|
||||
/*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.*/
|
||||
#ifdef __LP64__
|
||||
#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum))
|
||||
#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum))
|
||||
#else
|
||||
#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum))
|
||||
#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum))
|
||||
#endif /* __LP64__ */
|
||||
|
||||
/*
|
||||
* Apple reversed the scroll direction with the release of OSX 10.7 Lion.
|
||||
*/
|
||||
|
||||
#define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138)
|
||||
#define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138)
|
||||
|
||||
/*
|
||||
* Declaration of an extended scrollbar structure with Mac specific additions.
|
||||
@@ -48,9 +50,9 @@ typedef struct MacScrollbar {
|
||||
TkScrollbar information; /* Generic scrollbar info. */
|
||||
GC troughGC; /* For drawing trough. */
|
||||
GC copyGC; /* Used for copying from pixmap onto screen. */
|
||||
Bool buttonDown; /* Is the mouse button down? */
|
||||
Bool buttonDown; /* Is the mouse button down? */
|
||||
Bool mouseOver; /* Is the pointer over the scrollbar. */
|
||||
HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */
|
||||
HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */
|
||||
} MacScrollbar;
|
||||
|
||||
/* Used to initialize a MacScrollbar's info field. */
|
||||
@@ -69,33 +71,36 @@ HIThemeTrackDrawInfo defaultInfo = {
|
||||
|
||||
const Tk_ClassProcs tkpScrollbarProcs = {
|
||||
sizeof(Tk_ClassProcs), /* size */
|
||||
NULL, /* worldChangedProc */
|
||||
NULL, /* createProc */
|
||||
NULL /* modalProc */
|
||||
NULL, /* worldChangedProc */
|
||||
NULL, /* createProc */
|
||||
NULL /* modalProc */
|
||||
};
|
||||
|
||||
/*
|
||||
* Information on scrollbar layout, metrics, and draw info.
|
||||
*/
|
||||
|
||||
/* Information on scrollbar layout, metrics, and draw info.*/
|
||||
typedef struct ScrollbarMetrics {
|
||||
SInt32 width, minThumbHeight;
|
||||
int minHeight, topArrowHeight, bottomArrowHeight;
|
||||
NSControlSize controlSize;
|
||||
} ScrollbarMetrics;
|
||||
|
||||
|
||||
static ScrollbarMetrics metrics = {
|
||||
15, 54, 26, 14, 14, kControlSizeNormal /* kThemeScrollBarMedium */
|
||||
/* kThemeScrollBarMedium */
|
||||
15, MIN_SLIDER_LENGTH, 26, 14, 14, kControlSizeNormal
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Declarations of static functions defined later in this file:
|
||||
*/
|
||||
|
||||
static void ScrollbarEventProc(ClientData clientData, XEvent *eventPtr);
|
||||
static int ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr);
|
||||
static void UpdateControlValues(TkScrollbar *scrollPtr);
|
||||
|
||||
static void ScrollbarEventProc(ClientData clientData,
|
||||
XEvent *eventPtr);
|
||||
static int ScrollbarEvent(TkScrollbar *scrollPtr,
|
||||
XEvent *eventPtr);
|
||||
static void UpdateControlValues(TkScrollbar *scrollPtr);
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -114,26 +119,25 @@ static void UpdateControlValues(TkScrollbar *scrollPtr);
|
||||
|
||||
TkScrollbar *
|
||||
TkpCreateScrollbar(
|
||||
Tk_Window tkwin)
|
||||
Tk_Window tkwin)
|
||||
{
|
||||
MacScrollbar *scrollPtr = ckalloc(sizeof(MacScrollbar));
|
||||
|
||||
MacScrollbar *scrollPtr = (MacScrollbar *)ckalloc(sizeof(MacScrollbar));
|
||||
|
||||
scrollPtr->troughGC = None;
|
||||
scrollPtr->copyGC = None;
|
||||
scrollPtr->troughGC = NULL;
|
||||
scrollPtr->copyGC = NULL;
|
||||
scrollPtr->info = defaultInfo;
|
||||
scrollPtr->buttonDown = false;
|
||||
|
||||
|
||||
Tk_CreateEventHandler(tkwin,
|
||||
ExposureMask |
|
||||
StructureNotifyMask |
|
||||
FocusChangeMask |
|
||||
ButtonPressMask |
|
||||
ButtonReleaseMask |
|
||||
EnterWindowMask |
|
||||
LeaveWindowMask |
|
||||
VisibilityChangeMask,
|
||||
ScrollbarEventProc, scrollPtr);
|
||||
ExposureMask |
|
||||
StructureNotifyMask |
|
||||
FocusChangeMask |
|
||||
ButtonPressMask |
|
||||
ButtonReleaseMask |
|
||||
EnterWindowMask |
|
||||
LeaveWindowMask |
|
||||
VisibilityChangeMask,
|
||||
ScrollbarEventProc, scrollPtr);
|
||||
|
||||
return (TkScrollbar *) scrollPtr;
|
||||
}
|
||||
@@ -144,8 +148,8 @@ TkpCreateScrollbar(
|
||||
* TkpDisplayScrollbar --
|
||||
*
|
||||
* This procedure redraws the contents of a scrollbar window. It is
|
||||
* invoked as a do-when-idle handler, so it only runs when there's
|
||||
* nothing else for the application to do.
|
||||
* invoked as a do-when-idle handler, so it only runs when there's nothing
|
||||
* else for the application to do.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -156,11 +160,93 @@ TkpCreateScrollbar(
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080
|
||||
|
||||
/*
|
||||
* This stand-alone drawing function is used on macOS 10.9 and newer because
|
||||
* the HIToolbox does not draw the scrollbar thumb at the expected size on
|
||||
* those systems. The thumb is drawn too large, causing a mouse click on the
|
||||
* thumb to be interpreted as a mouse click in the trough.
|
||||
*/
|
||||
|
||||
static void drawMacScrollbar(
|
||||
TkScrollbar *scrollPtr,
|
||||
MacScrollbar *msPtr,
|
||||
CGContextRef context)
|
||||
{
|
||||
MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
|
||||
NSView *view = TkMacOSXDrawableView(macWin);
|
||||
CGPathRef path;
|
||||
CGPoint inner[2], outer[2], thumbOrigin;
|
||||
CGSize thumbSize;
|
||||
CGRect troughBounds = msPtr->info.bounds;
|
||||
troughBounds.origin.y = [view bounds].size.height -
|
||||
(troughBounds.origin.y + troughBounds.size.height);
|
||||
if (scrollPtr->vertical) {
|
||||
thumbOrigin.x = troughBounds.origin.x + MIN_GAP;
|
||||
thumbOrigin.y = troughBounds.origin.y + scrollPtr->sliderFirst;
|
||||
thumbSize.width = troughBounds.size.width - 2*MIN_GAP + 1;
|
||||
thumbSize.height = scrollPtr->sliderLast - scrollPtr->sliderFirst;
|
||||
inner[0] = troughBounds.origin;
|
||||
inner[1] = CGPointMake(inner[0].x,
|
||||
inner[0].y + troughBounds.size.height);
|
||||
outer[0] = CGPointMake(inner[0].x + troughBounds.size.width - 1,
|
||||
inner[0].y);
|
||||
outer[1] = CGPointMake(outer[0].x, inner[1].y);
|
||||
} else {
|
||||
thumbOrigin.x = troughBounds.origin.x + scrollPtr->sliderFirst;
|
||||
thumbOrigin.y = troughBounds.origin.y + MIN_GAP;
|
||||
thumbSize.width = scrollPtr->sliderLast - scrollPtr->sliderFirst;
|
||||
thumbSize.height = troughBounds.size.height - 2*MIN_GAP + 1;
|
||||
inner[0] = troughBounds.origin;
|
||||
inner[1] = CGPointMake(inner[0].x + troughBounds.size.width,
|
||||
inner[0].y + 1);
|
||||
outer[0] = CGPointMake(inner[0].x,
|
||||
inner[0].y + troughBounds.size.height);
|
||||
outer[1] = CGPointMake(inner[1].x, outer[0].y);
|
||||
}
|
||||
CGContextSetShouldAntialias(context, false);
|
||||
CGContextSetGrayFillColor(context, 250.0 / 255, 1.0);
|
||||
CGContextFillRect(context, troughBounds);
|
||||
CGContextSetGrayStrokeColor(context, 232.0 / 255, 1.0);
|
||||
CGContextStrokeLineSegments(context, inner, 2);
|
||||
CGContextSetGrayStrokeColor(context, 238.0 / 255, 1.0);
|
||||
CGContextStrokeLineSegments(context, outer, 2);
|
||||
|
||||
/*
|
||||
* Do not display the thumb unless scrolling is possible, in accordance
|
||||
* with macOS behavior.
|
||||
*
|
||||
* Native scrollbars and Ttk scrollbars are always 15 pixels wide, but we
|
||||
* allow Tk scrollbars to have any width, even if it looks bad. To prevent
|
||||
* sporadic assertion errors when drawing skinny thumbs we must make sure
|
||||
* the radius is at most half the width.
|
||||
*/
|
||||
|
||||
if (scrollPtr->firstFraction > 0.0 || scrollPtr->lastFraction < 1.0) {
|
||||
CGRect thumbBounds = {thumbOrigin, thumbSize};
|
||||
int width = scrollPtr->vertical ? thumbSize.width : thumbSize.height;
|
||||
int radius = width >= 8 ? 4 : width >> 1;
|
||||
path = CGPathCreateWithRoundedRect(thumbBounds, radius, radius, NULL);
|
||||
CGContextBeginPath(context);
|
||||
CGContextAddPath(context, path);
|
||||
if (msPtr->info.trackInfo.scrollbar.pressState != 0) {
|
||||
CGContextSetGrayFillColor(context, 133.0 / 255, 1.0);
|
||||
} else {
|
||||
CGContextSetGrayFillColor(context, 200.0 / 255, 1.0);
|
||||
}
|
||||
CGContextSetShouldAntialias(context, true);
|
||||
CGContextFillPath(context);
|
||||
CFRelease(path);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
TkpDisplayScrollbar(
|
||||
ClientData clientData) /* Information about window. */
|
||||
ClientData clientData) /* Information about window. */
|
||||
{
|
||||
register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
|
||||
register TkScrollbar *scrollPtr = clientData;
|
||||
MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
|
||||
register Tk_Window tkwin = scrollPtr->tkwin;
|
||||
TkWindow *winPtr = (TkWindow *) tkwin;
|
||||
@@ -169,23 +255,35 @@ TkpDisplayScrollbar(
|
||||
scrollPtr->flags &= ~REDRAW_PENDING;
|
||||
|
||||
if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
MacDrawable *macWin = (MacDrawable *) winPtr->window;
|
||||
MacDrawable *macWin = (MacDrawable *) winPtr->window;
|
||||
NSView *view = TkMacOSXDrawableView(macWin);
|
||||
if (!view ||
|
||||
macWin->flags & TK_DO_NOT_DRAW ||
|
||||
!TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
|
||||
return;
|
||||
|
||||
if ((view == NULL)
|
||||
|| (macWin->flags & TK_DO_NOT_DRAW)
|
||||
|| !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform NSView coordinates to CoreGraphics coordinates.
|
||||
*/
|
||||
|
||||
CGFloat viewHeight = [view bounds].size.height;
|
||||
CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
|
||||
.ty = viewHeight};
|
||||
CGAffineTransform t = {
|
||||
.a = 1, .b = 0,
|
||||
.c = 0, .d = -1,
|
||||
.tx = 0, .ty = viewHeight
|
||||
};
|
||||
|
||||
CGContextConcatCTM(dc.context, t);
|
||||
|
||||
/*Draw a 3D rectangle to provide a base for the native scrollbar.*/
|
||||
/*
|
||||
* Draw a 3D rectangle to provide a base for the native scrollbar.
|
||||
*/
|
||||
|
||||
if (scrollPtr->highlightWidth != 0) {
|
||||
GC fgGC, bgGC;
|
||||
|
||||
@@ -196,32 +294,46 @@ TkpDisplayScrollbar(
|
||||
fgGC = bgGC;
|
||||
}
|
||||
TkpDrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth,
|
||||
(Pixmap) macWin);
|
||||
(Pixmap) macWin);
|
||||
}
|
||||
|
||||
Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
|
||||
scrollPtr->highlightWidth, scrollPtr->highlightWidth,
|
||||
Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
|
||||
Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
|
||||
scrollPtr->borderWidth, scrollPtr->relief);
|
||||
scrollPtr->highlightWidth, scrollPtr->highlightWidth,
|
||||
Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
|
||||
Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
|
||||
scrollPtr->borderWidth, scrollPtr->relief);
|
||||
Tk_Fill3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
|
||||
scrollPtr->inset, scrollPtr->inset,
|
||||
Tk_Width(tkwin) - 2*scrollPtr->inset,
|
||||
Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT);
|
||||
scrollPtr->inset, scrollPtr->inset,
|
||||
Tk_Width(tkwin) - 2*scrollPtr->inset,
|
||||
Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT);
|
||||
|
||||
/*
|
||||
* Update values and then draw the native scrollbar over the rectangle.
|
||||
*/
|
||||
|
||||
/* Update values and then draw the native scrollbar over the rectangle.*/
|
||||
UpdateControlValues(scrollPtr);
|
||||
|
||||
if (SNOW_LEOPARD_STYLE) {
|
||||
HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationInverted);
|
||||
HIThemeDrawTrack(&msPtr->info, 0, dc.context,
|
||||
kHIThemeOrientationInverted);
|
||||
} else if ([NSApp macMinorVersion] <= 8) {
|
||||
HIThemeDrawTrack(&msPtr->info, 0, dc.context,
|
||||
kHIThemeOrientationNormal);
|
||||
} else {
|
||||
HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationNormal);
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > 1080
|
||||
|
||||
/*
|
||||
* Switch back to NSView coordinates and draw a modern scrollbar.
|
||||
*/
|
||||
|
||||
CGContextConcatCTM(dc.context, t);
|
||||
drawMacScrollbar(scrollPtr, msPtr, dc.context);
|
||||
#endif
|
||||
}
|
||||
TkMacOSXRestoreDrawingContext(&dc);
|
||||
|
||||
scrollPtr->flags &= ~REDRAW_PENDING;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -240,65 +352,63 @@ TkpDisplayScrollbar(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
extern void
|
||||
TkpComputeScrollbarGeometry(
|
||||
register TkScrollbar *scrollPtr)
|
||||
/* Scrollbar whose geometry may have
|
||||
* changed. */
|
||||
/* Scrollbar whose geometry may have
|
||||
* changed. */
|
||||
{
|
||||
|
||||
/*
|
||||
* The code below is borrowed from tkUnixScrlbr.c but has been adjusted to
|
||||
* account for some differences between macOS and X11. The Unix scrollbar
|
||||
* has an arrow button on each end. On macOS 10.6 (Snow Leopard) the
|
||||
* scrollbars by default have both arrow buttons at the bottom or right.
|
||||
* (There is a preferences setting to use the Unix layout, but we are not
|
||||
* supporting that!) On more recent versions of macOS there are no arrow
|
||||
* buttons at all. The case of no arrow buttons can be handled as a special
|
||||
* case of having both buttons at the end, but where scrollPtr->arrowLength
|
||||
* happens to be zero. To adjust for having both arrows at the same end we
|
||||
* shift the scrollbar up by the arrowLength.
|
||||
*/
|
||||
/*
|
||||
* The code below is borrowed from tkUnixScrlbr.c but has been adjusted to
|
||||
* account for some differences between macOS and X11. The Unix scrollbar
|
||||
* has an arrow button on each end. On macOS 10.6 (Snow Leopard) the
|
||||
* scrollbars by default have both arrow buttons at the bottom or right.
|
||||
* (There is a preferences setting to use the Unix layout, but we are not
|
||||
* supporting that!) On more recent versions of macOS there are no arrow
|
||||
* buttons at all. The case of no arrow buttons can be handled as a special
|
||||
* case of having both buttons at the end, but where scrollPtr->arrowLength
|
||||
* happens to be zero. To adjust for having both arrows at the same end we
|
||||
* shift the scrollbar up by the arrowLength.
|
||||
*/
|
||||
|
||||
int fieldLength;
|
||||
|
||||
if (scrollPtr->highlightWidth < 0) {
|
||||
scrollPtr->highlightWidth = 0;
|
||||
scrollPtr->highlightWidth = 0;
|
||||
}
|
||||
scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
|
||||
if ([NSApp macMinorVersion] == 6) {
|
||||
scrollPtr->arrowLength = scrollPtr->width;
|
||||
scrollPtr->arrowLength = scrollPtr->width;
|
||||
} else {
|
||||
scrollPtr->arrowLength = 0;
|
||||
scrollPtr->arrowLength = 0;
|
||||
}
|
||||
fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)
|
||||
: Tk_Width(scrollPtr->tkwin))
|
||||
- 2*(scrollPtr->arrowLength + scrollPtr->inset);
|
||||
: Tk_Width(scrollPtr->tkwin))
|
||||
- 2*(scrollPtr->arrowLength + scrollPtr->inset);
|
||||
if (fieldLength < 0) {
|
||||
fieldLength = 0;
|
||||
fieldLength = 0;
|
||||
}
|
||||
scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction;
|
||||
scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction;
|
||||
|
||||
/*
|
||||
* Adjust the slider so that some piece of it is always displayed in the
|
||||
* scrollbar and so that it has at least a minimal width (so it can be
|
||||
* grabbed with the mouse).
|
||||
* Adjust the slider so that it has at least a minimal size and so there
|
||||
* is a small gap on either end which can be used to scroll by one page.
|
||||
*/
|
||||
|
||||
if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) {
|
||||
scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH;
|
||||
if (scrollPtr->sliderFirst < MIN_GAP) {
|
||||
scrollPtr->sliderFirst = MIN_GAP;
|
||||
scrollPtr->sliderLast += MIN_GAP;
|
||||
}
|
||||
if (scrollPtr->sliderFirst < 0) {
|
||||
scrollPtr->sliderFirst = 0;
|
||||
if (scrollPtr->sliderLast > fieldLength - MIN_GAP) {
|
||||
scrollPtr->sliderLast = fieldLength - MIN_GAP;
|
||||
scrollPtr->sliderFirst -= MIN_GAP;
|
||||
}
|
||||
if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) {
|
||||
scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH;
|
||||
}
|
||||
if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) {
|
||||
scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;
|
||||
}
|
||||
if (scrollPtr->sliderLast > fieldLength) {
|
||||
scrollPtr->sliderLast = fieldLength;
|
||||
scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;
|
||||
}
|
||||
scrollPtr->sliderFirst += -scrollPtr->arrowLength + scrollPtr->inset;
|
||||
scrollPtr->sliderLast += scrollPtr->inset;
|
||||
@@ -310,20 +420,20 @@ TkpComputeScrollbarGeometry(
|
||||
* be redisplayed.
|
||||
*/
|
||||
|
||||
if (scrollPtr->vertical) {
|
||||
Tk_GeometryRequest(scrollPtr->tkwin,
|
||||
scrollPtr->width + 2*scrollPtr->inset,
|
||||
2*(scrollPtr->arrowLength + scrollPtr->borderWidth
|
||||
+ scrollPtr->inset) + metrics.minThumbHeight);
|
||||
if (scrollPtr->vertical) {
|
||||
Tk_GeometryRequest(scrollPtr->tkwin,
|
||||
scrollPtr->width + 2*scrollPtr->inset,
|
||||
2*(scrollPtr->arrowLength + scrollPtr->borderWidth
|
||||
+ scrollPtr->inset) + metrics.minThumbHeight);
|
||||
} else {
|
||||
Tk_GeometryRequest(scrollPtr->tkwin,
|
||||
2*(scrollPtr->arrowLength + scrollPtr->borderWidth
|
||||
+ scrollPtr->inset) + metrics.minThumbHeight,
|
||||
scrollPtr->width + 2*scrollPtr->inset);
|
||||
Tk_GeometryRequest(scrollPtr->tkwin,
|
||||
2*(scrollPtr->arrowLength + scrollPtr->borderWidth
|
||||
+ scrollPtr->inset) + metrics.minThumbHeight,
|
||||
scrollPtr->width + 2*scrollPtr->inset);
|
||||
}
|
||||
Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -342,9 +452,9 @@ TkpComputeScrollbarGeometry(
|
||||
|
||||
void
|
||||
TkpDestroyScrollbar(
|
||||
TkScrollbar *scrollPtr)
|
||||
TkScrollbar *scrollPtr)
|
||||
{
|
||||
MacScrollbar *macScrollPtr = (MacScrollbar *)scrollPtr;
|
||||
MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
|
||||
|
||||
if (macScrollPtr->troughGC != None) {
|
||||
Tk_FreeGC(scrollPtr->display, macScrollPtr->troughGC);
|
||||
@@ -353,15 +463,15 @@ TkpDestroyScrollbar(
|
||||
Tk_FreeGC(scrollPtr->display, macScrollPtr->copyGC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkpConfigureScrollbar --
|
||||
*
|
||||
* This procedure is called after the generic code has finished
|
||||
* processing configuration options, in order to configure platform
|
||||
* specific options. There are no such option on the Mac, however.
|
||||
* This procedure is called after the generic code has finished processing
|
||||
* configuration options, in order to configure platform specific options.
|
||||
* There are no such option on the Mac, however.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -374,11 +484,11 @@ TkpDestroyScrollbar(
|
||||
|
||||
void
|
||||
TkpConfigureScrollbar(
|
||||
register TkScrollbar *scrollPtr)
|
||||
register TkScrollbar *scrollPtr)
|
||||
{
|
||||
|
||||
/* empty */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
*
|
||||
@@ -403,29 +513,28 @@ TkpScrollbarPosition(
|
||||
/* Scrollbar widget record. */
|
||||
int x, int y) /* Coordinates within scrollPtr's window. */
|
||||
{
|
||||
|
||||
/*
|
||||
* The code below is borrowed from tkUnixScrlbr.c and needs no adjustment
|
||||
* since it does not involve the arrow buttons.
|
||||
*/
|
||||
/*
|
||||
* The code below is borrowed from tkUnixScrlbr.c and needs no adjustment
|
||||
* since it does not involve the arrow buttons.
|
||||
*/
|
||||
|
||||
int length, width, tmp;
|
||||
register const int inset = scrollPtr->inset;
|
||||
|
||||
if (scrollPtr->vertical) {
|
||||
length = Tk_Height(scrollPtr->tkwin);
|
||||
width = Tk_Width(scrollPtr->tkwin);
|
||||
length = Tk_Height(scrollPtr->tkwin);
|
||||
width = Tk_Width(scrollPtr->tkwin);
|
||||
} else {
|
||||
tmp = x;
|
||||
x = y;
|
||||
y = tmp;
|
||||
length = Tk_Width(scrollPtr->tkwin);
|
||||
width = Tk_Height(scrollPtr->tkwin);
|
||||
tmp = x;
|
||||
x = y;
|
||||
y = tmp;
|
||||
length = Tk_Width(scrollPtr->tkwin);
|
||||
width = Tk_Height(scrollPtr->tkwin);
|
||||
}
|
||||
|
||||
if (x < inset || x >= width - inset ||
|
||||
y < inset || y >= length - inset) {
|
||||
return OUTSIDE;
|
||||
y < inset || y >= length - inset) {
|
||||
return OUTSIDE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -436,31 +545,34 @@ TkpScrollbarPosition(
|
||||
*/
|
||||
|
||||
if (y < scrollPtr->sliderFirst + scrollPtr->arrowLength) {
|
||||
return TOP_GAP;
|
||||
}
|
||||
if (y < scrollPtr->sliderLast) {
|
||||
return SLIDER;
|
||||
}
|
||||
if (y < length - (2*scrollPtr->arrowLength + inset)) {
|
||||
return BOTTOM_GAP;
|
||||
}
|
||||
/* On systems newer than 10.6 we have already returned. */
|
||||
if (y < length - (scrollPtr->arrowLength + inset)) {
|
||||
return TOP_ARROW;
|
||||
}
|
||||
return BOTTOM_ARROW;
|
||||
}
|
||||
return TOP_GAP;
|
||||
}
|
||||
if (y < scrollPtr->sliderLast) {
|
||||
return SLIDER;
|
||||
}
|
||||
if (y < length - (2*scrollPtr->arrowLength + inset)) {
|
||||
return BOTTOM_GAP;
|
||||
}
|
||||
|
||||
/*
|
||||
* On systems newer than 10.6 we have already returned.
|
||||
*/
|
||||
|
||||
if (y < length - (scrollPtr->arrowLength + inset)) {
|
||||
return TOP_ARROW;
|
||||
}
|
||||
return BOTTOM_ARROW;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
*
|
||||
* UpdateControlValues --
|
||||
*
|
||||
* This procedure updates the Macintosh scrollbar control to
|
||||
* display the values defined by the Tk scrollbar. This is the
|
||||
* key interface to the Mac-native scrollbar; the Unix bindings
|
||||
* drive scrolling in the Tk window and all the Mac scrollbar has
|
||||
* to do is redraw itself.
|
||||
* This procedure updates the Macintosh scrollbar control to display the
|
||||
* values defined by the Tk scrollbar. This is the key interface to the
|
||||
* Mac-native scrollbar; the Unix bindings drive scrolling in the Tk
|
||||
* window and all the Mac scrollbar has to do is redraw itself.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -473,20 +585,21 @@ TkpScrollbarPosition(
|
||||
|
||||
static void
|
||||
UpdateControlValues(
|
||||
TkScrollbar *scrollPtr) /* Scrollbar data struct. */
|
||||
TkScrollbar *scrollPtr) /* Scrollbar data struct. */
|
||||
{
|
||||
MacScrollbar *msPtr = (MacScrollbar *)scrollPtr;
|
||||
MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
|
||||
Tk_Window tkwin = scrollPtr->tkwin;
|
||||
MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
|
||||
double dViewSize;
|
||||
HIRect contrlRect;
|
||||
HIRect contrlRect;
|
||||
short width, height;
|
||||
|
||||
NSView *view = TkMacOSXDrawableView(macWin);
|
||||
CGFloat viewHeight = [view bounds].size.height;
|
||||
NSRect frame;
|
||||
|
||||
frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin),
|
||||
Tk_Height(tkwin));
|
||||
Tk_Height(tkwin));
|
||||
frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset);
|
||||
frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
|
||||
|
||||
@@ -494,7 +607,7 @@ UpdateControlValues(
|
||||
msPtr->info.bounds = contrlRect;
|
||||
|
||||
width = contrlRect.size.width;
|
||||
height = contrlRect.size.height;
|
||||
height = contrlRect.size.height - scrollPtr->arrowLength;
|
||||
|
||||
/*
|
||||
* Ensure we set scrollbar control bounds only once all size adjustments
|
||||
@@ -503,9 +616,9 @@ UpdateControlValues(
|
||||
|
||||
msPtr->info.bounds = contrlRect;
|
||||
if (scrollPtr->vertical) {
|
||||
msPtr->info.attributes &= ~kThemeTrackHorizontal;
|
||||
msPtr->info.attributes &= ~kThemeTrackHorizontal;
|
||||
} else {
|
||||
msPtr->info.attributes |= kThemeTrackHorizontal;
|
||||
msPtr->info.attributes |= kThemeTrackHorizontal;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -518,69 +631,71 @@ UpdateControlValues(
|
||||
* the view area.
|
||||
*/
|
||||
|
||||
double maximum = 100, factor;
|
||||
factor = RangeToFactor(maximum);
|
||||
dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction)
|
||||
* factor;
|
||||
msPtr->info.max = MIN_SCROLLBAR_VALUE +
|
||||
factor - dViewSize;
|
||||
double factor = RangeToFactor(100.0);
|
||||
dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction) * factor;
|
||||
msPtr->info.max = factor - dViewSize;
|
||||
msPtr->info.trackInfo.scrollbar.viewsize = dViewSize;
|
||||
if (scrollPtr->vertical) {
|
||||
if (SNOW_LEOPARD_STYLE) {
|
||||
msPtr->info.value = factor * scrollPtr->firstFraction;
|
||||
} else {
|
||||
msPtr->info.value = msPtr->info.max - factor * scrollPtr->firstFraction;
|
||||
}
|
||||
if (SNOW_LEOPARD_STYLE) {
|
||||
msPtr->info.value = factor * scrollPtr->firstFraction;
|
||||
} else {
|
||||
msPtr->info.value = msPtr->info.max -
|
||||
factor * scrollPtr->firstFraction;
|
||||
}
|
||||
} else {
|
||||
msPtr->info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction;
|
||||
msPtr->info.value = factor * scrollPtr->firstFraction;
|
||||
}
|
||||
|
||||
if((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0)
|
||||
|| height <= metrics.minHeight) {
|
||||
if ((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0)
|
||||
|| height <= metrics.minHeight) {
|
||||
msPtr->info.enableState = kThemeTrackHideTrack;
|
||||
} else {
|
||||
msPtr->info.enableState = kThemeTrackActive;
|
||||
msPtr->info.attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost;
|
||||
msPtr->info.attributes =
|
||||
kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
*
|
||||
* ScrollbarEvent --
|
||||
*
|
||||
* This procedure is invoked in response to <ButtonPress>, <ButtonRelease>,
|
||||
* <EnterNotify>, and <LeaveNotify> events. The Scrollbar appearance is
|
||||
* modified for each event.
|
||||
* This procedure is invoked in response to <ButtonPress>,
|
||||
* <ButtonRelease>, <EnterNotify>, and <LeaveNotify> events. The
|
||||
* Scrollbar appearance is modified for each event.
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr)
|
||||
ScrollbarEvent(
|
||||
TkScrollbar *scrollPtr,
|
||||
XEvent *eventPtr)
|
||||
{
|
||||
MacScrollbar *msPtr = (MacScrollbar *)scrollPtr;
|
||||
|
||||
/* The pressState does not indicate whether the moused button was
|
||||
* pressed at some location in the Scrollbar. Rather, it indicates
|
||||
* that the scrollbar should appear as if it were pressed in that
|
||||
* location. The standard Mac behavior is that once the button is
|
||||
* pressed inside the Scrollbar the appearance should not change until
|
||||
* the button is released, even if the mouse moves outside of the
|
||||
* scrollbar. However, if the mouse lies over the scrollbar but the
|
||||
* button is not pressed then the appearance should be the same as if
|
||||
* the button had been pressed on the slider, i.e. kThemeThumbPressed.
|
||||
* See the file Appearance.r, or HIToolbox.bridgesupport on 10.14.
|
||||
MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
|
||||
|
||||
/*
|
||||
* The pressState does not indicate whether the moused button was pressed
|
||||
* at some location in the Scrollbar. Rather, it indicates that the
|
||||
* scrollbar should appear as if it were pressed in that location. The
|
||||
* standard Mac behavior is that once the button is pressed inside the
|
||||
* Scrollbar the appearance should not change until the button is released,
|
||||
* even if the mouse moves outside of the scrollbar. However, if the mouse
|
||||
* lies over the scrollbar but the button is not pressed then the
|
||||
* appearance should be the same as if the button had been pressed on the
|
||||
* slider, i.e. kThemeThumbPressed. See the file Appearance.r, or
|
||||
* HIToolbox.bridgesupport on 10.14.
|
||||
*/
|
||||
|
||||
if (eventPtr->type == ButtonPress) {
|
||||
msPtr->buttonDown = true;
|
||||
UpdateControlValues(scrollPtr);
|
||||
|
||||
int where = TkpScrollbarPosition(scrollPtr,
|
||||
eventPtr->xbutton.x,
|
||||
eventPtr->xbutton.y);
|
||||
switch(where) {
|
||||
eventPtr->xbutton.x, eventPtr->xbutton.y);
|
||||
|
||||
switch (where) {
|
||||
case OUTSIDE:
|
||||
msPtr->info.trackInfo.scrollbar.pressState = 0;
|
||||
break;
|
||||
@@ -591,14 +706,21 @@ ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr)
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed;
|
||||
break;
|
||||
case BOTTOM_GAP:
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomTrackPressed;
|
||||
msPtr->info.trackInfo.scrollbar.pressState =
|
||||
kThemeBottomTrackPressed;
|
||||
break;
|
||||
case TOP_ARROW:
|
||||
/* This looks wrong and the docs say it is wrong but it works. */
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeTopInsideArrowPressed;
|
||||
|
||||
/*
|
||||
* This looks wrong and the docs say it is wrong but it works.
|
||||
*/
|
||||
|
||||
msPtr->info.trackInfo.scrollbar.pressState =
|
||||
kThemeTopInsideArrowPressed;
|
||||
break;
|
||||
case BOTTOM_ARROW:
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomOutsideArrowPressed;
|
||||
msPtr->info.trackInfo.scrollbar.pressState =
|
||||
kThemeBottomOutsideArrowPressed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -620,11 +742,10 @@ ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr)
|
||||
msPtr->info.trackInfo.scrollbar.pressState = 0;
|
||||
}
|
||||
}
|
||||
TkScrollbarEventuallyRedraw(scrollPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
*
|
||||
@@ -645,8 +766,8 @@ ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr)
|
||||
|
||||
static void
|
||||
ScrollbarEventProc(
|
||||
ClientData clientData, /* Information about window. */
|
||||
XEvent *eventPtr) /* Information about event. */
|
||||
ClientData clientData, /* Information about window. */
|
||||
XEvent *eventPtr) /* Information about event. */
|
||||
{
|
||||
TkScrollbar *scrollPtr = clientData;
|
||||
|
||||
@@ -668,7 +789,7 @@ ScrollbarEventProc(
|
||||
TkScrollbarEventProc(clientData, eventPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
|
||||
@@ -51,7 +51,7 @@ typedef struct RegisteredInterp {
|
||||
* A registry of all interpreters for a display is kept in a property
|
||||
* "InterpRegistry" on the root window of the display. It is organized as a
|
||||
* series of zero or more concatenated strings (in no particular order), each
|
||||
* of the form
|
||||
* of the form:
|
||||
* window space name '\0'
|
||||
* where "window" is the hex id of the comm. window to use to talk to an
|
||||
* interpreter named "name".
|
||||
@@ -78,7 +78,7 @@ typedef struct NameRegistry {
|
||||
* XFree; zero means use ckfree. */
|
||||
} NameRegistry;
|
||||
|
||||
static int initialized = 0; /* A flag to denote if we have initialized
|
||||
static int initialized = 0; /* A flag to denote if we have initialized
|
||||
* yet. */
|
||||
|
||||
static RegisteredInterp *interpListPtr = NULL;
|
||||
@@ -325,7 +325,7 @@ Tk_SendObjCmd(
|
||||
int objc, /* Number of arguments */
|
||||
Tcl_Obj *const objv[]) /* The arguments */
|
||||
{
|
||||
const char *const sendOptions[] = {"-async", "-displayof", "-", NULL};
|
||||
const char *const sendOptions[] = {"-async", "-displayof", "--", NULL};
|
||||
char *stringRep, *destName;
|
||||
/*int async = 0;*/
|
||||
int i, index, firstArg;
|
||||
|
||||
158
macosx/tkMacOSXServices.c
Normal file
158
macosx/tkMacOSXServices.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* tkMacOSXServices.c --
|
||||
*\
|
||||
* This file allows the integration of Tk and the Cocoa NSServices API.
|
||||
*
|
||||
* Copyright (c) 2010-2019 Kevin Walzer/WordTech Communications LLC.
|
||||
* Copyright (c) 2019 Marc Culler.
|
||||
* Copyright (c) 2010 Adrian Robert.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#include <tkInt.h>
|
||||
#include <tkMacOSXInt.h>
|
||||
|
||||
/*
|
||||
* Event proc which calls the PerformService procedure.
|
||||
*/
|
||||
|
||||
static int
|
||||
ServicesEventProc(
|
||||
Tcl_Event *event,
|
||||
int flags)
|
||||
{
|
||||
TkMainInfo *info = TkGetMainInfoList();
|
||||
Tcl_GlobalEval(info->interp, "::tk::mac::PerformService");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The Wish application can send the current selection in the Tk clipboard
|
||||
* to other applications which accept messages of type NSString. The TkService
|
||||
* object provides this service via its provideService method. (The method
|
||||
* must be specified in the application's Info.plist file for this to work.)
|
||||
*/
|
||||
|
||||
@interface TkService : NSObject {
|
||||
|
||||
}
|
||||
|
||||
+ (void) initialize;
|
||||
- (void) provideService:(NSPasteboard *)pboard
|
||||
userData:(NSString *)data
|
||||
error:(NSString **)error;
|
||||
- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
|
||||
types:(NSArray *)types;
|
||||
|
||||
@end
|
||||
|
||||
/*
|
||||
* Class methods.
|
||||
*/
|
||||
|
||||
@implementation TkService
|
||||
|
||||
+ (void) initialize {
|
||||
NSArray *sendTypes = [NSArray arrayWithObjects:@"NSStringPboardType",
|
||||
@"NSPasteboardTypeString", nil];
|
||||
[NSApp registerServicesMenuSendTypes:sendTypes returnTypes:sendTypes];
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current Tk selection and copy it to the system pasteboard.
|
||||
*/
|
||||
|
||||
- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
|
||||
types:(NSArray *)types
|
||||
{
|
||||
NSArray *typesDeclared = nil;
|
||||
NSString *pboardType = nil;
|
||||
TkMainInfo *info = TkGetMainInfoList();
|
||||
|
||||
for (NSString *typeString in types) {
|
||||
if ([typeString isEqualToString:@"NSStringPboardType"] ||
|
||||
[typeString isEqualToString:@"NSPasteboardTypeString"]) {
|
||||
typesDeclared = [NSArray arrayWithObject:typeString];
|
||||
pboardType = typeString;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!typesDeclared) {
|
||||
return NO;
|
||||
}
|
||||
Tcl_Eval(info->interp, "selection get");
|
||||
|
||||
char *copystring = Tcl_GetString(Tcl_GetObjResult(info->interp));
|
||||
NSString *writestring = [NSString stringWithUTF8String:copystring];
|
||||
|
||||
[pboard declareTypes:typesDeclared owner:nil];
|
||||
return [pboard setString:writestring forType:pboardType];
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the method that actually calls the Tk service; it must be specified
|
||||
* in Info.plist.
|
||||
*/
|
||||
|
||||
- (void)provideService:(NSPasteboard *)pboard
|
||||
userData:(NSString *)data
|
||||
error:(NSString **)error
|
||||
{
|
||||
NSString *pboardString = nil, *pboardType = nil;
|
||||
NSArray *types = [pboard types];
|
||||
Tcl_Event *event;
|
||||
|
||||
/*
|
||||
* Get a string from the private pasteboard and copy it to the general
|
||||
* pasteboard to make it available to other applications.
|
||||
*/
|
||||
|
||||
for (NSString *typeString in types) {
|
||||
if ([typeString isEqualToString:@"NSStringPboardType"] ||
|
||||
[typeString isEqualToString:@"NSPasteboardTypeString"]) {
|
||||
pboardString = [pboard stringForType:typeString];
|
||||
pboardType = typeString;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pboardString) {
|
||||
NSPasteboard *generalpasteboard = [NSPasteboard generalPasteboard];
|
||||
[generalpasteboard declareTypes:[NSArray arrayWithObjects:pboardType, nil]
|
||||
owner:nil];
|
||||
[generalpasteboard setString:pboardString forType:pboardType];
|
||||
event = ckalloc(sizeof(Tcl_Event));
|
||||
event->proc = ServicesEventProc;
|
||||
Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
/*
|
||||
* Instantiate a TkService object and register it with the NSApplication.
|
||||
* This is called exactly one time from TkpInit.
|
||||
*/
|
||||
|
||||
int
|
||||
TkMacOSXServices_Init(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
/*
|
||||
* Initialize an instance of TkService and register it with the NSApp.
|
||||
*/
|
||||
|
||||
TkService *service = [[TkService alloc] init];
|
||||
[NSApp setServicesProvider:service];
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 79
|
||||
* coding: utf-8
|
||||
* End:
|
||||
*/
|
||||
@@ -49,7 +49,7 @@ static void NotifyVisibility(TkWindow *winPtr, XEvent *eventPtr);
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
XDestroyWindow(
|
||||
Display *display, /* Display. */
|
||||
Window window) /* Window. */
|
||||
@@ -65,35 +65,41 @@ XDestroyWindow(
|
||||
TkMacOSXSelDeadWindow(macWin->winPtr);
|
||||
macWin->toplevel->referenceCount--;
|
||||
|
||||
if (!Tk_IsTopLevel(macWin->winPtr) ) {
|
||||
if (!Tk_IsTopLevel(macWin->winPtr)) {
|
||||
TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
|
||||
if (macWin->winPtr->parentPtr != NULL) {
|
||||
TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
|
||||
}
|
||||
if (macWin->visRgn) {
|
||||
CFRelease(macWin->visRgn);
|
||||
macWin->visRgn = NULL;
|
||||
}
|
||||
if (macWin->aboveVisRgn) {
|
||||
CFRelease(macWin->aboveVisRgn);
|
||||
macWin->aboveVisRgn = NULL;
|
||||
}
|
||||
if (macWin->drawRgn) {
|
||||
CFRelease(macWin->drawRgn);
|
||||
macWin->drawRgn = NULL;
|
||||
}
|
||||
|
||||
if (macWin->toplevel->referenceCount == 0) {
|
||||
ckfree(macWin->toplevel);
|
||||
}
|
||||
ckfree(macWin);
|
||||
return;
|
||||
return Success;
|
||||
}
|
||||
if (macWin->visRgn) {
|
||||
CFRelease(macWin->visRgn);
|
||||
macWin->visRgn = NULL;
|
||||
}
|
||||
if (macWin->aboveVisRgn) {
|
||||
CFRelease(macWin->aboveVisRgn);
|
||||
macWin->aboveVisRgn = NULL;
|
||||
}
|
||||
if (macWin->drawRgn) {
|
||||
CFRelease(macWin->drawRgn);
|
||||
macWin->drawRgn = NULL;
|
||||
}
|
||||
macWin->view = nil;
|
||||
|
||||
@@ -105,6 +111,7 @@ XDestroyWindow(
|
||||
if (macWin->toplevel->referenceCount == 0) {
|
||||
ckfree(macWin->toplevel);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -124,12 +131,14 @@ XDestroyWindow(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
XMapWindow(
|
||||
Display *display, /* Display. */
|
||||
Window window) /* Window. */
|
||||
{
|
||||
MacDrawable *macWin = (MacDrawable *) window;
|
||||
TkWindow *winPtr = macWin->winPtr;
|
||||
NSWindow *win = TkMacOSXDrawableWindow(window);
|
||||
XEvent event;
|
||||
|
||||
/*
|
||||
@@ -145,33 +154,40 @@ XMapWindow(
|
||||
}
|
||||
|
||||
display->request++;
|
||||
macWin->winPtr->flags |= TK_MAPPED;
|
||||
if (Tk_IsTopLevel(macWin->winPtr)) {
|
||||
if (!Tk_IsEmbedded(macWin->winPtr)) {
|
||||
NSWindow *win = TkMacOSXDrawableWindow(window);
|
||||
winPtr->flags |= TK_MAPPED;
|
||||
if (Tk_IsTopLevel(winPtr)) {
|
||||
if (!Tk_IsEmbedded(winPtr)) {
|
||||
|
||||
/*
|
||||
* We want to activate Tk when a toplevel is mapped
|
||||
* but we must not supply YES here. This is because
|
||||
* during Tk initialization the root window is mapped
|
||||
* before applicationDidFinishLaunching returns. Forcing
|
||||
* the app to activate too early can make the menu bar
|
||||
* unresponsive.
|
||||
* We want to activate Tk when a toplevel is mapped but we must not
|
||||
* supply YES here. This is because during Tk initialization the
|
||||
* root window is mapped before applicationDidFinishLaunching
|
||||
* returns. Forcing the app to activate too early can make the menu
|
||||
* bar unresponsive.
|
||||
*/
|
||||
|
||||
TkMacOSXApplyWindowAttributes(winPtr, win);
|
||||
[win setExcludedFromWindowsMenu:NO];
|
||||
[NSApp activateIgnoringOtherApps:NO];
|
||||
if ( [win canBecomeKeyWindow] ) {
|
||||
[[win contentView] setNeedsDisplay:YES];
|
||||
if ([win canBecomeKeyWindow]) {
|
||||
[win makeKeyAndOrderFront:NSApp];
|
||||
} else {
|
||||
[win orderFrontRegardless];
|
||||
}
|
||||
TkMacOSXApplyWindowAttributes(macWin->winPtr, win);
|
||||
} else {
|
||||
TkWindow *contWinPtr = TkpGetOtherWindow(winPtr);
|
||||
|
||||
/*
|
||||
* Rebuild the container's clipping region and display
|
||||
* the window.
|
||||
*/
|
||||
TkWindow *contWinPtr = TkpGetOtherWindow(macWin->winPtr);
|
||||
TkMacOSXInvalClipRgns((Tk_Window)contWinPtr);
|
||||
|
||||
TkMacOSXInvalClipRgns((Tk_Window) contWinPtr);
|
||||
TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
|
||||
}
|
||||
TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr);
|
||||
|
||||
TkMacOSXInvalClipRgns((Tk_Window) winPtr);
|
||||
|
||||
/*
|
||||
* We only need to send the MapNotify event for toplevel windows.
|
||||
@@ -184,16 +200,22 @@ XMapWindow(
|
||||
event.xmap.window = window;
|
||||
event.xmap.type = MapNotify;
|
||||
event.xmap.event = window;
|
||||
event.xmap.override_redirect = macWin->winPtr->atts.override_redirect;
|
||||
event.xmap.override_redirect = winPtr->atts.override_redirect;
|
||||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Rebuild the parent's clipping region and display the window.
|
||||
*
|
||||
* For non-toplevel windows, rebuild the parent's clipping region
|
||||
* and redisplay the window.
|
||||
*/
|
||||
|
||||
TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
|
||||
TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
|
||||
TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
|
||||
}
|
||||
|
||||
if ([NSApp isDrawing]) {
|
||||
[[win contentView] setNeedsRedisplay:YES];
|
||||
} else {
|
||||
[[win contentView] setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -204,14 +226,8 @@ XMapWindow(
|
||||
event.xany.display = display;
|
||||
event.xvisibility.type = VisibilityNotify;
|
||||
event.xvisibility.state = VisibilityUnobscured;
|
||||
NotifyVisibility(macWin->winPtr, &event);
|
||||
|
||||
/*
|
||||
* Make sure that subwindows get displayed.
|
||||
*/
|
||||
|
||||
GenerateConfigureNotify(macWin->winPtr, 1);
|
||||
|
||||
NotifyVisibility(winPtr, &event);
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -265,7 +281,7 @@ NotifyVisibility(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
XUnmapWindow(
|
||||
Display *display, /* Display. */
|
||||
Window window) /* Window. */
|
||||
@@ -273,18 +289,14 @@ XUnmapWindow(
|
||||
MacDrawable *macWin = (MacDrawable *) window;
|
||||
TkWindow *winPtr = macWin->winPtr;
|
||||
TkWindow *parentPtr = winPtr->parentPtr;
|
||||
NSWindow *win = TkMacOSXDrawableWindow(window);
|
||||
XEvent event;
|
||||
|
||||
display->request++;
|
||||
if (Tk_IsTopLevel(winPtr)) {
|
||||
if (!Tk_IsEmbedded(winPtr) &&
|
||||
winPtr->wmInfoPtr->hints.initial_state!=IconicState) {
|
||||
NSWindow *win = TkMacOSXDrawableWindow(window);
|
||||
|
||||
if ([win isVisible]) {
|
||||
[[win parentWindow] removeChildWindow:win];
|
||||
[win orderOut:NSApp];
|
||||
}
|
||||
[win orderOut:nil];
|
||||
}
|
||||
TkMacOSXInvalClipRgns((Tk_Window) winPtr);
|
||||
|
||||
@@ -302,20 +314,27 @@ XUnmapWindow(
|
||||
event.xunmap.from_configure = false;
|
||||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Rebuild the visRgn clip region for the parent so it will be allowed
|
||||
* to draw in the space from which this subwindow was removed.
|
||||
* to draw in the space from which this subwindow was removed and then
|
||||
* redraw the window.
|
||||
*/
|
||||
|
||||
if (parentPtr && parentPtr->privatePtr->visRgn) {
|
||||
TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(parentPtr->privatePtr),
|
||||
parentPtr->privatePtr->visRgn);
|
||||
TkMacOSXInvalidateViewRegion(
|
||||
TkMacOSXDrawableView(parentPtr->privatePtr),
|
||||
parentPtr->privatePtr->visRgn);
|
||||
}
|
||||
TkMacOSXInvalClipRgns((Tk_Window) parentPtr);
|
||||
TkMacOSXUpdateClipRgn(parentPtr);
|
||||
}
|
||||
winPtr->flags &= ~TK_MAPPED;
|
||||
if ([NSApp isDrawing]) {
|
||||
[[win contentView] setNeedsRedisplay:YES];
|
||||
} else {
|
||||
[[win contentView] setNeedsDisplay:YES];
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -335,7 +354,7 @@ XUnmapWindow(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
XResizeWindow(
|
||||
Display *display, /* Display. */
|
||||
Window window, /* Window. */
|
||||
@@ -343,11 +362,14 @@ XResizeWindow(
|
||||
unsigned int height)
|
||||
{
|
||||
MacDrawable *macWin = (MacDrawable *) window;
|
||||
|
||||
display->request++;
|
||||
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
|
||||
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
|
||||
|
||||
if (w) {
|
||||
NSRect r = [w contentRectForFrameRect:[w frame]];
|
||||
|
||||
r.origin.y += r.size.height - height;
|
||||
r.size.width = width;
|
||||
r.size.height = height;
|
||||
@@ -356,6 +378,7 @@ XResizeWindow(
|
||||
} else {
|
||||
MoveResizeWindow(macWin);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -363,8 +386,8 @@ XResizeWindow(
|
||||
*
|
||||
* XMoveResizeWindow --
|
||||
*
|
||||
* Move or resize a given X window. See X windows documentation
|
||||
* for further details.
|
||||
* Move or resize a given X window. See X windows documentation for
|
||||
* further details.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -375,7 +398,7 @@ XResizeWindow(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
XMoveResizeWindow(
|
||||
Display *display, /* Display. */
|
||||
Window window, /* Window. */
|
||||
@@ -388,27 +411,30 @@ XMoveResizeWindow(
|
||||
display->request++;
|
||||
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
|
||||
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
|
||||
if (w) {
|
||||
|
||||
/* We explicitly convert everything to doubles so we don't get
|
||||
if (w) {
|
||||
/*
|
||||
* We explicitly convert everything to doubles so we don't get
|
||||
* surprised (again) by what happens when you do arithmetic with
|
||||
* unsigned ints.
|
||||
*/
|
||||
|
||||
CGFloat X = (CGFloat)x;
|
||||
CGFloat Y = (CGFloat)y;
|
||||
CGFloat Width = (CGFloat)width;
|
||||
CGFloat Height = (CGFloat)height;
|
||||
CGFloat XOff = (CGFloat)macWin->winPtr->wmInfoPtr->xInParent;
|
||||
CGFloat YOff = (CGFloat)macWin->winPtr->wmInfoPtr->yInParent;
|
||||
NSRect r = NSMakeRect(X + XOff,
|
||||
tkMacOSXZeroScreenHeight - Y - YOff - Height,
|
||||
Width, Height);
|
||||
CGFloat X = (CGFloat) x;
|
||||
CGFloat Y = (CGFloat) y;
|
||||
CGFloat Width = (CGFloat) width;
|
||||
CGFloat Height = (CGFloat) height;
|
||||
CGFloat XOff = (CGFloat) macWin->winPtr->wmInfoPtr->xInParent;
|
||||
CGFloat YOff = (CGFloat) macWin->winPtr->wmInfoPtr->yInParent;
|
||||
NSRect r = NSMakeRect(
|
||||
X + XOff, TkMacOSXZeroScreenHeight() - Y - YOff - Height,
|
||||
Width, Height);
|
||||
|
||||
[w setFrame:[w frameRectForContentRect:r] display:YES];
|
||||
}
|
||||
} else {
|
||||
MoveResizeWindow(macWin);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -416,8 +442,7 @@ XMoveResizeWindow(
|
||||
*
|
||||
* XMoveWindow --
|
||||
*
|
||||
* Move a given X window. See X windows documentation for further
|
||||
* details.
|
||||
* Move a given X window. See X windows documentation for further details.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -428,7 +453,7 @@ XMoveResizeWindow(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
XMoveWindow(
|
||||
Display *display, /* Display. */
|
||||
Window window, /* Window. */
|
||||
@@ -439,12 +464,15 @@ XMoveWindow(
|
||||
display->request++;
|
||||
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
|
||||
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
|
||||
|
||||
if (w) {
|
||||
[w setFrameTopLeftPoint:NSMakePoint(x, tkMacOSXZeroScreenHeight - y)];
|
||||
[w setFrameTopLeftPoint: NSMakePoint(
|
||||
x, TkMacOSXZeroScreenHeight() - y)];
|
||||
}
|
||||
} else {
|
||||
MoveResizeWindow(macWin);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -481,7 +509,6 @@ MoveResizeWindow(
|
||||
if (contWinPtr) {
|
||||
macParent = contWinPtr->privatePtr;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Here we should handle out of process embedding. At this point,
|
||||
* we are assuming that the changes.x,y is not maintained, if you
|
||||
@@ -490,7 +517,6 @@ MoveResizeWindow(
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
* TODO: update all xOff & yOffs
|
||||
*/
|
||||
@@ -571,7 +597,7 @@ GenerateConfigureNotify(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
XRaiseWindow(
|
||||
Display *display, /* Display. */
|
||||
Window window) /* Window. */
|
||||
@@ -582,11 +608,11 @@ XRaiseWindow(
|
||||
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
|
||||
TkWmRestackToplevel(macWin->winPtr, Above, NULL);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* TODO: this should generate damage
|
||||
*/
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -617,7 +643,6 @@ XLowerWindow(
|
||||
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
|
||||
TkWmRestackToplevel(macWin->winPtr, Below, NULL);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* TODO: this should generate damage
|
||||
*/
|
||||
@@ -643,7 +668,7 @@ XLowerWindow(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
XConfigureWindow(
|
||||
Display *display, /* Display. */
|
||||
Window w, /* Window. */
|
||||
@@ -680,14 +705,17 @@ XConfigureWindow(
|
||||
TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
|
||||
TkMacOSXWinBounds(winPtr, &bounds);
|
||||
r = NSMakeRect(bounds.left,
|
||||
[view bounds].size.height - bounds.bottom,
|
||||
bounds.right - bounds.left, bounds.bottom - bounds.top);
|
||||
[view bounds].size.height - bounds.bottom,
|
||||
bounds.right - bounds.left, bounds.bottom - bounds.top);
|
||||
[view setNeedsDisplayInRect:r];
|
||||
}
|
||||
}
|
||||
|
||||
/* TkGenWMMoveRequestEvent(macWin->winPtr,
|
||||
macWin->winPtr->changes.x, macWin->winPtr->changes.y); */
|
||||
#if 0
|
||||
TkGenWMMoveRequestEvent(macWin->winPtr,
|
||||
macWin->winPtr->changes.x, macWin->winPtr->changes.y);
|
||||
#endif
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -709,14 +737,14 @@ XConfigureWindow(
|
||||
|
||||
void
|
||||
TkMacOSXSetDrawingEnabled(
|
||||
TkWindow *winPtr,
|
||||
int flag)
|
||||
TkWindow *winPtr,
|
||||
int flag)
|
||||
{
|
||||
TkWindow *childPtr;
|
||||
MacDrawable *macWin = winPtr->privatePtr;
|
||||
|
||||
if (macWin) {
|
||||
if (flag ) {
|
||||
if (flag) {
|
||||
macWin->flags &= ~TK_DO_NOT_DRAW;
|
||||
} else {
|
||||
macWin->flags |= TK_DO_NOT_DRAW;
|
||||
@@ -724,8 +752,8 @@ TkMacOSXSetDrawingEnabled(
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the flag for all children & their descendants, excluding
|
||||
* Toplevels. (??? Do we need to exclude Toplevels?)
|
||||
* Set the flag for all children & their descendants, excluding Toplevels.
|
||||
* (??? Do we need to exclude Toplevels?)
|
||||
*/
|
||||
|
||||
childPtr = winPtr->childList;
|
||||
@@ -889,7 +917,6 @@ TkMacOSXUpdateClipRgn(
|
||||
}
|
||||
CFRelease(rgn);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* An unmapped window has empty clip regions to prevent any
|
||||
* (erroneous) drawing into it or its children from becoming
|
||||
@@ -919,8 +946,8 @@ TkMacOSXUpdateClipRgn(
|
||||
* TkMacOSXVisableClipRgn --
|
||||
*
|
||||
* This function returns the Macintosh clipping region for the given
|
||||
* window. The caller is responsible for disposing of the returned
|
||||
* region via TkDestroyRegion().
|
||||
* window. The caller is responsible for disposing of the returned region
|
||||
* via TkDestroyRegion().
|
||||
*
|
||||
* Results:
|
||||
* The region.
|
||||
@@ -938,7 +965,7 @@ TkMacOSXVisableClipRgn(
|
||||
if (winPtr->privatePtr->flags & TK_CLIP_INVALID) {
|
||||
TkMacOSXUpdateClipRgn(winPtr);
|
||||
}
|
||||
return (TkRegion)HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn);
|
||||
return (TkRegion) HIShapeCreateMutableCopy(winPtr->privatePtr->visRgn);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -958,7 +985,12 @@ TkMacOSXVisableClipRgn(
|
||||
*/
|
||||
|
||||
static OSStatus
|
||||
InvalViewRect(int msg, HIShapeRef rgn, const CGRect *rect, void *ref) {
|
||||
InvalViewRect(
|
||||
int msg,
|
||||
HIShapeRef rgn,
|
||||
const CGRect *rect,
|
||||
void *ref)
|
||||
{
|
||||
static CGAffineTransform t;
|
||||
NSView *view = ref;
|
||||
|
||||
@@ -1038,7 +1070,7 @@ TkMacOSXInvalidateWindow(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
NSWindow*
|
||||
NSWindow *
|
||||
TkMacOSXDrawableWindow(
|
||||
Drawable drawable)
|
||||
{
|
||||
@@ -1056,6 +1088,7 @@ TkMacOSXDrawableWindow(
|
||||
result = macWin->winPtr->wmInfoPtr->window;
|
||||
} else if (macWin->toplevel && (macWin->toplevel->flags & TK_EMBEDDED)) {
|
||||
TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
|
||||
|
||||
if (contWinPtr) {
|
||||
result = TkMacOSXDrawableWindow((Drawable) contWinPtr->privatePtr);
|
||||
}
|
||||
@@ -1109,7 +1142,7 @@ TkMacOSXGetDrawablePort(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
NSView*
|
||||
NSView *
|
||||
TkMacOSXDrawableView(
|
||||
MacDrawable *macWin)
|
||||
{
|
||||
@@ -1123,6 +1156,7 @@ TkMacOSXDrawableView(
|
||||
result = macWin->toplevel->view;
|
||||
} else {
|
||||
TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
|
||||
|
||||
if (contWinPtr) {
|
||||
result = TkMacOSXDrawableView(contWinPtr->privatePtr);
|
||||
}
|
||||
@@ -1150,7 +1184,6 @@ void *
|
||||
TkMacOSXGetRootControl(
|
||||
Drawable drawable)
|
||||
{
|
||||
|
||||
/*
|
||||
* will probably need to fix this up for embedding
|
||||
*/
|
||||
@@ -1267,7 +1300,8 @@ TkMacOSXWinBounds(
|
||||
TkWindow *winPtr,
|
||||
void *bounds)
|
||||
{
|
||||
Rect *b = (Rect *)bounds;
|
||||
Rect *b = (Rect *) bounds;
|
||||
|
||||
b->left = winPtr->privatePtr->xOff;
|
||||
b->top = winPtr->privatePtr->yOff;
|
||||
b->right = b->left + winPtr->changes.width;
|
||||
@@ -1310,7 +1344,7 @@ TkMacOSXWinCGBounds(
|
||||
* UpdateOffsets --
|
||||
*
|
||||
* Updates the X & Y offsets of the given TkWindow from the TopLevel it is
|
||||
* a decendant of.
|
||||
* a descendant of.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -1331,7 +1365,6 @@ UpdateOffsets(
|
||||
TkWindow *childPtr;
|
||||
|
||||
if (winPtr->privatePtr == NULL) {
|
||||
|
||||
/*
|
||||
* We haven't called Tk_MakeWindowExist for this window yet. The offset
|
||||
* information will be postponed and calulated at that time. (This will
|
||||
|
||||
@@ -13,13 +13,19 @@
|
||||
*/
|
||||
|
||||
#include "tkMacOSXPrivate.h"
|
||||
#include "tkMacOSXConstants.h"
|
||||
|
||||
/*
|
||||
* Forward declarations of procedures defined later in this file:
|
||||
*/
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
|
||||
static int DebuggerObjCmd (ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const objv[]);
|
||||
int objc, Tcl_Obj *const objv[]);
|
||||
#endif
|
||||
static int PressButtonObjCmd (ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const objv[]);
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -46,8 +52,10 @@ TkplatformtestInit(
|
||||
* Add commands for platform specific tests on MacOS here.
|
||||
*/
|
||||
|
||||
Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd,
|
||||
(ClientData) 0, (Tcl_CmdDeleteProc *) NULL);
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
|
||||
Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd, NULL, NULL);
|
||||
#endif
|
||||
Tcl_CreateObjCommand(interp, "pressbutton", PressButtonObjCmd, NULL, NULL);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -57,7 +65,8 @@ TkplatformtestInit(
|
||||
*
|
||||
* DebuggerObjCmd --
|
||||
*
|
||||
* This procedure simply calls the low level debugger.
|
||||
* This procedure simply calls the low level debugger, which was
|
||||
* deprecated in OSX 10.8.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
@@ -68,6 +77,7 @@ TkplatformtestInit(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
|
||||
static int
|
||||
DebuggerObjCmd(
|
||||
ClientData clientData, /* Not used. */
|
||||
@@ -78,34 +88,136 @@ DebuggerObjCmd(
|
||||
Debugger();
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkTestSimulateDrawing --
|
||||
*
|
||||
* A test widget display procedure which records calls can use this to
|
||||
* avoid duplicate calls which would occur due to fact that no valid
|
||||
* graphics context is available to the idle task which is running the
|
||||
* display proc. Note that no actual drawing to the screen will take
|
||||
* place when this flag is set. This is just a wrapper for the NSApp
|
||||
* property.
|
||||
* TkTestLogDisplay --
|
||||
*
|
||||
* The test image display procedure calls this to determine whether it
|
||||
* should write a log message recording that it has being run. On OSX
|
||||
* 10.14 and later, only calls to the display procedure which occur inside
|
||||
* of the drawRect method should be logged, since those are the only ones
|
||||
* which actually draw anything. On earlier systems the opposite is true.
|
||||
* The calls from within the drawRect method are redundant, since the
|
||||
* first time the display procedure is run it will do the drawing and that
|
||||
* first call will usually not occur inside of drawRect.
|
||||
*
|
||||
* Results:
|
||||
* Calls to low level drawing routines will return without actually
|
||||
* drawing anything to the screen.
|
||||
* On OSX 10.14 and later, returns true if and only if called from
|
||||
* within [NSView drawRect]. On earlier systems returns false if
|
||||
* and only if called from with [NSView drawRect].
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
MODULE_SCOPE void
|
||||
TkTestSimulateDrawing(Bool yesno) {
|
||||
[NSApp setSimulateDrawing:yesno];
|
||||
MODULE_SCOPE Bool
|
||||
TkTestLogDisplay(void) {
|
||||
if ([NSApp macMinorVersion] >= 14) {
|
||||
return [NSApp isDrawing];
|
||||
} else {
|
||||
return ![NSApp isDrawing];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* PressButtonObjCmd --
|
||||
*
|
||||
* This Tcl command simulates a button press at a specific screen
|
||||
* location. It injects NSEvents into the NSApplication event queue,
|
||||
* as opposed to adding events to the Tcl queue as event generate
|
||||
* would do. One application is for testing the grab command.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
PressButtonObjCmd(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
int x, y, i, value, wNum;
|
||||
CGPoint pt;
|
||||
NSPoint loc;
|
||||
NSEvent *motion, *press, *release;
|
||||
NSArray *screens = [NSScreen screens];
|
||||
CGFloat ScreenHeight = 0;
|
||||
enum {X=1, Y};
|
||||
|
||||
if (screens && [screens count]) {
|
||||
ScreenHeight = [[screens objectAtIndex:0] frame].size.height;
|
||||
}
|
||||
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "x y");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
for (i = 1; i < objc; i++) {
|
||||
if (Tcl_GetIntFromObj(interp,objv[i],&value) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch (i) {
|
||||
case X:
|
||||
x = value;
|
||||
break;
|
||||
case Y:
|
||||
y = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pt.x = loc.x = x;
|
||||
pt.y = y;
|
||||
loc.y = ScreenHeight - y;
|
||||
wNum = 0;
|
||||
CGWarpMouseCursorPosition(pt);
|
||||
motion = [NSEvent mouseEventWithType:NSMouseMoved
|
||||
location:loc
|
||||
modifierFlags:0
|
||||
timestamp:GetCurrentEventTime()
|
||||
windowNumber:wNum
|
||||
context:nil
|
||||
eventNumber:0
|
||||
clickCount:1
|
||||
pressure:0.0];
|
||||
[NSApp postEvent:motion atStart:NO];
|
||||
press = [NSEvent mouseEventWithType:NSLeftMouseDown
|
||||
location:loc
|
||||
modifierFlags:0
|
||||
timestamp:GetCurrentEventTime()
|
||||
windowNumber:wNum
|
||||
context:nil
|
||||
eventNumber:1
|
||||
clickCount:1
|
||||
pressure:0.0];
|
||||
[NSApp postEvent:press atStart:NO];
|
||||
release = [NSEvent mouseEventWithType:NSLeftMouseUp
|
||||
location:loc
|
||||
modifierFlags:0
|
||||
timestamp:GetCurrentEventTime()
|
||||
windowNumber:wNum
|
||||
context:nil
|
||||
eventNumber:2
|
||||
clickCount:1
|
||||
pressure:0.0];
|
||||
[NSApp postEvent:release atStart:NO];
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
static int GenerateUpdates(HIShapeRef updateRgn,
|
||||
CGRect *updateBounds, TkWindow *winPtr);
|
||||
CGRect *updateBounds, TkWindow *winPtr);
|
||||
static int GenerateActivateEvents(TkWindow *winPtr,
|
||||
int activeFlag);
|
||||
static void DoWindowActivate(ClientData clientData);
|
||||
@@ -68,8 +68,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
#endif
|
||||
BOOL movedOnly = [[notification name]
|
||||
isEqualToString:NSWindowDidMoveNotification];
|
||||
|
||||
isEqualToString:NSWindowDidMoveNotification];
|
||||
NSWindow *w = [notification object];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
|
||||
@@ -79,8 +78,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
int x, y, width = -1, height = -1, flags = 0;
|
||||
|
||||
x = bounds.origin.x;
|
||||
y = tkMacOSXZeroScreenHeight - (bounds.origin.y + bounds.size.height);
|
||||
if (winPtr->changes.x != x || winPtr->changes.y != y){
|
||||
y = TkMacOSXZeroScreenHeight() - (bounds.origin.y + bounds.size.height);
|
||||
if (winPtr->changes.x != x || winPtr->changes.y != y) {
|
||||
flags |= TK_LOCATION_CHANGED;
|
||||
} else {
|
||||
x = y = -1;
|
||||
@@ -92,15 +91,16 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
flags |= TK_SIZE_CHANGED;
|
||||
}
|
||||
if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
|
||||
|
||||
/*
|
||||
* Propagate geometry changes immediately.
|
||||
*/
|
||||
|
||||
flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
|
||||
}
|
||||
|
||||
TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void) windowExpanded: (NSNotification *) notification
|
||||
@@ -136,6 +136,46 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
|
||||
defaultFrame:(NSRect)newFrame
|
||||
{
|
||||
/*
|
||||
* This method needs to be implemented in order for [NSWindow isZoomed] to
|
||||
* give the correct answer. But it suffices to always validate every
|
||||
* request.
|
||||
*/
|
||||
|
||||
return newFrame;
|
||||
}
|
||||
|
||||
- (NSSize)window:(NSWindow *)window
|
||||
willUseFullScreenContentSize:(NSSize)proposedSize
|
||||
{
|
||||
/*
|
||||
* We don't need to change the proposed size, but we do need to implement
|
||||
* this method. Otherwise the full screen window will be sized to the
|
||||
* screen's visibleFrame, leaving black bands at the top and bottom.
|
||||
*/
|
||||
|
||||
return proposedSize;
|
||||
}
|
||||
|
||||
- (void) windowEnteredFullScreen: (NSNotification *) notification
|
||||
{
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
#endif
|
||||
[(TKWindow *)[notification object] tkLayoutChanged];
|
||||
}
|
||||
|
||||
- (void) windowExitedFullScreen: (NSNotification *) notification
|
||||
{
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
#endif
|
||||
[(TKWindow *)[notification object] tkLayoutChanged];
|
||||
}
|
||||
|
||||
- (void) windowCollapsed: (NSNotification *) notification
|
||||
{
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
@@ -158,21 +198,16 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
|
||||
if (winPtr) {
|
||||
TkGenWMDestroyEvent((Tk_Window) winPtr);
|
||||
if (_windowWithMouse == w) {
|
||||
_windowWithMouse = nil;
|
||||
[w release];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If necessary, TkGenWMDestroyEvent() handles [close]ing the window,
|
||||
* so can always return NO from -windowShouldClose: for a Tk window.
|
||||
* If necessary, TkGenWMDestroyEvent() handles [close]ing the window, so
|
||||
* can always return NO from -windowShouldClose: for a Tk window.
|
||||
*/
|
||||
|
||||
return (winPtr ? NO : YES);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
|
||||
- (void) windowDragStart: (NSNotification *) notification
|
||||
@@ -213,7 +248,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* TK_MAC_DEBUG_NOTIFICATIONS */
|
||||
|
||||
- (void) _setupWindowNotifications
|
||||
@@ -222,12 +256,19 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
|
||||
#define observe(n, s) \
|
||||
[nc addObserver:self selector:@selector(s) name:(n) object:nil]
|
||||
|
||||
observe(NSWindowDidBecomeKeyNotification, windowActivation:);
|
||||
observe(NSWindowDidResignKeyNotification, windowActivation:);
|
||||
observe(NSWindowDidMoveNotification, windowBoundsChanged:);
|
||||
observe(NSWindowDidResizeNotification, windowBoundsChanged:);
|
||||
observe(NSWindowDidDeminiaturizeNotification, windowExpanded:);
|
||||
observe(NSWindowDidMiniaturizeNotification, windowCollapsed:);
|
||||
|
||||
#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
|
||||
observe(NSWindowDidEnterFullScreenNotification, windowEnteredFullScreen:);
|
||||
observe(NSWindowDidExitFullScreenNotification, windowExitedFullScreen:);
|
||||
#endif
|
||||
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
observe(NSWindowWillMoveNotification, windowDragStart:);
|
||||
observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:);
|
||||
@@ -251,6 +292,22 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
#endif
|
||||
[NSApp tkCheckPasteboard];
|
||||
|
||||
/*
|
||||
* When the application is activated with Command-Tab it will create a
|
||||
* zombie window for every Tk window which has been withdrawn. So iterate
|
||||
* through the list of windows and order out any withdrawn window.
|
||||
*/
|
||||
|
||||
for (NSWindow *win in [NSApp windows]) {
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(win);
|
||||
if (!winPtr || !winPtr->wmInfoPtr) {
|
||||
continue;
|
||||
}
|
||||
if (winPtr->wmInfoPtr->hints.initial_state == WithdrawnState) {
|
||||
[win orderOut:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) applicationDeactivate: (NSNotification *) notification
|
||||
@@ -260,6 +317,20 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender
|
||||
hasVisibleWindows:(BOOL)flag
|
||||
{
|
||||
/*
|
||||
* Allowing the default response means that withdrawn windows will get
|
||||
* displayed on the screen with unresponsive title buttons. We don't
|
||||
* really want that. Besides, we can write our own code to handle this
|
||||
* with ::tk::mac::ReopenApplication. So we just say NO.
|
||||
*/
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (void) applicationShowHide: (NSNotification *) notification
|
||||
{
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
@@ -299,11 +370,11 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
*
|
||||
* TkpAppIsDrawing --
|
||||
*
|
||||
* A widget display procedure can call this to determine whether it
|
||||
* is being run inside of the drawRect method. This is needed for
|
||||
* some tests, especially of the Text widget, which record data in
|
||||
* a global Tcl variable and assume that display procedures will be
|
||||
* run in a predictable sequence as Tcl idle tasks.
|
||||
* A widget display procedure can call this to determine whether it is
|
||||
* being run inside of the drawRect method. This is needed for some tests,
|
||||
* especially of the Text widget, which record data in a global Tcl
|
||||
* variable and assume that display procedures will be run in a
|
||||
* predictable sequence as Tcl idle tasks.
|
||||
*
|
||||
* Results:
|
||||
* True only while running the drawRect method of a TKContentView;
|
||||
@@ -313,11 +384,11 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MODULE_SCOPE Bool
|
||||
TkpAppIsDrawing(void) {
|
||||
return [NSApp isDrawing];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -443,7 +514,9 @@ GenerateActivateEvents(
|
||||
int activeFlag)
|
||||
{
|
||||
TkGenerateActivateEvents(winPtr, activeFlag);
|
||||
TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
|
||||
if (activeFlag || ![NSApp isActive]) {
|
||||
TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -600,17 +673,14 @@ TkGenWMConfigureEvent(
|
||||
if (flags & TK_LOCATION_CHANGED) {
|
||||
wmPtr->x = x;
|
||||
wmPtr->y = y;
|
||||
wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y);
|
||||
}
|
||||
if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) &&
|
||||
((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) {
|
||||
if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) {
|
||||
|
||||
/*
|
||||
* Don't set external width, since the user didn't change it
|
||||
* from what the widgets asked for.
|
||||
*/
|
||||
|
||||
} else if (wmPtr->gridWin != NULL) {
|
||||
wmPtr->width = wmPtr->reqGridWidth
|
||||
+ (width - winPtr->reqWidth)/wmPtr->widthInc;
|
||||
@@ -622,12 +692,10 @@ TkGenWMConfigureEvent(
|
||||
}
|
||||
|
||||
if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) {
|
||||
|
||||
/*
|
||||
* Don't set external height, since the user didn't change it
|
||||
* from what the widgets asked for.
|
||||
*/
|
||||
|
||||
} else if (wmPtr->gridWin != NULL) {
|
||||
wmPtr->height = wmPtr->reqGridHeight
|
||||
+ (height - winPtr->reqHeight)/wmPtr->heightInc;
|
||||
@@ -800,7 +868,10 @@ Tk_MacOSXIsAppInFront(void)
|
||||
*
|
||||
*/
|
||||
|
||||
/*Restrict event processing to Expose events.*/
|
||||
/*
|
||||
* Restrict event processing to Expose events.
|
||||
*/
|
||||
|
||||
static Tk_RestrictAction
|
||||
ExposeRestrictProc(
|
||||
ClientData arg,
|
||||
@@ -810,7 +881,10 @@ ExposeRestrictProc(
|
||||
? TK_PROCESS_EVENT : TK_DEFER_EVENT);
|
||||
}
|
||||
|
||||
/*Restrict event processing to ConfigureNotify events.*/
|
||||
/*
|
||||
* Restrict event processing to ConfigureNotify events.
|
||||
*/
|
||||
|
||||
static Tk_RestrictAction
|
||||
ConfigureRestrictProc(
|
||||
ClientData arg,
|
||||
@@ -819,6 +893,30 @@ ConfigureRestrictProc(
|
||||
return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a window gets mapped inside the drawRect method, this will be run as an
|
||||
* idle task, after drawRect returns, to clean up the mess.
|
||||
*/
|
||||
|
||||
static void
|
||||
RedisplayView(
|
||||
ClientData clientdata)
|
||||
{
|
||||
NSView *view = (NSView *) clientdata;
|
||||
|
||||
/*
|
||||
* Make sure that we are not trying to displaying a view that no longer
|
||||
* exists.
|
||||
*/
|
||||
|
||||
for (NSWindow *w in [NSApp orderedWindows]) {
|
||||
if ([w contentView] == view) {
|
||||
[view setNeedsDisplay:YES];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@implementation TKContentView(TKWindowEvent)
|
||||
|
||||
- (void) drawRect: (NSRect) rect
|
||||
@@ -832,17 +930,15 @@ ConfigureRestrictProc(
|
||||
Tk_PathName(winPtr));
|
||||
#endif
|
||||
|
||||
if ([NSApp simulateDrawing]) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do not allow recursive calls to drawRect, but we only log
|
||||
* them on OSX > 10.13, where they should never happen.
|
||||
* We do not allow recursive calls to drawRect, but we only log them on OSX
|
||||
* > 10.13, where they should never happen.
|
||||
*/
|
||||
|
||||
if ([NSApp isDrawing] && [NSApp macMinorVersion] > 13) {
|
||||
TKLog(@"WARNING: a recursive call to drawRect was aborted.");
|
||||
if ([NSApp isDrawing]) {
|
||||
if ([NSApp macMinorVersion] > 13) {
|
||||
TKLog(@"WARNING: a recursive call to drawRect was aborted.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -867,6 +963,11 @@ ConfigureRestrictProc(
|
||||
CFRelease(drawShape);
|
||||
[NSApp setIsDrawing: NO];
|
||||
|
||||
if ([self needsRedisplay]) {
|
||||
[self setNeedsRedisplay:NO];
|
||||
Tcl_DoWhenIdle(RedisplayView, self);
|
||||
}
|
||||
|
||||
#ifdef TK_MAC_DEBUG_DRAWING
|
||||
fprintf(stderr, "drawRect: done.\n");
|
||||
#endif
|
||||
@@ -878,22 +979,22 @@ ConfigureRestrictProc(
|
||||
NSWindow *w = [self window];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
|
||||
if (![self inLiveResize] &&
|
||||
[w respondsToSelector: @selector (tkLayoutChanged)]) {
|
||||
[(TKWindow *)w tkLayoutChanged];
|
||||
}
|
||||
|
||||
if (winPtr) {
|
||||
/* On OSX versions below 10.14 setFrame calls drawRect.
|
||||
* On 10.14 it does its own drawing.
|
||||
*/
|
||||
if ([NSApp macMinorVersion] > 13) {
|
||||
[NSApp setIsDrawing:YES];
|
||||
}
|
||||
unsigned int width = (unsigned int)newsize.width;
|
||||
unsigned int height=(unsigned int)newsize.height;
|
||||
ClientData oldArg;
|
||||
Tk_RestrictProc *oldProc;
|
||||
|
||||
/*
|
||||
* This can be called from outside the Tk event loop.
|
||||
* Since it calls Tcl_DoOneEvent, we need to make sure we
|
||||
* don't clobber the AutoreleasePool set up by the caller.
|
||||
* This can be called from outside the Tk event loop. Since it calls
|
||||
* Tcl_DoOneEvent, we need to make sure we don't clobber the
|
||||
* AutoreleasePool set up by the caller.
|
||||
*/
|
||||
|
||||
[NSApp _lockAutoreleasePool];
|
||||
@@ -909,7 +1010,7 @@ ConfigureRestrictProc(
|
||||
*/
|
||||
|
||||
TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,
|
||||
TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
|
||||
TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
|
||||
oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg);
|
||||
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
|
||||
|
||||
@@ -933,7 +1034,7 @@ ConfigureRestrictProc(
|
||||
/*
|
||||
* Finally, unlock the main autoreleasePool.
|
||||
*/
|
||||
|
||||
|
||||
[NSApp _unlockAutoreleasePool];
|
||||
}
|
||||
}
|
||||
@@ -997,16 +1098,15 @@ ConfigureRestrictProc(
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called when a user changes between light and dark mode.
|
||||
* The implementation here generates a Tk virtual event which can be bound
|
||||
* to a function that redraws the window in an appropriate style.
|
||||
* This method is called when a user changes between light and dark mode. The
|
||||
* implementation here generates a Tk virtual event which can be bound to a
|
||||
* function that redraws the window in an appropriate style.
|
||||
*/
|
||||
|
||||
- (void) viewDidChangeEffectiveAppearance
|
||||
{
|
||||
XVirtualEvent event;
|
||||
int x, y;
|
||||
NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
||||
NSWindow *w = [self window];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
@@ -1027,21 +1127,17 @@ ConfigureRestrictProc(
|
||||
&event.x_root, &event.y_root, &x, &y, &event.state);
|
||||
Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
|
||||
event.same_screen = true;
|
||||
if (osxMode == nil) {
|
||||
event.name = Tk_GetUid("LightAqua");
|
||||
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
|
||||
return;
|
||||
}
|
||||
if ([osxMode isEqual:@"Dark"]) {
|
||||
if (TkMacOSXInDarkMode(tkwin)) {
|
||||
event.name = Tk_GetUid("DarkAqua");
|
||||
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
|
||||
return;
|
||||
} else {
|
||||
event.name = Tk_GetUid("LightAqua");
|
||||
}
|
||||
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is no-op on 10.7 and up because Apple has removed this widget,
|
||||
* but we are leaving it here for backwards compatibility.
|
||||
* This is no-op on 10.7 and up because Apple has removed this widget, but we
|
||||
* are leaving it here for backwards compatibility.
|
||||
*/
|
||||
|
||||
- (void) tkToolbarButton: (id) sender
|
||||
@@ -1090,6 +1186,11 @@ ConfigureRestrictProc(
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*
|
||||
* This keyDown method does nothing, which is a huge improvement over the
|
||||
* default keyDown method which beeps every time a key is pressed.
|
||||
*/
|
||||
|
||||
- (void) keyDown: (NSEvent *) theEvent
|
||||
{
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
@@ -1097,6 +1198,23 @@ ConfigureRestrictProc(
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* When the services menu is opened this is called for each Responder in
|
||||
* the Responder chain until a service provider is found. The TkContentView
|
||||
* should be the first (and generally only) Responder in the chain. We
|
||||
* return the TkServices object that was created in TkpInit.
|
||||
*/
|
||||
|
||||
- (id)validRequestorForSendType:(NSString *)sendType
|
||||
returnType:(NSString *)returnType
|
||||
{
|
||||
if ([sendType isEqualToString:@"NSStringPboardType"] ||
|
||||
[sendType isEqualToString:@"NSPasteboardTypeString"]) {
|
||||
return [NSApp servicesProvider];
|
||||
}
|
||||
return [super validRequestorForSendType:sendType returnType:returnType];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/*
|
||||
|
||||
1455
macosx/tkMacOSXWm.c
1455
macosx/tkMacOSXWm.c
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,17 @@ typedef struct ProtocolHandler {
|
||||
* THE LAST FIELD OF THE STRUCTURE. */
|
||||
} ProtocolHandler;
|
||||
|
||||
/* The following data structure is used in the TkWmInfo to maintain a list of all of the
|
||||
* transient windows belonging to a given master.
|
||||
*/
|
||||
|
||||
typedef struct Transient {
|
||||
TkWindow *winPtr;
|
||||
int flags;
|
||||
struct Transient *nextPtr;
|
||||
} Transient;
|
||||
|
||||
#define WITHDRAWN_BY_MASTER 0x1
|
||||
|
||||
/*
|
||||
* A data structure of the following type holds window-manager-related
|
||||
@@ -54,7 +65,7 @@ typedef struct TkWmInfo {
|
||||
Tk_Uid titleUid; /* Title to display in window caption. If NULL,
|
||||
* use name of widget. */
|
||||
char *iconName; /* Name to display in icon. */
|
||||
Window master; /* Master window for TRANSIENT_FOR property, or
|
||||
Tk_Window master; /* Master window for TRANSIENT_FOR property, or
|
||||
* None. */
|
||||
XWMHints hints; /* Various pieces of information for window
|
||||
* manager. */
|
||||
@@ -62,14 +73,13 @@ typedef struct TkWmInfo {
|
||||
* (corresponds to hints.window_group).
|
||||
* Malloc-ed. Note: this field doesn't get
|
||||
* updated if leader is destroyed. */
|
||||
char *masterWindowName; /* Path name of window specified as master in
|
||||
* "wm transient" command, or NULL. Malloc-ed.
|
||||
* Note: this field doesn't get updated if
|
||||
* masterWindowName is destroyed. */
|
||||
Tk_Window icon; /* Window to use as icon for this window, or
|
||||
* NULL. */
|
||||
Tk_Window iconFor; /* Window for which this window is icon, or
|
||||
* NULL if this isn't an icon for anyone. */
|
||||
Transient *transientPtr; /* First item in a list of all transient windows
|
||||
* belonging to this window, or NULL if there
|
||||
* are no transients. */
|
||||
|
||||
/*
|
||||
* Information used to construct an XSizeHints structure for the window
|
||||
|
||||
@@ -33,9 +33,6 @@
|
||||
|
||||
#define ROOT_ID 10
|
||||
|
||||
CGFloat tkMacOSXZeroScreenHeight = 0;
|
||||
CGFloat tkMacOSXZeroScreenTop = 0;
|
||||
|
||||
/*
|
||||
* Declarations of static variables used in this file.
|
||||
*/
|
||||
@@ -90,13 +87,9 @@ TkMacOSXDisplayChanged(
|
||||
nsScreens = [NSScreen screens];
|
||||
if (nsScreens && [nsScreens count]) {
|
||||
NSScreen *s = [nsScreens objectAtIndex:0];
|
||||
NSRect bounds = [s frame], visible = [s visibleFrame];
|
||||
NSRect bounds = [s frame];
|
||||
NSRect maxBounds = NSZeroRect;
|
||||
|
||||
tkMacOSXZeroScreenHeight = bounds.size.height;
|
||||
tkMacOSXZeroScreenTop = tkMacOSXZeroScreenHeight -
|
||||
(visible.origin.y + visible.size.height);
|
||||
|
||||
screen->root_depth = NSBitsPerPixelFromDepth([s depth]);
|
||||
screen->width = bounds.size.width;
|
||||
screen->height = bounds.size.height;
|
||||
@@ -110,6 +103,67 @@ TkMacOSXDisplayChanged(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkMacOSXZeroScreenHeight --
|
||||
*
|
||||
* Replacement for the tkMacOSXZeroScreenHeight variable to avoid
|
||||
* caching values from NSScreen (fixes bug aea00be199).
|
||||
*
|
||||
* Results:
|
||||
* Returns the height of screen 0 (the screen assigned the menu bar
|
||||
* in System Preferences), or 0.0 if getting [NSScreen screens] fails.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
CGFloat
|
||||
TkMacOSXZeroScreenHeight()
|
||||
{
|
||||
NSArray *nsScreens = [NSScreen screens];
|
||||
if (nsScreens && [nsScreens count]) {
|
||||
NSScreen *s = [nsScreens objectAtIndex:0];
|
||||
NSRect bounds = [s frame];
|
||||
return bounds.size.height;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkMacOSXZeroScreenTop --
|
||||
*
|
||||
* Replacement for the tkMacOSXZeroScreenTop variable to avoid
|
||||
* caching values from visibleFrame.
|
||||
*
|
||||
* Results:
|
||||
* Returns how far below the top of screen 0 to draw
|
||||
* (i.e. the height of the menu bar if it is always shown),
|
||||
* or 0.0 if getting [NSScreen screens] fails.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
CGFloat
|
||||
TkMacOSXZeroScreenTop()
|
||||
{
|
||||
NSArray *nsScreens = [NSScreen screens];
|
||||
if (nsScreens && [nsScreens count]) {
|
||||
NSScreen *s = [nsScreens objectAtIndex:0];
|
||||
NSRect bounds = [s frame], visible = [s visibleFrame];
|
||||
return bounds.size.height - (visible.origin.y + visible.size.height);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -178,7 +232,7 @@ TkpOpenDisplay(
|
||||
{
|
||||
int major, minor, patch;
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
|
||||
Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
|
||||
Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
|
||||
Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
|
||||
@@ -202,7 +256,7 @@ TkpOpenDisplay(
|
||||
|
||||
screen->root_visual = ckalloc(sizeof(Visual));
|
||||
screen->root_visual->visualid = 0;
|
||||
screen->root_visual->class = TrueColor;
|
||||
screen->root_visual->c_class = TrueColor;
|
||||
screen->root_visual->red_mask = 0x00FF0000;
|
||||
screen->root_visual->green_mask = 0x0000FF00;
|
||||
screen->root_visual->blue_mask = 0x000000FF;
|
||||
@@ -225,6 +279,12 @@ TkpOpenDisplay(
|
||||
bzero(gMacDisplay, sizeof(TkDisplay));
|
||||
gMacDisplay->display = display;
|
||||
[pool drain];
|
||||
|
||||
/*
|
||||
* Key map info must be available immediately, because of "send event".
|
||||
*/
|
||||
TkpInitKeymapInfo(gMacDisplay);
|
||||
|
||||
return gMacDisplay;
|
||||
}
|
||||
|
||||
@@ -429,7 +489,7 @@ XGetGeometry(
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XChangeProperty(
|
||||
Display* display,
|
||||
Window w,
|
||||
@@ -441,15 +501,17 @@ XChangeProperty(
|
||||
int nelements)
|
||||
{
|
||||
Debugger();
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XSelectInput(
|
||||
Display* display,
|
||||
Window w,
|
||||
long event_mask)
|
||||
{
|
||||
Debugger();
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -508,11 +570,12 @@ XSendEvent(
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XClearWindow(
|
||||
Display* display,
|
||||
Window w)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -524,6 +587,7 @@ XDrawPoint(
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -535,6 +599,7 @@ XDrawPoints(
|
||||
int npoints,
|
||||
int mode)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -553,7 +618,7 @@ XWarpPointer(
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XQueryColor(
|
||||
Display* display,
|
||||
Colormap colormap,
|
||||
@@ -572,9 +637,10 @@ XQueryColor(
|
||||
d->blue = (b << 8) | b;
|
||||
d->flags = DoRed|DoGreen|DoBlue;
|
||||
d->pad = 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XQueryColors(
|
||||
Display* display,
|
||||
Colormap colormap,
|
||||
@@ -597,6 +663,7 @@ XQueryColors(
|
||||
d->flags = DoRed|DoGreen|DoBlue;
|
||||
d->pad = 0;
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -635,15 +702,16 @@ XGetWindowProperty(
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XRefreshKeyboardMapping(
|
||||
XMappingEvent *x)
|
||||
{
|
||||
/* used by tkXEvent.c */
|
||||
Debugger();
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XSetIconName(
|
||||
Display* display,
|
||||
Window w,
|
||||
@@ -653,9 +721,10 @@ XSetIconName(
|
||||
* This is a no-op, no icon name for Macs.
|
||||
*/
|
||||
display->request++;
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XForceScreenSaver(
|
||||
Display* display,
|
||||
int mode)
|
||||
@@ -667,6 +736,7 @@ XForceScreenSaver(
|
||||
*/
|
||||
|
||||
display->request++;
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -680,7 +750,7 @@ Tk_FreeXId(
|
||||
int
|
||||
XSync(
|
||||
Display *display,
|
||||
Bool flag)
|
||||
Bool discard)
|
||||
{
|
||||
TkMacOSXFlushWindows();
|
||||
display->request++;
|
||||
@@ -770,62 +840,69 @@ TkGetServerInfo(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
XChangeWindowAttributes(
|
||||
Display *display,
|
||||
Window w,
|
||||
unsigned long value_mask,
|
||||
XSetWindowAttributes *attributes)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XSetWindowBackground(
|
||||
Display *display,
|
||||
Window window,
|
||||
unsigned long value)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XSetWindowBackgroundPixmap(
|
||||
Display *display,
|
||||
Window w,
|
||||
Pixmap background_pixmap)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XSetWindowBorder(
|
||||
Display *display,
|
||||
Window w,
|
||||
unsigned long border_pixel)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XSetWindowBorderPixmap(
|
||||
Display *display,
|
||||
Window w,
|
||||
Pixmap border_pixmap)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XSetWindowBorderWidth(
|
||||
Display *display,
|
||||
Window w,
|
||||
unsigned int width)
|
||||
{
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
XSetWindowColormap(
|
||||
Display *display,
|
||||
Window w,
|
||||
Colormap colormap)
|
||||
{
|
||||
Debugger();
|
||||
return Success;
|
||||
}
|
||||
|
||||
Status
|
||||
@@ -848,12 +925,73 @@ XSetWMClientMachine(
|
||||
}
|
||||
|
||||
XIC
|
||||
XCreateIC(void)
|
||||
XCreateIC(XIM xim, ...)
|
||||
{
|
||||
Debugger();
|
||||
return (XIC) 0;
|
||||
}
|
||||
|
||||
#undef XVisualIDFromVisual
|
||||
VisualID
|
||||
XVisualIDFromVisual(
|
||||
Visual *visual)
|
||||
{
|
||||
return visual->visualid;
|
||||
}
|
||||
|
||||
#undef XSynchronize
|
||||
XAfterFunction
|
||||
XSynchronize(
|
||||
Display *display,
|
||||
Bool onoff)
|
||||
{
|
||||
display->request++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#undef XUngrabServer
|
||||
int
|
||||
XUngrabServer(
|
||||
Display *display)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef XNoOp
|
||||
int
|
||||
XNoOp(
|
||||
Display *display)
|
||||
{
|
||||
display->request++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef XGrabServer
|
||||
int
|
||||
XGrabServer(
|
||||
Display *display)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef XFree
|
||||
int
|
||||
XFree(
|
||||
void *data)
|
||||
{
|
||||
if ((data) != NULL) {
|
||||
ckfree(data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#undef XFlush
|
||||
int
|
||||
XFlush(
|
||||
Display *display)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user