summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
authorculler <culler>2020-11-10 13:59:25 (GMT)
committerculler <culler>2020-11-10 13:59:25 (GMT)
commitd94200fdcf927707b43670e7751208ea902b382e (patch)
treec8f724ce055955eef67c4b799866138c5389715d /macosx
parenta49d6e52a72b1f086503ae32cb28b0da62e5fa99 (diff)
parent6133a711414cfb8fcc3a8b52ecf25b59a09e5800 (diff)
downloadtk-d94200fdcf927707b43670e7751208ea902b382e.zip
tk-d94200fdcf927707b43670e7751208ea902b382e.tar.gz
tk-d94200fdcf927707b43670e7751208ea902b382e.tar.bz2
Merge main
Diffstat (limited to 'macosx')
-rw-r--r--macosx/Credits.html.in24
-rw-r--r--macosx/GNUmakefile32
-rw-r--r--macosx/README82
-rw-r--r--macosx/Tk-Common.xcconfig2
-rw-r--r--macosx/Tk.xcode/project.pbxproj4
-rw-r--r--macosx/Tk.xcodeproj/project.pbxproj4
-rw-r--r--macosx/tkMacOSX.h2
-rw-r--r--macosx/tkMacOSXBitmap.c9
-rw-r--r--macosx/tkMacOSXButton.c42
-rw-r--r--macosx/tkMacOSXClipboard.c11
-rw-r--r--macosx/tkMacOSXColor.c824
-rw-r--r--macosx/tkMacOSXColor.h198
-rw-r--r--macosx/tkMacOSXConstants.h12
-rw-r--r--macosx/tkMacOSXCursor.c75
-rw-r--r--macosx/tkMacOSXDefault.h40
-rw-r--r--macosx/tkMacOSXDialog.c184
-rw-r--r--macosx/tkMacOSXDraw.c852
-rw-r--r--macosx/tkMacOSXEmbed.c55
-rw-r--r--macosx/tkMacOSXEntry.c8
-rw-r--r--macosx/tkMacOSXEvent.c49
-rw-r--r--macosx/tkMacOSXFont.c50
-rw-r--r--macosx/tkMacOSXHLEvents.c85
-rw-r--r--macosx/tkMacOSXImage.c654
-rw-r--r--macosx/tkMacOSXInit.c243
-rw-r--r--macosx/tkMacOSXInt.h25
-rw-r--r--macosx/tkMacOSXKeyEvent.c44
-rw-r--r--macosx/tkMacOSXKeyboard.c13
-rw-r--r--macosx/tkMacOSXKeysyms.h4
-rw-r--r--macosx/tkMacOSXMenu.c179
-rw-r--r--macosx/tkMacOSXMenubutton.c15
-rw-r--r--macosx/tkMacOSXMenus.c29
-rw-r--r--macosx/tkMacOSXMouseEvent.c402
-rw-r--r--macosx/tkMacOSXNotify.c187
-rw-r--r--macosx/tkMacOSXPort.h39
-rw-r--r--macosx/tkMacOSXPrivate.h97
-rw-r--r--macosx/tkMacOSXRegion.c50
-rw-r--r--macosx/tkMacOSXScale.c36
-rw-r--r--macosx/tkMacOSXScrlbr.c20
-rw-r--r--macosx/tkMacOSXSend.c2
-rw-r--r--macosx/tkMacOSXServices.c9
-rw-r--r--macosx/tkMacOSXSubwindows.c361
-rw-r--r--macosx/tkMacOSXTest.c115
-rw-r--r--macosx/tkMacOSXWindowEvent.c506
-rw-r--r--macosx/tkMacOSXWm.c722
-rw-r--r--macosx/tkMacOSXWm.h8
-rw-r--r--macosx/tkMacOSXXStubs.c36
-rw-r--r--macosx/ttkMacOSXTheme.c224
47 files changed, 3518 insertions, 3146 deletions
diff --git a/macosx/Credits.html.in b/macosx/Credits.html.in
new file mode 100644
index 0000000..cc409b1
--- /dev/null
+++ b/macosx/Credits.html.in
@@ -0,0 +1,24 @@
+<!doctype htmL>
+<html>
+<head>
+</head>
+<body style="font-size:120%;font-family:Arial,sans-serif;">
+<p>
+Tcl and Tk are distributed under a modified BSD license:<br>
+<a href="https:www.tcl.tk/software/tcltk/license.html">
+ https:www.tcl.tk/software/tcltk/license.html
+</a>
+</p>
+<ul style="list-style-type:none;">
+<li>&copy; 1987-@TK_YEAR@ Tcl Core Team and Contributers.</li>
+<li>&copy; 2011-@TK_YEAR@ Kevin Walzer/WordTech Communications LLC.</li>
+<li>&copy; 2014-@TK_YEAR@ Marc Culler.</li>
+<li>&copy; 2002-2012 Daniel A. Steffen.</li>
+<li>&copy; 2001-2009 Apple Inc.</li>
+<li>&copy; 2001-2002 Jim Ingham &amp; Ian Reid.</li>
+<li>&copy; 1998-2000 Jim Ingham &amp; Ray Johnson.</li>
+<li>&copy; 1998-2000 Scriptics Inc.</li>
+<li>&copy; 1996-1997 Sun Microsystems Inc.</li>
+</ul>
+</body>
+</html>
diff --git a/macosx/GNUmakefile b/macosx/GNUmakefile
index e753c29..2451e5c 100644
--- a/macosx/GNUmakefile
+++ b/macosx/GNUmakefile
@@ -44,6 +44,18 @@ INSTALL_MANPAGES ?=
# set to non-empty value to build TkX11 instead of TkAqua:
TK_X11 ?=
+# Checks and overrides for subframework builds
+ifeq (${SUBFRAMEWORK}_${TK_X11},1_)
+ifeq (${DYLIB_INSTALL_DIR},)
+ @echo "Cannot install subframework with empty DYLIB_INSTALL_DIR !" && false
+endif
+ifeq (${DESTDIR},)
+ @echo "Cannot install subframework with empty DESTDIR !" && false
+endif
+override BUILD_DIR = ${DESTDIR}/build
+override INSTALL_PATH = /Frameworks
+endif
+
#-------------------------------------------------------------------------------------------------------
# meta targets
@@ -211,9 +223,15 @@ install-${PROJECT}: build-${PROJECT}
ifeq (${EMBEDDED_BUILD}_${INSTALL_ROOT},1_)
@echo "Cannot install-embedded with empty INSTALL_ROOT !" && false
endif
+ifeq (${SUBFRAMEWORK}_${DYLIB_INSTALL_DIR},1_)
+ @echo "Cannot install subframework with empty DYLIB_INSTALL_DIR !" && false
+endif
ifeq (${EMBEDDED_BUILD},1)
@rm -rf "${INSTALL_ROOT}/${LIBDIR}/Tk.framework"
endif
+ifeq (${SUBFRAMEWORK},1)
+ @rm -rf "${INSTALL_ROOT}/Frameworks/Tk.framework"
+endif
${DO_MAKE}
ifeq (${EMBEDDED_BUILD}_${TK_X11},1_)
# workaround bug with 'cp -pRH' on Darwin 6 and earlier
@@ -228,8 +246,8 @@ ifeq (${EMBEDDED_BUILD},1)
else
# install wish symbolic link
@ln -fs ${WISH} "${INSTALL_ROOT}${BINDIR}/${wish}"
-endif
-endif
+endif # embedded
+endif # install
ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)
# keep copy of debug library around, so that
# Deployment build can be installed on top
@@ -237,8 +255,9 @@ ifeq (${BUILD_STYLE}_${EMBEDDED_BUILD},Development_)
# the debug library
@cd "${INSTALL_ROOT}${LIBDIR}/${PRODUCT_NAME}.framework/Versions/${VERSION}" && \
ln -f "${PRODUCT_NAME}" "${PRODUCT_NAME}_debug"
-endif
+endif # Development, not embedded
ifeq (${TK_X11},)
+ifeq (${SUBFRAMEWORK},)
ifeq (${EMBEDDED_BUILD},)
# install Wish.app link in APPLICATION_INSTALL_PATH and setup 'Wish Shell' compatibility links
@cd "${TOP_DIR}" && if [ -n "${APP_DIR}" ]; then mkdir -p "./${APP_DIR}" && rm -rf "./${APP_DIR}/Wish.app" && \
@@ -272,9 +291,10 @@ else
fix_install_name MacOS/Wish Tcl && fix_install_name MacOS/Wish Tk
ifeq (${INSTALL_BUILD},1)
@cd "${TOP_DIR}" && rm -rf "./${FMWK_DIR}"/T{cl,k}.framework && rmdir -p "./${FMWK_DIR}" 2>&- || true
-endif
-endif
-endif
+endif # install not subframework
+endif # embedded
+endif # not subframework
+endif # not X11
clean-${PROJECT}: %-${PROJECT}:
${DO_MAKE}
diff --git a/macosx/README b/macosx/README
index a3f10b6..ac641b1 100644
--- a/macosx/README
+++ b/macosx/README
@@ -272,20 +272,24 @@ 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, systemLinkColor, and
-systemControlAccentColor. All of these except the last three were
-present in OSX 10.0 (and those three 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.
+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.
+
+Tk now provides colors corresponding to all of the NSColors in Apple's System
+ColorList. The convention for naming these colors is that the Tk name is
+generated by capitalizing the macOS name and adding the prefix "system". The
+System ColorList differs between releases of macOS and some colors, such as
+systemLinkColor and systemControlAccentColor, are simulated on older systems
+which did not provide them. The following colors are available on all
+supported macOS releases, although newer systems will support additional
+colors: systemControlAccentColor, systemControlTextColor,
+systemDisabledControlTextColor, systemLabelColor, systemLinkColor,
+systemPlaceholderTextColor, systemSelectedTextBackgroundColor,
+systemSelectedTextColor, systemSeparatorColor, systemTextBackgroundColor, and
+systemTextColor. One additional color, systemSelectedTabTextColor, does not
+exist in macOS but is used by Tk to match the different colors used for
+Notebook tab titles 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
@@ -455,6 +459,20 @@ 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.
+- To build a Tcl.framework and Tk.framework for use as subframeworks in another
+framework, use the install-embedded target and set SUBFRAMEWORK=1. Set the
+DYLIB_INSTALL_DIR variable to the path which should be the install_name path of
+the shared library and set the DESTDIR variable to the pathname of a staging
+directory where the frameworks will be written. The Tcl framework must be
+built first.
+For example, running the commands:
+ make -C ../tcl8.6/macosx install-embedded SUBFRAMEWORK=1 DESTDIR=/tmp/tcltk \
+ DYLIB_INSTALL_DIR=/Library/Frameworks/Some.framework/Versions/X.Y/Frameworks/Tcl.framework
+ make -C macosx install-embedded SUBFRAMEWORK=1 DESTDIR=/tmp/tcltk \
+ DYLIB_INSTALL_DIR=/Library/Frameworks/Some.framework/Versions/X.Y/Frameworks/Tk.framework
+will produce a Tcl.framework and a Tk.framework usable as subframeworks of
+Some.framework. The frameworks will be found in /tmp/tcltk/Frameworks/
+
5. Details regarding the macOS port of Tk.
-------------------------------------------
@@ -662,15 +680,35 @@ 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.
-6.0 Virtual events on 10.14
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
+6.0 Virtual events on macOS 10.14 and later
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The 10.14 release added support for system appearance changes,
+including a "Dark Mode" that renders all window frames and menus in
+dark colors. Tk 8.6.11 provides three virtual events <<LightAqua>>,
+<<DarkAqua>> and <<AppearanceChanged>>, to allow you to update your Tk
+app's appearance when the system appearance changes. These events are
+generated in [NSView effectiveAppearanceChanged], which is called by
+the Apple window manager when the General Preferences is changed
+either by switching between Light Mode and Dark Mode or by changing
+the Accent Color or Highlight Color.
+
+The <<AppearanceChanged>> virtual event has a data string which can be
+accessed with the %d substitution. The format of the data string is
+that it consists of 6 words:
+ "Appearance XXXX Accent YYYY Highlight ZZZZ"
+For example, the following code will print the current appearance
+name, accent color and highlight color when the <<AppearanceChanged>>
+virtual event fires:
+
+bind . <<AppearanceChanged>> {
+ array set data [split %d]
+ puts " Appearance: $data(Appearance)"
+ puts " Accent: $data(Accent)"
+ puts " Highlight: $data(Highlight)\n"
+}
+
-10.14 supports system appearance changes, and has added a "Dark Mode"
-that casts all window frames and menus as black. Tk 8.6.9 has added two
-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
~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/macosx/Tk-Common.xcconfig b/macosx/Tk-Common.xcconfig
index 6219135..72ef08a 100644
--- a/macosx/Tk-Common.xcconfig
+++ b/macosx/Tk-Common.xcconfig
@@ -23,7 +23,7 @@ GCC_NO_COMMON_BLOCKS = YES
GCC_DYNAMIC_NO_PIC = YES
GCC_VERSION = 4.2
GCC = gcc-$(GCC_VERSION)
-WARNING_CFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-value -Winit-self -Wpointer-arith -Wcast-align -Wdisabled-optimization -Winline $(WARNING_CFLAGS)
+WARNING_CFLAGS = -Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith -Winit-self -Wcast-align -Wdisabled-optimization -Winline $(WARNING_CFLAGS)
REZ_RESOURCE_MAP_READ_ONLY = YES
APPLICATION_INSTALL_PATH = /Applications/Utilities
BINDIR = $(PREFIX)/bin
diff --git a/macosx/Tk.xcode/project.pbxproj b/macosx/Tk.xcode/project.pbxproj
index 9598af9..c1c5b41 100644
--- a/macosx/Tk.xcode/project.pbxproj
+++ b/macosx/Tk.xcode/project.pbxproj
@@ -1408,7 +1408,7 @@
F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
- F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = "<group>"; };
+ F96D3E2208F272A5004A47F5 /* CrtAlias.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtAlias.3; sourceTree = "<group>"; };
F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
@@ -3073,7 +3073,7 @@
F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
- F96D3E2208F272A5004A47F5 /* CrtSlave.3 */,
+ F96D3E2208F272A5004A47F5 /* CrtAlias.3 */,
F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
F96D3E2508F272A5004A47F5 /* dde.n */,
diff --git a/macosx/Tk.xcodeproj/project.pbxproj b/macosx/Tk.xcodeproj/project.pbxproj
index 121c8a0..ea4ecfc 100644
--- a/macosx/Tk.xcodeproj/project.pbxproj
+++ b/macosx/Tk.xcodeproj/project.pbxproj
@@ -1408,7 +1408,7 @@
F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtInterp.3; sourceTree = "<group>"; };
F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtMathFnc.3; sourceTree = "<group>"; };
F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtObjCmd.3; sourceTree = "<group>"; };
- F96D3E2208F272A5004A47F5 /* CrtSlave.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtSlave.3; sourceTree = "<group>"; };
+ F96D3E2208F272A5004A47F5 /* CrtAlias.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtAlias.3; sourceTree = "<group>"; };
F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTimerHdlr.3; sourceTree = "<group>"; };
F96D3E2408F272A5004A47F5 /* CrtTrace.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = CrtTrace.3; sourceTree = "<group>"; };
F96D3E2508F272A5004A47F5 /* dde.n */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = dde.n; sourceTree = "<group>"; };
@@ -3072,7 +3072,7 @@
F96D3E1F08F272A5004A47F5 /* CrtInterp.3 */,
F96D3E2008F272A5004A47F5 /* CrtMathFnc.3 */,
F96D3E2108F272A5004A47F5 /* CrtObjCmd.3 */,
- F96D3E2208F272A5004A47F5 /* CrtSlave.3 */,
+ F96D3E2208F272A5004A47F5 /* CrtAlias.3 */,
F96D3E2308F272A5004A47F5 /* CrtTimerHdlr.3 */,
F96D3E2408F272A5004A47F5 /* CrtTrace.3 */,
F96D3E2508F272A5004A47F5 /* dde.n */,
diff --git a/macosx/tkMacOSX.h b/macosx/tkMacOSX.h
index a9e3082..3ab0a34 100644
--- a/macosx/tkMacOSX.h
+++ b/macosx/tkMacOSX.h
@@ -26,7 +26,7 @@
typedef int (Tk_MacOSXEmbedRegisterWinProc) (long winID, Tk_Window window);
typedef void* (Tk_MacOSXEmbedGetGrafPortProc) (Tk_Window window);
typedef int (Tk_MacOSXEmbedMakeContainerExistProc) (Tk_Window window);
-typedef void (Tk_MacOSXEmbedGetClipProc) (Tk_Window window, Region rgn);
+typedef void (Tk_MacOSXEmbedGetClipProc) (Tk_Window window, void *rgn);
typedef void (Tk_MacOSXEmbedGetOffsetInParentProc) (Tk_Window window, void *ulCorner);
#include "tkPlatDecls.h"
diff --git a/macosx/tkMacOSXBitmap.c b/macosx/tkMacOSXBitmap.c
index a63a1b6..29bb163 100644
--- a/macosx/tkMacOSXBitmap.c
+++ b/macosx/tkMacOSXBitmap.c
@@ -136,15 +136,13 @@ PixmapFromImage(
Pixmap pixmap;
pixmap = Tk_GetPixmap(display, None, size.width, size.height, 0);
- if (TkMacOSXSetupDrawingContext(pixmap, NULL, 1, &dc)) {
+ if (TkMacOSXSetupDrawingContext(pixmap, NULL, &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]];
+ [NSGraphicsContext setCurrentContext:GET_NSCONTEXT(dc.context, NO)];
[image drawAtPoint:NSZeroPoint fromRect:NSZeroRect
operation:NSCompositeCopy fraction:1.0];
[NSGraphicsContext restoreGraphicsState];
@@ -343,7 +341,7 @@ TkpGetNativeAppBitmap(
int
TkMacOSXIconBitmapObjCmd(
- ClientData dummy, /* Unused. */
+ TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
@@ -352,7 +350,6 @@ TkMacOSXIconBitmapObjCmd(
int i = 1, len, isNew, result = TCL_ERROR;
const char *name, *value;
IconBitmap ib, *iconBitmap;
- (void)dummy;
if (objc != 6) {
Tcl_WrongNumArgs(interp, 1, objv, "name width height "
diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c
index aa45895..857ce34 100644
--- a/macosx/tkMacOSXButton.c
+++ b/macosx/tkMacOSXButton.c
@@ -194,13 +194,6 @@ TkpDisplayButton(
}
pixmap = (Pixmap) Tk_WindowId(tkwin);
- /*
- * 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(Tk_WindowId(tkwin));
-
if (TkMacOSXComputeButtonDrawParams(butPtr, dpPtr)) {
macButtonPtr->useTkText = 0;
} else {
@@ -399,7 +392,7 @@ TkpComputeButtonGeometry(
width += butPtr->inset*2;
height += butPtr->inset*2;
- if ([NSApp macMinorVersion] == 6) {
+ if ([NSApp macOSVersion] == 100600) {
width += 12;
}
if (mbPtr->btnkind == kThemePushButton) {
@@ -726,7 +719,7 @@ TkpDestroyButton(
static void
TkMacOSXDrawButton(
MacButton *mbPtr, /* Mac button. */
- GC gc, /* The GC we are drawing into - needed for
+ TCL_UNUSED(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 */
@@ -737,7 +730,6 @@ TkMacOSXDrawButton(
TkMacOSXDrawingContext dc;
DrawParams *dpPtr = &mbPtr->drawParams;
int useNewerHITools = 1;
- (void)gc;
TkMacOSXComputeButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
@@ -752,7 +744,7 @@ TkMacOSXDrawButton(
ButtonBackgroundDrawCB(&cntrRect, mbPtr, 32, true);
- if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {
return;
}
@@ -785,7 +777,7 @@ TkMacOSXDrawButton(
ButtonContentDrawCB(&contHIRec, mbPtr->btnkind, &mbPtr->drawinfo,
(MacButton *) mbPtr, 32, true);
} else {
- if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {
return;
}
@@ -813,19 +805,16 @@ TkMacOSXDrawButton(
static void
ButtonBackgroundDrawCB(
- const HIRect *btnbounds,
+ TCL_UNUSED(const HIRect *),
MacButton *ptr,
- SInt16 depth,
- Boolean isColorDev)
+ TCL_UNUSED(SInt16),
+ TCL_UNUSED(Boolean))
{
MacButton *mbPtr = (MacButton *) ptr;
TkButton *butPtr = (TkButton *) mbPtr;
Tk_Window tkwin = butPtr->tkwin;
Pixmap pixmap;
int usehlborder = 0;
- (void)btnbounds;
- (void)depth;
- (void)isColorDev;
if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
return;
@@ -868,20 +857,15 @@ ButtonBackgroundDrawCB(
*/
static void
ButtonContentDrawCB (
- const HIRect * btnbounds,
- ThemeButtonKind kind,
- const HIThemeButtonDrawInfo *drawinfo,
+ TCL_UNUSED(const HIRect *),
+ TCL_UNUSED(ThemeButtonKind),
+ TCL_UNUSED(const HIThemeButtonDrawInfo *),
MacButton *ptr,
- SInt16 depth,
- Boolean isColorDev)
+ TCL_UNUSED(SInt16),
+ TCL_UNUSED(Boolean))
{
TkButton *butPtr = (TkButton *) ptr;
Tk_Window tkwin = butPtr->tkwin;
- (void)btnbounds;
- (void)kind;
- (void)drawinfo;
- (void)depth;
- (void)isColorDev;
if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
return;
@@ -1063,7 +1047,7 @@ TkMacOSXComputeButtonParams(
* the button periodically.
*/
- if (!mbPtr->defaultPulseHandler && ([NSApp macMinorVersion] <= 9)) {
+ if (!mbPtr->defaultPulseHandler && ([NSApp macOSVersion] <= 100900)) {
mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(
PULSE_TIMER_MSECS, PulseDefaultButtonProc, butPtr);
}
diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c
index 7df5bb9..47203e2 100644
--- a/macosx/tkMacOSXClipboard.c
+++ b/macosx/tkMacOSXClipboard.c
@@ -177,7 +177,7 @@ XSetSelectionOwner(
Display *display, /* X Display. */
Atom selection, /* What selection to own. */
Window owner, /* Window to be the owner. */
- Time time) /* The current time? */
+ TCL_UNUSED(Time)) /* The current time? */
{
TkDisplay *dispPtr = TkGetDisplayList();
(void)time;
@@ -238,13 +238,11 @@ TkMacOSXSelDeadWindow(
void
TkSelUpdateClipboard(
- TkWindow *winPtr, /* Window associated with clipboard. */
- TkClipboardTarget *targetPtr)
+ TCL_UNUSED(TkWindow *), /* Window associated with clipboard. */
+ TCL_UNUSED(TkClipboardTarget *))
/* Info about the content. */
{
NSPasteboard *pb = [NSPasteboard generalPasteboard];
- (void)winPtr;
- (void)targetPtr;
changeCount = [pb addTypes:[NSArray arrayWithObject:NSStringPboardType]
owner:NSApp];
@@ -297,9 +295,8 @@ TkSelEventProc(
void
TkSelPropProc(
- XEvent *eventPtr) /* X PropertyChange event. */
+ TCL_UNUSED(XEvent *)) /* X PropertyChange event. */
{
- (void)eventPtr;
}
/*
diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c
index 40b537e..acbfa0e 100644
--- a/macosx/tkMacOSXColor.c
+++ b/macosx/tkMacOSXColor.c
@@ -1,5 +1,5 @@
/*
- * tkMacOSXColor.c --
+ * TkMacOSXColor.c --
*
* This file maintains a database of color values for the Tk
* toolkit, in order to avoid round-trips to the server to
@@ -9,6 +9,7 @@
* Copyright (c) 1994-1996 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2020 Marc Culler
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -16,286 +17,272 @@
#include "tkMacOSXPrivate.h"
#include "tkColor.h"
+#include "tkMacOSXColor.h"
+
+static Tcl_HashTable systemColors;
+static int numSystemColors;
+static int rgbColorIndex;
+static int controlAccentIndex;
+static int selectedTabTextIndex;
+static Bool useFakeAccentColor = NO;
+static SystemColorDatum **systemColorIndex;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+static NSAppearance *lightAqua = nil;
+static NSAppearance *darkAqua = nil;
+#endif
+static NSColorSpace* sRGB = NULL;
+static const CGFloat WINDOWBACKGROUND[4] =
+ {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};
-/*
- * 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.
- */
+void initColorTable()
+{
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ Tcl_InitHashTable(&systemColors, TCL_STRING_KEYS);
+ SystemColorDatum *entry, *oldEntry;
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hPtr;
+ int newPtr, index = 0;
+ NSColorList *systemColorList = [NSColorList colorListNamed:@"System"];
+ NSString *key;
-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.*/
-};
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ if (@available(macOS 10.14, *)) {
+ darkAqua = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
+ lightAqua = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
+ }
+#endif
-/*
+ /*
+ * Build a hash table for looking up a color by its name.
+ * First add all of the static entries from tkMacOSXColor.h
+ */
- */
+ for (entry = systemColorData; entry->name != NULL; entry++) {
+ hPtr = Tcl_CreateHashEntry(&systemColors, entry->name, &newPtr);
+ if (entry->type == semantic) {
+ NSString *colorName = [[NSString alloc]
+ initWithCString:entry->macName
+ encoding:NSUTF8StringEncoding];
+ SEL colorSelector = NSSelectorFromString(colorName);
+ if (![NSColor respondsToSelector:colorSelector]) {
+ if ([colorName isEqualToString:@"controlAccentColor"]) {
+ useFakeAccentColor = YES;
+ } else if (![colorName isEqualToString:@"selectedTabTextColor"]) {
+ /* Uncomment to print all unsupported colors: */
+ /* printf("Unsupported color %s\n", colorName.UTF8String); */
+ continue;
+ }
+ }
+ entry->selector = [colorName retain];
+ }
+ if (newPtr == 0) {
+ oldEntry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ entry->index = oldEntry->index;
+ [oldEntry->selector release];
+ } else {
+ entry->index = index++;
+ }
+ Tcl_SetHashValue(hPtr, entry);
+ }
-struct SystemColorMapEntry {
- const char *name;
- enum colorType type;
- long value;
-}; /* unsigned char pixelCode; */
+ /*
+ * Add all of the colors in the System ColorList.
+ */
-/*
- * Array of system color definitions: the array index is required to equal the
- * color's (pixelCode - MIN_PIXELCODE), i.e. the array order needs to be kept
- * in sync with the public pixel code values in tkMacOSXPort.h !
- */
+ for (key in [systemColorList allKeys]) {
+ int length = [key lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+ char *name;
+ entry = (SystemColorDatum *)ckalloc(sizeof(SystemColorDatum));
+ bzero(entry, sizeof(SystemColorDatum));
+ name = (char *)ckalloc(length + 1);
+ strcpy(name, key.UTF8String);
+ name[0] = toupper(name[0]);
+ if (!strcmp(name, "WindowBackgroundColor")) {
+
+ /*
+ * Avoid black windows on old systems.
+ */
+
+ continue;
+ }
+ entry->type=semantic;
+ entry->name = name;
+ entry->selector = [key retain];
+ hPtr = Tcl_CreateHashEntry(&systemColors, entry->name, &newPtr);
+ if (newPtr == 0) {
+ oldEntry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ entry->index = oldEntry->index;
+ [oldEntry->selector release];
+ } else {
+ entry->index = index++;
+ }
+ Tcl_SetHashValue(hPtr, entry);
+ }
-#define MIN_PIXELCODE 30
-static const struct SystemColorMapEntry systemColorMap[] = {
- { "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 */
+ /*
+ * Build an array for looking up a color by its index.
+ */
+
+ numSystemColors = index;
+ systemColorIndex = (SystemColorDatum **)ckalloc(numSystemColors * sizeof(SystemColorDatum *));
+ for (hPtr = Tcl_FirstHashEntry(&systemColors, &search); hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&search)) {
+ entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ if (entry == NULL) {
+ Tcl_Panic("Unsupported semantic color with no supported backup!");
+ }
+ systemColorIndex[entry->index] = entry;
+ }
/*
- * Colors based on "semantic" NSColors.
+ * Remember the indexes of some special entries.
*/
- { "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 */
- /* Apple's SecondaryLabelColor is the same as their LabelColor so we roll our own. */
- { "SecondaryLabelColor", ttkBackground, 14 }, /* 183 */
- { "LinkColor", semantic, 9 }, /* 184 */
- { NULL, 0, 0 }
-};
-#define FIRST_SEMANTIC_COLOR 166
-#define MAX_PIXELCODE 184
+ hPtr = Tcl_FindHashEntry(&systemColors, "Pixel");
+ entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ rgbColorIndex = entry->index;
+ hPtr = Tcl_FindHashEntry(&systemColors, "ControlAccentColor");
+ entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ controlAccentIndex = entry->index;
+ hPtr = Tcl_FindHashEntry(&systemColors, "SelectedTabTextColor");
+ entry = (SystemColorDatum *) Tcl_GetHashValue(hPtr);
+ selectedTabTextIndex = entry->index;
+ [pool drain];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXRGBPixel --
+ *
+ * Return an unsigned long value suitable for use in the pixel
+ * field of an XColor with the specified red, green and blue
+ * intensities. The inputs are cast as unsigned longs but are
+ * expected to have values representable by an unsigned char.
+ *
+ * This is called in the TkpGetPixel macro, used in xcolor.c,
+ * and in ImageGetPixel.
+ *
+ * Results:
+ * An unsigned long that can be used as the pixel field of an XColor.
+ *
+ * Side effects:
+ * None.
+ *----------------------------------------------------------------------
+ */
+MODULE_SCOPE
+unsigned long
+TkMacOSXRGBPixel(
+ unsigned long red,
+ unsigned long green,
+ unsigned long blue)
+{
+ MacPixel p;
+ p.pixel.colortype = rgbColor;
+ p.pixel.value = ((red & 0xff) << 16) |
+ ((green & 0xff) << 8) |
+ (blue & 0xff);
+ return p.ulong;
+}
/*
*----------------------------------------------------------------------
*
- * GetEntryFromPixelCode --
+ * TkMacOSXClearPixel --
*
- * Extract a SystemColorMapEntry from the table.
+ * Return the unsigned long value that appears in the pixel
+ * field of the XColor for systemTransparentColor.
+ *
+ * This is used in tkMacOSXImage.c.
*
* Results:
- * Returns false if the code is out of bounds.
+ * The unsigned long that appears in the pixel field of the XColor
+ * for systemTransparentPixel.
*
* Side effects:
* None.
+ *----------------------------------------------------------------------
+ */
+MODULE_SCOPE
+unsigned long TkMacOSXClearPixel(
+ void)
+{
+ MacPixel p;
+ p.pixel.value = 0;
+ p.pixel.colortype = clearColor;
+ return p.ulong;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetEntryFromPixel --
+ *
+ * Look up a SystemColorDatum which describes the XColor with
+ * the specified value as its pixel field.
+ *
+ * Results:
+ * A pointer to a SystemColorDatum, or NULL if the pixel value is
+ * invalid.
+ *
+ * Side effects:
+ * None
*
*----------------------------------------------------------------------
*/
-static bool
-GetEntryFromPixelCode(
- unsigned char code,
- struct SystemColorMapEntry *entry)
+SystemColorDatum*
+GetEntryFromPixel(
+ unsigned long pixel)
{
- if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) {
- *entry = systemColorMap[code - MIN_PIXELCODE];
- return true;
+ MacPixel p;
+ int index = rgbColorIndex;
+
+ p.ulong = pixel;
+ if (p.pixel.colortype != rgbColor) {
+ index = p.pixel.value;
+ }
+ if (index < numSystemColors) {
+ return systemColorIndex[index];
} else {
- return false;
+ return NULL;
}
}
+
/*
*----------------------------------------------------------------------
*
- * SetCGColorComponents --
+ * GetRGBA --
*
- * 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.
+ * Given a SystemColorDatum and a pointer to an array of 4 CGFloats, store
+ * the associated RGBA color values in the array. In the case of the
+ * RGBColor datum, the unsigned long pixel value containing the RGB values
+ * must also be provided as the pixel parameter. Otherwise the pixel
+ * parameter is ignored.
*
* Results:
- * OSStatus
+ * None
*
* Side effects:
- * None.
+ * The array rgba is filled in.
*
*----------------------------------------------------------------------
*/
-static NSColorSpace* sRGB = NULL;
-static CGFloat windowBackground[4] =
- {236.0 / 255, 236.0 / 255, 236.0 / 255, 1.0};
-
-static OSStatus
-SetCGColorComponents(
- struct SystemColorMapEntry entry,
+static void
+GetRGBA(
+ SystemColorDatum *entry,
unsigned long pixel,
- CGColorRef *c)
+ CGFloat *rgba)
{
- OSStatus err = noErr;
NSColor *bgColor, *color = nil;
- CGFloat rgba[4] = {0, 0, 0, 1};
if (!sRGB) {
sRGB = [NSColorSpace sRGBColorSpace];
}
-
- /*
- * 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;
+ switch (entry->type) {
case rgbColor:
rgba[0] = ((pixel >> 16) & 0xff) / 255.0;
rgba[1] = ((pixel >> 8) & 0xff) / 255.0;
@@ -308,9 +295,9 @@ SetCGColorComponents(
* windowBackGroundColor.
*/
- if ([NSApp macMinorVersion] < 14) {
- for (int i=0; i<3; i++) {
- rgba[i] = windowBackground[i];
+ if ([NSApp macOSVersion] < 101400) {
+ for (int i = 0; i < 3; i++) {
+ rgba[i] = WINDOWBACKGROUND[i];
}
} else {
bgColor = [[NSColor windowBackgroundColor] colorUsingColorSpace:sRGB];
@@ -318,104 +305,80 @@ SetCGColorComponents(
}
if (rgba[0] + rgba[1] + rgba[2] < 1.5) {
for (int i=0; i<3; i++) {
- rgba[i] += entry.value*8.0 / 255.0;
+ rgba[i] += entry->value*8.0 / 255.0;
}
} else {
for (int i=0; i<3; i++) {
- rgba[i] -= entry.value*8.0 / 255.0;
+ rgba[i] -= entry->value*8.0 / 255.0;
}
}
break;
case semantic:
- switch (entry.value) {
- case 0:
- color = [[NSColor textColor] colorUsingColorSpace:sRGB];
- break;
- case 1:
- color = [[NSColor selectedTextColor] colorUsingColorSpace:sRGB];
- break;
- case 2:
- if ([NSApp macMinorVersion] > 9) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED > 1090
- color = [[NSColor labelColor] colorUsingColorSpace:sRGB];
+ if (entry->index == controlAccentIndex && useFakeAccentColor) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
+ color = [[NSColor colorForControlTint: [NSColor currentControlTint]]
+ colorUsingColorSpace:sRGB];
#endif
- } else {
- color = [[NSColor textColor] colorUsingColorSpace:sRGB];
- }
- break;
- case 3:
- color = [[NSColor controlTextColor] colorUsingColorSpace:sRGB];
- break;
- case 4:
- color = [[NSColor disabledControlTextColor]
- colorUsingColorSpace:sRGB];
- break;
- case 5:
- if ([NSApp macMinorVersion] > 6) {
+ } else if (entry->index == selectedTabTextIndex) {
+ int OSVersion = [NSApp macOSVersion];
+ if (OSVersion > 100600 && OSVersion < 110000) {
color = [[NSColor whiteColor] colorUsingColorSpace:sRGB];
- } else {
- color = [[NSColor blackColor] colorUsingColorSpace:sRGB];
}
- break;
- case 6:
- color = [[NSColor textBackgroundColor] colorUsingColorSpace:sRGB];
- break;
- case 7:
- color = [[NSColor selectedTextBackgroundColor]
- colorUsingColorSpace:sRGB];
- break;
- case 8:
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
- if (@available(macOS 14, *)) {
- color = [[NSColor controlAccentColor] colorUsingColorSpace:sRGB];
-#else
- if(false) {
-#endif
- } else {
- color = [[NSColor
- colorForControlTint:[NSColor currentControlTint]]
- colorUsingColorSpace: sRGB];
- }
- break;
- case 9:
- if ([NSApp macMinorVersion] >= 10) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
- color = [[NSColor linkColor] colorUsingColorSpace:sRGB];
-#endif
- } else {
- color = [[NSColor blueColor] colorUsingColorSpace:sRGB];
- }
- break;
- default:
- if ([NSApp macMinorVersion] >= 10) {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
- color = [[NSColor labelColor] colorUsingColorSpace:sRGB];
-#endif
- } else {
- color = [[NSColor textColor] colorUsingColorSpace:sRGB];
- }
- break;
+ } else {
+ color = [[NSColor valueForKey:entry->selector] colorUsingColorSpace:sRGB];
}
[color getComponents: rgba];
break;
case clearColor:
- rgba[3] = 0.0;
+ rgba[3] = 0;
+ default:
break;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCGColorComponents --
+ *
+ * Set the components of a CGColorRef from an XColor pixel value and a
+ * SystemColorDatum. 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. Otherwise the components are
+ * computed from the SystemColorDatum.
+ *
+ * Results:
+ * True if the function succeeds, false otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Bool
+SetCGColorComponents(
+ SystemColorDatum *entry,
+ unsigned long pixel,
+ CGColorRef *c)
+{
+ CGFloat rgba[4] = {0, 0, 0, 1};
/*
- * 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.
+ * This function is called before our autorelease pool is set up,
+ * so it needs its own pool.
*/
- case HIText:
- case HIBackground:
- default:
- break;
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+
+ if (entry->type == HIBrush) {
+ OSStatus err = ChkErr(HIThemeBrushCreateCGColor, entry->value, c);
+ return err == noErr;
}
+ GetRGBA(entry, pixel, rgba);
*c = CGColorCreate(sRGB.CGColorSpace, rgba);
[pool drain];
- return err;
+ return true;
}
/*
@@ -437,27 +400,24 @@ SetCGColorComponents(
MODULE_SCOPE Bool
TkMacOSXInDarkMode(Tk_Window tkwin)
{
- int result = false;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
- static NSAppearanceName darkAqua = @"NSAppearanceNameDarkAqua";
-
- if ([NSApp macMinorVersion] >= 14) {
+ if (@available(macOS 10.14, *)) {
TkWindow *winPtr = (TkWindow*) tkwin;
+ NSAppearanceName name;
NSView *view = nil;
if (winPtr && winPtr->privatePtr) {
- view = TkMacOSXDrawableView(winPtr->privatePtr);
+ view = TkMacOSXGetNSViewForDrawable((Drawable)winPtr->privatePtr);
}
if (view) {
- result = [view.effectiveAppearance.name isEqualToString:darkAqua];
+ name = [[view effectiveAppearance] name];
} else {
- result = [[NSAppearance currentAppearance].name
- isEqualToString:darkAqua];
+ name = [[NSAppearance currentAppearance] name];
}
+ return (name == NSAppearanceNameDarkAqua);
}
#endif
-
- return result;
+ return false;
}
/*
@@ -465,14 +425,13 @@ TkMacOSXInDarkMode(Tk_Window tkwin)
*
* TkSetMacColor --
*
- * 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.
+ * Sets the components of a CGColorRef from an XColor pixel value. The
+ * pixel value is used to look up the color in the system color table, and
+ * then SetCGColorComponents is called with the table entry and the pixel
+ * value.
*
* Results:
- * Returns false if the high order byte is not a valid index, true
- * otherwise.
+ * Returns false if the color is not found, true otherwise.
*
* Side effects:
* The variable macColor is set to a new CGColorRef, the caller is
@@ -487,13 +446,13 @@ TkSetMacColor(
void *macColor) /* CGColorRef to modify. */
{
CGColorRef *color = (CGColorRef*)macColor;
- OSStatus err = -1;
- struct SystemColorMapEntry entry;
+ SystemColorDatum *entry = GetEntryFromPixel(pixel);
- if (GetEntryFromPixelCode((pixel >> 24) & 0xff, &entry)) {
- err = ChkErr(SetCGColorComponents, entry, pixel, color);
+ if (entry) {
+ return SetCGColorComponents(entry, pixel, color);
+ } else {
+ return false;
}
- return (err == noErr);
}
/*
@@ -506,7 +465,7 @@ TkSetMacColor(
* Results:
* None resp. retained CGColorRef for CopyCachedColor()
*
- * Side effects:M
+ * Side effects:
* None.
*
*----------------------------------------------------------------------
@@ -614,9 +573,10 @@ TkMacOSXCreateCGColor(
* TkMacOSXGetNSColor --
*
* Creates an autoreleased NSColor from a X style pixel value.
+ * The return value is nil if the pixel value is invalid.
*
* Results:
- * Returns nil if not a real pixel, NSColor* otherwise.
+ * A possibly nil pointer to an NSColor.
*
* Side effects:
* None
@@ -650,10 +610,9 @@ TkMacOSXGetNSColor(
*
* TkMacOSXSetColorInContext --
*
- * Sets fill and stroke color in the given CG context from an X
- * pixel value, or if the pixel code indicates a system color,
- * sets the corresponding brush, textColor or background via
- * HITheme APIs if available or Appearance mgr APIs.
+ * Sets the fill and stroke colors in the given CGContext to the CGColor
+ * which corresponds to the XColor having the specified value for its pixel
+ * field.
*
* Results:
* None.
@@ -672,37 +631,20 @@ TkMacOSXSetColorInContext(
{
OSStatus err = noErr;
CGColorRef cgColor = nil;
- struct SystemColorMapEntry entry;
- CGRect rect;
- int code = (pixel >> 24) & 0xff;
- HIThemeBackgroundDrawInfo info = {0, kThemeStateActive, 0};;
+ SystemColorDatum *entry = GetEntryFromPixel(pixel);
- if (code < FIRST_SEMANTIC_COLOR) {
- cgColor = CopyCachedColor(gc, pixel);
- }
- if (!cgColor && GetEntryFromPixelCode(code, &entry)) {
- switch (entry.type) {
+ if (entry) {
+ switch (entry->type) {
case HIBrush:
- err = ChkErr(HIThemeSetFill, entry.value, NULL, context,
+ err = ChkErr(HIThemeSetFill, entry->value, NULL, context,
kHIThemeOrientationNormal);
if (err == noErr) {
- err = ChkErr(HIThemeSetStroke, entry.value, NULL, context,
+ err = ChkErr(HIThemeSetStroke, entry->value, NULL, context,
kHIThemeOrientationNormal);
}
break;
- case HIText:
- err = ChkErr(HIThemeSetTextFill, entry.value, NULL, context,
- kHIThemeOrientationNormal);
- 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) {
+ if (SetCGColorComponents(entry, pixel, &cgColor)){
SetCachedColor(gc, pixel, cgColor);
}
break;
@@ -723,15 +665,20 @@ TkMacOSXSetColorInContext(
*
* TkpGetColor --
*
- * Allocate a new TkColor for the color with the given name.
+ * Create a new TkColor for the color with the given name, for use in the
+ * specified window. The colormap field is set to lightColormap if the
+ * window has a LightAqua appearance, or darkColormap if the window has a
+ * DarkAqua appearance. TkColors with different colormaps are managed
+ * separately in the per-display table of TkColors maintained by Tk.
+ *
+ * This function is called by Tk_GetColor.
*
* Results:
* Returns a newly allocated TkColor, or NULL on failure.
*
* Side effects:
- * May invalidate the colormap cache associated with tkwin upon
- * allocating a new colormap entry. Allocates a new TkColor
- * structure.
+ *
+ * Allocates memory for the TkColor structure.
*
*----------------------------------------------------------------------
*/
@@ -742,31 +689,68 @@ TkpGetColor(
Tk_Uid name) /* Name of color to be allocated (in form
* suitable for passing to XParseColor). */
{
- Display *display = tkwin != None ? Tk_Display(tkwin) : NULL;
- Colormap colormap = tkwin!= None ? Tk_Colormap(tkwin) : None;
+ Display *display = NULL;
TkColor *tkColPtr;
XColor color;
+ Colormap colormap = tkwin ? Tk_Colormap(tkwin) : noColormap;
+ NSView *view = nil;
+ static Bool initialized = NO;
+ static NSColorSpace* sRGB = NULL;
+
+ if (!initialized) {
+ initialized = YES;
+ sRGB = [NSColorSpace sRGBColorSpace];
+ initColorTable();
+ }
+ if (tkwin) {
+ display = Tk_Display(tkwin);
+ Drawable d = Tk_WindowId(tkwin);
+ view = TkMacOSXGetNSViewForDrawable(d);
+ }
/*
- * Check to see if this is a system color. Otherwise, XParseColor
- * will do all the work.
+ * Check to see if this is a system color. If not, just call XParseColor.
*/
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);
- Tcl_DecrRefCount(strPtr);
- if (result == TCL_OK) {
- OSStatus err;
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&systemColors, name + 6);
+ MacPixel p;
+
+ if (hPtr != NULL) {
+ SystemColorDatum *entry = (SystemColorDatum *)Tcl_GetHashValue(hPtr);
CGColorRef c;
- unsigned char pixelCode = idx + MIN_PIXELCODE;
- struct SystemColorMapEntry entry = systemColorMap[idx];
- err = ChkErr(SetCGColorComponents, entry, 0, &c);
- if (err == noErr) {
+ p.pixel.colortype = entry->type;
+ p.pixel.value = entry->index;
+ color.pixel = p.ulong;
+ if (entry->type == semantic) {
+ CGFloat rgba[4];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+ if (@available(macOS 10.14, *)) {
+ NSAppearance *savedAppearance = [NSAppearance currentAppearance];
+ NSAppearance *windowAppearance = savedAppearance;
+ if (view) {
+ windowAppearance = [view effectiveAppearance];
+ }
+ if ([windowAppearance name] == NSAppearanceNameDarkAqua) {
+ colormap = darkColormap;
+ } else {
+ colormap = lightColormap;
+ }
+ [NSAppearance setCurrentAppearance:windowAppearance];
+ GetRGBA(entry, p.ulong, rgba);
+ [NSAppearance setCurrentAppearance:savedAppearance];
+ } else {
+ GetRGBA(entry, p.ulong, rgba);
+ }
+#else
+ GetRGBA(entry, p.ulong, rgba);
+#endif
+ color.red = rgba[0] * 65535.0;
+ color.green = rgba[1] * 65535.0;
+ color.blue = rgba[2] * 65535.0;
+ goto validXColor;
+ } else if (SetCGColorComponents(entry, 0, &c)) {
const size_t n = CGColorGetNumberOfComponents(c);
const CGFloat *rgba = CGColorGetComponents(c);
@@ -782,25 +766,19 @@ TkpGetColor(
default:
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));
CGColorRelease(c);
goto validXColor;
}
- CGColorRelease(c);
}
}
-
if (TkParseColor(display, colormap, name, &color) == 0) {
return NULL;
}
validXColor:
tkColPtr = (TkColor *)ckalloc(sizeof(TkColor));
+ tkColPtr->colormap = colormap;
tkColPtr->color = color;
-
return tkColPtr;
}
@@ -809,36 +787,35 @@ validXColor:
*
* TkpGetColorByValue --
*
- * Given a desired set of red-green-blue intensities for a color,
- * locate a pixel value to use to draw that color in a given
- * window.
+ * Given an pointer to an XColor, construct a TkColor whose red, green and
+ * blue intensities match those of the XColor as closely as possible. For
+ * the Macintosh, this means that the colortype bitfield of the pixel
+ * value will be RGBColor and that the color intensities stored in its
+ * 24-bit value bitfield are computed from the 16-bit red green and blue
+ * values in the XColor by dividing by 256.
*
* Results:
- * The return value is a pointer to an TkColor structure that
- * indicates the closest red, blue, and green intensities available
- * to those specified in colorPtr, and also specifies a pixel
- * value to use to draw in that color.
+ * A pointer to a newly allocated TkColor structure.
*
* Side effects:
* May invalidate the colormap cache for the specified window.
- * Allocates a new TkColor structure.
+ * Allocates memory for a TkColor structure.
*
*----------------------------------------------------------------------
*/
TkColor *
TkpGetColorByValue(
- Tk_Window tkwin, /* Window in which color will be used. */
+ TCL_UNUSED(Tk_Window), /* Window in which color will be used. */
XColor *colorPtr) /* Red, green, and blue fields indicate
* desired color. */
{
TkColor *tkColPtr = (TkColor *)ckalloc(sizeof(TkColor));
- (void)tkwin;
tkColPtr->color.red = colorPtr->red;
tkColPtr->color.green = colorPtr->green;
tkColPtr->color.blue = colorPtr->blue;
- tkColPtr->color.pixel = TkpGetPixel(&tkColPtr->color);
+ tkColPtr->color.pixel = TkpGetPixel(colorPtr);
return tkColPtr;
}
@@ -862,11 +839,9 @@ TkpGetColorByValue(
Status
XAllocColor(
Display *display, /* Display. */
- Colormap map, /* Not used. */
+ TCL_UNUSED(Colormap), /* Not used. */
XColor *colorPtr) /* XColor struct to modify. */
{
- (void)map;
-
display->request++;
colorPtr->pixel = TkpGetPixel(colorPtr);
return 1;
@@ -874,52 +849,39 @@ XAllocColor(
Colormap
XCreateColormap(
- Display *display, /* Display. */
- Window window, /* X window. */
- Visual *visual, /* Not used. */
- int alloc) /* Not used. */
+ TCL_UNUSED(Display *), /* Display. */
+ TCL_UNUSED(Window), /* X window. */
+ TCL_UNUSED(Visual *), /* Not used. */
+ TCL_UNUSED(int)) /* Not used. */
{
- static Colormap index = 1;
- (void)display;
- (void)window;
- (void)visual;
- (void)alloc;
+ static Colormap index = 16;
/*
- * Just return a new value each time.
+ * Just return a new value each time, large enough that it will not
+ * conflict with any value of the macColormap enum.
*/
return index++;
}
int
XFreeColormap(
- Display* display, /* Display. */
- Colormap colormap) /* Colormap. */
+ TCL_UNUSED(Display *), /* Display. */
+ TCL_UNUSED(Colormap)) /* Colormap. */
{
- (void)display;
- (void)colormap;
-
return Success;
}
int
XFreeColors(
- Display* display, /* Display. */
- Colormap colormap, /* Colormap. */
- unsigned long* pixels, /* Array of pixels. */
- int npixels, /* Number of pixels. */
- unsigned long planes) /* Number of pixel planes. */
+ TCL_UNUSED(Display *), /* Display. */
+ TCL_UNUSED(Colormap), /* Colormap. */
+ TCL_UNUSED(unsigned long *), /* Array of pixels. */
+ TCL_UNUSED(int), /* Number of pixels. */
+ TCL_UNUSED(unsigned long)) /* Number of pixel planes. */
{
- (void)display;
- (void)colormap;
- (void)pixels;
- (void)npixels;
- (void)planes;
-
/*
- * The Macintosh version of Tk uses TrueColor. Nothing
- * needs to be done to release colors as there really is
- * no colormap in the Tk sense.
+ * Nothing needs to be done to release colors as there really is no
+ * colormap in the Tk sense.
*/
return Success;
}
diff --git a/macosx/tkMacOSXColor.h b/macosx/tkMacOSXColor.h
new file mode 100644
index 0000000..7449095
--- /dev/null
+++ b/macosx/tkMacOSXColor.h
@@ -0,0 +1,198 @@
+#ifndef MACOSXCOLOR_H
+#define MACOSXCOLOR_H
+/*
+ * The generic Tk code uses the X11 GC type to describe a graphics context.
+ * (A GC is a pointer to a struct XGCValues). The foreground and background
+ * colors in a GC are unsigned longs. These are meant to be used as indexes
+ * into a table of XColors, where an XColor is declared in Xlib.h as:
+ * typedef struct {
+ * unsigned long pixel;
+ * unsigned short red, green, blue;
+ * char flags;
+ * char pad;
+ * } XColor;
+ *
+ * The xlib function XParseColor creates XColors from strings. It recognizes
+ * literal hexadecimal color specifications such as "#RRGGBB" as well as the
+ * standard X11 color names. When XParseColor creates an XColor it fills in
+ * all of the fields except for the pixel field, and then passes the XColor
+ * to TkpGetPixel to get a value to use for the pixel field. Since TkpGetPixel
+ * is platform specific, each platform is free to choose a value which can
+ * be used to set the foreground or background color in the platform's graphics
+ * context.
+ *
+ * Tk represents a color by a struct TkColor, which extends the XColor struct.
+ * Tk provides a mapping from color names to TkColors which extends the mapping
+ * provided by XParseColor but also allows for platform specific color names.
+ * By convention, these platform specific color names begin with the string
+ * "system". The mapping from names to TkColors is implemented by the function
+ * TkpGetColor defined for the Macintosh in this file. The pixel field in the
+ * XColor contained in a TkColor will be stored in the X11 graphics context.
+ * In X11 the pixel field is used as an index into a colormap. On the Mac
+ * the high order byte of the pixel is used to indicate a color type and
+ * the low 24 bits are either used as an rgb value (if the type is rgbColor)
+ * or as an index into a table of color descriptions.
+ */
+
+enum colorType {
+ rgbColor, /* The 24 bit value is an rgb color. */
+ clearColor, /* The unique rgba color with all channels 0. */
+ HIBrush, /* A HITheme brush color.*/
+ ttkBackground, /* A background color which indicates nesting level.*/
+ semantic, /* A semantic NSColor.*/
+};
+
+typedef struct xpixel_t {
+ unsigned value: 24; /* Either RGB or an index into systemColorData. */
+ unsigned colortype: 8;
+} xpixel;
+
+typedef union MacPixel_t {
+ unsigned long ulong;
+ xpixel pixel;
+} MacPixel;
+
+/*
+ * We maintain two colormaps, one for the LightAqua appearance and one for the
+ * DarkAqua appearance.
+ */
+
+enum macColormap {
+ noColormap,
+ lightColormap,
+ darkColormap,
+};
+
+/*
+ * In TkMacOSXColor.c a Tk hash table is constructed from the static data
+ * below to map system color names to CGColors.
+ */
+
+typedef struct {
+ const char *name;
+ enum colorType type;
+ int value;
+ const char *macName;
+ /* Fields below are filled in after or during construction of the hash table. */
+ int index;
+ NSString *selector;
+} SystemColorDatum;
+
+/*
+ * WARNING: Semantic colors which are not supported on all systems must be
+ * preceded by a backup color with the same name which *is* supported. Systems
+ * which do support the color will replace the backup value when the table is
+ * constructed. Failing to ensure this will result in a Tcl_Panic abort.
+ */
+
+static SystemColorDatum systemColorData[] = {
+{"Pixel", rgbColor, 0, NULL, 0, NULL },
+{"Transparent", clearColor, 0, NULL, 0, NULL },
+
+{"Highlight", HIBrush, kThemeBrushPrimaryHighlightColor, NULL, 0, NULL },
+{"HighlightSecondary", HIBrush, kThemeBrushSecondaryHighlightColor, NULL, 0, NULL },
+{"HighlightText", HIBrush, kThemeBrushBlack, NULL, 0, NULL },
+{"HighlightAlternate", HIBrush, kThemeBrushAlternatePrimaryHighlightColor, NULL, 0, NULL },
+{"PrimaryHighlightColor", HIBrush, kThemeBrushPrimaryHighlightColor, NULL, 0, NULL },
+{"ButtonFace", HIBrush, kThemeBrushButtonFaceActive, NULL, 0, NULL },
+{"SecondaryHighlightColor", HIBrush, kThemeBrushSecondaryHighlightColor, NULL, 0, NULL },
+{"ButtonFrame", HIBrush, kThemeBrushButtonFrameActive, NULL, 0, NULL },
+{"AlternatePrimaryHighlightColor", HIBrush, kThemeBrushAlternatePrimaryHighlightColor, NULL, 0, NULL },
+{"WindowBody", HIBrush, kThemeBrushDocumentWindowBackground, NULL, 0, NULL },
+{"SheetBackground", HIBrush, kThemeBrushSheetBackground, NULL, 0, NULL },
+{"MenuActive", HIBrush, kThemeBrushMenuBackgroundSelected, NULL, 0, NULL },
+{"Menu", HIBrush, kThemeBrushMenuBackground, NULL, 0, NULL },
+{"DialogBackgroundInactive", HIBrush, kThemeBrushDialogBackgroundInactive, NULL, 0, NULL },
+{"DialogBackgroundActive", HIBrush, kThemeBrushDialogBackgroundActive, NULL, 0, NULL },
+{"AlertBackgroundActive", HIBrush, kThemeBrushAlertBackgroundActive, NULL, 0, NULL },
+{"AlertBackgroundInactive", HIBrush, kThemeBrushAlertBackgroundInactive, NULL, 0, NULL },
+{"ModelessDialogBackgroundActive", HIBrush, kThemeBrushModelessDialogBackgroundActive, NULL, 0, NULL },
+{"ModelessDialogBackgroundInactive", HIBrush, kThemeBrushModelessDialogBackgroundInactive, NULL, 0, NULL },
+{"UtilityWindowBackgroundActive", HIBrush, kThemeBrushUtilityWindowBackgroundActive, NULL, 0, NULL },
+{"UtilityWindowBackgroundInactive", HIBrush, kThemeBrushUtilityWindowBackgroundInactive, NULL, 0, NULL },
+{"ListViewSortColumnBackground", HIBrush, kThemeBrushListViewSortColumnBackground, NULL, 0, NULL },
+{"ListViewBackground", HIBrush, kThemeBrushListViewBackground, NULL, 0, NULL },
+{"IconLabelBackground", HIBrush, kThemeBrushIconLabelBackground, NULL, 0, NULL },
+{"ListViewSeparator", HIBrush, kThemeBrushListViewSeparator, NULL, 0, NULL },
+{"ChasingArrows", HIBrush, kThemeBrushChasingArrows, NULL, 0, NULL },
+{"DragHilite", HIBrush, kThemeBrushDragHilite, NULL, 0, NULL },
+{"DocumentWindowBackground", HIBrush, kThemeBrushDocumentWindowBackground, NULL, 0, NULL },
+{"FinderWindowBackground", HIBrush, kThemeBrushFinderWindowBackground, NULL, 0, NULL },
+{"ScrollBarDelimiterActive", HIBrush, kThemeBrushScrollBarDelimiterActive, NULL, 0, NULL },
+{"ScrollBarDelimiterInactive", HIBrush, kThemeBrushScrollBarDelimiterInactive, NULL, 0, NULL },
+{"FocusHighlight", HIBrush, kThemeBrushFocusHighlight, NULL, 0, NULL },
+{"PopupArrowActive", HIBrush, kThemeBrushPopupArrowActive, NULL, 0, NULL },
+{"PopupArrowPressed", HIBrush, kThemeBrushPopupArrowPressed, NULL, 0, NULL },
+{"PopupArrowInactive", HIBrush, kThemeBrushPopupArrowInactive, NULL, 0, NULL },
+{"AppleGuideCoachmark", HIBrush, kThemeBrushAppleGuideCoachmark, NULL, 0, NULL },
+{"IconLabelBackgroundSelected", HIBrush, kThemeBrushIconLabelBackgroundSelected, NULL, 0, NULL },
+{"StaticAreaFill", HIBrush, kThemeBrushStaticAreaFill, NULL, 0, NULL },
+{"ActiveAreaFill", HIBrush, kThemeBrushActiveAreaFill, NULL, 0, NULL },
+{"ButtonFrameActive", HIBrush, kThemeBrushButtonFrameActive, NULL, 0, NULL },
+{"ButtonFrameInactive", HIBrush, kThemeBrushButtonFrameInactive, NULL, 0, NULL },
+{"ButtonFaceActive", HIBrush, kThemeBrushButtonFaceActive, NULL, 0, NULL },
+{"ButtonFaceInactive", HIBrush, kThemeBrushButtonFaceInactive, NULL, 0, NULL },
+{"ButtonFacePressed", HIBrush, kThemeBrushButtonFacePressed, NULL, 0, NULL },
+{"ButtonActiveDarkShadow", HIBrush, kThemeBrushButtonActiveDarkShadow, NULL, 0, NULL },
+{"ButtonActiveDarkHighlight", HIBrush, kThemeBrushButtonActiveDarkHighlight, NULL, 0, NULL },
+{"ButtonActiveLightShadow", HIBrush, kThemeBrushButtonActiveLightShadow, NULL, 0, NULL },
+{"ButtonActiveLightHighlight", HIBrush, kThemeBrushButtonActiveLightHighlight, NULL, 0, NULL },
+{"ButtonInactiveDarkShadow", HIBrush, kThemeBrushButtonInactiveDarkShadow, NULL, 0, NULL },
+{"ButtonInactiveDarkHighlight", HIBrush, kThemeBrushButtonInactiveDarkHighlight, NULL, 0, NULL },
+{"ButtonInactiveLightShadow", HIBrush, kThemeBrushButtonInactiveLightShadow, NULL, 0, NULL },
+{"ButtonInactiveLightHighlight", HIBrush, kThemeBrushButtonInactiveLightHighlight, NULL, 0, NULL },
+{"ButtonPressedDarkShadow", HIBrush, kThemeBrushButtonPressedDarkShadow, NULL, 0, NULL },
+{"ButtonPressedDarkHighlight", HIBrush, kThemeBrushButtonPressedDarkHighlight, NULL, 0, NULL },
+{"ButtonPressedLightShadow", HIBrush, kThemeBrushButtonPressedLightShadow, NULL, 0, NULL },
+{"ButtonPressedLightHighlight", HIBrush, kThemeBrushButtonPressedLightHighlight, NULL, 0, NULL },
+{"BevelActiveLight", HIBrush, kThemeBrushBevelActiveLight, NULL, 0, NULL },
+{"BevelActiveDark", HIBrush, kThemeBrushBevelActiveDark, NULL, 0, NULL },
+{"BevelInactiveLight", HIBrush, kThemeBrushBevelInactiveLight, NULL, 0, NULL },
+{"BevelInactiveDark", HIBrush, kThemeBrushBevelInactiveDark, NULL, 0, NULL },
+{"NotificationWindowBackground", HIBrush, kThemeBrushNotificationWindowBackground, NULL, 0, NULL },
+{"MovableModalBackground", HIBrush, kThemeBrushMovableModalBackground, NULL, 0, NULL },
+{"SheetBackgroundOpaque", HIBrush, kThemeBrushSheetBackgroundOpaque, NULL, 0, NULL },
+{"DrawerBackground", HIBrush, kThemeBrushDrawerBackground, NULL, 0, NULL },
+{"ToolbarBackground", HIBrush, kThemeBrushToolbarBackground, NULL, 0, NULL },
+{"SheetBackgroundTransparent", HIBrush, kThemeBrushSheetBackgroundTransparent, NULL, 0, NULL },
+{"MenuBackground", HIBrush, kThemeBrushMenuBackground, NULL, 0, NULL },
+{"MenuBackgroundSelected", HIBrush, kThemeBrushMenuBackgroundSelected, NULL, 0, NULL },
+{"ListViewOddRowBackground", HIBrush, kThemeBrushListViewOddRowBackground, NULL, 0, NULL },
+{"ListViewEvenRowBackground", HIBrush, kThemeBrushListViewEvenRowBackground, NULL, 0, NULL },
+{"ListViewColumnDivider", HIBrush, kThemeBrushListViewColumnDivider, NULL, 0, NULL },
+
+ /*
+ * Dynamic Colors
+ */
+
+{"WindowBackgroundColor", ttkBackground, 0, NULL, 0, NULL },
+{"WindowBackgroundColor1", ttkBackground, 1, NULL, 0, NULL },
+{"WindowBackgroundColor2", ttkBackground, 2, NULL, 0, NULL },
+{"WindowBackgroundColor3", ttkBackground, 3, NULL, 0, NULL },
+{"WindowBackgroundColor4", ttkBackground, 4, NULL, 0, NULL },
+{"WindowBackgroundColor5", ttkBackground, 5, NULL, 0, NULL },
+{"WindowBackgroundColor6", ttkBackground, 6, NULL, 0, NULL },
+{"WindowBackgroundColor7", ttkBackground, 7, NULL, 0, NULL },
+/* Apple's SecondaryLabelColor is the same as their LabelColor so we roll our own. */
+{"SecondaryLabelColor", ttkBackground, 14, NULL, 0, NULL },
+/* Color to use for notebook tab labels -- depends on OS version. */
+{"SelectedTabTextColor", semantic, 0, "textColor", 0, NULL },
+/* Semantic colors that we simulate on older systems which don't supoort them. */
+{"SelectedMenuItemTextColor", semantic, 0, "selectedMenuItemTextColor", 0, NULL },
+{"ControlAccentColor", semantic, 0, "controlAccentColor", 0, NULL },
+{"LabelColor", semantic, 0, "blackColor", 0, NULL },
+{"LinkColor", semantic, 0, "blueColor", 0, NULL },
+{"PlaceholderTextColor", semantic, 0, "grayColor", 0, NULL },
+{"SeparatorColor", semantic, 0, "grayColor", 0, NULL },
+{NULL, 0, 0, NULL, 0, NULL }
+};
+
+#endif
+/*
+ * Local Variables:
+ * mode: objc
+ * c-basic-offset: 4
+ * fill-column: 79
+ * coding: utf-8
+ * End:
+ */
diff --git a/macosx/tkMacOSXConstants.h b/macosx/tkMacOSXConstants.h
index e019ea1..0b6ae2b 100644
--- a/macosx/tkMacOSXConstants.h
+++ b/macosx/tkMacOSXConstants.h
@@ -102,10 +102,18 @@ typedef NSInteger NSModalResponse;
#define NSStringPboardType NSPasteboardTypeString
#define NSOnState NSControlStateValueOn
#define NSOffState NSControlStateValueOff
-// Now we are also changing names of methods!
-#define graphicsContextWithGraphicsPort graphicsContextWithCGContext
#endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000
+#define NSWindowStyleMaskTexturedBackground 0
+#endif
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
+#define GET_NSCONTEXT(context, flip) [NSGraphicsContext \
+ graphicsContextWithGraphicsPort:context flipped:flip]
+#else
+#define GET_NSCONTEXT(context, flip) [NSGraphicsContext \
+ graphicsContextWithCGContext:context flipped:NO]
#endif
+#endif
diff --git a/macosx/tkMacOSXCursor.c b/macosx/tkMacOSXCursor.c
index 812f54e..9371889 100644
--- a/macosx/tkMacOSXCursor.c
+++ b/macosx/tkMacOSXCursor.c
@@ -187,15 +187,6 @@ static const struct CursorName cursorNames[] = {
static TkMacOSXCursor *gCurrentCursor = NULL;
/* A pointer to the current cursor. */
-static int gResizeOverride = false;
- /* A boolean indicating whether we should use
- * the resize cursor during installations. */
-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
- * the cursor. */
/*
* Declarations of procedures local to this file
@@ -375,14 +366,13 @@ FindCursorByName(
TkCursor *
TkGetCursorByName(
Tcl_Interp *interp, /* Interpreter to use for error reporting. */
- Tk_Window tkwin, /* Window in which cursor will be used. */
+ TCL_UNUSED(Tk_Window), /* Window in which cursor will be used. */
Tk_Uid string) /* Description of cursor. See manual entry
* for details on legal syntax. */
{
TkMacOSXCursor *macCursorPtr = NULL;
const char **argv = NULL;
int argc;
- (void)tkwin;
/*
* All cursor names are valid lists of one element (for
@@ -430,24 +420,16 @@ TkGetCursorByName(
TkCursor *
TkCreateCursorFromData(
- Tk_Window tkwin, /* Window in which cursor will be used. */
- const char *source, /* Bitmap data for cursor shape. */
- const char *mask, /* Bitmap data for cursor mask. */
- int width, int height, /* Dimensions of cursor. */
- int xHot, int yHot, /* Location of hot-spot in cursor. */
- XColor fgColor, /* Foreground color for cursor. */
- XColor bgColor) /* Background color for cursor. */
+ TCL_UNUSED(Tk_Window), /* Window in which cursor will be used. */
+ TCL_UNUSED(const char *), /* Bitmap data for cursor shape. */
+ TCL_UNUSED(const char *), /* Bitmap data for cursor mask. */
+ TCL_UNUSED(int), /* Dimensions of cursor. */
+ TCL_UNUSED(int),
+ TCL_UNUSED(int), /* Location of hot-spot in cursor. */
+ TCL_UNUSED(int),
+ TCL_UNUSED(XColor), /* Foreground color for cursor. */
+ TCL_UNUSED(XColor)) /* Background color for cursor. */
{
- (void)tkwin;
- (void)source;
- (void)mask;
- (void)width;
- (void)height;
- (void)xHot;
- (void)yHot;
- (void)fgColor;
- (void)bgColor;
-
return NULL;
}
@@ -498,17 +480,15 @@ TkpFreeCursor(
*----------------------------------------------------------------------
*/
-void
+static void
TkMacOSXInstallCursor(
- int resizeOverride)
+ void)
{
TkMacOSXCursor *macCursorPtr = gCurrentCursor;
static int cursorHidden = 0;
int cursorNone = 0;
- gResizeOverride = resizeOverride;
-
- if (resizeOverride || !macCursorPtr) {
+ if (!macCursorPtr) {
[[NSCursor arrowCursor] set];
} else {
switch (macCursorPtr->type) {
@@ -556,10 +536,6 @@ TkpSetCursor(
{
int cursorChanged = 1;
- if (!gTkOwnsCursor) {
- return;
- }
-
if (cursor == None) {
/*
* This is a little tricky. We can't really tell whether
@@ -578,34 +554,11 @@ TkpSetCursor(
}
if (Tk_MacOSXIsAppInFront() && cursorChanged) {
- TkMacOSXInstallCursor(gResizeOverride);
+ TkMacOSXInstallCursor();
}
}
/*
- *----------------------------------------------------------------------
- *
- * Tk_MacOSXTkOwnsCursor --
- *
- * Sets whether Tk has the right to adjust the cursor.
- *
- * Results:
- * None.
- *
- * Side effects:
- * May keep Tk from changing the cursor.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tk_MacOSXTkOwnsCursor(
- int tkOwnsIt)
-{
- gTkOwnsCursor = tkOwnsIt;
-}
-
-/*
* Local Variables:
* mode: objc
* c-basic-offset: 4
diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h
index efaaa91..8a6546f 100644
--- a/macosx/tkMacOSXDefault.h
+++ b/macosx/tkMacOSXDefault.h
@@ -45,7 +45,7 @@
#define INACTIVE_SELECT_BG "systemSelectedTextBackgroundColor"
#define TROUGH "#c3c3c3"
#define INDICATOR "#b03060"
-#define DISABLED "#a3a3a3"
+#define DISABLED "systemDisabledControlTextColor"
/*
* Defaults for labels, buttons, checkbuttons, and radiobuttons:
@@ -193,7 +193,7 @@
#define DEF_ENTRY_INSERT_WIDTH "1"
#define DEF_ENTRY_JUSTIFY "left"
#define DEF_ENTRY_PLACEHOLDER ""
-#define DEF_ENTRY_PLACEHOLDERFG "#b3b3b3"
+#define DEF_ENTRY_PLACEHOLDERFG "systemPlaceholderTextColor"
#define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG
#define DEF_ENTRY_READONLY_BG_MONO WHITE
#define DEF_ENTRY_RELIEF "sunken"
@@ -311,24 +311,24 @@
* Defaults for menus overall:
*/
-#define DEF_MENU_ACTIVE_BG_COLOR "systemMenuActive"
-#define DEF_MENU_ACTIVE_BG_MONO BLACK
+#define DEF_MENU_ACTIVE_BG_COLOR NORMAL_BG /*ignored*/
+#define DEF_MENU_ACTIVE_BG_MONO NORMAL_BG /*ignored*/
#define DEF_MENU_ACTIVE_BORDER_WIDTH "0"
-#define DEF_MENU_ACTIVE_FG_COLOR "systemMenuActiveText"
-#define DEF_MENU_ACTIVE_FG_MONO WHITE
+#define DEF_MENU_ACTIVE_FG_COLOR NORMAL_FG
+#define DEF_MENU_ACTIVE_FG_MONO NORMAL_FG
#define DEF_MENU_ACTIVE_RELIEF "flat"
-#define DEF_MENU_BG_COLOR "systemMenu"
-#define DEF_MENU_BG_MONO WHITE
+#define DEF_MENU_BG_COLOR NORMAL_BG /*ignored*/
+#define DEF_MENU_BG_MONO NORMAL_BG /*ignored*/
#define DEF_MENU_BORDER_WIDTH "0"
#define DEF_MENU_CURSOR "arrow"
-#define DEF_MENU_DISABLED_FG_COLOR "systemMenuDisabled"
-#define DEF_MENU_DISABLED_FG_MONO ""
+#define DEF_MENU_DISABLED_FG_COLOR DISABLED
+#define DEF_MENU_DISABLED_FG_MONO DISABLED
#define DEF_MENU_FONT "menu" /* special: see tkMacOSXMenu.c */
-#define DEF_MENU_FG "systemMenuText"
+#define DEF_MENU_FG NORMAL_FG
#define DEF_MENU_POST_COMMAND ""
#define DEF_MENU_RELIEF "flat"
-#define DEF_MENU_SELECT_COLOR "systemMenuActive"
-#define DEF_MENU_SELECT_MONO BLACK
+#define DEF_MENU_SELECT_COLOR "systemSelectedMenuItemTextColor"
+#define DEF_MENU_SELECT_MONO "systemSelectedMenuItemTextColor"
#define DEF_MENU_TAKE_FOCUS "0"
#define DEF_MENU_TEAROFF "0"
#define DEF_MENU_TEAROFF_CMD NULL
@@ -340,12 +340,12 @@
*/
#define DEF_MENUBUTTON_ANCHOR "w"
-#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG
-#define DEF_MENUBUTTON_ACTIVE_BG_MONO WHITE
-#define DEF_MENUBUTTON_ACTIVE_FG_COLOR ACTIVE_FG
-#define DEF_MENUBUTTON_ACTIVE_FG_MONO BLACK
-#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG
-#define DEF_MENUBUTTON_BG_MONO WHITE
+#define DEF_MENUBUTTON_ACTIVE_BG_COLOR NORMAL_BG /*ignored*/
+#define DEF_MENUBUTTON_ACTIVE_BG_MONO NORMAL_BG /*ignored*/
+#define DEF_MENUBUTTON_ACTIVE_FG_COLOR "systemTextColor"
+#define DEF_MENUBUTTON_ACTIVE_FG_MONO "systemTextColor"
+#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG /*ignored*/
+#define DEF_MENUBUTTON_BG_MONO NORMAL_BG /*ignored*/
#define DEF_MENUBUTTON_BITMAP ""
#define DEF_MENUBUTTON_BORDER_WIDTH "0"
#define DEF_MENUBUTTON_CURSOR ""
@@ -357,7 +357,7 @@
#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 NORMAL_BG
#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0"
#define DEF_MENUBUTTON_IMAGE NULL
#define DEF_MENUBUTTON_INDICATOR "1"
diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c
index 898547e..91383d2 100644
--- a/macosx/tkMacOSXDialog.c
+++ b/macosx/tkMacOSXDialog.c
@@ -23,7 +23,7 @@
#define modalOK NSModalResponseOK
#define modalCancel NSModalResponseCancel
#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1090
-#define modalOther -1
+#define modalOther -1 // indicates that the -command option was used.
#define modalError -2
/*
@@ -52,6 +52,10 @@ typedef struct {
* filter. */
} filepanelFilterInfo;
+/*
+ * Only one of these is needed for the application, so they can be static.
+ */
+
static filepanelFilterInfo filterInfo;
static NSOpenPanel *openpanel;
static NSSavePanel *savepanel;
@@ -250,13 +254,13 @@ getFileURL(
} else if (returnCode == modalCancel) {
Tcl_ResetResult(callbackInfo->interp);
}
- if (panel == [NSApp modalWindow]) {
- [NSApp stopModalWithCode:returnCode];
- }
if (callbackInfo->cmdObj) {
Tcl_DecrRefCount(callbackInfo->cmdObj);
+ }
+ if (callbackInfo) {
ckfree(callbackInfo);
}
+ [NSApp stopModalWithCode:returnCode];
}
- (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode
@@ -356,14 +360,42 @@ static NSInteger showOpenSavePanel(
contextInfo:callbackInfo ];
}];
- modalReturnCode = callbackInfo->cmdObj ? modalOther :
- [panel runModal];
+ /*
+ * The sheet has been prepared, so now we have to run it as a modal
+ * window. Using [NSApp runModalForWindow:] on macOS 10.15 or later
+ * generates warnings on stderr. But using [NSOpenPanel runModal] or
+ * [NSSavePanel runModal] on 10.14 or earler does not cause the
+ * completion handler to run when the panel is closed.
+ */
+
+ if ([NSApp macOSVersion] > 101400) {
+ modalReturnCode = [panel runModal];
+ } else {
+ modalReturnCode = [NSApp runModalForWindow:panel];
+ }
} else {
- modalReturnCode = [panel runModal];
- [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
- contextInfo:callbackInfo];
+
+ /*
+ * For the standalone file dialog, completion handlers do not work
+ * at all on macOS 10.14 and earlier.
+ */
+
+ if ([NSApp macOSVersion] > 101400) {
+ [panel beginWithCompletionHandler:^(NSModalResponse returnCode) {
+ [NSApp tkFilePanelDidEnd:panel
+ returnCode:returnCode
+ contextInfo:callbackInfo ];
+ }];
+ modalReturnCode = [panel runModal];
+ } else {
+ modalReturnCode = [panel runModal];
+ [NSApp tkFilePanelDidEnd:panel
+ returnCode:modalReturnCode
+ contextInfo:callbackInfo ];
+ [panel close];
+ }
}
- return modalReturnCode;
+ return callbackInfo->cmdObj ? modalOther : modalReturnCode;
}
/*
@@ -729,7 +761,7 @@ Tk_GetOpenFileObjCmd(
* panel. Prepend the title to the message in this case.
*/
- if ([NSApp macMinorVersion] > 10) {
+ if ([NSApp macOSVersion] > 101000) {
if (message) {
NSString *fullmessage =
[[NSString alloc] initWithFormat:@"%@\n%@", title, message];
@@ -818,7 +850,7 @@ Tk_GetOpenFileObjCmd(
[openpanel setDirectoryURL:fileURL];
}
if (haveParentOption) {
- parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
+ parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
parentIsKey = parent && [parent isKeyWindow];
} else {
parent = nil;
@@ -870,15 +902,15 @@ Tk_GetOpenFileObjCmd(
selectedFilterIndex = filterInfo.fileTypeIndex; // The preselection from the typevariable
selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
} else {
- NSUInteger i;
+ NSUInteger j;
- for (i = 0; i < [filterInfo.fileTypeNames count]; i++) {
- if (filterCompatible(extension, i)) {
- selectedFilterIndex = i;
+ for (j = 0; j < [filterInfo.fileTypeNames count]; j++) {
+ if (filterCompatible(extension, j)) {
+ selectedFilterIndex = j;
break;
}
}
- if (i == selectedFilterIndex) {
+ if (j == selectedFilterIndex) {
selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
} else {
selectedFilter = @"";
@@ -917,7 +949,7 @@ Tk_GetSaveFileObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tk_Window tkwin = clientData;
+ Tk_Window tkwin = (Tk_Window)clientData;
char *str;
int i, result = TCL_ERROR, haveParentOption = 0;
int confirmOverwrite = 1;
@@ -1104,7 +1136,7 @@ Tk_GetSaveFileObjCmd(
[savepanel setNameFieldStringValue:@""];
}
if (haveParentOption) {
- parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
+ parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
parentIsKey = parent && [parent isKeyWindow];
} else {
parent = nil;
@@ -1159,7 +1191,7 @@ Tk_ChooseDirectoryObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tk_Window tkwin = clientData;
+ Tk_Window tkwin = (Tk_Window)clientData;
char *str;
int i, result = TCL_ERROR, haveParentOption = 0;
int index, len, mustexist = 0;
@@ -1246,10 +1278,10 @@ Tk_ChooseDirectoryObjCmd(
if (!directory) {
directory = @"/";
}
- parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
+ parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
[panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]];
if (haveParentOption) {
- parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
+ parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
parentIsKey = parent && [parent isKeyWindow];
} else {
parent = nil;
@@ -1283,64 +1315,9 @@ Tk_ChooseDirectoryObjCmd(
void
TkAboutDlg(void)
{
- NSImage *image;
- NSString *path = [NSApp tkFrameworkImagePath: @"Tk.tiff"];
-
- if (path) {
- image = [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
- } else {
- image = [NSApp applicationIconImage];
- }
-
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
-
- [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
- [dateFormatter setDateFormat:@"Y"];
-
- 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";
- 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: "
- "www.tcl.tk/software/tcltk/license.html\n\n"
- "%1$C 1987-%2$@ Tcl Core Team and Contributers.\n\n"
- "%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC.\n\n"
- "%1$C 2014-%2$@ Marc Culler.\n\n"
- "%1$C 2002-2012 Daniel A. Steffen.\n\n"
- "%1$C 2001-2009 Apple Inc.\n\n"
- "%1$C 2001-2002 Jim Ingham & Ian Reid\n\n"
- "%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)];
- [credits setDrawsBackground:NO];
- [credits setEditable:NO];
-
- NSAlert *about = [[NSAlert alloc] init];
-
- [[about window] setTitle:@"About Tcl & Tk"];
- [about setMessageText: version];
- [about setInformativeText:url];
- about.accessoryView = credits;
- [about runModal];
- [about release];
+ [NSApp orderFrontStandardAboutPanel:nil];
}
-
+
/*
*----------------------------------------------------------------------
*
@@ -1359,18 +1336,16 @@ TkAboutDlg(void)
int
TkMacOSXStandardAboutPanelObjCmd(
- ClientData dummy, /* Unused. */
+ TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- (void)dummy;
-
if (objc > 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
- TkAboutDlg();
+ [NSApp orderFrontStandardAboutPanel:nil];
return TCL_OK;
}
@@ -1397,7 +1372,7 @@ Tk_MessageBoxObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tk_Window tkwin = clientData;
+ Tk_Window tkwin = (Tk_Window)clientData;
char *str;
int i, result = TCL_ERROR, haveParentOption = 0;
int index, typeIndex, iconIndex, indexDefaultOption = 0;
@@ -1535,7 +1510,7 @@ Tk_MessageBoxObjCmd(
callbackInfo->cmdObj = cmdObj;
callbackInfo->interp = interp;
callbackInfo->typeIndex = typeIndex;
- parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
+ parent = TkMacOSXGetNSWindowForDrawable(((TkWindow *)tkwin)->window);
if (haveParentOption && parent && ![parent attachedSheet]) {
parentIsKey = [parent isKeyWindow];
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
@@ -1656,7 +1631,7 @@ enum FontchooserOption {
}
}
-- (NSUInteger) validModesForFontPanel: (NSFontPanel *) fontPanel
+- (NSUInteger) validModesForFontPanel: (NSFontPanel *)fontPanel
{
(void)fontPanel;
@@ -1665,7 +1640,7 @@ enum FontchooserOption {
NSFontPanelStrikethroughEffectModeMask;
}
-- (void) windowDidOrderOffScreen: (NSNotification *) notification
+- (void) windowDidOrderOffScreen: (NSNotification *)notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
@@ -1689,7 +1664,7 @@ enum FontchooserOption {
* None.
*
* Side effects:
- * Additional events may be place on the Tk event queue.
+ * Additional events may be placed on the Tk event queue.
*
*----------------------------------------------------------------------
*/
@@ -1708,7 +1683,7 @@ FontchooserEvent(
switch (kind) {
case FontchooserClosed:
if (fcdPtr->parent != None) {
- TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
+ Tk_SendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
fontchooserInterp = NULL;
}
break;
@@ -1731,7 +1706,7 @@ FontchooserEvent(
ckfree(tmpv);
}
}
- TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL);
+ Tk_SendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL);
}
break;
}
@@ -1765,7 +1740,7 @@ FontchooserCget(
case FontchooserParent:
if (fcdPtr->parent != None) {
resObj = Tcl_NewStringObj(
- ((TkWindow *) fcdPtr->parent)->pathName, -1);
+ ((TkWindow *)fcdPtr->parent)->pathName, -1);
} else {
resObj = Tcl_NewStringObj(".", 1);
}
@@ -1940,7 +1915,7 @@ FontchooserConfigureCmd(
[fm setSelectedAttributes:fontPanelFontAttributes
isMultiple:NO];
if ([fp isVisible]) {
- TkSendVirtualEvent(fcdPtr->parent,
+ Tk_SendVirtualEvent(fcdPtr->parent,
"TkFontchooserFontChanged", NULL);
}
break;
@@ -1986,16 +1961,14 @@ static int
FontchooserShowCmd(
ClientData clientData, /* Main window */
Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const objv[])
+ TCL_UNUSED(int),
+ TCL_UNUSED(Tcl_Obj *const *))
{
FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser",
NULL);
- (void)objc;
- (void)objv;
if (fcdPtr->parent == None) {
- fcdPtr->parent = (Tk_Window) clientData;
+ fcdPtr->parent = (Tk_Window)clientData;
Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask,
FontchooserParentEventHandler, fcdPtr);
}
@@ -2008,7 +1981,7 @@ FontchooserShowCmd(
}
if (![fp isVisible]) {
[fm orderFrontFontPanel:NSApp];
- TkSendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
+ Tk_SendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL);
}
fontchooserInterp = interp;
@@ -2034,16 +2007,12 @@ FontchooserShowCmd(
static int
FontchooserHideCmd(
- ClientData dummy, /* Main window */
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const objv[])
+ TCL_UNUSED(void *), /* Main window */
+ TCL_UNUSED(Tcl_Interp *),
+ TCL_UNUSED(int),
+ TCL_UNUSED(Tcl_Obj *const *))
{
NSFontPanel *fp = [[NSFontManager sharedFontManager] fontPanel:NO];
- (void)dummy;
- (void)interp;
- (void)objc;
- (void)objv;
if ([fp isVisible]) {
[fp orderOut:NSApp];
@@ -2140,10 +2109,9 @@ DeleteFontchooserData(
MODULE_SCOPE int
TkInitFontchooser(
Tcl_Interp *interp,
- ClientData dummy)
+ TCL_UNUSED(void *))
{
FontchooserData *fcdPtr = (FontchooserData *)ckalloc(sizeof(FontchooserData));
- (void)dummy;
bzero(fcdPtr, sizeof(FontchooserData));
Tcl_SetAssocData(interp, "::tk::fontchooser", DeleteFontchooserData,
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index 66027cd..a7314f1 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -1,13 +1,13 @@
/*
* tkMacOSXDraw.c --
*
- * This file contains functions that perform drawing to Xlib windows. Most
- * of the functions simply emulate Xlib functions.
+ * This file contains functions that draw to windows. Many of thees
+ * functions emulate Xlib functions.
*
* 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 2014 Marc Culler.
+ * Copyright (c) 2014-2020 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -17,7 +17,7 @@
#include "tkMacOSXDebug.h"
#include "tkButton.h"
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
#define GET_CGCONTEXT [[NSGraphicsContext currentContext] CGContext]
#else
#define GET_CGCONTEXT [[NSGraphicsContext currentContext] graphicsPort]
@@ -43,12 +43,15 @@ static int cgAntiAliasLimit = 0;
static int useThemedToplevel = 0;
static int useThemedFrame = 0;
+static unsigned long transparentColor;
/*
* Prototypes for functions used only in this file.
*/
static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr);
+static NSImage *CreateNSImageFromPixmap(Pixmap pixmap, int width, int height);
+
/*
*----------------------------------------------------------------------
@@ -69,11 +72,10 @@ static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr);
MODULE_SCOPE int
TkMacOSXInitCGDrawing(
Tcl_Interp *interp,
- int enable,
+ TCL_UNUSED(int),
int limit)
{
static Boolean initialized = FALSE;
- (void)enable;
if (!initialized) {
initialized = TRUE;
@@ -83,7 +85,7 @@ TkMacOSXInitCGDrawing(
}
if (Tcl_LinkVar(interp, "::tk::mac::CGAntialiasLimit",
- (char *) &cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) {
+ (char *)&cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) {
Tcl_ResetResult(interp);
}
cgAntiAliasLimit = limit;
@@ -93,13 +95,14 @@ TkMacOSXInitCGDrawing(
*/
if (Tcl_LinkVar(interp, "::tk::mac::useThemedToplevel",
- (char *) &useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) {
+ (char *)&useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) {
Tcl_ResetResult(interp);
}
if (Tcl_LinkVar(interp, "::tk::mac::useThemedFrame",
- (char *) &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) {
+ (char *)&useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) {
Tcl_ResetResult(interp);
}
+ transparentColor = TkMacOSXClearPixel();
}
return TCL_OK;
}
@@ -107,382 +110,7 @@ TkMacOSXInitCGDrawing(
/*
*----------------------------------------------------------------------
*
- * TkMacOSXBitmapRepFromDrawableRect
- *
- * Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep.
- *
- * This is only used by XGetImage, which is never called. And this
- * implementation does not work correctly. Originally it relied on
- * [NSBitmapImageRep initWithFocusedViewRect:view_rect] which was
- * deprecated by Apple in OSX 10.14 and also required the use of other
- * deprecated functions such as [NSView lockFocus]. Apple's suggested
- * replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that
- * is what is being used here. However, that method only works when the
- * view has a valid CGContext, and a view is only guaranteed to have a
- * valid context during a call to [NSView drawRect]. To further complicate
- * matters, cacheDisplayInRect calls [NSView drawRect]. Essentially it is
- * asking the view to draw a subrectangle of itself into a special
- * graphics context which is linked to the BitmapImageRep. But our
- * implementation of [NSView drawRect] does not allow recursive calls. If
- * called recursively it returns immediately without doing any drawing.
- * So the bottom line is that this function either returns a NULL pointer
- * or a black image. To make it useful would require a significant amount
- * of rewriting of the drawRect method. Perhaps the next release of OSX
- * will include some more helpful ways of doing this.
- *
- * Results:
- * Returns an NSBitmapRep representing the image of the given rectangle of
- * the given drawable. This object is retained. The caller is responsible
- * for releasing it.
- *
- * NOTE: The x,y coordinates should be relative to a coordinate system
- * with origin at the top left, as used by XImage and CGImage, not bottom
- * left as used by NSView.
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------
- */
-
-NSBitmapImageRep *
-TkMacOSXBitmapRepFromDrawableRect(
- Drawable drawable,
- int x,
- int y,
- unsigned int width,
- unsigned int height)
-{
- MacDrawable *mac_drawable = (MacDrawable *) drawable;
- CGContextRef cg_context = NULL;
- CGImageRef cg_image = NULL, sub_cg_image = NULL;
- NSBitmapImageRep *bitmap_rep = NULL;
- NSView *view = NULL;
- if (mac_drawable->flags & TK_IS_PIXMAP) {
- /*
- * This MacDrawable is a bitmap, so its view is NULL.
- */
-
- CGRect image_rect = CGRectMake(x, y, width, height);
-
- cg_context = TkMacOSXGetCGContextForDrawable(drawable);
- cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context);
- sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect);
- if (sub_cg_image) {
- bitmap_rep = [NSBitmapImageRep alloc];
- [bitmap_rep initWithCGImage:sub_cg_image];
- }
- if (cg_image) {
- CGImageRelease(cg_image);
- }
- } else if ((view = TkMacOSXDrawableView(mac_drawable)) != NULL) {
- /*
- * Convert Tk top-left to NSView bottom-left coordinates.
- */
-
- int view_height = [view bounds].size.height;
- NSRect view_rect = NSMakeRect(x + mac_drawable->xOff,
- view_height - height - y - mac_drawable->yOff,
- width, height);
-
- /*
- * Attempt to copy from the view to a bitmapImageRep. If the view does
- * not have a valid CGContext, doing this will silently corrupt memory
- * and make a big mess. So, in that case, we mark the view as needing
- * display and return NULL.
- */
-
- if (view == [NSView focusView]) {
- bitmap_rep = [view bitmapImageRepForCachingDisplayInRect: view_rect];
- [bitmap_rep retain];
- [view cacheDisplayInRect:view_rect toBitmapImageRep:bitmap_rep];
- } else {
- TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap.");
- [view setNeedsDisplay:YES];
- return NULL;
- }
- } else {
- TkMacOSXDbgMsg("Invalid source drawable");
- }
- return bitmap_rep;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XCopyArea --
- *
- * Copies data from one drawable to another.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Data is moved from a window or bitmap to a second window or bitmap.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XCopyArea(
- Display *display, /* Display. */
- Drawable src, /* Source drawable. */
- Drawable dst, /* Destination drawable. */
- GC gc, /* GC to use. */
- int src_x, /* X & Y, width & height */
- int src_y, /* define the source rectangle */
- unsigned int width, /* that will be copied. */
- unsigned int height,
- int dest_x, /* Dest X & Y on dest rect. */
- int dest_y)
-{
- TkMacOSXDrawingContext dc;
- MacDrawable *srcDraw = (MacDrawable *) src;
- NSBitmapImageRep *bitmap_rep = NULL;
- CGImageRef img = NULL;
- CGRect bounds, srcRect, dstRect;
-
- display->request++;
- if (!width || !height) {
- return BadDrawable;
- }
-
- if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
- TkMacOSXDbgMsg("Failed to setup drawing context.");
- return BadDrawable;
- }
-
- if (!dc.context) {
- TkMacOSXDbgMsg("Invalid destination drawable - no context.");
- return BadDrawable;
- }
-
- if (srcDraw->flags & TK_IS_PIXMAP) {
- img = TkMacOSXCreateCGImageWithDrawable(src);
- } else if (TkMacOSXDrawableWindow(src)) {
- bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src,
- src_x, src_y, width, height);
- if (bitmap_rep) {
- img = [bitmap_rep CGImage];
- }
- } else {
- TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
- }
-
- if (img) {
- bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
- srcRect = CGRectMake(src_x, src_y, width, height);
- dstRect = CGRectMake(dest_x, dest_y, width, height);
- TkMacOSXDrawCGImage(dst, gc, dc.context, img,
- gc->foreground, gc->background, bounds, srcRect, dstRect);
- CFRelease(img);
- } else {
- TkMacOSXDbgMsg("Failed to construct CGImage.");
- }
-
- TkMacOSXRestoreDrawingContext(&dc);
- return Success;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * XCopyPlane --
- *
- * Copies a bitmap from a source drawable to a destination drawable. The
- * plane argument specifies which bit plane of the source contains the
- * bitmap. Note that this implementation ignores the gc->function.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Changes the destination drawable.
- *
- *----------------------------------------------------------------------
- */
-
-int
-XCopyPlane(
- Display *display, /* Display. */
- Drawable src, /* Source drawable. */
- Drawable dst, /* Destination drawable. */
- GC gc, /* GC to use. */
- int src_x, /* X & Y, width & height */
- int src_y, /* define the source rectangle */
- unsigned int width, /* that will be copied. */
- unsigned int height,
- int dest_x, /* Dest X & Y on dest rect. */
- int dest_y,
- unsigned long plane) /* Which plane to copy. */
-{
- TkMacOSXDrawingContext dc;
- MacDrawable *srcDraw = (MacDrawable *) src;
- MacDrawable *dstDraw = (MacDrawable *) dst;
- CGRect bounds, srcRect, dstRect;
- display->request++;
- if (!width || !height) {
- /* TkMacOSXDbgMsg("Drawing of empty area requested"); */
- return BadDrawable;
- }
- if (plane != 1) {
- Tcl_Panic("Unexpected plane specified for XCopyPlane");
- }
- if (srcDraw->flags & TK_IS_PIXMAP) {
- if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
- return BadDrawable;
- }
-
- CGContextRef context = dc.context;
-
- if (context) {
- CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);
-
- if (img) {
- TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
- unsigned long imageBackground = gc->background;
-
- if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP) {
- srcRect = CGRectMake(src_x, src_y, width, height);
- CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(
- clipPtr->value.pixmap);
- CGImageRef submask = CGImageCreateWithImageInRect(
- img, srcRect);
- CGRect rect = CGRectMake(dest_x, dest_y, width, height);
-
- rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);
- CGContextSaveGState(context);
-
- /*
- * Move the origin of the destination to top left.
- */
-
- CGContextTranslateCTM(context,
- 0, rect.origin.y + CGRectGetMaxY(rect));
- CGContextScaleCTM(context, 1, -1);
-
- /*
- * Fill with the background color, clipping to the mask.
- */
-
- CGContextClipToMask(context, rect, submask);
- TkMacOSXSetColorInContext(gc, gc->background, dc.context);
- CGContextFillRect(context, rect);
-
- /*
- * Fill with the foreground color, clipping to the
- * intersection of img and mask.
- */
-
- CGImageRef subimage = CGImageCreateWithImageInRect(
- img, srcRect);
- CGContextClipToMask(context, rect, subimage);
- TkMacOSXSetColorInContext(gc, gc->foreground, context);
- CGContextFillRect(context, rect);
- CGContextRestoreGState(context);
- CGImageRelease(img);
- CGImageRelease(mask);
- CGImageRelease(submask);
- CGImageRelease(subimage);
- } else {
- bounds = CGRectMake(0, 0,
- srcDraw->size.width, srcDraw->size.height);
- srcRect = CGRectMake(src_x, src_y, width, height);
- dstRect = CGRectMake(dest_x, dest_y, width, height);
- TkMacOSXDrawCGImage(dst, gc, dc.context, img,
- gc->foreground, imageBackground, bounds,
- srcRect, dstRect);
- CGImageRelease(img);
- }
- } else {
- /* no image */
- TkMacOSXDbgMsg("Invalid source drawable");
- }
- } else {
- TkMacOSXDbgMsg("Invalid destination drawable - "
- "could not get a bitmap context.");
- }
- TkMacOSXRestoreDrawingContext(&dc);
- return Success;
- } else {
- /*
- * Source drawable is a Window, not a Pixmap.
- */
-
- return XCopyArea(display, src, dst, gc, src_x, src_y, width, height,
- dest_x, dest_y);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacOSXCreateCGImageWithDrawable --
- *
- * Create a CGImage from the given Drawable.
- *
- * Results:
- * CGImage, release after use.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-CGImageRef
-TkMacOSXCreateCGImageWithDrawable(
- Drawable drawable)
-{
- CGImageRef img = NULL;
- CGContextRef context = TkMacOSXGetCGContextForDrawable(drawable);
-
- if (context) {
- img = CGBitmapContextCreateImage(context);
- }
- return img;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * CreateNSImageWithPixmap --
- *
- * Create NSImage for Pixmap.
- *
- * Results:
- * NSImage.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static NSImage *
-CreateNSImageWithPixmap(
- Pixmap pixmap,
- int width,
- int height)
-{
- CGImageRef cgImage;
- NSImage *nsImage;
- NSBitmapImageRep *bitmapImageRep;
-
- cgImage = TkMacOSXCreateCGImageWithDrawable(pixmap);
- nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
- bitmapImageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
- [nsImage addRepresentation:bitmapImageRep];
- [bitmapImageRep release];
- CFRelease(cgImage);
-
- return nsImage;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacOSXGetNSImageWithTkImage --
+ * TkMacOSXGetNSImageFromTkImage --
*
* Get autoreleased NSImage for Tk_Image.
*
@@ -496,7 +124,7 @@ CreateNSImageWithPixmap(
*/
NSImage *
-TkMacOSXGetNSImageWithTkImage(
+TkMacOSXGetNSImageFromTkImage(
Display *display,
Tk_Image image,
int width,
@@ -509,7 +137,7 @@ TkMacOSXGetNSImageWithTkImage(
}
pixmap = Tk_GetPixmap(display, None, width, height, 0);
Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);
- nsImage = CreateNSImageWithPixmap(pixmap, width, height);
+ nsImage = CreateNSImageFromPixmap(pixmap, width, height);
Tk_FreePixmap(display, pixmap);
return [nsImage autorelease];
@@ -518,7 +146,7 @@ TkMacOSXGetNSImageWithTkImage(
/*
*----------------------------------------------------------------------
*
- * TkMacOSXGetNSImageWithBitmap --
+ * TkMacOSXGetNSImageFromBitmap --
*
* Get autoreleased NSImage for Bitmap.
*
@@ -532,7 +160,7 @@ TkMacOSXGetNSImageWithTkImage(
*/
NSImage *
-TkMacOSXGetNSImageWithBitmap(
+TkMacOSXGetNSImageFromBitmap(
Display *display,
Pixmap bitmap,
GC gc,
@@ -544,11 +172,11 @@ TkMacOSXGetNSImageWithBitmap(
unsigned long origBackground = gc->background;
- gc->background = TRANSPARENT_PIXEL << 24;
+ gc->background = transparentColor;
XSetClipOrigin(display, gc, 0, 0);
XCopyPlane(display, bitmap, pixmap, gc, 0, 0, width, height, 0, 0, 1);
gc->background = origBackground;
- nsImage = CreateNSImageWithPixmap(pixmap, width, height);
+ nsImage = CreateNSImageFromPixmap(pixmap, width, height);
Tk_FreePixmap(display, pixmap);
return [nsImage autorelease];
@@ -557,7 +185,48 @@ TkMacOSXGetNSImageWithBitmap(
/*
*----------------------------------------------------------------------
*
- * TkMacOSXGetCGContextForDrawable --
+ * CreateNSImageFromPixmap --
+ *
+ * Create NSImage for Pixmap.
+ *
+ * Results:
+ * NSImage.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static NSImage *
+CreateNSImageFromPixmap(
+ Pixmap pixmap,
+ int width,
+ int height)
+{
+ CGImageRef cgImage;
+ NSImage *nsImage;
+ NSBitmapImageRep *bitmapImageRep;
+ CGContextRef context = TkMacOSXGetCGContextForDrawable(pixmap);
+
+ if (context) {
+ cgImage = CGBitmapContextCreateImage(context);
+ } else {
+ return NULL;
+ }
+ nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
+ bitmapImageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
+ [nsImage addRepresentation:bitmapImageRep];
+ [bitmapImageRep release];
+ CFRelease(cgImage);
+
+ return nsImage;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_MacOSXGetCGContextForDrawable --
*
* Get CGContext for given Drawable, creating one if necessary.
*
@@ -570,11 +239,11 @@ TkMacOSXGetNSImageWithBitmap(
*----------------------------------------------------------------------
*/
-CGContextRef
-TkMacOSXGetCGContextForDrawable(
+void *
+Tk_MacOSXGetCGContextForDrawable(
Drawable drawable)
{
- MacDrawable *macDraw = (MacDrawable *) drawable;
+ MacDrawable *macDraw = (MacDrawable *)drawable;
if (macDraw && (macDraw->flags & TK_IS_PIXMAP) && !macDraw->context) {
const size_t bitsPerComponent = 8;
@@ -592,7 +261,7 @@ TkMacOSXGetCGContextForDrawable(
if (macDraw->flags & TK_IS_BW_PIXMAP) {
bitsPerPixel = 8;
- bitmapInfo = (CGBitmapInfo) kCGImageAlphaOnly;
+ bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly;
} else {
colorspace = CGColorSpaceCreateDeviceRGB();
bitsPerPixel = 32;
@@ -645,7 +314,7 @@ TkMacOSXDrawCGImage(
CGRect srcBounds,
CGRect dstBounds)
{
- MacDrawable *macDraw = (MacDrawable *) d;
+ MacDrawable *macDraw = (MacDrawable *)d;
if (macDraw && context && image) {
CGImageRef subImage = NULL;
@@ -663,17 +332,18 @@ TkMacOSXDrawCGImage(
dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff);
if (CGImageIsMask(image)) {
if (macDraw->flags & TK_IS_BW_PIXMAP) {
+
/*
* Set fill color to black; background comes from the context,
* or is transparent.
*/
- if (imageBackground != TRANSPARENT_PIXEL << 24) {
+ if (imageBackground != transparentColor) {
CGContextClearRect(context, dstBounds);
}
CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0);
} else {
- if (imageBackground != TRANSPARENT_PIXEL << 24) {
+ if (imageBackground != transparentColor) {
TkMacOSXSetColorInContext(gc, imageBackground, context);
CGContextFillRect(context, dstBounds);
}
@@ -740,7 +410,7 @@ XDrawLines(
int npoints, /* Number of points. */
int mode) /* Line drawing mode. */
{
- MacDrawable *macWin = (MacDrawable *) d;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
int i, lw = gc->line_width;
@@ -749,7 +419,7 @@ XDrawLines(
}
display->request++;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -812,12 +482,12 @@ XDrawSegments(
XSegment *segments,
int nsegments)
{
- MacDrawable *macWin = (MacDrawable *) d;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
int i, lw = gc->line_width;
display->request++;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -861,16 +531,15 @@ XFillPolygon(
GC gc, /* Use this GC. */
XPoint *points, /* Array of points. */
int npoints, /* Number of points. */
- int shape, /* Shape to draw. */
+ TCL_UNUSED(int), /* Shape to draw. */
int mode) /* Drawing mode. */
{
- MacDrawable *macWin = (MacDrawable *) d;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
int i;
- (void)shape;
display->request++;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -923,7 +592,7 @@ XDrawRectangle(
unsigned int width, /* Width & height of rect. */
unsigned int height)
{
- MacDrawable *macWin = (MacDrawable *) d;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
int lw = gc->line_width;
@@ -932,7 +601,7 @@ XDrawRectangle(
}
display->request++;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -975,18 +644,18 @@ XDrawRectangle(
int
XDrawRectangles(
Display *display,
- Drawable drawable,
+ Drawable d,
GC gc,
XRectangle *rectArr,
int nRects)
{
- MacDrawable *macWin = (MacDrawable *) drawable;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
XRectangle * rectPtr;
int i, lw = gc->line_width;
display->request++;
- if (!TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -1032,13 +701,13 @@ XFillRectangles(
XRectangle *rectangles, /* Rectangle array. */
int n_rectangles) /* Number of rectangles. */
{
- MacDrawable *macWin = (MacDrawable *) d;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
XRectangle * rectPtr;
int i;
display->request++;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -1091,7 +760,7 @@ TkMacOSXDrawSolidBorder(
TkMacOSXDrawingContext dc;
CGRect outerRect, innerRect;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return;
}
if (dc.context) {
@@ -1134,7 +803,7 @@ XDrawArc(
int angle1, /* Staring angle of arc. */
int angle2) /* Extent of arc. */
{
- MacDrawable *macWin = (MacDrawable *) d;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
int lw = gc->line_width;
@@ -1143,7 +812,7 @@ XDrawArc(
}
display->request++;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -1207,13 +876,13 @@ XDrawArcs(
XArc *arcArr,
int nArcs)
{
- MacDrawable *macWin = (MacDrawable *) d;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
XArc *arcPtr;
int i, lw = gc->line_width;
display->request++;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -1285,7 +954,7 @@ XFillArc(
int angle1, /* Staring angle of arc. */
int angle2) /* Extent of arc. */
{
- MacDrawable *macWin = (MacDrawable *) d;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
int lw = gc->line_width;
@@ -1294,7 +963,7 @@ XFillArc(
}
display->request++;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -1361,13 +1030,13 @@ XFillArcs(
XArc *arcArr,
int nArcs)
{
- MacDrawable *macWin = (MacDrawable *) d;
+ MacDrawable *macWin = (MacDrawable *)d;
TkMacOSXDrawingContext dc;
XArc * arcPtr;
int i, lw = gc->line_width;
display->request++;
- if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -1440,20 +1109,19 @@ XFillArcs(
int
TkScrollWindow(
Tk_Window tkwin, /* The window to be scrolled. */
- GC gc, /* GC for window to be scrolled. */
+ TCL_UNUSED(GC), /* GC for window to be scrolled. */
int x, int y, /* Position rectangle to be scrolled. */
int width, int height,
int dx, int dy, /* Distance rectangle should be moved. */
Region damageRgn) /* Region to accumulate damage in. */
{
Drawable drawable = Tk_WindowId(tkwin);
- MacDrawable *macDraw = (MacDrawable *) drawable;
- TKContentView *view = (TKContentView *) TkMacOSXDrawableView(macDraw);
+ MacDrawable *macDraw = (MacDrawable *)drawable;
+ TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(macDraw);
CGRect srcRect, dstRect;
HIShapeRef dmgRgn = NULL, extraRgn = NULL;
NSRect bounds, visRect, scrollSrc, scrollDst;
int result = 0;
- (void)gc;
if (view) {
/*
@@ -1537,12 +1205,9 @@ TkScrollWindow(
void
TkMacOSXSetUpGraphicsPort(
- GC gc, /* GC to apply to current port. */
- void *destPort)
+ TCL_UNUSED(GC), /* GC to apply to current port. */
+ TCL_UNUSED(void *))
{
- (void)gc;
- (void)destPort;
-
Tcl_Panic("TkMacOSXSetUpGraphicsPort: Obsolete, no more QD!");
}
@@ -1552,15 +1217,17 @@ TkMacOSXSetUpGraphicsPort(
*
* TkMacOSXSetUpDrawingContext --
*
- * Set up a drawing context for the given drawable and GC.
+ * Set up a drawing context for the given drawable from an X GC.
*
* Results:
- * Boolean indicating whether it is ok to draw; if false, drawing context
- * was not setup, so do not attempt to draw and do not call
+ * Boolean indicating whether it is ok to draw; if false, the drawing
+ * context was not setup, so do not attempt to draw and do not call
* TkMacOSXRestoreDrawingContext().
*
* Side effects:
- * None.
+ * May modify or create the drawable's graphics context. May expand the
+ * drawable's dirty rectangle. When the result is true The dcPtr
+ * parameter is set to reference the new or updated drawing context.
*
*----------------------------------------------------------------------
*/
@@ -1569,27 +1236,28 @@ Bool
TkMacOSXSetupDrawingContext(
Drawable d,
GC gc,
- int useCG, /* advisory only ! */
TkMacOSXDrawingContext *dcPtr)
{
- MacDrawable *macDraw = (MacDrawable *) d;
+ MacDrawable *macDraw = (MacDrawable *)d;
Bool canDraw = true;
- NSWindow *win = NULL;
+ TKContentView *view = nil;
TkMacOSXDrawingContext dc = {};
- CGRect clipBounds;
- (void)useCG;
/*
- * If the drawable is not a pixmap and it has an associated NSWindow then
- * we know we are drawing to a window.
+ * If the drawable is not a pixmap, get the associated NSView.
*/
if (!(macDraw->flags & TK_IS_PIXMAP)) {
- win = TkMacOSXDrawableWindow(d);
+ view = (TKContentView *)TkMacOSXGetNSViewForDrawable(d);
+ if (!view) {
+ Tcl_Panic("TkMacOSXSetupDrawingContext(): "
+ "no NSView to draw into !");
+ }
}
/*
- * Check that we have a non-empty clipping region.
+ * Intersect the drawable's clipping region with the region stored in the
+ * X GC. If the resulting region is empty, don't do any drawing.
*/
dc.clipRgn = TkMacOSXGetClipRgn(d);
@@ -1600,165 +1268,158 @@ TkMacOSXSetupDrawingContext(
}
/*
- * If we already have a CGContext, use it. Otherwise, if we are drawing to
- * a window then we can get one from the window.
+ * If the drawable already has a CGContext, use it. Otherwise, we must be
+ * drawing to a window and we use the current context of its ContentView.
*/
dc.context = TkMacOSXGetCGContextForDrawable(d);
if (dc.context) {
- dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
- } else if (win) {
- NSView *view = TkMacOSXDrawableView(macDraw);
+ dc.portBounds = CGContextGetClipBoundingBox(dc.context);
+ } else {
+ NSRect drawingBounds, currentBounds;
- if (!view) {
- Tcl_Panic("TkMacOSXSetupDrawingContext(): "
- "no NSView to draw into !");
+ dc.view = view;
+ dc.context = GET_CGCONTEXT;
+ dc.portBounds = NSRectToCGRect([view bounds]);
+ if (dc.clipRgn) {
+ CGRect clipBounds;
+ CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
+ .ty = [view bounds].size.height};
+ HIShapeGetBounds(dc.clipRgn, &clipBounds);
+ clipBounds = CGRectApplyAffineTransform(clipBounds, t);
+ drawingBounds = NSRectFromCGRect(clipBounds);
+ } else {
+ drawingBounds = [view bounds];
}
/*
- * We can only draw into the view when the current CGContext is valid
- * and belongs to the view. Validity can only be guaranteed inside of
- * a view's drawRect or setFrame methods. The isDrawing attribute
- * tells us whether we are being called from one of those methods.
- *
- * If the CGContext is not valid then we mark our view as needing
- * display in the bounding rectangle of the clipping region and
- * return failure. That rectangle should get drawn in a later call
- * to drawRect.
- *
- * As an exception to the above, if mouse buttons are pressed at the
- * moment when we fail to obtain a valid context we schedule the entire
- * view for a redraw rather than just the clipping region. The purpose
- * of this is to make sure that scrollbars get updated correctly.
+ * We can only draw into the NSView which is the current focusView.
+ * When the current [NSView focusView] is nil, the CGContext for
+ * [NSGraphicsContext currentContext] is nil. Otherwise the current
+ * CGContext draws into the current focusView. An NSView is guaranteed
+ * to be the focusView when its drawRect or setFrame methods are
+ * running. Prior to OSX 10.14 it was also possible to call the
+ * lockFocus method to force an NSView to become the current focusView.
+ * But that method was deprecated in 10.14 and so is no longer used by
+ * Tk. Instead, if the view is not the current focusView then we add
+ * the drawing bounds to its dirty rectangle and return false. The
+ * part of the view inside the drawing bounds will get redrawn during
+ * the next call to its drawRect method.
*/
- if (![NSApp isDrawing] || view != [NSView focusView]) {
- NSRect bounds = [view bounds];
- NSRect dirtyNS = bounds;
- if ([NSEvent pressedMouseButtons]) {
- [view setNeedsDisplay:YES];
- } else {
- CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
- .ty = dirtyNS.size.height};
- if (dc.clipRgn) {
- CGRect dirtyCG = NSRectToCGRect(dirtyNS);
- HIShapeGetBounds(dc.clipRgn, &dirtyCG);
- dirtyNS = NSRectToCGRect(CGRectApplyAffineTransform(dirtyCG, t));
- }
- [view setNeedsDisplayInRect:dirtyNS];
- }
+ if (view != [NSView focusView]) {
+ [view addTkDirtyRect:drawingBounds];
canDraw = false;
goto end;
}
- dc.view = view;
- dc.context = GET_CGCONTEXT;
- dc.portBounds = NSRectToCGRect([view bounds]);
- if (dc.clipRgn) {
- clipBounds = CGContextGetClipBoundingBox(dc.context);
+ /*
+ * Drawing will also fail when the view is the current focusView but
+ * the clipping rectangle set by drawRect does not contain the clipping
+ * region of our drawing context. (See bug [2a61eca3a8].) If part of
+ * the drawing bounds will be clipped then we draw whatever we can, but
+ * we also add the drawing bounds to the view's dirty rectangle so it
+ * will get redrawn in the next call to its drawRect method.
+ */
+
+ currentBounds = CGContextGetClipBoundingBox(dc.context);
+ if (!NSContainsRect(currentBounds, drawingBounds)) {
+ [view addTkDirtyRect:drawingBounds];
}
- } else {
- Tcl_Panic("TkMacOSXSetupDrawingContext(): "
- "no context to draw into !");
}
/*
- * Configure the drawing context.
+ * Finish configuring the drawing context.
*/
- if (dc.context) {
- CGAffineTransform t = {
- .a = 1, .b = 0,
- .c = 0, .d = -1,
- .tx = 0,
- .ty = dc.portBounds.size.height
- };
+ CGAffineTransform t = {
+ .a = 1, .b = 0,
+ .c = 0, .d = -1,
+ .tx = 0,
+ .ty = dc.portBounds.size.height
+ };
+
+ dc.portBounds.origin.x += macDraw->xOff;
+ dc.portBounds.origin.y += macDraw->yOff;
+ CGContextSaveGState(dc.context);
+ CGContextSetTextDrawingMode(dc.context, kCGTextFill);
+ CGContextConcatCTM(dc.context, t);
+ if (dc.clipRgn) {
- dc.portBounds.origin.x += macDraw->xOff;
- dc.portBounds.origin.y += macDraw->yOff;
- CGContextSaveGState(dc.context);
- CGContextSetTextDrawingMode(dc.context, kCGTextFill);
- CGContextConcatCTM(dc.context, t);
- if (dc.clipRgn) {
#ifdef TK_MAC_DEBUG_DRAWING
- CGContextSaveGState(dc.context);
- ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
- CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.1);
- CGContextEOFillPath(dc.context);
- CGContextRestoreGState(dc.context);
+ CGContextSaveGState(dc.context);
+ ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
+ CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.1);
+ CGContextEOFillPath(dc.context);
+ CGContextRestoreGState(dc.context);
#endif /* TK_MAC_DEBUG_DRAWING */
- CGRect r;
- if (!HIShapeIsRectangular(dc.clipRgn) || !CGRectContainsRect(
- *HIShapeGetBounds(dc.clipRgn, &r),
- CGRectApplyAffineTransform(clipBounds, t))) {
- ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
- CGContextEOClip(dc.context);
- }
+ CGRect r;
+ CGRect b = CGRectApplyAffineTransform(
+ CGContextGetClipBoundingBox(dc.context), t);
+ if (!HIShapeIsRectangular(dc.clipRgn) ||
+ !CGRectContainsRect(*HIShapeGetBounds(dc.clipRgn, &r), b)) {
+ ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
+ CGContextEOClip(dc.context);
}
- if (gc) {
- static const CGLineCap cgCap[] = {
- [CapNotLast] = kCGLineCapButt,
- [CapButt] = kCGLineCapButt,
- [CapRound] = kCGLineCapRound,
- [CapProjecting] = kCGLineCapSquare,
- };
- static const CGLineJoin cgJoin[] = {
- [JoinMiter] = kCGLineJoinMiter,
- [JoinRound] = kCGLineJoinRound,
- [JoinBevel] = kCGLineJoinBevel,
- };
- bool shouldAntialias;
- double w = gc->line_width;
-
- TkMacOSXSetColorInContext(gc, gc->foreground, dc.context);
- if (win) {
- CGContextSetPatternPhase(dc.context, CGSizeMake(
- dc.portBounds.size.width, dc.portBounds.size.height));
- }
- if (gc->function != GXcopy) {
- TkMacOSXDbgMsg("Logical functions other than GXcopy are "
- "not supported for CG drawing!");
- }
+ }
+ if (gc) {
+ static const CGLineCap cgCap[] = {
+ [CapNotLast] = kCGLineCapButt,
+ [CapButt] = kCGLineCapButt,
+ [CapRound] = kCGLineCapRound,
+ [CapProjecting] = kCGLineCapSquare,
+ };
+ static const CGLineJoin cgJoin[] = {
+ [JoinMiter] = kCGLineJoinMiter,
+ [JoinRound] = kCGLineJoinRound,
+ [JoinBevel] = kCGLineJoinBevel,
+ };
+ bool shouldAntialias = !notAA(gc->line_width);
+ double w = gc->line_width;
+
+ TkMacOSXSetColorInContext(gc, gc->foreground, dc.context);
+ if (view) {
+ CGContextSetPatternPhase(dc.context, CGSizeMake(
+ dc.portBounds.size.width, dc.portBounds.size.height));
+ }
+ if (gc->function != GXcopy) {
+ TkMacOSXDbgMsg("Logical functions other than GXcopy are "
+ "not supported for CG drawing!");
+ }
+ if (!shouldAntialias) {
/*
- * When should we antialias?
+ * Make non-antialiased CG drawing look more like X11.
*/
- shouldAntialias = !notAA(gc->line_width);
- if (!shouldAntialias) {
- /*
- * Make non-antialiased CG drawing look more like X11.
- */
-
- w -= (gc->line_width ? NON_AA_CG_OFFSET : 0);
- }
- CGContextSetShouldAntialias(dc.context, shouldAntialias);
- CGContextSetLineWidth(dc.context, w);
- if (gc->line_style != LineSolid) {
- int num = 0;
- char *p = &gc->dashes;
- CGFloat dashOffset = gc->dash_offset;
- CGFloat lengths[10];
-
- while (p[num] != '\0' && num < 10) {
- lengths[num] = p[num];
- num++;
- }
- CGContextSetLineDash(dc.context, dashOffset, lengths, num);
- }
- if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {
- CGContextSetLineCap(dc.context,
- cgCap[(unsigned) gc->cap_style]);
- }
- if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) {
- CGContextSetLineJoin(dc.context,
- cgJoin[(unsigned) gc->join_style]);
+ w -= (gc->line_width ? NON_AA_CG_OFFSET : 0);
+ }
+ CGContextSetShouldAntialias(dc.context, shouldAntialias);
+ CGContextSetLineWidth(dc.context, w);
+ if (gc->line_style != LineSolid) {
+ int num = 0;
+ char *p = &gc->dashes;
+ CGFloat dashOffset = gc->dash_offset;
+ dashOffset -= (gc->line_width % 2) ? 0.5 : 0.0;
+ CGFloat lengths[10];
+
+ while (p[num] != '\0' && num < 10) {
+ lengths[num] = p[num];
+ num++;
}
+ CGContextSetLineDash(dc.context, dashOffset, lengths, num);
+ }
+ if ((unsigned) gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {
+ CGContextSetLineCap(dc.context, cgCap[(unsigned) gc->cap_style]);
+ }
+ if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) {
+ CGContextSetLineJoin(dc.context, cgJoin[(unsigned) gc->join_style]);
}
}
end:
+
#ifdef TK_MAC_DEBUG_DRAWING
if (!canDraw && win != NULL) {
TkWindow *winPtr = TkMacOSXGetTkWindow(win);
@@ -1769,6 +1430,7 @@ end:
}
}
#endif
+
if (!canDraw && dc.clipRgn) {
CFRelease(dc.clipRgn);
dc.clipRgn = NULL;
@@ -1830,7 +1492,7 @@ HIShapeRef
TkMacOSXGetClipRgn(
Drawable drawable) /* Drawable. */
{
- MacDrawable *macDraw = (MacDrawable *) drawable;
+ MacDrawable *macDraw = (MacDrawable *)drawable;
HIShapeRef clipRgn = NULL;
if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) {
@@ -1838,7 +1500,7 @@ TkMacOSXGetClipRgn(
#ifdef TK_MAC_DEBUG_DRAWING
TkMacOSXDbgMsg("%s", macDraw->winPtr->pathName);
- NSView *view = TkMacOSXDrawableView(macDraw);
+ NSView *view = TkMacOSXGetNSViewForDrawable(macDraw);
CGContextRef context = GET_CGCONTEXT;
CGContextSaveGState(context);
@@ -1862,30 +1524,6 @@ TkMacOSXGetClipRgn(
/*
*----------------------------------------------------------------------
*
- * TkMacOSXSetUpClippingRgn --
- *
- * Set up the clipping region so that drawing only occurs on the specified
- * X subwindow.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkMacOSXSetUpClippingRgn(
- Drawable drawable) /* Drawable to update. */
-{
- (void)drawable;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TkpClipDrawableToRect --
*
* Clip all drawing into the drawable d to the given rectangle. If width
@@ -1902,13 +1540,12 @@ TkMacOSXSetUpClippingRgn(
void
TkpClipDrawableToRect(
- Display *display,
+ TCL_UNUSED(Display *),
Drawable d,
int x, int y,
int width, int height)
{
- MacDrawable *macDraw = (MacDrawable *) d;
- (void)display;
+ MacDrawable *macDraw = (MacDrawable *)d;
if (macDraw->drawRgn) {
CFRelease(macDraw->drawRgn);
@@ -1955,10 +1592,10 @@ ClipToGC(
HIShapeRef *clipRgnPtr) /* must point to initialized variable */
{
if (gc && gc->clip_mask &&
- ((TkpClipMask *) gc->clip_mask)->type == TKP_CLIP_REGION) {
- Region gcClip = ((TkpClipMask *) gc->clip_mask)->value.region;
- int xOffset = ((MacDrawable *) d)->xOff + gc->clip_x_origin;
- int yOffset = ((MacDrawable *) d)->yOff + gc->clip_y_origin;
+ ((TkpClipMask *)gc->clip_mask)->type == TKP_CLIP_REGION) {
+ Region gcClip = ((TkpClipMask *)gc->clip_mask)->value.region;
+ int xOffset = ((MacDrawable *)d)->xOff + gc->clip_x_origin;
+ int yOffset = ((MacDrawable *)d)->yOff + gc->clip_y_origin;
HIShapeRef clipRgn = *clipRgnPtr, gcClipRgn;
XOffsetRegion(gcClip, xOffset, yOffset);
@@ -1994,12 +1631,9 @@ ClipToGC(
void *
TkMacOSXMakeStippleMap(
- Drawable drawable, /* Window to apply stipple. */
- Drawable stipple) /* The stipple pattern. */
+ TCL_UNUSED(Drawable), /* Window to apply stipple. */
+ TCL_UNUSED(Drawable)) /* The stipple pattern. */
{
- (void)drawable;
- (void)stipple;
-
return NULL;
}
diff --git a/macosx/tkMacOSXEmbed.c b/macosx/tkMacOSXEmbed.c
index 5afb408..f275815 100644
--- a/macosx/tkMacOSXEmbed.c
+++ b/macosx/tkMacOSXEmbed.c
@@ -43,11 +43,6 @@ typedef struct Container {
static Container *firstContainerPtr = NULL;
/* First in list of all containers managed by
* this process. */
-/*
- * Globals defined in this file:
- */
-
-TkMacOSXEmbedHandler *tkMacOSXEmbedHandler = NULL;
/*
* Prototypes for static procedures defined in this file:
@@ -66,42 +61,6 @@ static void EmbedWindowDeleted(TkWindow *winPtr);
/*
*----------------------------------------------------------------------
*
- * Tk_MacOSXSetEmbedHandler --
- *
- * Registers a handler for an in process form of embedding, like Netscape
- * plugins, where Tk is loaded into the process, but does not control the
- * main window
- *
- * Results:
- * None
- *
- * Side effects:
- * The embed handler is set.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tk_MacOSXSetEmbedHandler(
- Tk_MacOSXEmbedRegisterWinProc *registerWinProc,
- Tk_MacOSXEmbedGetGrafPortProc *getPortProc,
- Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc,
- Tk_MacOSXEmbedGetClipProc *getClipProc,
- Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc)
-{
- if (tkMacOSXEmbedHandler == NULL) {
- tkMacOSXEmbedHandler = (TkMacOSXEmbedHandler *)ckalloc(sizeof(TkMacOSXEmbedHandler));
- }
- tkMacOSXEmbedHandler->registerWinProc = registerWinProc;
- tkMacOSXEmbedHandler->getPortProc = getPortProc;
- tkMacOSXEmbedHandler->containerExistProc = containerExistProc;
- tkMacOSXEmbedHandler->getClipProc = getClipProc;
- tkMacOSXEmbedHandler->getOffsetProc = getOffsetProc;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TkpMakeWindow --
*
* Creates an X Window (Mac subwindow).
@@ -447,7 +406,7 @@ TkMacOSXContainerId(
for (containerPtr = firstContainerPtr; containerPtr != NULL;
containerPtr = containerPtr->nextPtr) {
if (containerPtr->embeddedPtr == winPtr) {
- return (MacDrawable *) containerPtr->parent;
+ return (MacDrawable *)containerPtr->parent;
}
}
Tcl_Panic("TkMacOSXContainerId couldn't find window");
@@ -859,7 +818,7 @@ ContainerEventProc(
* Here we are following unix, by destroying the container.
*/
- Tk_DestroyWindow((Tk_Window) winPtr);
+ Tk_DestroyWindow((Tk_Window)winPtr);
}
Tk_DeleteErrorHandler(errHandler);
}
@@ -908,8 +867,8 @@ EmbedStructureProc(
errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
-1, -1, NULL, NULL);
- Tk_MoveResizeWindow((Tk_Window) containerPtr->embeddedPtr, 0, 0,
- (unsigned) Tk_Width((Tk_Window) containerPtr->parentPtr),
+ Tk_MoveResizeWindow((Tk_Window)containerPtr->embeddedPtr, 0, 0,
+ (unsigned) Tk_Width((Tk_Window)containerPtr->parentPtr),
(unsigned) Tk_Height((Tk_Window)containerPtr->parentPtr));
Tk_DeleteErrorHandler(errHandler);
}
@@ -1054,10 +1013,8 @@ EmbedGeometryRequest(
* if the window's size didn't change then generate a configure event.
*/
- Tk_GeometryRequest((Tk_Window) winPtr, width, height);
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {
- /* Empty loop body. */
- }
+ Tk_GeometryRequest((Tk_Window)winPtr, width, height);
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_TIMER_EVENTS|TCL_DONT_WAIT)) {}
if ((winPtr->changes.width != width)
|| (winPtr->changes.height != height)) {
EmbedSendConfigure(containerPtr);
diff --git a/macosx/tkMacOSXEntry.c b/macosx/tkMacOSXEntry.c
index 7915f6f..75cd198 100644
--- a/macosx/tkMacOSXEntry.c
+++ b/macosx/tkMacOSXEntry.c
@@ -92,7 +92,7 @@ TkpDrawEntryBorderAndFocus(
GC bgGC;
Tk_Window tkwin = entryPtr->tkwin;
int oldWidth = 0;
- MacDrawable *macDraw = (MacDrawable *) d;
+ MacDrawable *macDraw = (MacDrawable *)d;
const HIThemeFrameDrawInfo info = {
.version = 0,
.kind = kHIThemeFrameTextFieldSquare,
@@ -155,7 +155,7 @@ TkpDrawEntryBorderAndFocus(
bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH;
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)) {
+ if (!TkMacOSXSetupDrawingContext(d, NULL, &dc)) {
/*
* No graphics context is available. If the widget is a Spinbox, we
@@ -208,7 +208,7 @@ TkpDrawSpinboxButtons(
TkMacOSXDrawingContext dc;
XRectangle rects[1];
GC bgGC;
- MacDrawable *macDraw = (MacDrawable *) d;
+ MacDrawable *macDraw = (MacDrawable *)d;
HIThemeButtonDrawInfo info = {
.version = 0,
.adornment = kThemeAdornmentNone,
@@ -265,7 +265,7 @@ TkpDrawSpinboxButtons(
rects[0].height = Tk_Height(tkwin);
XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1);
- if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(d, NULL, &dc)) {
return 0;
}
ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c
index af68eb6..66ca964 100644
--- a/macosx/tkMacOSXEvent.c
+++ b/macosx/tkMacOSXEvent.c
@@ -104,47 +104,26 @@ enum {
return processedEvent;
}
@end
-
#pragma mark -
-
-/*
- *----------------------------------------------------------------------
- *
- * XSync --
- *
- * This routine is a stub called 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 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: Processes all pending idle events then calls the display
- * method of each visible window.
- *
- *----------------------------------------------------------------------
- */
-
int
XSync(
Display *display,
- Bool discard)
+ TCL_UNUSED(Bool))
{
- (void)discard;
+ /*
+ * The main use of XSync is by the update command, which alternates
+ * between running an event loop to process all events without waiting and
+ * calling XSync on all displays until no events are left. There is
+ * nothing for the mac to do with respect to syncing its one display but
+ * it can (and, during regression testing, frequently does) happen that
+ * timer events fire during the event loop. Processing those here seems
+ * to make the update command work in a way that is more consistent with
+ * its behavior on other platforms.
+ */
- if (display) {
- display->request++;
- }
- if (Tk_GetNumMainWindows() != 0) {
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
- for (NSWindow *w in [NSApp orderedWindows]) {
- [w display];
- }
- }
- return Success;
+ while (Tcl_DoOneEvent(TCL_TIMER_EVENTS|TCL_DONT_WAIT)){}
+ display->request++;
+ return 0;
}
/*
diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c
index 7527429..6c66ed8 100644
--- a/macosx/tkMacOSXFont.c
+++ b/macosx/tkMacOSXFont.c
@@ -93,10 +93,6 @@ static void InitFont(NSFont *nsFont,
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:
@@ -455,7 +451,7 @@ TkpFontPkgInit(
TkMainInfo *mainPtr) /* The application being created. */
{
Tcl_Interp *interp = mainPtr->interp;
- Tk_Window tkwin = (Tk_Window) mainPtr->winPtr;
+ Tk_Window tkwin = (Tk_Window)mainPtr->winPtr;
const struct SystemFontMapEntry *systemFont = systemFontMap;
NSFont *nsFont;
TkFontAttributes fa;
@@ -554,13 +550,12 @@ TkpFontPkgInit(
TkFont *
TkpGetNativeFont(
- Tk_Window tkwin, /* For display where font will be used. */
+ TCL_UNUSED(Tk_Window), /* For display where font will be used. */
const char *name) /* Platform-specific font name. */
{
MacFont *fontPtr = NULL;
ThemeFontID themeFontId;
CTFontRef ctFont;
- (void)tkwin;
if (strcmp(name, SYSTEMFONT_NAME) == 0) {
themeFontId = kThemeSystemFont;
@@ -704,11 +699,10 @@ TkpDeleteFont(
void
TkpGetFontFamilies(
Tcl_Interp *interp, /* Interp to hold result. */
- Tk_Window tkwin) /* For display to query. */
+ TCL_UNUSED(Tk_Window)) /* For display to query. */
{
Tcl_Obj *resultPtr = Tcl_NewListObj(0, NULL);
NSArray *list = [[NSFontManager sharedFontManager] availableFontFamilies];
- (void)tkwin;
for (NSString *family in list) {
Tcl_ListObjAppendElement(NULL, resultPtr,
@@ -778,7 +772,7 @@ TkpGetSubFonts(
void
TkpGetFontAttrsForChar(
- Tk_Window tkwin, /* Window on the font's display */
+ TCL_UNUSED(Tk_Window), /* Window on the font's display */
Tk_Font tkfont, /* Font to query */
int c, /* Character of interest */
TkFontAttributes* faPtr) /* Output: Font attributes */
@@ -788,7 +782,6 @@ TkpGetFontAttrsForChar(
*faPtr = fontPtr->font.fa;
if (nsFont && ![[nsFont coveredCharacterSet] characterIsMember:c]) {
UTF16Char ch = (UTF16Char) c;
- (void)tkwin;
nsFont = [nsFont bestMatchingFontForCharacters:&ch
length:1 attributes:nil actualCoveredLength:NULL];
@@ -1066,7 +1059,7 @@ done:
* Draw a string of characters on the screen.
*
* With ATSUI we need the line context to do this right, so we have the
- * actual implementation in TkpDrawCharsInContext().
+ * actual implementation in TkpDrawAngledCharsInContext().
*
* Results:
* None.
@@ -1095,7 +1088,7 @@ Tk_DrawChars(
int x, int y) /* Coordinates at which to place origin of the
* string when drawing. */
{
- DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
+ TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes,
0, numBytes, x, y, 0.0);
}
@@ -1118,7 +1111,7 @@ TkDrawAngledChars(
* string when drawing. */
double angle) /* What angle to put text at, in degrees. */
{
- DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
+ TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes,
0, numBytes, x, y, angle);
}
@@ -1164,13 +1157,13 @@ TkpDrawCharsInContext(
* drawing. */
{
(void)display;
- DrawCharsInContext(display, drawable, gc, tkfont, source, numBytes,
+ TkpDrawAngledCharsInContext(display, drawable, gc, tkfont, source, numBytes,
rangeStart, rangeLength, x, y, 0.0);
}
-static void
-DrawCharsInContext(
- Display *display, /* Display on which to draw. */
+void
+TkpDrawAngledCharsInContext(
+ TCL_UNUSED(Display *), /* Display on which to draw. */
Drawable drawable, /* Window or pixmap in which to draw. */
GC gc, /* Graphics context for drawing characters. */
Tk_Font tkfont, /* Font in which characters will be drawn; must
@@ -1185,10 +1178,10 @@ DrawCharsInContext(
int numBytes, /* Number of bytes in string. */
int rangeStart, /* Index of first byte to draw. */
int rangeLength, /* Length of range to draw in bytes. */
- int x, int y, /* Coordinates at which to place origin of the
+ double x, double y, /* Coordinates at which to place origin of the
* whole (not just the range) string when
* drawing. */
- double angle)
+ double angle) /* What angle to put text at, in degrees. */
{
const MacFont *fontPtr = (const MacFont *) tkfont;
NSString *string;
@@ -1197,18 +1190,17 @@ DrawCharsInContext(
CTTypesetterRef typesetter;
CFIndex start, length;
CTLineRef line, full=nil;
- MacDrawable *macWin = (MacDrawable *) drawable;
+ MacDrawable *macWin = (MacDrawable *)drawable;
TkMacOSXDrawingContext drawingContext;
CGContextRef context;
CGColorRef fg;
NSFont *nsFont;
CGAffineTransform t;
CGFloat width, height, textX = (CGFloat) x, textY = (CGFloat) y;
- (void)display;
if (rangeStart < 0 || rangeLength <= 0 ||
rangeStart + rangeLength > numBytes ||
- !TkMacOSXSetupDrawingContext(drawable, gc, 1, &drawingContext)) {
+ !TkMacOSXSetupDrawingContext(drawable, gc, &drawingContext)) {
return;
}
string = [[TKNSString alloc] initWithTclUtfBytes:source length:numBytes];
@@ -1222,8 +1214,7 @@ DrawCharsInContext(
[attributes setObject:(id)fg forKey:(id)kCTForegroundColorAttributeName];
CFRelease(fg);
nsFont = [attributes objectForKey:NSFontAttributeName];
- [nsFont setInContext:[NSGraphicsContext graphicsContextWithGraphicsPort:
- context flipped:NO]];
+ [nsFont setInContext:GET_NSCONTEXT(context, NO)];
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
attributedString = [[NSAttributedString alloc] initWithString:string
attributes:attributes];
@@ -1336,12 +1327,9 @@ TkMacOSXNSFontAttributesForFont(
int
TkMacOSXIsCharacterMissing(
- Tk_Font tkfont, /* The font we are looking in. */
- unsigned int searchChar) /* The character we are looking for. */
+ TCL_UNUSED(Tk_Font), /* The font we are looking in. */
+ TCL_UNUSED(unsigned int)) /* The character we are looking for. */
{
- (void)tkfont;
- (void)searchChar;
-
return 0;
}
@@ -1380,7 +1368,7 @@ TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
objv[i++] = Tcl_NewStringObj(familyName, -1);
objv[i++] = Tcl_NewWideIntObj([nsFont pointSize]);
-#define S(s) Tcl_NewStringObj(STRINGIFY(s), (int)(sizeof(STRINGIFY(s))-1))
+#define S(s) Tcl_NewStringObj(STRINGIFY(s), (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)] &&
diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c
index e2ff0f1..f405a53 100644
--- a/macosx/tkMacOSXHLEvents.c
+++ b/macosx/tkMacOSXHLEvents.c
@@ -39,6 +39,7 @@ typedef struct AppleEventInfo {
const char *procedure;
Tcl_DString command;
NSAppleEventDescriptor *replyEvent; /* Only used for DoScriptText. */
+ int retryCount;
} AppleEventInfo;
/*
@@ -53,11 +54,11 @@ 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";
+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)
@@ -68,6 +69,11 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText";
[self handleQuitApplicationEvent:Nil withReplyEvent:Nil];
}
+- (void) superTerminate: (id) sender
+{
+ [super terminate:nil];
+}
+
- (void) preferences: (id) sender
{
(void)sender;
@@ -230,6 +236,13 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText";
AEInfo->procedure = openDocumentProc;
AEInfo->replyEvent = nil;
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
+ AEInfo->retryCount = 0;
+
+ if (Tcl_FindCommand(_eventInterp, "::tk::mac::OpenDocuments", NULL, 0)){
+ ProcessAppleEvent((ClientData)AEInfo);
+ } else {
+ Tcl_CreateTimerHandler(500, ProcessAppleEvent, (ClientData)AEInfo);
+ }
}
- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
@@ -249,6 +262,8 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText";
AEInfo->procedure = printDocProc;
AEInfo->replyEvent = nil;
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
+ AEInfo->retryCount = 0;
+ ProcessAppleEvent((ClientData)AEInfo);
}
- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
@@ -310,6 +325,8 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText";
AEInfo->procedure = scriptFileProc;
AEInfo->replyEvent = nil;
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
+ AEInfo->retryCount = 0;
+ ProcessAppleEvent((ClientData)AEInfo);
}
}
} else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
@@ -325,19 +342,22 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText";
if (noErr == AEGetParamPtr(theDesc, keyDirectObject,
typeUTF8Text, &type,
data, actual, NULL)) {
- AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo));
- Tcl_DString *scriptTextCommand = &AEInfo->command;
- Tcl_DStringInit(scriptTextCommand);
- Tcl_DStringAppend(scriptTextCommand, scriptTextProc, -1);
+ data[actual] = '\0';
+ AppleEventInfo *AEInfo = (AppleEventInfo *)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;
+ AEInfo->retryCount = 0;
if (Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
AEInfo->replyEvent = replyEvent;
- ProcessAppleEvent((ClientData)AEInfo);
+ ProcessAppleEvent(AEInfo);
} else {
AEInfo->replyEvent = nil;
- Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
+ Tcl_DoWhenIdle(ProcessAppleEvent, AEInfo);
+ ProcessAppleEvent(AEInfo);
}
}
}
@@ -361,6 +381,8 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText";
AEInfo->procedure = launchURLProc;
AEInfo->replyEvent = nil;
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
+ AEInfo->retryCount = 0;
+ ProcessAppleEvent((ClientData)AEInfo);
}
@end
@@ -395,15 +417,30 @@ static void ProcessAppleEvent(
{
int code;
AppleEventInfo *AEInfo = (AppleEventInfo*) clientData;
- if (!AEInfo->interp ||
- !Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
+
+ if (!AEInfo->interp) {
+ return;
+ }
+
+ /*
+ * Apple events that are delivered during the app startup can arrive
+ * before the Tcl procedure for handling the events has been defined.
+ * If the command is not found we create a timer handler to process
+ * the event later, hopefully after the command has been created.
+ * We retry up to 2 times before giving up.
+ */
+
+ if (!Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) {
+ if (AEInfo->retryCount < 2) {
+ AEInfo->retryCount++;
+ Tcl_CreateTimerHandler(200, ProcessAppleEvent, clientData);
+ } else {
+ ckfree(clientData);
+ }
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;
@@ -418,7 +455,10 @@ static void ProcessAppleEvent(
AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc],
keyErrorNumber, typeSInt32, (Ptr) &code, sizeof(int));
}
+ } else if (code != TCL_OK) {
+ Tcl_BackgroundException(AEInfo->interp, code);
}
+
Tcl_DStringFree(&AEInfo->command);
ckfree(clientData);
}
@@ -442,11 +482,10 @@ static void ProcessAppleEvent(
void
TkMacOSXInitAppleEvents(
- Tcl_Interp *dummy) /* not used */
+ TCL_UNUSED(Tcl_Interp *))
{
NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];
static Boolean initialized = FALSE;
- (void)dummy;
if (!initialized) {
initialized = TRUE;
@@ -553,14 +592,18 @@ TkMacOSXDoHLEvent(
static int
ReallyKillMe(
Tcl_Event *eventPtr,
- int flags)
+ TCL_UNUSED(int))
{
Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp;
int quit = Tcl_FindCommand(interp, "::tk::mac::Quit", NULL, 0)!=NULL;
- int code = Tcl_EvalEx(interp, quit ? "::tk::mac::Quit" : "exit", -1, TCL_EVAL_GLOBAL);
- (void)flags;
+ if (!quit) {
+ Tcl_Exit(0);
+ }
+
+ int code = Tcl_EvalEx(interp, "::tk::mac::Quit", -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
+
/*
* Should be never reached...
*/
diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c
index 07a20ac..0df23d9 100644
--- a/macosx/tkMacOSXImage.c
+++ b/macosx/tkMacOSXImage.c
@@ -6,7 +6,7 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
- * Copyright 2017-2018 Marc Culler.
+ * Copyright (c) 2017-2020 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -15,14 +15,16 @@
#include "tkMacOSXPrivate.h"
#include "xbytes.h"
+static CGImageRef CreateCGImageFromPixmap(Drawable pixmap);
+static CGImageRef CreateCGImageFromDrawableRect( Drawable drawable,
+ int x, int y, unsigned int width, unsigned int height);
+
#pragma mark XImage handling
int
_XInitImageFuncPtrs(
- XImage *image)
+ TCL_UNUSED(XImage *)) /* image */
{
- (void)image;
-
return 0;
}
@@ -43,10 +45,11 @@ _XInitImageFuncPtrs(
*----------------------------------------------------------------------
*/
-static void ReleaseData(void *info, const void *data, size_t size) {
- (void)data;
- (void)size;
-
+static void ReleaseData(
+ void *info,
+ TCL_UNUSED(const void *), /* data */
+ TCL_UNUSED(size_t)) /* size */
+{
ckfree(info);
}
@@ -136,142 +139,6 @@ TkMacOSXCreateCGImageWithXImage(
/*
*----------------------------------------------------------------------
*
- * XGetImage --
- *
- * This function copies data from a pixmap or window into an XImage. It
- * is essentially never used. At one time it was called by
- * pTkImgPhotoDisplay, but that is no longer the case. Currently it is
- * called two places, one of which is requesting an XY image which we do
- * not support. It probably does not work correctly -- see the comments
- * for TkMacOSXBitmapRepFromDrawableRect.
- *
- * Results:
- * Returns a newly allocated XImage containing the data from the given
- * rectangle of the given drawable, or NULL if the XImage could not be
- * constructed. NOTE: If we are copying from a window on a Retina
- * display, the dimensions of the XImage will be 2*width x 2*height.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-struct pixel_fmt {int r; int g; int b; int a;};
-static struct pixel_fmt bgra = {2, 1, 0, 3};
-static struct pixel_fmt abgr = {3, 2, 1, 0};
-
-XImage *
-XGetImage(
- Display *display,
- Drawable drawable,
- int x,
- int y,
- unsigned int width,
- unsigned int height,
- unsigned long plane_mask,
- int format)
-{
- NSBitmapImageRep* bitmap_rep = NULL;
- NSUInteger bitmap_fmt = 0;
- XImage* imagePtr = NULL;
- char* bitmap = NULL;
- char R, G, B, A;
- int depth = 32, offset = 0, bitmap_pad = 0;
- unsigned int bytes_per_row, size, row, n, m;
- unsigned int scalefactor=1, scaled_height=height, scaled_width=width;
- NSWindow *win = TkMacOSXDrawableWindow(drawable);
- static enum {unknown, no, yes} has_retina = unknown;
- (void)plane_mask;
-
- if (win && has_retina == unknown) {
-#ifdef __clang__
- 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.
- */
-
-#ifdef __clang__
- scalefactor = [win backingScaleFactor] == 2.0 ? 2 : 1;
-#endif
- scaled_height *= scalefactor;
- scaled_width *= scalefactor;
- }
-
- if (format == ZPixmap) {
- if (width == 0 || height == 0) {
- return NULL;
- }
-
- bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(drawable,
- x, y, width, height);
- if (!bitmap_rep) {
- TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
- return NULL;
- }
- bitmap_fmt = [bitmap_rep bitmapFormat];
- size = [bitmap_rep bytesPerPlane];
- bytes_per_row = [bitmap_rep bytesPerRow];
- bitmap = (char *)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) {
- TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
- CFRelease(bitmap_rep);
- return NULL;
- }
- memcpy(bitmap, (char *)[bitmap_rep bitmapData], size);
- 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.
- */
-
- struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr;
-
- for (row = 0, n = 0; row < scaled_height; row++, n += bytes_per_row) {
- for (m = n; m < n + 4*scaled_width; m += 4) {
- R = *(bitmap + m + pixel.r);
- G = *(bitmap + m + pixel.g);
- B = *(bitmap + m + pixel.b);
- A = *(bitmap + m + pixel.a);
-
- *(bitmap + m) = R;
- *(bitmap + m + 1) = G;
- *(bitmap + m + 2) = B;
- *(bitmap + m + 3) = A;
- }
- }
- imagePtr = XCreateImage(display, NULL, depth, format, offset,
- (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.
- */
- TkMacOSXDbgMsg("XGetImage does not handle XYPixmaps at the moment.");
- }
- return imagePtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* DestroyImage --
*
* Destroys storage associated with an image.
@@ -306,7 +173,11 @@ DestroyImage(
* Get a single pixel from an image.
*
* Results:
- * Returns the 32 bit pixel value.
+ * The XColor structure contains an unsigned long field named pixel which
+ * identifies the color. This function returns the unsigned long that
+ * would be used as the pixel value of an XColor that has the same red
+ * green and blue components as the XImage pixel at the specified
+ * location.
*
* Side effects:
* None.
@@ -322,13 +193,18 @@ ImageGetPixel(
{
unsigned char r = 0, g = 0, b = 0;
+ /*
+ * Compute 8 bit red green and blue values, which are passed as inputs to
+ * TkMacOSXRGBPixel to produce the pixel value.
+ */
+
if (image && image->data) {
unsigned char *srcPtr = ((unsigned char*) image->data)
+ (y * image->bytes_per_line)
+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);
switch (image->bits_per_pixel) {
- case 32:
+ case 32: /* 8 bits per channel */
r = (*((unsigned int*) srcPtr) >> 16) & 0xff;
g = (*((unsigned int*) srcPtr) >> 8) & 0xff;
b = (*((unsigned int*) srcPtr) ) & 0xff;
@@ -338,12 +214,12 @@ ImageGetPixel(
r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3];
}*/
break;
- case 16:
+ case 16: /* 5 bits per channel */
r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
break;
- case 8:
+ case 8: /* 2 bits per channel */
r = (*srcPtr << 2) & 0xc0;
g = (*srcPtr << 4) & 0xc0;
b = (*srcPtr << 6) & 0xc0;
@@ -351,7 +227,7 @@ ImageGetPixel(
g |= g >> 2 | g >> 4 | g >> 6;
b |= b >> 2 | b >> 4 | b >> 6;
break;
- case 4: {
+ case 4: { /* 1 bit per channel */
unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);
r = (c & 0x04) ? 0xff : 0;
@@ -359,12 +235,13 @@ ImageGetPixel(
b = (c & 0x01) ? 0xff : 0;
break;
}
- case 1:
+ case 1: /* Black-white bitmap. */
r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
break;
}
}
- return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b;
+
+ return TkMacOSXRGBPixel(r, g, b);
}
/*
@@ -446,7 +323,7 @@ ImagePutPixel(
XImage *
XCreateImage(
Display* display,
- Visual* visual,
+ TCL_UNUSED(Visual*), /* visual */
unsigned int depth,
int format,
int offset,
@@ -457,10 +334,9 @@ XCreateImage(
int bytes_per_line)
{
XImage *ximage;
- (void)visual;
display->request++;
- ximage = (XImage *)ckalloc(sizeof(XImage));
+ ximage = ckalloc(sizeof(XImage));
ximage->height = height;
ximage->width = width;
@@ -470,13 +346,6 @@ XCreateImage(
ximage->data = data;
ximage->obdata = NULL;
- /*
- * 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) {
ximage->bits_per_pixel = 32;
ximage->bitmap_unit = 32;
@@ -552,10 +421,10 @@ XPutImage(
unsigned int height) /* distination and source. */
{
TkMacOSXDrawingContext dc;
- MacDrawable *macDraw = (MacDrawable *) drawable;
+ MacDrawable *macDraw = (MacDrawable *)drawable;
display->request++;
- if (!TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(drawable, gc, &dc)) {
return BadDrawable;
}
if (dc.context) {
@@ -571,17 +440,8 @@ XPutImage(
}
if (img) {
- /*
- * 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);
+ srcRect = CGRectMake(src_x, src_y, width, height);
dstRect = CGRectMake(dest_x, dest_y, width, height);
TkMacOSXDrawCGImage(drawable, gc, dc.context,
img, gc->foreground, gc->background,
@@ -598,6 +458,454 @@ XPutImage(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * CreateCGImageFromDrawableRect
+ *
+ * Extract image data from a MacOSX drawable as a CGImage.
+ *
+ * This is only called by XGetImage and XCopyArea. The Tk core uses
+ * these functions on some platforms, but on macOS the core does not
+ * call them with a source drawable which is a window. Such calls are
+ * used only for double-buffered drawing. Since macOS defines the
+ * macro TK_NO_DOUBLE_BUFFERING, the generic code never calls XGetImage
+ * or XCopyArea on macOS. Nonetheless, these function are in the stubs
+ * table and therefore could be used by extensions.
+ *
+ * This implementation does not work correctly. Originally it relied on
+ * [NSBitmapImageRep initWithFocusedViewRect:view_rect] which was
+ * deprecated by Apple in OSX 10.14 and also required the use of other
+ * deprecated functions such as [NSView lockFocus]. Apple's suggested
+ * replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that
+ * is what is being used here. However, that method only works when the
+ * view has a valid CGContext, and a view is only guaranteed to have a
+ * valid context during a call to [NSView drawRect]. To further complicate
+ * matters, cacheDisplayInRect calls [NSView drawRect]. Essentially it is
+ * asking the view to draw a subrectangle of itself using a special
+ * graphics context which is linked to the BitmapImageRep. But our
+ * implementation of [NSView drawRect] does not allow recursive calls. If
+ * called recursively it returns immediately without doing any drawing.
+ * So the bottom line is that this function either returns a NULL pointer
+ * or a black image. To make it useful would require a significant amount
+ * of rewriting of the drawRect method. Perhaps the next release of OSX
+ * will include some more helpful ways of doing this.
+ *
+ * Results:
+ * Returns an NSBitmapRep representing the image of the given rectangle of
+ * the given drawable. This object is retained. The caller is responsible
+ * for releasing it.
+ *
+ * NOTE: The x,y coordinates should be relative to a coordinate system
+ * with origin at the top left, as used by XImage and CGImage, not bottom
+ * left as used by NSView.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+static CGImageRef
+CreateCGImageFromDrawableRect(
+ Drawable drawable,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ MacDrawable *mac_drawable = (MacDrawable *)drawable;
+ CGContextRef cg_context = NULL;
+ CGImageRef cg_image = NULL, result = NULL;
+ NSBitmapImageRep *bitmapRep = NULL;
+ NSView *view = NULL;
+ if (mac_drawable->flags & TK_IS_PIXMAP) {
+ /*
+ * This MacDrawable is a bitmap, so its view is NULL.
+ */
+
+ CGRect image_rect = CGRectMake(x, y, width, height);
+
+ cg_context = TkMacOSXGetCGContextForDrawable(drawable);
+ cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context);
+ if (cg_image) {
+ result = CGImageCreateWithImageInRect(cg_image, image_rect);
+ CGImageRelease(cg_image);
+ }
+ } else if (TkMacOSXGetNSViewForDrawable(mac_drawable) != NULL) {
+
+ /*
+ * Convert Tk top-left to NSView bottom-left coordinates.
+ */
+
+ int view_height = [view bounds].size.height;
+ NSRect view_rect = NSMakeRect(x + mac_drawable->xOff,
+ view_height - height - y - mac_drawable->yOff,
+ width, height);
+
+ /*
+ * Attempt to copy from the view to a bitmapImageRep. If the view does
+ * not have a valid CGContext, doing this will silently corrupt memory
+ * and make a big mess. So, in that case, we just return NULL.
+ */
+
+ if (view == [NSView focusView]) {
+ bitmapRep = [view bitmapImageRepForCachingDisplayInRect: view_rect];
+ [view cacheDisplayInRect:view_rect toBitmapImageRep:bitmapRep];
+ result = [bitmapRep CGImage];
+ CFRelease(bitmapRep);
+ } else {
+ TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap.");
+ result = NULL;
+ }
+ } else {
+ TkMacOSXDbgMsg("Invalid source drawable");
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateCGImageFromPixmap --
+ *
+ * Create a CGImage from an X Pixmap.
+ *
+ * Results:
+ * CGImage, release after use.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static CGImageRef
+CreateCGImageFromPixmap(
+ Drawable pixmap)
+{
+ CGImageRef img = NULL;
+ CGContextRef context = TkMacOSXGetCGContextForDrawable(pixmap);
+
+ if (context) {
+ img = CGBitmapContextCreateImage(context);
+ }
+ return img;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XGetImage --
+ *
+ * This function copies data from a pixmap or window into an XImage. It
+ * is essentially never used. At one time it was called by
+ * pTkImgPhotoDisplay, but that is no longer the case. Currently it is
+ * called two places, one of which is requesting an XY image which we do
+ * not support. It probably does not work correctly -- see the comments
+ * for CGImageFromDrawableRect.
+ *
+ * Results:
+ * Returns a newly allocated XImage containing the data from the given
+ * rectangle of the given drawable, or NULL if the XImage could not be
+ * constructed.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+struct pixel_fmt {int r; int g; int b; int a;};
+static struct pixel_fmt bgra = {2, 1, 0, 3};
+static struct pixel_fmt abgr = {3, 2, 1, 0};
+
+XImage *
+XGetImage(
+ Display *display,
+ Drawable drawable,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height,
+ TCL_UNUSED(unsigned long), /* plane_mask */
+ int format)
+{
+ NSBitmapImageRep* bitmapRep = NULL;
+ NSUInteger bitmap_fmt = 0;
+ XImage* imagePtr = NULL;
+ char* bitmap = NULL;
+ char R, G, B, A;
+ int depth = 32, offset = 0, bitmap_pad = 0;
+ unsigned int bytes_per_row, size, row, n, m;
+
+ if (format == ZPixmap) {
+ CGImageRef cgImage;
+ if (width == 0 || height == 0) {
+ return NULL;
+ }
+
+ cgImage = CreateCGImageFromDrawableRect(drawable, x, y, width, height);
+ if (cgImage) {
+ bitmapRep = [NSBitmapImageRep alloc];
+ [bitmapRep initWithCGImage:cgImage];
+ CFRelease(cgImage);
+ } else {
+ TkMacOSXDbgMsg("XGetImage: Failed to construct CGImage");
+ return NULL;
+ }
+ bitmap_fmt = [bitmapRep bitmapFormat];
+ size = [bitmapRep bytesPerPlane];
+ bytes_per_row = [bitmapRep bytesPerRow];
+ bitmap = ckalloc(size);
+ if (!bitmap
+ || (bitmap_fmt != 0 && bitmap_fmt != 1)
+ || [bitmapRep samplesPerPixel] != 4
+ || [bitmapRep isPlanar] != 0
+ || bytes_per_row < 4 * width
+ || size != bytes_per_row * height) {
+ TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
+ CFRelease(bitmapRep);
+ return NULL;
+ }
+ memcpy(bitmap, (char *)[bitmapRep bitmapData], size);
+ CFRelease(bitmapRep);
+
+ /*
+ * 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;
+
+ for (row = 0, n = 0; row < height; row++, n += bytes_per_row) {
+ for (m = n; m < n + 4*width; m += 4) {
+ R = *(bitmap + m + pixel.r);
+ G = *(bitmap + m + pixel.g);
+ B = *(bitmap + m + pixel.b);
+ A = *(bitmap + m + pixel.a);
+
+ *(bitmap + m) = R;
+ *(bitmap + m + 1) = G;
+ *(bitmap + m + 2) = B;
+ *(bitmap + m + 3) = A;
+ }
+ }
+ imagePtr = XCreateImage(display, NULL, depth, format, offset,
+ (char*) bitmap, width, height,
+ bitmap_pad, bytes_per_row);
+ } 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.
+ */
+ TkMacOSXDbgMsg("XGetImage does not handle XYPixmaps at the moment.");
+ }
+ return imagePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XCopyArea --
+ *
+ * Copies image data from one drawable to another.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Image data is moved from a window or bitmap to a second window or bitmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XCopyArea(
+ Display *display, /* Display. */
+ Drawable src, /* Source drawable. */
+ Drawable dst, /* Destination drawable. */
+ GC gc, /* GC to use. */
+ int src_x, /* X & Y, width & height */
+ int src_y, /* define the source rectangle */
+ unsigned int width, /* that will be copied. */
+ unsigned int height,
+ int dest_x, /* Dest X & Y on dest rect. */
+ int dest_y)
+{
+ TkMacOSXDrawingContext dc;
+ MacDrawable *srcDraw = (MacDrawable *)src;
+ CGImageRef img = NULL;
+ CGRect bounds, srcRect, dstRect;
+
+ display->request++;
+ if (!width || !height) {
+ return BadDrawable;
+ }
+
+ if (!TkMacOSXSetupDrawingContext(dst, gc, &dc)) {
+ TkMacOSXDbgMsg("Failed to setup drawing context.");
+ return BadDrawable;
+ }
+
+ if (!dc.context) {
+ TkMacOSXDbgMsg("Invalid destination drawable - no context.");
+ return BadDrawable;
+ }
+
+ if (srcDraw->flags & TK_IS_PIXMAP) {
+ img = CreateCGImageFromPixmap(src);
+ } else if (TkMacOSXGetNSWindowForDrawable(src)) {
+ img = CreateCGImageFromDrawableRect(src, src_x, src_y, width, height);
+ } else {
+ TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
+ }
+
+ if (img) {
+ bounds = CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height);
+ srcRect = CGRectMake(src_x, src_y, width, height);
+ dstRect = CGRectMake(dest_x, dest_y, width, height);
+ TkMacOSXDrawCGImage(dst, gc, dc.context, img,
+ gc->foreground, gc->background, bounds, srcRect, dstRect);
+ CFRelease(img);
+ } else {
+ TkMacOSXDbgMsg("Failed to construct CGImage.");
+ }
+
+ TkMacOSXRestoreDrawingContext(&dc);
+ return Success;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XCopyPlane --
+ *
+ * Copies a bitmap from a source drawable to a destination drawable. The
+ * plane argument specifies which bit plane of the source contains the
+ * bitmap. Note that this implementation ignores the gc->function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the destination drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+XCopyPlane(
+ Display *display, /* Display. */
+ Drawable src, /* Source drawable. */
+ Drawable dst, /* Destination drawable. */
+ GC gc, /* GC to use. */
+ int src_x, /* X & Y, width & height */
+ int src_y, /* define the source rectangle */
+ unsigned int width, /* that will be copied. */
+ unsigned int height,
+ int dest_x, /* Dest X & Y on dest rect. */
+ int dest_y,
+ unsigned long plane) /* Which plane to copy. */
+{
+ TkMacOSXDrawingContext dc;
+ MacDrawable *srcDraw = (MacDrawable *)src;
+ MacDrawable *dstDraw = (MacDrawable *)dst;
+ CGRect bounds, srcRect, dstRect;
+ display->request++;
+ if (!width || !height) {
+ /* TkMacOSXDbgMsg("Drawing of empty area requested"); */
+ return BadDrawable;
+ }
+ if (plane != 1) {
+ Tcl_Panic("Unexpected plane specified for XCopyPlane");
+ }
+ if (srcDraw->flags & TK_IS_PIXMAP) {
+ if (!TkMacOSXSetupDrawingContext(dst, gc, &dc)) {
+ return BadDrawable;
+ }
+
+ CGContextRef context = dc.context;
+
+ if (context) {
+ CGImageRef img = CreateCGImageFromPixmap(src);
+
+ if (img) {
+ TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
+ unsigned long imageBackground = gc->background;
+
+ if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP) {
+ srcRect = CGRectMake(src_x, src_y, width, height);
+ CGImageRef mask = CreateCGImageFromPixmap(
+ clipPtr->value.pixmap);
+ CGImageRef submask = CGImageCreateWithImageInRect(
+ img, srcRect);
+ CGRect rect = CGRectMake(dest_x, dest_y, width, height);
+
+ rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);
+ CGContextSaveGState(context);
+
+ /*
+ * Move the origin of the destination to top left.
+ */
+
+ CGContextTranslateCTM(context,
+ 0, rect.origin.y + CGRectGetMaxY(rect));
+ CGContextScaleCTM(context, 1, -1);
+
+ /*
+ * Fill with the background color, clipping to the mask.
+ */
+
+ CGContextClipToMask(context, rect, submask);
+ TkMacOSXSetColorInContext(gc, gc->background, dc.context);
+ CGContextFillRect(context, rect);
+
+ /*
+ * Fill with the foreground color, clipping to the
+ * intersection of img and mask.
+ */
+
+ CGImageRef subimage = CGImageCreateWithImageInRect(
+ img, srcRect);
+ CGContextClipToMask(context, rect, subimage);
+ TkMacOSXSetColorInContext(gc, gc->foreground, context);
+ CGContextFillRect(context, rect);
+ CGContextRestoreGState(context);
+ CGImageRelease(img);
+ CGImageRelease(mask);
+ CGImageRelease(submask);
+ CGImageRelease(subimage);
+ } else {
+ bounds = CGRectMake(0, 0,
+ srcDraw->size.width, srcDraw->size.height);
+ srcRect = CGRectMake(src_x, src_y, width, height);
+ dstRect = CGRectMake(dest_x, dest_y, width, height);
+ TkMacOSXDrawCGImage(dst, gc, dc.context, img,
+ gc->foreground, imageBackground, bounds,
+ srcRect, dstRect);
+ CGImageRelease(img);
+ }
+ } else {
+ /* no image */
+ TkMacOSXDbgMsg("Invalid source drawable");
+ }
+ } else {
+ TkMacOSXDbgMsg("Invalid destination drawable - "
+ "could not get a bitmap context.");
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+ return Success;
+ } else {
+ /*
+ * Source drawable is a Window, not a Pixmap.
+ */
+
+ return XCopyArea(display, src, dst, gc, src_x, src_y, width, height,
+ dest_x, dest_y);
+ }
+}
+
+/*
* Local Variables:
* mode: objc
* c-basic-offset: 4
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index 881fb1b..06ff367 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -14,10 +14,9 @@
*/
#include "tkMacOSXPrivate.h"
-
-#include <sys/stat.h>
#include <dlfcn.h>
#include <objc/objc-auto.h>
+#include <sys/stat.h>
static char tkLibPath[PATH_MAX + 1] = "";
@@ -39,8 +38,9 @@ static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip,
@implementation TKApplication
@synthesize poolLock = _poolLock;
-@synthesize macMinorVersion = _macMinorVersion;
+@synthesize macOSVersion = _macOSVersion;
@synthesize isDrawing = _isDrawing;
+@synthesize needsToDraw = _needsToDraw;
@end
/*
@@ -113,6 +113,7 @@ static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip,
/*
* Initialize event processing.
*/
+
TkMacOSXInitAppleEvents(_eventInterp);
/*
@@ -144,7 +145,7 @@ static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip,
*/
[NSApp _lockAutoreleasePool];
- while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
+ while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}
[NSApp _unlockAutoreleasePool];
}
@@ -164,15 +165,18 @@ static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip,
/*
* Record the OS version we are running on.
*/
- int minorVersion;
+
+ int minorVersion, majorVersion;
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000
Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion);
+ majorVersion = 10;
#else
NSOperatingSystemVersion systemVersion;
systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
+ majorVersion = systemVersion.majorVersion;
minorVersion = systemVersion.minorVersion;
#endif
- [NSApp setMacMinorVersion: minorVersion];
+ [NSApp setMacOSVersion: 10000*majorVersion + 100*minorVersion];
/*
* We are not drawing right now.
@@ -267,6 +271,80 @@ static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip,
*----------------------------------------------------------------------
*/
+/*
+ * Helper function which closes the shared NSFontPanel and NSColorPanel.
+ */
+
+static void closePanels(
+ void)
+{
+ if ([NSFontPanel sharedFontPanelExists]) {
+ [[NSFontPanel sharedFontPanel] orderOut:nil];
+ }
+ if ([NSColorPanel sharedColorPanelExists]) {
+ [[NSColorPanel sharedColorPanel] orderOut:nil];
+ }
+}
+
+/*
+ * This custom exit procedure is called by Tcl_Exit in place of the exit
+ * function from the C runtime. It calls the terminate method of the
+ * NSApplication class (superTerminate for a TKApplication). The purpose of
+ * doing this is to ensure that the NSFontPanel and the NSColorPanel are closed
+ * before the process exits, and that the application state is recorded
+ * correctly for all termination scenarios.
+ *
+ * TkpWantsExitProc tells Tcl_AppInit whether to install our custom exit proc,
+ * which terminates the process by calling [NSApplication terminate]. This
+ * does not work correctly if the process is part of an exec pipeline, so it is
+ * only done if the process was launched by the launcher or if both stdin and
+ * stdout are ttys. To disable using the custom exit proc altogether, undefine
+ * USE_CUSTOM_EXIT_PROC.
+ */
+
+#if defined(USE_CUSTOM_EXIT_PROC)
+static Bool doCleanupFromExit = NO;
+
+int TkpWantsExitProc(void) {
+ return doCleanupFromExit == YES;
+}
+
+TCL_NORETURN void TkpExitProc(
+ void *clientdata)
+{
+ Bool doCleanup = doCleanupFromExit;
+ if (doCleanupFromExit) {
+ doCleanupFromExit = NO; /* prevent possible recursive call. */
+ closePanels();
+ }
+
+ /*
+ * Tcl_Exit does not call Tcl_Finalize if there is an exit proc installed.
+ */
+
+ Tcl_Finalize();
+ if (doCleanup == YES) {
+ [(TKApplication *)NSApp superTerminate:nil]; /* Should not return. */
+ }
+ exit((long)clientdata); /* Convince the compiler that we don't return. */
+}
+#endif
+
+/*
+ * This signal handler is installed for the SIGINT, SIGHUP and SIGTERM signals
+ * so that normal finalization occurs when a Tk app is killed by one of these
+ * signals (e.g when ^C is pressed while running Wish in the shell). It calls
+ * Tcl_Exit instead of the C runtime exit function called by the default handler.
+ * This is consistent with the Tcl_Exit manual page, which says that Tcl_Exit
+ * should always be called instead of exit. When Tk is killed by a signal we
+ * return exit status 1.
+ */
+
+static void TkMacOSXSignalHandler(TCL_UNUSED(int)) {
+
+ Tcl_Exit(1);
+}
+
int
TkpInit(
Tcl_Interp *interp)
@@ -274,15 +352,15 @@ TkpInit(
static int initialized = 0;
/*
- * Since it is possible for TkInit to be called multiple times and we
- * don't want to do the following initialization multiple times we protect
- * against doing it more than once.
+ * TkpInit can be called multiple times with different interpreters. But
+ * The application initialization should only be done onece.
*/
if (!initialized) {
struct stat st;
-
- initialized = 1;
+ Bool shouldOpenConsole = NO;
+ Bool stdinIsNullish = (!isatty(0) &&
+ (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0)));
/*
* Initialize/check OS version variable for runtime checks.
@@ -292,7 +370,10 @@ TkpInit(
# error Mac OS X 10.6 required
#endif
+ initialized = 1;
+
#ifdef TK_FRAMEWORK
+
/*
* When Tk is in a framework, force tcl_findLibrary to look in the
* framework scripts directory.
@@ -309,16 +390,6 @@ TkpInit(
#endif
/*
- * FIXME: Close stdin & stdout for remote debugging otherwise we will
- * fight with gdb for stdin & stdout
- */
-
- if (getenv("XCNOSTDIN") != NULL) {
- close(0);
- close(1);
- }
-
- /*
* Instantiate our NSApplication object. This needs to be done before
* we check whether to open a console window.
*/
@@ -333,20 +404,20 @@ TkpInit(
nil]];
[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.
+ * WARNING: The finishLaunching method runs asynchronously. 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 handled in
+ * tkMacOSXHLEvents.c by scheduling a timer event to handle the
+ * ApplEvent later, after the required procedure has been defined.
*/
+ [NSApp _setup:interp];
[NSApp finishLaunching];
/*
@@ -373,36 +444,60 @@ TkpInit(
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
- * clicking Wish) then use the Tk based console interpreter.
+ * Decide whether to open a console window. If the TK_CONSOLE
+ * environment variable is not defined we only show the console if
+ * stdin is not a tty and there is no startup script.
*/
- if (getenv("TK_CONSOLE") ||
- (!isatty(0) && (fstat(0, &st) ||
- (S_ISCHR(st.st_mode) && st.st_blocks == 0)))) {
+ if (getenv("TK_CONSOLE")) {
+ shouldOpenConsole = YES;
+ } else if (stdinIsNullish && Tcl_GetStartupScript(NULL) == NULL) {
+ const char *intvar = Tcl_GetVar2(interp, "tcl_interactive",
+ NULL, TCL_GLOBAL_ONLY);
+ if (intvar == NULL) {
+ Tcl_SetVar2(interp, "tcl_interactive", NULL, "1",
+ TCL_GLOBAL_ONLY);
+ }
+
+#if defined(USE_CUSTOM_EXIT_PROC)
+ doCleanupFromExit = YES;
+#endif
+
+ shouldOpenConsole = YES;
+ }
+ if (shouldOpenConsole) {
Tk_InitConsoleChannels(interp);
Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN));
Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT));
Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR));
+ if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ } else if (stdinIsNullish) {
/*
- * Only show the console if we don't have a startup script and
- * tcl_interactive hasn't been set already.
+ * When launched as a macOS application with no console,
+ * redirect stderr and stdout to /dev/null. This avoids waiting
+ * forever for those files to become writable if the underlying
+ * Tcl program tries to write to them with a puts command.
*/
- if (Tcl_GetStartupScript(NULL) == NULL) {
- const char *intvar = Tcl_GetVar2(interp,
- "tcl_interactive", NULL, TCL_GLOBAL_ONLY);
+ FILE *null = fopen("/dev/null", "w");
+ dup2(fileno(null), STDOUT_FILENO);
+ dup2(fileno(null), STDERR_FILENO);
+#if defined(USE_CUSTOM_EXIT_PROC)
+ doCleanupFromExit = YES;
+#endif
+ }
- if (intvar == NULL) {
- Tcl_SetVar2(interp, "tcl_interactive", NULL, "1",
- TCL_GLOBAL_ONLY);
- }
- }
- if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {
- return TCL_ERROR;
- }
+ /*
+ * FIXME: Close stdin & stdout for remote debugging if XCNOSTDIN is
+ * set. Otherwise we will fight with gdb for stdin & stdout
+ */
+
+ if (getenv("XCNOSTDIN") != NULL) {
+ close(0);
+ close(1);
}
/*
@@ -412,8 +507,46 @@ TkpInit(
*/
TkMacOSXServices_Init(interp);
+
+ /*
+ * The root window has been created and mapped, but XMapWindow deferred its
+ * call to makeKeyAndOrderFront because the first call to XMapWindow
+ * occurs too early in the initialization process for that. Process idle
+ * tasks now, so the root window is configured, then order it front.
+ */
+
+ while(Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {};
+ for (NSWindow *window in [NSApp windows]) {
+ TkWindow *winPtr = TkMacOSXGetTkWindow(window);
+ if (winPtr && Tk_IsMapped(winPtr)) {
+ [window makeKeyAndOrderFront:NSApp];
+ break;
+ }
+ }
+
+# if defined(USE_CUSTOM_EXIT_PROC)
+
+ if ((isatty(0) && isatty(1))) {
+ doCleanupFromExit = YES;
+ }
+
+# endif
+
+ /*
+ * Install a signal handler for SIGINT, SIGHUP and SIGTERM which uses
+ * Tcl_Exit instead of exit so that normal cleanup takes place if a TK
+ * application is killed with one of these signals.
+ */
+
+ signal(SIGINT, TkMacOSXSignalHandler);
+ signal(SIGHUP, TkMacOSXSignalHandler);
+ signal(SIGTERM, TkMacOSXSignalHandler);
}
+ /*
+ * Initialization steps that are needed for all interpreters.
+ */
+
if (tkLibPath[0] != '\0') {
Tcl_SetVar2(interp, "tk_library", NULL, tkLibPath, TCL_GLOBAL_ONLY);
}
@@ -429,6 +562,7 @@ TkpInit(
TkMacOSXIconBitmapObjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath",
TkMacOSXGetAppPathCmd, NULL, NULL);
+
return TCL_OK;
}
@@ -487,13 +621,11 @@ TkpGetAppName(
static int
TkMacOSXGetAppPathCmd(
- ClientData dummy,
+ TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
- (void)dummy;
-
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
@@ -622,11 +754,10 @@ TkMacOSXDefaultStartupScript(void)
MODULE_SCOPE void*
TkMacOSXGetNamedSymbol(
- const char* module,
- const char* symbol)
+ TCL_UNUSED(const char *),
+ const char *symbol)
{
void *addr = dlsym(RTLD_NEXT, symbol);
- (void)module;
if (!addr) {
(void) dlerror(); /* Clear dlfcn error state */
diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h
index bd669c0..0380596 100644
--- a/macosx/tkMacOSXInt.h
+++ b/macosx/tkMacOSXInt.h
@@ -99,24 +99,6 @@ typedef struct TkWindowPrivate MacDrawable;
*/
/*
- * This structure is for handling Netscape-type in process
- * embedding where Tk does not control the top-level. It contains
- * various functions that are needed by Mac specific routines, like
- * TkMacOSXGetDrawablePort. The definitions of the function types
- * are in tkMacOSX.h.
- */
-
-typedef struct {
- Tk_MacOSXEmbedRegisterWinProc *registerWinProc;
- Tk_MacOSXEmbedGetGrafPortProc *getPortProc;
- Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc;
- Tk_MacOSXEmbedGetClipProc *getClipProc;
- Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc;
-} TkMacOSXEmbedHandler;
-
-MODULE_SCOPE TkMacOSXEmbedHandler *tkMacOSXEmbedHandler;
-
-/*
* GC CGColorRef cache for tkMacOSXColor.c
*/
@@ -180,7 +162,7 @@ MODULE_SCOPE void TkpFreeGCCache(GC gc);
#define TK_MACOSX_HANDLE_EVENT_IMMEDIATELY 1024
/*
- * Defines for tkTextDisp.c
+ * Defines for tkTextDisp.c and tkFont.c
*/
#define TK_LAYOUT_WITH_BASE_CHUNKS 1
@@ -196,10 +178,7 @@ MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x,
MODULE_SCOPE void TkpRetainRegion(Region r);
MODULE_SCOPE void TkpReleaseRegion(Region r);
MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
-MODULE_SCOPE Bool TkpAppIsDrawing(void);
-MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin);
-MODULE_SCOPE Bool TkTestLogDisplay(void);
-MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin);
+MODULE_SCOPE Bool TkTestLogDisplay(Drawable drawable);
/*
* Include the stubbed internal platform-specific API.
diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c
index cd369ed..6e4a764 100644
--- a/macosx/tkMacOSXKeyEvent.c
+++ b/macosx/tkMacOSXKeyEvent.c
@@ -51,7 +51,7 @@ static NSUInteger textInputModifiers;
#endif
NSWindow *w = [theEvent window];
TkWindow *winPtr = TkMacOSXGetTkWindow(w), *grabWinPtr, *focusWinPtr;
- Tk_Window tkwin = (Tk_Window) winPtr;
+ Tk_Window tkwin = (Tk_Window)winPtr;
NSEventType type = [theEvent type];
NSUInteger virtual = [theEvent keyCode];
NSUInteger modifiers = ([theEvent modifierFlags] &
@@ -83,7 +83,7 @@ static NSUInteger textInputModifiers;
if (winPtr->dispPtr->grabFlags || /* global grab */
grabWinPtr->mainPtr == winPtr->mainPtr){ /* same application */
winPtr =winPtr->dispPtr->focusPtr;
- tkwin = (Tk_Window) winPtr;
+ tkwin = (Tk_Window)winPtr;
}
}
@@ -255,12 +255,11 @@ static NSUInteger textInputModifiers;
*/
if (type == NSKeyDown && [theEvent isARepeat]) {
+
xEvent.xany.type = KeyRelease;
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
xEvent.xany.type = KeyPress;
}
- if (xEvent.xany.type == KeyPress) {
- }
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
return theEvent;
}
@@ -268,14 +267,8 @@ static NSUInteger textInputModifiers;
@implementation TKContentView
-
--(id)init {
- self = [super init];
- if (self) {
- _needsRedisplay = NO;
- }
- return self;
-}
+@synthesize tkDirtyRect = _tkDirtyRect;
+@synthesize tkNeedsDisplay = _tkNeedsDisplay;;
/*
* Implementation of the NSTextInputClient protocol.
@@ -293,7 +286,7 @@ static NSUInteger textInputModifiers;
XEvent xEvent;
NSString *str, *keystr, *lower;
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
- Tk_Window tkwin = (Tk_Window) winPtr;
+ Tk_Window tkwin = (Tk_Window)winPtr;
Bool sendingIMEText = NO;
str = ([aString isKindOfClass: [NSAttributedString class]]) ?
@@ -329,8 +322,8 @@ static NSUInteger textInputModifiers;
*/
if (repRange.location == 0) {
- Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
- TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
+ Tk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;
+ Tk_SendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
}
/*
@@ -403,7 +396,7 @@ static NSUInteger textInputModifiers;
replacementRange: (NSRange)repRange
{
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
- Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ Tk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;
NSString *temp;
NSString *str;
(void)selRange;
@@ -439,12 +432,12 @@ static NSUInteger textInputModifiers;
* Use our insertText method to display the marked text.
*/
- TkSendVirtualEvent(focusWin, "TkStartIMEMarkedText", NULL);
+ Tk_SendVirtualEvent(focusWin, "TkStartIMEMarkedText", NULL);
processingCompose = YES;
temp = [str copy];
[self insertText: temp replacementRange:repRange];
privateWorkingText = temp;
- TkSendVirtualEvent(focusWin, "TkEndIMEMarkedText", NULL);
+ Tk_SendVirtualEvent(focusWin, "TkEndIMEMarkedText", NULL);
}
- (BOOL)hasMarkedText
@@ -512,8 +505,8 @@ static NSUInteger textInputModifiers;
processingCompose = NO;
if (aSelector == @selector (deleteBackward:)) {
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
- Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
- TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
+ Tk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;
+ Tk_SendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
}
}
@@ -562,7 +555,6 @@ static NSUInteger textInputModifiers;
}
/* End of NSTextInputClient implementation. */
-@synthesize needsRedisplay = _needsRedisplay;
@end
@@ -588,7 +580,7 @@ static NSUInteger textInputModifiers;
privateWorkingText = nil;
processingCompose = NO;
if (composeWin) {
- TkSendVirtualEvent(composeWin, "TkClearIMEMarkedText", NULL);
+ Tk_SendVirtualEvent(composeWin, "TkClearIMEMarkedText", NULL);
}
}
}
@@ -709,8 +701,8 @@ XGrabKeyboard(
(void)time;
if (keyboardGrabWinPtr && captureWinPtr) {
- NSWindow *w = TkMacOSXDrawableWindow(grab_window);
- MacDrawable *macWin = (MacDrawable *) grab_window;
+ NSWindow *w = TkMacOSXGetNSWindowForDrawable(grab_window);
+ MacDrawable *macWin = (MacDrawable *)grab_window;
if (w && macWin->toplevel->winPtr == (TkWindow *) captureWinPtr) {
if (modalSession) {
@@ -788,7 +780,7 @@ TkMacOSXGetModalSession(void)
* This enables correct placement of the popups used for character
* selection by the NSTextInputClient. It gets called by text entry
* widgets whenever the cursor is drawn. It does nothing if the widget's
- * NSWindow is not the current KeyWindow. Otherwise it udpates the
+ * NSWindow is not the current KeyWindow. Otherwise it updates the
* display's caret structure and records the caret geometry in static
* variables for use by the NSTextInputClient implementation. Any
* widget passed to this function will be marked as being able to input
@@ -814,7 +806,7 @@ Tk_SetCaretPos(
{
TkWindow *winPtr = (TkWindow *) tkwin;
TkCaret *caretPtr = &(winPtr->dispPtr->caret);
- NSWindow *w = TkMacOSXDrawableWindow(Tk_WindowId(tkwin));
+ NSWindow *w = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));
/*
* Register this widget as being capable of text input, so we know we
diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c
index ca2a9e5..60d1d0d 100644
--- a/macosx/tkMacOSXKeyboard.c
+++ b/macosx/tkMacOSXKeyboard.c
@@ -489,13 +489,12 @@ XKeycodeToKeysym(
const char *
TkpGetString(
- TkWindow *winPtr, /* Window where event occurred: Needed to get
+ TCL_UNUSED(TkWindow *), /* Window where event occurred: Needed to get
* input context. */
XEvent *eventPtr, /* X keyboard event. */
Tcl_DString *dsPtr) /* Uninitialized or empty string to hold
* result. */
{
- (void) winPtr; /*unused*/
MacKeycode macKC;
char utfChars[8];
int length = 0;
@@ -588,19 +587,15 @@ XFreeModifiermap(
char *
XKeysymToString(
- KeySym keysym)
+ TCL_UNUSED(KeySym))
{
- (void)keysym;
-
return NULL;
}
KeySym
XStringToKeysym(
- const char* string)
+ TCL_UNUSED(const char *))
{
- (void)string;
-
return NoSymbol;
}
@@ -666,7 +661,7 @@ XKeysymToKeycode(
macKC.x.keychar = (unsigned int) data;
hPtr = Tcl_FindHashEntry(&unichar2xvirtual, INT2PTR(macKC.x.keychar));
if (hPtr != NULL) {
- unsigned long data = (unsigned long) Tcl_GetHashValue(hPtr);
+ data = (unsigned long) Tcl_GetHashValue(hPtr);
macKC.x.xvirtual = (unsigned int) data;
}
}
diff --git a/macosx/tkMacOSXKeysyms.h b/macosx/tkMacOSXKeysyms.h
index 726f318..da364ea 100644
--- a/macosx/tkMacOSXKeysyms.h
+++ b/macosx/tkMacOSXKeysyms.h
@@ -91,7 +91,7 @@ static const KeyInfo keyArray[] = {
{114, XK_Help, NSHelpFunctionKey},
{115, XK_Home, NSHomeFunctionKey}, /* Fn Left */
{116, XK_Page_Up, NSPageUpFunctionKey}, /* Fn Up */
- {117, XK_Delete, NSDeleteFunctionKey}, /* Fn Deleete */
+ {117, XK_Delete, NSDeleteFunctionKey}, /* Fn Delete */
{118, XK_F4, NSF4FunctionKey},
{119, XK_End, NSEndFunctionKey}, /* Fn Right */
{120, XK_F2, NSF2FunctionKey},
@@ -293,7 +293,7 @@ const KeysymInfo keysymTable[] = {
{0x00d5, 0x00d5}, /* Otilde */
{0x00d6, 0x00d6}, /* Odiaeresis */
{0x00d7, 0x00d7}, /* multiply */
- {0x00d8, 0x00d8}, /* Ooblique */
+ {0x00d8, 0x00d8}, /* Oslash */
{0x00d9, 0x00d9}, /* Ugrave */
{0x00da, 0x00da}, /* Uacute */
{0x00db, 0x00db}, /* Ucircumflex */
diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c
index 1ed9408..8970109 100644
--- a/macosx/tkMacOSXMenu.c
+++ b/macosx/tkMacOSXMenu.c
@@ -36,7 +36,7 @@
#define SPECIALMENU(n, f) {.name = "." #n, .len = sl(#n) + 1, \
.flag = ENTRY_##f##_MENU }
static const struct {
- const char *name; const size_t len; const int flag;
+ const char *name; size_t len; int flag;
} specialMenus[] = {
SPECIALMENU(help, HELP),
SPECIALMENU(apple, APPLE),
@@ -47,8 +47,8 @@ static const struct {
#define MODIFIER(n, f) {.name = #n, .len = sl(#n), .mask = f }
static const struct {
- const char *name; const size_t len; const NSUInteger mask;
-} modifiers[] = {
+ const char *name; size_t len; NSUInteger mask;
+} allModifiers[] = {
MODIFIER(Control, NSControlKeyMask),
MODIFIER(Ctrl, NSControlKeyMask),
MODIFIER(Option, NSAlternateKeyMask),
@@ -64,7 +64,7 @@ static const struct {
#define ACCEL(n, c) {.name = #n, .len = sl(#n), .ch = c }
static const struct {
- const char *name; const size_t len; const UniChar ch;
+ const char *name; size_t len; UniChar ch;
} specialAccelerators[] = {
ACCEL(PageUp, NSPageUpFunctionKey),
ACCEL(PageDown, NSPageDownFunctionKey),
@@ -91,11 +91,7 @@ static const struct {
#undef ACCEL
#undef sl
-static int gNoTkMenus = 0; /* This is used by Tk_MacOSXTurnOffMenus as
- * the flag that Tk is not to draw any
- * menus. */
static int inPostMenu = 0;
-static unsigned long defaultBg = 0, defaultFg = 0;
static SInt32 menuMarkColumnWidth = 0, menuIconTrailingEdgeMargin = 0;
static SInt32 menuTextLeadingEdgeMargin = 0, menuTextTrailingEdgeMargin = 0;
static SInt16 menuItemExtraHeight = 0, menuItemExtraWidth = 0;
@@ -108,6 +104,67 @@ static void MenuSelectEvent(TkMenu *menuPtr);
static void RecursivelyClearActiveMenu(TkMenu *menuPtr);
static int ModifierCharWidth(Tk_Font tkfont);
+#pragma mark TkBackgroundLoop
+
+/*
+ * The function TkMacOSXEventsCheckProc (in tkMacOSXNotify.c) is the "check
+ * proc" for the macOS event source. Its job is to remove NSEvents from the
+ * default event queue of the NSApplication. It does this by calling the
+ * method [NSApp nextEventMatchingMask: untilDate: inMode: dequeue:]. As a
+ * rule, when the untilDate is set to the distant past this method returns
+ * immediately. An exception to that rule is when the next event is the button
+ * press on a menu button. In that case, the method starts running a nested
+ * event loop in the mode NSEventTrackingRunLoopMode which does not return
+ * until the menu has been dismissed. In Tk 8.6.10 and earlier, this meant
+ * that the Tk event loop would block in its call to the check proc as long as
+ * the menu was posted. For example, opening a menu during the Rube Goldberg
+ * demo would cause the animation to stop. This was also the case for
+ * menubuttons.
+ *
+ * The TKBackground object below works around this problem, and allows a Tk
+ * event loop to run while a menu is open. It is a subclass of NSThread which
+ * inserts requests to call [NSApp _runBackgroundLoop] onto the queue
+ * associated with the NSEventTrackingRunLoopMode. One of these threads gets
+ * started in the callback [NSApp menuBeginTracking] and cancelled in [NSApp
+ * menuEndTracking].
+ */
+
+@interface TKBackgroundLoop: NSThread
+@end
+
+@implementation TKBackgroundLoop
+- (void) main
+{
+ NSAutoreleasePool *pool = [NSAutoreleasePool new];
+ NSArray *modeArray = [NSArray arrayWithObjects: NSEventTrackingRunLoopMode,
+ nil];
+ while(1) {
+
+ /*
+ * Queue a request to process Tk events during event tracking.
+ */
+
+ [NSApp performSelectorOnMainThread:@selector(_runBackgroundLoop)
+ withObject:nil
+ waitUntilDone:true
+ modes:modeArray];
+ if ([self isCancelled]) {
+ [NSThread exit];
+ }
+
+ /*
+ * Allow the tracked events to be processed too.
+ */
+
+ [NSThread sleepForTimeInterval:0.001];
+ }
+ [pool drain];
+}
+@end
+
+TKBackgroundLoop *backgroundLoop = nil;
+
+
#pragma mark TKMenu
/*
@@ -405,6 +462,12 @@ static int ModifierCharWidth(Tk_Font tkfont);
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
+ if (backgroundLoop) {
+ [backgroundLoop cancel];
+ [backgroundLoop release];
+ }
+ backgroundLoop = [[TKBackgroundLoop alloc] init];
+ [backgroundLoop start];
//TkMacOSXClearMenubarActive();
//TkMacOSXPreprocessMenu();
}
@@ -415,6 +478,11 @@ static int ModifierCharWidth(Tk_Font tkfont);
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
+ if (backgroundLoop) {
+ [backgroundLoop cancel];
+ [backgroundLoop release];
+ backgroundLoop = nil;
+ }
if (!inPostMenu) {
TkMacOSXClearMenubarActive();
}
@@ -422,10 +490,6 @@ static int ModifierCharWidth(Tk_Font tkfont);
- (void) tkSetMainMenu: (TKMenu *) menu
{
- if (gNoTkMenus) {
- return;
- }
-
TKMenu *applicationMenu = nil;
if (menu) {
@@ -624,12 +688,23 @@ TkpConfigureMenuEntry(
NSDictionary *attributes;
int imageWidth, imageHeight;
GC gc = (mePtr->textGC ? mePtr->textGC : mePtr->menuPtr->textGC);
- Tcl_Obj *fontPtr = (mePtr->fontPtr ? mePtr->fontPtr :
- mePtr->menuPtr->fontPtr);
+ Tcl_Obj *fontPtr = (mePtr->fontPtr ?
+ mePtr->fontPtr : mePtr->menuPtr->fontPtr);
+ static unsigned long defaultBg, defaultFg;
+ static int initialized = 0;
+
+ if (!initialized) {
+ TkColor *tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);
+ defaultBg = tkColPtr->color.pixel;
+ ckfree(tkColPtr);
+ tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);
+ defaultFg = tkColPtr->color.pixel;
+ ckfree(tkColPtr);
+ }
if (mePtr->image) {
Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight);
- image = TkMacOSXGetNSImageWithTkImage(mePtr->menuPtr->display,
+ image = TkMacOSXGetNSImageFromTkImage(mePtr->menuPtr->display,
mePtr->image, imageWidth, imageHeight);
} else if (mePtr->bitmapPtr != None) {
Pixmap bitmap = Tk_GetBitmapFromObj(mePtr->menuPtr->tkwin,
@@ -637,10 +712,9 @@ TkpConfigureMenuEntry(
Tk_SizeOfBitmap(mePtr->menuPtr->display, bitmap, &imageWidth,
&imageHeight);
- image = TkMacOSXGetNSImageWithBitmap(mePtr->menuPtr->display, bitmap,
+ image = TkMacOSXGetNSImageFromBitmap(mePtr->menuPtr->display, bitmap,
gc, imageWidth, imageHeight);
if (gc->foreground == defaultFg) {
- // Use a semantic foreground color by default
[image setTemplate:YES];
}
}
@@ -820,7 +894,7 @@ TkpPostMenu(
* rather than the appearance of the root window.
*/
realWinPtr = (TkWindow*) realWin;
- realWinView = TkMacOSXDrawableView(realWinPtr->privatePtr);
+ realWinView = TkMacOSXGetNSViewForDrawable(realWinPtr->privatePtr);
if (realWinView != nil) {
break;
}
@@ -1041,8 +1115,8 @@ TkpSetMainMenubar(
if (winPtr->wmInfoPtr &&
winPtr->wmInfoPtr->menuPtr &&
- winPtr->wmInfoPtr->menuPtr->masterMenuPtr) {
- menubar = winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin;
+ winPtr->wmInfoPtr->menuPtr->mainMenuPtr) {
+ menubar = winPtr->wmInfoPtr->menuPtr->mainMenuPtr->tkwin;
}
/*
@@ -1096,25 +1170,25 @@ static void
CheckForSpecialMenu(
TkMenu *menuPtr) /* The menu we are checking */
{
- if (!menuPtr->masterMenuPtr->tkwin) {
+ if (!menuPtr->mainMenuPtr->tkwin) {
return;
}
for (TkMenuEntry *cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr;
cascadeEntryPtr;
cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
if (cascadeEntryPtr->menuPtr->menuType == MENUBAR
- && cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin) {
- TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr;
+ && cascadeEntryPtr->menuPtr->mainMenuPtr->tkwin) {
+ TkMenu *mainMenuPtr = cascadeEntryPtr->menuPtr->mainMenuPtr;
int i = 0;
Tcl_DString ds;
Tcl_DStringInit(&ds);
- Tcl_DStringAppend(&ds, Tk_PathName(masterMenuPtr->tkwin), -1);
+ Tcl_DStringAppend(&ds, Tk_PathName(mainMenuPtr->tkwin), -1);
while (specialMenus[i].name) {
Tcl_DStringAppend(&ds, specialMenus[i].name,
specialMenus[i].len);
if (strcmp(Tcl_DStringValue(&ds),
- Tk_PathName(menuPtr->masterMenuPtr->tkwin)) == 0) {
+ Tk_PathName(menuPtr->mainMenuPtr->tkwin)) == 0) {
cascadeEntryPtr->entryFlags |= specialMenus[i].flag;
} else {
cascadeEntryPtr->entryFlags &= ~specialMenus[i].flag;
@@ -1156,18 +1230,18 @@ ParseAccelerator(
*maskPtr = 0;
while (1) {
i = 0;
- while (modifiers[i].name) {
- int l = modifiers[i].len;
+ while (allModifiers[i].name) {
+ int l = allModifiers[i].len;
- if (!strncasecmp(accel, modifiers[i].name, l) &&
+ if (!strncasecmp(accel, allModifiers[i].name, l) &&
(accel[l] == '-' || accel[l] == '+')) {
- *maskPtr |= modifiers[i].mask;
+ *maskPtr |= allModifiers[i].mask;
accel += l+1;
break;
}
i++;
}
- if (!modifiers[i].name || !*accel) {
+ if (!allModifiers[i].name || !*accel) {
break;
}
}
@@ -1273,7 +1347,7 @@ TkpComputeStandardMenuGeometry(
* Do nothing if this menu is a clone.
*/
- if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) {
+ if (menuPtr->tkwin == NULL || menuPtr->mainMenuPtr != menuPtr) {
return;
}
@@ -1391,14 +1465,14 @@ TkpComputeStandardMenuGeometry(
}
} else {
NSUInteger modifMask = [menuItem keyEquivalentModifierMask];
- int i = 0;
+ int j = 0;
- while (modifiers[i].name) {
- if (modifMask & modifiers[i].mask) {
- modifMask &= ~modifiers[i].mask;
+ while (allModifiers[j].name) {
+ if (modifMask & allModifiers[j].mask) {
+ modifMask &= ~allModifiers[j].mask;
modifierWidth += modifierCharWidth;
}
- i++;
+ j++;
}
accelWidth = [[menuItem keyEquivalent] sizeWithAttributes:
TkMacOSXNSFontAttributesForFont(tkfont)].width;
@@ -1584,30 +1658,6 @@ TkMacOSXClearMenubarActive(void)
/*
*----------------------------------------------------------------------
*
- * Tk_MacOSXTurnOffMenus --
- *
- * Turns off all the menu drawing code. This is more than just disabling
- * the "menu" command, this means that Tk will NEVER touch the menubar.
- * It is needed in the Plugin, where Tk does not own the menubar.
- *
- * Results:
- * None.
- *
- * Side effects:
- * A flag is set which will disable all menu drawing.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tk_MacOSXTurnOffMenus(void)
-{
- gNoTkMenus = 1;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TkpMenuInit --
*
* Initializes Mac-specific menu data.
@@ -1624,7 +1674,7 @@ Tk_MacOSXTurnOffMenus(void)
void
TkpMenuInit(void)
{
- TkColor *tkColPtr;
+ // TkColor *tkColPtr;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
@@ -1635,13 +1685,6 @@ TkpMenuInit(void)
#undef observe
[NSMenuItem setUsesUserKeyEquivalents:NO];
- tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);
- defaultBg = tkColPtr->color.pixel;
- ckfree(tkColPtr);
- tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);
- defaultFg = tkColPtr->color.pixel;
- ckfree(tkColPtr);
-
ChkErr(GetThemeMetric, kThemeMetricMenuMarkColumnWidth,
&menuMarkColumnWidth);
ChkErr(GetThemeMetric, kThemeMetricMenuTextLeadingEdgeMargin,
diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c
index 1e88f3a..2fad3cb 100644
--- a/macosx/tkMacOSXMenubutton.c
+++ b/macosx/tkMacOSXMenubutton.c
@@ -181,13 +181,6 @@ 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.
- */
-
- TkMacOSXSetUpClippingRgn(pixmap);
-
- /*
* Draw the native portion of the buttons.
*/
@@ -364,7 +357,7 @@ TkpComputeMenuButtonGeometry(butPtr)
*
* DrawMenuButtonImageAndText --
*
- * Draws the image and text associated witha button or label.
+ * Draws the image and text associated with a button or label.
*
* Results:
* None.
@@ -567,7 +560,7 @@ TkMacOSXDrawMenuButton(
static HIThemeButtonDrawInfo hiinfo;
MenuButtonBackgroundDrawCB(mbPtr, 32, true);
- if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {
return;
}
@@ -598,7 +591,7 @@ TkMacOSXDrawMenuButton(
MenuButtonContentDrawCB(mbPtr->btnkind, &mbPtr->drawinfo,
mbPtr, 32, true);
} else {
- if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
+ if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {
return;
}
TkMacOSXRestoreDrawingContext(&dc);
@@ -710,7 +703,7 @@ MenuButtonEventProc(
mbPtr->flags &= ~ACTIVE;
}
if ((buttonPtr->flags & REDRAW_PENDING) == 0) {
- Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) buttonPtr);
+ Tcl_DoWhenIdle(TkpDisplayMenuButton, buttonPtr);
buttonPtr->flags |= REDRAW_PENDING;
}
}
diff --git a/macosx/tkMacOSXMenus.c b/macosx/tkMacOSXMenus.c
index 1029704..fe53f25 100644
--- a/macosx/tkMacOSXMenus.c
+++ b/macosx/tkMacOSXMenus.c
@@ -112,7 +112,7 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
* On OS X 10.12 we get duplicate tab control items if we create them here.
*/
- if ([NSApp macMinorVersion] > 12) {
+ if ([NSApp macOSVersion] > 101200) {
_defaultWindowsMenuItems = [_defaultWindowsMenuItems
arrayByAddingObjectsFromArray:
[NSArray arrayWithObjects:
@@ -203,7 +203,7 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
if (!_eventInterp || !Tcl_FindCommand(_eventInterp, "tkAboutDialog",
NULL, 0) || (GetCurrentEventKeyModifiers() & optionKey)) {
- TkAboutDlg();
+ [super orderFrontStandardAboutPanel:nil];
} else {
int code = Tcl_EvalEx(_eventInterp, "tkAboutDialog", -1,
TCL_EVAL_GLOBAL);
@@ -373,29 +373,6 @@ TkMacOSXHandleMenuSelect(
/*
*----------------------------------------------------------------------
*
- * TkMacOSXInitMenus --
- *
- * This procedure initializes the Macintosh menu bar.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkMacOSXInitMenus(
- TCL_UNUSED(Tcl_Interp *))
-{
- [NSApp _setupMenus];
-}
-
-/*
- *----------------------------------------------------------------------
- *
* GenerateEditEvent --
*
* Takes an edit menu item and posts the corasponding a virtual event to
@@ -422,7 +399,7 @@ GenerateEditEvent(
if (!winPtr) {
return;
}
- tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ tkwin = (Tk_Window)winPtr->dispPtr->focusPtr;
if (!tkwin) {
return;
}
diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c
index 7dcfa10..83eef3d 100644
--- a/macosx/tkMacOSXMouseEvent.c
+++ b/macosx/tkMacOSXMouseEvent.c
@@ -24,6 +24,7 @@ typedef struct {
Point global;
Point local;
} MouseEventData;
+
static Tk_Window captureWinPtr = NULL; /* Current capture window; may be
* NULL. */
@@ -42,9 +43,9 @@ enum {
* window attribute pointing to the active window. As of 10.8 this behavior
* had changed. The new behavior was that if the mouse were ever moved outside
* of a window, all subsequent NSMouseMoved NSEvents would have a Nil window
- * attribute. To work around this the TKApplication remembers the last non-Nil
- * window that it received in a mouse event. If it receives an NSEvent with a
- * Nil window attribute then the saved window is used.
+ * attribute until the mouse returned to the window. In 11.1 it changed again.
+ * The window attribute can be non-nil, but referencing a window which does not
+ * belong to the application.
*/
@implementation TKApplication(TKMouseEvent)
@@ -52,151 +53,167 @@ enum {
{
NSWindow *eventWindow = [theEvent window];
NSEventType eventType = [theEvent type];
+ NSRect viewFrame = [[eventWindow contentView] frame];
+ NSPoint location = [theEvent locationInWindow];
TkWindow *winPtr = NULL, *grabWinPtr;
- Tk_Window tkwin;
+ Tk_Window tkwin = NULL, capture, target;
NSPoint local, global;
- NSInteger button = -1;
-#if 0
- NSTrackingArea *trackingArea = nil;
- NSInteger eventNumber, clickCount, buttonNumber;
-#endif
- [NSEvent stopPeriodicEvents];
+ NSInteger button;
+ Bool inTitleBar = NO;
+ int win_x, win_y;
+ unsigned int buttonState = 0;
+ static int validPresses = 0, ignoredPresses = 0;
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
+
+ /*
+ * If this event is not for a Tk toplevel, it should just be passed up the
+ * responder chain. However, there is an exception for synthesized events,
+ * which are used in testing. Those events are recognized by having their
+ * both the windowNumber and the eventNumber set to -1.
+ */
+
+ if (eventWindow && ![eventWindow isMemberOfClass:[TKWindow class]]) {
+ if ([theEvent windowNumber] != -1 || [theEvent eventNumber] != -1)
+ return theEvent;
+ }
+
+ /*
+ * Check if the event is located in the titlebar.
+ */
+
+ if (eventWindow) {
+ inTitleBar = viewFrame.size.height < location.y;
+ }
+
+ button = [theEvent buttonNumber] + Button1;
+ if ((button & -2) == Button2) {
+ button ^= 1; /* Swap buttons 2/3 */
+ }
switch (eventType) {
- case NSLeftMouseDown:
- case NSRightMouseDown:
- case NSOtherMouseDown:
+ case NSRightMouseUp:
+ case NSOtherMouseUp:
+ buttonState &= ~Tk_GetButtonMask(button);
+ break;
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
- button = [theEvent buttonNumber] + Button1;
+ case NSRightMouseDown:
+ case NSOtherMouseDown:
+ buttonState |= Tk_GetButtonMask(button);
+ break;
case NSMouseEntered:
+ if ([eventWindow respondsToSelector:@selector(mouseInResizeArea)] &&
+ !inTitleBar) {
+ [(TKWindow *)eventWindow setMouseInResizeArea:YES];
+ }
+ break;
case NSMouseExited:
- case NSCursorUpdate:
+ if ([eventWindow respondsToSelector:@selector(mouseInResizeArea)]) {
+ [(TKWindow *)eventWindow setMouseInResizeArea:NO];
+ break;
+ }
case NSLeftMouseUp:
- case NSRightMouseUp:
- case NSOtherMouseUp:
+ case NSLeftMouseDown:
case NSMouseMoved:
+ case NSScrollWheel:
+#if 0
+ case NSCursorUpdate:
case NSTabletPoint:
case NSTabletProximity:
- case NSScrollWheel:
+#endif
break;
- default: /* Unrecognized mouse event. */
+ default: /* This type of event is ignored. */
return theEvent;
}
/*
- * 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.
+ * Update the button state. We ignore left button presses that start a
+ * resize or occur in the title bar. See tickets [d72abe6b54] and
+ * [39cbacb9e8].
*/
- if (eventWindow) {
- local = [theEvent locationInWindow];
+ if (eventType == NSLeftMouseDown) {
+ if ([eventWindow respondsToSelector:@selector(mouseInResizeArea)] &&
+ [(TKWindow *) eventWindow mouseInResizeArea]) {
- /*
- * Do not send ButtonPress XEvents for MouseDown NSEvents that start a
- * resize. (The MouseUp will be handled during LiveResize.) See
- * ticket [d72abe6b54].
- */
+ /*
+ * When the left button is pressed in the resize area, we receive
+ * NSMouseDown, but when it is released we do not receive
+ * NSMouseUp. So ignore the event and clear the button state but
+ * do not change the ignoredPresses count.
+ */
- if (eventType == NSLeftMouseDown &&
- ([eventWindow styleMask] & NSResizableWindowMask) &&
- [NSApp macMinorVersion] > 6) {
- NSRect frame = [eventWindow frame];
- if (local.x < 3 || local.x > frame.size.width - 3 || local.y < 3) {
- return theEvent;
- }
+ buttonState &= ~Tk_GetButtonMask(Button1);
+ return theEvent;
}
- global = [eventWindow tkConvertPointToScreen: local];
- tkwin = TkpGetCapture();
- if (tkwin) {
- winPtr = (TkWindow *) tkwin;
- eventWindow = TkMacOSXDrawableWindow(winPtr->window);
- if (eventWindow) {
- local = [eventWindow tkConvertPointFromScreen: global];
- } else {
- return theEvent;
- }
+ if (inTitleBar) {
+ ignoredPresses++;
+ return theEvent;
}
- local.y = [eventWindow frame].size.height - local.y;
- global.y = TkMacOSXZeroScreenHeight() - global.y;
- } else {
-
- /*
- * If the event has no NSWindow, the location is in screen coordinates.
- */
-
- global = [theEvent locationInWindow];
- tkwin = TkpGetCapture();
- if (tkwin) {
- winPtr = (TkWindow *) tkwin;
- eventWindow = TkMacOSXDrawableWindow(winPtr->window);
- } else {
- eventWindow = [NSApp mainWindow];
+ validPresses++;
+ buttonState |= Tk_GetButtonMask(Button1);
+ }
+ if (eventType == NSLeftMouseUp) {
+ if (ignoredPresses > 0) {
+ ignoredPresses--;
+ } else if (validPresses > 0) {
+ validPresses--;
}
- if (!eventWindow) {
- return theEvent;
+ if (validPresses == 0) {
+ buttonState &= ~Tk_GetButtonMask(Button1);
}
- 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.
+ * Find an appropriate NSWindow to attach to this event, and its
+ * associated Tk window.
*/
- if (!tkwin) {
- winPtr = TkMacOSXGetTkWindow(eventWindow);
- tkwin = (Tk_Window) winPtr;
+ capture = TkpGetCapture();
+ if (capture) {
+ winPtr = (TkWindow *) capture;
+ eventWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
+ if (!eventWindow) {
+ return theEvent;
+ }
+ } else {
+ if (eventWindow) {
+ winPtr = TkMacOSXGetTkWindow(eventWindow);
+ }
+ if (!winPtr) {
+ eventWindow = [NSApp mainWindow];
+ winPtr = TkMacOSXGetTkWindow(eventWindow);
+ }
}
- if (!tkwin) {
+ if (!winPtr) {
/*
- * We can't find a window for this event. We have to ignore it.
+ * We couldn't find a Tk window for this event. We have to ignore it.
*/
#ifdef TK_MAC_DEBUG_EVENTS
- TkMacOSXDbgMsg("tkwin == NULL");
+ TkMacOSXDbgMsg("Event received with no Tk window.");
#endif
return theEvent;
}
+ tkwin = (Tk_Window) winPtr;
/*
- * 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;
- }
- }
-
- /*
- * Convert local from NSWindow flipped coordinates to the toplevel's
- * coordinates.
+ * Compute the mouse position in local (window) and global (screen)
+ * coordinates. These are Tk coordinates, meaning that the local origin is
+ * at the top left corner of the containing toplevel and the global origin
+ * is at top left corner of the primary screen.
*/
+ global = [NSEvent mouseLocation];
+ local = [eventWindow tkConvertPointFromScreen: global];
+ global.x = floor(global.x);
+ global.y = floor(TkMacOSXZeroScreenHeight() - global.y);
+ local.x = floor(local.x);
+ local.y = floor([eventWindow frame].size.height - local.y);
if (Tk_IsEmbedded(winPtr)) {
TkWindow *contPtr = TkpGetOtherWindow(winPtr);
if (Tk_IsTopLevel(contPtr)) {
@@ -213,25 +230,44 @@ enum {
}
/*
- * 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.)
+ * Use the local coordinates to find the Tk window which should receive
+ * this event. Also 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);
- local.x = win_x;
- local.y = win_y;
+ target = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
/*
- * Generate an XEvent for this mouse event.
+ * Ignore the event if a local grab is in effect and the Tk window is
+ * not in the grabber's subtree.
*/
- unsigned int state = 0;
- if (button > 0) {
- state |= TkGetButtonMask(button);
+ 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;
+ if (!target) {
+ return theEvent;
+ }
+ for (tkwin2 = target;
+ !Tk_IsTopLevel(tkwin2);
+ tkwin2 = Tk_Parent(tkwin2)) {
+ if (tkwin2 == (Tk_Window)grabWinPtr) {
+ break;
+ }
+ }
+ if (tkwin2 != (Tk_Window)grabWinPtr) {
+ return theEvent;
+ }
}
+ /*
+ * Generate an XEvent for this mouse event.
+ */
+
+ unsigned int state = buttonState;
NSUInteger modifiers = [theEvent modifierFlags];
if (modifiers & NSAlphaShiftKeyMask) {
@@ -259,48 +295,45 @@ enum {
if (eventType != NSScrollWheel) {
/*
- * For normal mouse events, Tk_UpdatePointer will send the XEvent.
+ * For normal mouse events, Tk_UpdatePointer will send the appropriate
+ * XEvents using its cached state information. Unfortunately, it will
+ * also recompute the local coordinates.
*/
#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 %.1f y %.1f %d",
+ target, global.x, global.y, state);
#endif
- Tk_UpdatePointer(tkwin, global.x, global.y, state);
+
+ Tk_UpdatePointer(target, global.x, global.y, state);
} else {
+ CGFloat delta;
+ XEvent xEvent;
/*
* For scroll wheel events we need to send the XEvent here.
*/
- CGFloat delta;
- int coarseDelta;
- XEvent xEvent;
-
xEvent.type = MouseWheelEvent;
- xEvent.xbutton.x = local.x;
- xEvent.xbutton.y = local.y;
+ xEvent.xbutton.x = win_x;
+ xEvent.xbutton.y = win_y;
xEvent.xbutton.x_root = global.x;
xEvent.xbutton.y_root = global.y;
xEvent.xany.send_event = false;
- xEvent.xany.display = Tk_Display(tkwin);
- xEvent.xany.window = Tk_WindowId(tkwin);
+ xEvent.xany.display = Tk_Display(target);
+ xEvent.xany.window = Tk_WindowId(target);
- delta = [theEvent deltaY];
+ delta = [theEvent deltaY] * 120;
if (delta != 0.0) {
- coarseDelta = (delta > -1.0 && delta < 1.0) ?
- (signbit(delta) ? -1 : 1) : lround(delta);
xEvent.xbutton.state = state;
- xEvent.xkey.keycode = coarseDelta;
+ xEvent.xkey.keycode = (delta > 0) ? ceil(delta) : floor(delta);
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
}
- delta = [theEvent deltaX];
+ delta = [theEvent deltaX] * 120;
if (delta != 0.0) {
- coarseDelta = (delta > -1.0 && delta < 1.0) ?
- (signbit(delta) ? -1 : 1) : lround(delta);
xEvent.xbutton.state = state | ShiftMask;
- xEvent.xkey.keycode = coarseDelta;
+ xEvent.xkey.keycode = (delta > 0) ? ceil(delta) : floor(delta);
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
}
@@ -314,34 +347,6 @@ enum {
/*
*----------------------------------------------------------------------
*
- * TkMacOSXKeyModifiers --
- *
- * Returns the current state of the modifier keys.
- *
- * Results:
- * An OS Modifier state.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-EventModifiers
-TkMacOSXModifierState(void)
-{
- UInt32 keyModifiers;
- int isFrontProcess = (GetCurrentEvent() && Tk_MacOSXIsAppInFront());
-
- keyModifiers = isFrontProcess ? GetCurrentEventKeyModifiers() :
- GetCurrentKeyModifiers();
-
- return (EventModifiers) (keyModifiers & USHRT_MAX);
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TkMacOSXButtonKeyState --
*
* Returns the current state of the button & modifier keys.
@@ -398,8 +403,15 @@ ButtonModifiers2State(
* Tk on OSX supports at most 9 buttons.
*/
- state = (buttonState & 0x7F) * Button1Mask;
- /* Handle buttons 8/9 */
+ state = (buttonState & 0x079) * Button1Mask;
+ /* Handle swapped buttons 2/3 */
+ if (buttonState & 0x02) {
+ state |= Button3Mask;
+ }
+ if (buttonState & 0x04) {
+ state |= Button2Mask;
+ }
+ /* Handle buttons 8/9 */
state |= (buttonState & 0x180) * (Button8Mask >> 7);
if (keyModifiers & alphaLock) {
@@ -468,8 +480,8 @@ XQueryPointer(
NSPoint global = [NSEvent mouseLocation];
if (getLocal) {
- MacDrawable *macWin = (MacDrawable *) w;
- NSWindow *win = TkMacOSXDrawableWindow(w);
+ MacDrawable *macWin = (MacDrawable *)w;
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(w);
if (win) {
NSPoint local;
@@ -507,7 +519,7 @@ XQueryPointer(
* True if event(s) are generated - false otherwise.
*
* Side effects:
- * Additional events may be place on the Tk event queue. Grab state may
+ * Additional events may be placed on the Tk event queue. Grab state may
* also change.
*
*----------------------------------------------------------------------
@@ -545,7 +557,7 @@ TkGenerateButtonEventForXPointer(
* True if event(s) are generated, false otherwise.
*
* Side effects:
- * Additional events may be place on the Tk event queue. Grab state may
+ * Additional events may be placed on the Tk event queue. Grab state may
* also change.
*
*----------------------------------------------------------------------
@@ -558,8 +570,8 @@ TkGenerateButtonEvent(
Window window, /* X Window containing button event. */
unsigned int state) /* Button Key state suitable for X event. */
{
- MacDrawable *macWin = (MacDrawable *) window;
- NSWindow *win = TkMacOSXDrawableWindow(window);
+ MacDrawable *macWin = (MacDrawable *)window;
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);
MouseEventData med;
bzero(&med, sizeof(MouseEventData));
@@ -597,7 +609,7 @@ TkGenerateButtonEvent(
* True if event(s) are generated - false otherwise.
*
* Side effects:
- * Additional events may be place on the Tk event queue. Grab state may
+ * Additional events may be placed on the Tk event queue. Grab state may
* also change.
*
*----------------------------------------------------------------------
@@ -611,7 +623,7 @@ GenerateButtonEvent(
int dummy;
TkDisplay *dispPtr;
-#if UNUSED
+#ifdef UNUSED
/*
* ButtonDown events will always occur in the front window. ButtonUp
@@ -640,51 +652,40 @@ GenerateButtonEvent(
return true;
}
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpWarpPointer --
+ *
+ * Move the mouse cursor to the screen location specified by the warpX and
+ * warpY fields of a TkDisplay.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The mouse cursor is moved.
+ *
+ *----------------------------------------------------------------------
+ */
+
void
TkpWarpPointer(
TkDisplay *dispPtr)
{
CGPoint pt;
- 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 {
- wNum = 0;
- pt.x = loc.x = dispPtr->warpX;
+ pt.x = dispPtr->warpX;
pt.y = dispPtr->warpY;
- loc.y = TkMacOSXZeroScreenHeight() - pt.y;
}
- /*
- * 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.
- */
-
CGWarpMouseCursorPosition(pt);
- 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];
}
/*
@@ -712,8 +713,7 @@ TkpSetCapture(
while (winPtr && !Tk_IsTopLevel(winPtr)) {
winPtr = winPtr->parentPtr;
}
- [NSEvent stopPeriodicEvents];
- captureWinPtr = (Tk_Window) winPtr;
+ captureWinPtr = (Tk_Window)winPtr;
}
/*
diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c
index 82ded8a..e169a7d 100644
--- a/macosx/tkMacOSXNotify.c
+++ b/macosx/tkMacOSXNotify.c
@@ -13,10 +13,10 @@
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
+#include <tclInt.h>
#include "tkMacOSXPrivate.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXConstants.h"
-#include <tclInt.h>
#import <objc/objc-auto.h>
/* This is not used for anything at the moment. */
@@ -156,6 +156,7 @@ void DebugPrintQueue(void)
* this block should be removed.
*/
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
if ([theEvent type] == NSAppKitDefined) {
static Bool aWindowIsMoving = NO;
switch([theEvent subtype]) {
@@ -174,6 +175,8 @@ void DebugPrintQueue(void)
break;
}
}
+#endif
+
[super sendEvent:theEvent];
[NSApp tkCheckPasteboard];
@@ -183,6 +186,13 @@ void DebugPrintQueue(void)
#endif
}
+
+- (void) _runBackgroundLoop
+{
+ while(Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_TIMER_EVENTS|TCL_DONT_WAIT)){
+ TkMacOSXDrawAllViews(NULL);
+ }
+}
@end
#pragma mark -
@@ -201,15 +211,13 @@ void DebugPrintQueue(void)
*----------------------------------------------------------------------
*/
-NSString *
+static NSString *
GetRunLoopMode(NSModalSession modalSession)
{
NSString *runLoopMode = nil;
if (modalSession) {
runLoopMode = NSModalPanelRunLoopMode;
- } else if (TkpGetCapture()) {
- runLoopMode = NSEventTrackingRunLoopMode;
}
if (!runLoopMode) {
runLoopMode = [[NSRunLoop currentRunLoop] currentMode];
@@ -261,7 +269,6 @@ Tk_MacOSXSetupTkNotifier(void)
Tcl_CreateEventSource(TkMacOSXEventsSetupProc,
TkMacOSXEventsCheckProc, NULL);
TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
- Tcl_SetServiceMode(TCL_SERVICE_ALL);
TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);
TclMacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode);
}
@@ -300,10 +307,90 @@ TkMacOSXNotifyExitHandler(
/*
*----------------------------------------------------------------------
*
+ * TkMacOSXDrawAllViews --
+ *
+ * This static function is meant to be run as an idle task. It attempts
+ * to redraw all views which have the tkNeedsDisplay property set to YES.
+ * This relies on a feature of [NSApp nextEventMatchingMask: ...] which
+ * is undocumented, namely that it sometimes blocks and calls drawRect
+ * for all views that need display before it returns. We call it with
+ * deQueue=NO so that it will not change anything on the AppKit event
+ * queue, because we only want the side effect that it runs drawRect. The
+ * only time when any NSViews have the needsDisplay property set to YES
+ * is during execution of this function.
+ *
+ * The reason for running this function as an idle task is to try to
+ * arrange that all widgets will be fully configured before they are
+ * drawn. Any idle tasks that might reconfigure them should be higher on
+ * the idle queue, so they should be run before the display procs are run
+ * by drawRect.
+ *
+ * If this function is called directly with non-NULL clientData parameter
+ * then the int which it references will be set to the number of windows
+ * that need display, but the needsDisplay property of those windows will
+ * not be changed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Parts of windows my get redrawn.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXDrawAllViews(
+ ClientData clientData)
+{
+ int count = 0, *dirtyCount = (int *)clientData;
+
+ for (NSWindow *window in [NSApp windows]) {
+ if ([[window contentView] isMemberOfClass:[TKContentView class]]) {
+ TKContentView *view = [window contentView];
+ if ([view tkNeedsDisplay]) {
+ count++;
+ if (dirtyCount) {
+ continue;
+ }
+ [view setNeedsDisplayInRect:[view tkDirtyRect]];
+ }
+ } else {
+ [window displayIfNeeded];
+ }
+ }
+ if (dirtyCount) {
+ *dirtyCount = count;
+ }
+ [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:GetRunLoopMode(TkMacOSXGetModalSession())
+ dequeue:NO];
+ for (NSWindow *window in [NSApp windows]) {
+ if ([[window contentView] isMemberOfClass:[TKContentView class]]) {
+ TKContentView *view = [window contentView];
+
+ /*
+ * If we did not run drawRect, we set needsDisplay back to NO.
+ * Note that if drawRect did run it may have added to Tk's dirty
+ * rect, due to attempts to draw outside of drawRect's dirty rect.
+ */
+
+ if ([view needsDisplay]) {
+ [view setNeedsDisplay: NO];
+ }
+ }
+ }
+ [NSApp setNeedsToDraw:NO];
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkMacOSXEventsSetupProc --
*
* This procedure implements the setup part of the MacOSX event source. It
- * is invoked by Tcl_DoOneEvent before calling TkMacOSXEventsProc to
+ * is invoked by Tcl_DoOneEvent before calling TkMacOSXEventsCheckProc 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.
@@ -313,18 +400,33 @@ TkMacOSXNotifyExitHandler(
*
* 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, or if there is any drawing that needs to be
+ * done, then the maximum block time will be set to 0 to ensure that
+ * Tcl_WaitForEvent returns immediately.
*
*----------------------------------------------------------------------
*/
+#define TICK 200
+static Tcl_TimerToken ticker = NULL;
+
+static void
+Heartbeat(
+ TCL_UNUSED(ClientData))
+{
+
+ if (ticker) {
+ ticker = Tcl_CreateTimerHandler(TICK, Heartbeat, NULL);
+ }
+}
+
+static const Tcl_Time zeroBlockTime = { 0, 0 };
+
static void
TkMacOSXEventsSetupProc(
ClientData dummy,
int flags)
{
- static Bool havePeriodicEvents = NO;
NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
(void)dummy;
@@ -333,35 +435,39 @@ TkMacOSXEventsSetupProc(
*/
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.
- */
+ /*
+ * After calling this setup proc, Tcl_DoOneEvent will call
+ * Tcl_WaitForEvent. Then it will call check proc to collect the
+ * events and translate them into XEvents.
+ *
+ * If we have any events waiting or if there is any drawing to be done
+ * we want Tcl_WaitForEvent to return immediately. So we set the block
+ * time to 0 and stop the heatbeat.
+ */
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){
+ if ((currentEvent) || [NSApp needsToDraw] ) {
+ Tcl_SetMaxBlockTime(&zeroBlockTime);
+ Tcl_DeleteTimerHandler(ticker);
+ ticker = NULL;
+ } else if (ticker == NULL) {
/*
- * 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.
+ * When the user is not generating events we schedule a "heartbeat"
+ * TimerHandler to fire every 200 milliseconds. The handler does
+ * nothing, but when its timer fires it causes Tcl_WaitForEvent to
+ * return. This helps avoid hangs when calling vwait during the
+ * non-regression tests.
*/
- havePeriodicEvents = YES;
- [NSEvent startPeriodicEventsAfterDelay:0.0 withPeriod:0.1];
+ ticker = Tcl_CreateTimerHandler(TICK, Heartbeat, NULL);
}
}
}
@@ -385,11 +491,11 @@ TkMacOSXEventsSetupProc(
*/
static void
TkMacOSXEventsCheckProc(
- ClientData dummy,
+ TCL_UNUSED(ClientData),
int flags)
{
NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
- (void)dummy;
+ int eventsFound = 0;
/*
* runloopMode will be nil if we are in a Tcl event loop.
@@ -428,17 +534,19 @@ TkMacOSXEventsCheckProc(
inMode:GetRunLoopMode(modalSession)
dequeue:YES];
if (currentEvent) {
+
/*
* Generate Xevents.
*/
- int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent];
- Tcl_SetServiceMode(oldServiceMode);
if (processedEvent) {
+ eventsFound++;
+
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@" event: %@", currentEvent);
#endif
+
if (modalSession) {
[NSApp _modalSession:modalSession sendEvent:currentEvent];
} else {
@@ -455,6 +563,25 @@ TkMacOSXEventsCheckProc(
*/
[NSApp _unlockAutoreleasePool];
+
+ /*
+ * Add an idle task to the end of the idle queue which will redisplay
+ * all of our dirty windows. We want this to happen after all other
+ * idle tasks have run so that all widgets will be configured before
+ * they are displayed. The drawRect method "borrows" the idle queue
+ * while drawing views. That is, it sends expose events which cause
+ * display procs to be posted as idle tasks and then runs an inner
+ * event loop to processes those idle tasks. We are trying to arrange
+ * for the idle queue to be empty when it starts that process and empty
+ * when it finishes.
+ */
+
+ int dirtyCount = 0;
+ TkMacOSXDrawAllViews(&dirtyCount);
+ if (dirtyCount > 0) {
+ Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL);
+ Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL);
+ }
}
}
diff --git a/macosx/tkMacOSXPort.h b/macosx/tkMacOSXPort.h
index 28010ec..d875873 100644
--- a/macosx/tkMacOSXPort.h
+++ b/macosx/tkMacOSXPort.h
@@ -131,29 +131,38 @@
*/
#define TK_NO_DOUBLE_BUFFERING 1
+#define TK_HAS_DYNAMIC_COLORS 1
+#define TK_DYNAMIC_COLORMAP 0x0fffffff
/*
- * Magic pixel code values for system colors.
- *
- * NOTE: values must be kept in sync with indices into the
- * systemColorMap array in tkMacOSXColor.c !
+ * Inform tkImgPhInstance.c that our tkPutImage can render an image with an
+ * alpha channel directly into a window.
+ */
+
+#define TKPUTIMAGE_CAN_BLEND
+
+/*
+ * Used by xcolor.c
*/
-#define TRANSPARENT_PIXEL 30
-#define APPEARANCE_PIXEL 52
-#define PIXEL_MAGIC ((unsigned char) 0x69)
+MODULE_SCOPE unsigned long TkMacOSXRGBPixel(unsigned long red, unsigned long green,
+ unsigned long blue);
+#define TkpGetPixel(p) (TkMacOSXRGBPixel(p->red >> 8, p->green >> 8, p->blue >> 8))
/*
- * 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.
+ * Used by tkWindow.c
*/
-#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \
- | (((p)->red >> 8) & 0xff)) << 8) \
- | (((p)->green >> 8) & 0xff)) << 8) \
- | (((p)->blue >> 8) & 0xff))
+MODULE_SCOPE void TkMacOSXHandleMapOrUnmap(Tk_Window tkwin, XEvent *event);
+
+#define TkpHandleMapOrUnmap(tkwin, event) TkMacOSXHandleMapOrUnmap(tkwin, event)
+
+/*
+ * Used by tkAppInit
+ */
+#define USE_CUSTOM_EXIT_PROC
+EXTERN int TkpWantsExitProc(void);
+EXTERN TCL_NORETURN void TkpExitProc(void *);
#endif /* _TKMACPORT */
diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h
index 079e033..8149860 100644
--- a/macosx/tkMacOSXPrivate.h
+++ b/macosx/tkMacOSXPrivate.h
@@ -4,7 +4,8 @@
* Macros and declarations that are purely internal & private to TkAqua.
*
* Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
- * Copyright 2008-2009, Apple Inc.
+ * Copyright (c) 2008-2009 Apple Inc.
+ * Copyright (c) 2020 Marc Culler
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -102,11 +103,11 @@
* debug message in case of failure.
*/
#define ChkErr(f, ...) ({ \
- OSStatus err = f(__VA_ARGS__); \
- if (err != noErr) { \
- TkMacOSXDbgOSErr(f, err); \
+ OSStatus err_ = f(__VA_ARGS__); \
+ if (err_ != noErr) { \
+ TkMacOSXDbgOSErr(f, err_); \
} \
- err;})
+ err_;})
#else /* TK_MAC_DEBUG */
#define TKLog(f, ...)
@@ -225,10 +226,6 @@ MODULE_SCOPE HIMutableShapeRef TkMacOSXHIShapeCreateMutableWithRect(
MODULE_SCOPE OSStatus TkMacOSXHIShapeSetWithShape(
HIMutableShapeRef inDestShape,
HIShapeRef inSrcShape);
-#if 0
-MODULE_SCOPE OSStatus TkMacOSXHIShapeSetWithRect(HIMutableShapeRef inShape,
- const CGRect *inRect);
-#endif
MODULE_SCOPE OSStatus TkMacOSHIShapeDifferenceWithRect(
HIMutableShapeRef inShape, const CGRect *inRect);
MODULE_SCOPE OSStatus TkMacOSHIShapeUnionWithRect(HIMutableShapeRef inShape,
@@ -249,45 +246,32 @@ MODULE_SCOPE int TkMacOSXUseAntialiasedText(Tcl_Interp *interp,
int enable);
MODULE_SCOPE int TkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable,
int antiAlias);
-MODULE_SCOPE int TkMacOSXGenerateFocusEvent(TkWindow *winPtr,
- int activeFlag);
-MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr);
MODULE_SCOPE int TkMacOSXIsWindowZoomed(TkWindow *winPtr);
MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window);
-MODULE_SCOPE EventModifiers TkMacOSXModifierState(void);
-MODULE_SCOPE NSBitmapImageRep* TkMacOSXBitmapRepFromDrawableRect(Drawable drawable,
- int x, int y, unsigned int width, unsigned int height);
-MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image);
MODULE_SCOPE void TkMacOSXDrawCGImage(Drawable d, GC gc, CGContextRef context,
CGImageRef image, unsigned long imageForeground,
unsigned long imageBackground, CGRect imageBounds,
CGRect srcBounds, CGRect dstBounds);
MODULE_SCOPE int TkMacOSXSetupDrawingContext(Drawable d, GC gc,
- int useCG, TkMacOSXDrawingContext *dcPtr);
+ TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void TkMacOSXRestoreDrawingContext(
TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void TkMacOSXSetColorInContext(GC gc, unsigned long pixel,
CGContextRef context);
-MODULE_SCOPE int TkMacOSXMakeFullscreen(TkWindow *winPtr,
- NSWindow *window, int fullscreen,
- Tcl_Interp *interp);
-MODULE_SCOPE void TkMacOSXEnterExitFullscreen(TkWindow *winPtr,
- int active);
-MODULE_SCOPE NSWindow* TkMacOSXDrawableWindow(Drawable drawable);
-MODULE_SCOPE NSView* TkMacOSXDrawableView(MacDrawable *macWin);
+#define TkMacOSXGetTkWindow(window) (TkWindow *)Tk_MacOSXGetTkWindow(window)
+#define TkMacOSXGetNSWindowForDrawable(drawable) ((NSWindow *)Tk_MacOSXGetNSWindowForDrawable(drawable))
+#define TkMacOSXGetNSViewForDrawable(macWin) ((NSView *)Tk_MacOSXGetNSViewForDrawable((Drawable)(macWin)))
+#define TkMacOSXGetCGContextForDrawable(drawable) ((CGContextRef)Tk_MacOSXGetCGContextForDrawable(drawable))
MODULE_SCOPE void TkMacOSXWinCGBounds(TkWindow *winPtr, CGRect *bounds);
MODULE_SCOPE HIShapeRef TkMacOSXGetClipRgn(Drawable drawable);
MODULE_SCOPE void TkMacOSXInvalidateViewRegion(NSView *view,
HIShapeRef rgn);
-MODULE_SCOPE CGContextRef TkMacOSXGetCGContextForDrawable(Drawable drawable);
-MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithDrawable(Drawable drawable);
-MODULE_SCOPE NSImage* TkMacOSXGetNSImageWithTkImage(Display *display,
+MODULE_SCOPE NSImage* TkMacOSXGetNSImageFromTkImage(Display *display,
Tk_Image image, int width, int height);
-MODULE_SCOPE NSImage* TkMacOSXGetNSImageWithBitmap(Display *display,
+MODULE_SCOPE NSImage* TkMacOSXGetNSImageFromBitmap(Display *display,
Pixmap bitmap, GC gc, int width, int height);
MODULE_SCOPE CGColorRef TkMacOSXCreateCGColor(GC gc, unsigned long pixel);
MODULE_SCOPE NSColor* TkMacOSXGetNSColor(GC gc, unsigned long pixel);
-MODULE_SCOPE TkWindow* TkMacOSXGetTkWindow(NSWindow *w);
MODULE_SCOPE NSFont* TkMacOSXNSFontForFont(Tk_Font tkfont);
MODULE_SCOPE NSDictionary* TkMacOSXNSFontAttributesForFont(Tk_Font tkfont);
MODULE_SCOPE NSModalSession TkMacOSXGetModalSession(void);
@@ -304,9 +288,13 @@ 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[]);
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE unsigned TkMacOSXAddVirtual(unsigned int keycode);
+MODULE_SCOPE void TkMacOSXWinNSBounds(TkWindow *winPtr, NSView *view,
+ NSRect *bounds);
+MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin);
+MODULE_SCOPE void TkMacOSXDrawAllViews(ClientData clientData);
+MODULE_SCOPE unsigned long TkMacOSXClearPixel(void);
#pragma mark Private Objective-C Classes
@@ -337,16 +325,21 @@ VISIBILITY_HIDDEN
NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
NSArray *_defaultHelpMenuItems, *_defaultFileMenuItems;
NSAutoreleasePool *_mainPool;
+ NSThread *_backgoundLoop;
+
#ifdef __i386__
/* The Objective C runtime used on i386 requires this. */
int _poolLock;
- int _macMinorVersion;
+ int _macOSVersion; /* 10000 * major + 100*minor */
Bool _isDrawing;
+ Bool _needsToDraw;
#endif
+
}
@property int poolLock;
-@property int macMinorVersion;
+@property int macOSVersion;
@property Bool isDrawing;
+@property Bool needsToDraw;
@end
@interface TKApplication(TKInit)
@@ -372,6 +365,7 @@ VISIBILITY_HIDDEN
@interface NSApplication(TKNotify)
/* We need to declare this hidden method. */
- (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event;
+- (void) _runBackgroundLoop;
@end
@interface TKApplication(TKEvent)
- (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;
@@ -388,6 +382,7 @@ VISIBILITY_HIDDEN
@end
@interface TKApplication(TKHLEvents)
- (void) terminate: (id) sender;
+- (void) superTerminate: (id) sender;
- (void) preferences: (id) sender;
- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
@@ -417,9 +412,11 @@ VISIBILITY_HIDDEN
{
@private
NSString *privateWorkingText;
- Bool _needsRedisplay;
+ Bool _tkNeedsDisplay;
+ NSRect _tkDirtyRect;
}
-@property Bool needsRedisplay;
+@property Bool tkNeedsDisplay;
+@property NSRect tkDirtyRect;
@end
@interface TKContentView(TKKeyEvent)
@@ -428,7 +425,9 @@ VISIBILITY_HIDDEN
@end
@interface TKContentView(TKWindowEvent)
-- (void) generateExposeEvents: (HIShapeRef) shape;
+- (void) addTkDirtyRect: (NSRect) rect;
+- (void) clearTkDirtyRect;
+- (void) generateExposeEvents: (NSRect) rect;
- (void) tkToolbarButton: (id) sender;
@end
@@ -439,16 +438,40 @@ VISIBILITY_HIDDEN
VISIBILITY_HIDDEN
@interface TKWindow : NSWindow
+{
+#ifdef __i386__
+ /* The Objective C runtime used on i386 requires this. */
+ Bool _mouseInResizeArea;
+ Window _tkWindow;
+#endif
+}
+@property Bool mouseInResizeArea;
+@property Window tkWindow;
@end
@interface TKWindow(TKWm)
- (void) tkLayoutChanged;
@end
-@interface NSDrawerWindow : NSWindow
+@interface TKDrawerWindow : NSWindow
{
id _i1, _i2;
+#ifdef __i386__
+ /* The Objective C runtime used on i386 requires this. */
+ Window _tkWindow;
+#endif
+}
+@property Window tkWindow;
+@end
+
+@interface TKPanel : NSPanel
+{
+#ifdef __i386__
+ /* The Objective C runtime used on i386 requires this. */
+ Window _tkWindow;
+#endif
}
+@property Window tkWindow;
@end
#pragma mark NSMenu & NSMenuItem Utilities
diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c
index 0a5ff6d..6cb61dd 100644
--- a/macosx/tkMacOSXRegion.c
+++ b/macosx/tkMacOSXRegion.c
@@ -12,6 +12,16 @@
*/
#include "tkMacOSXPrivate.h"
+static void RetainRegion(TkRegion r);
+static void ReleaseRegion(TkRegion r);
+
+#ifdef DEBUG
+static int totalRegions = 0;
+static int totalRegionRetainCount = 0;
+#define DebugLog(msg, ...) fprintf(stderr, (msg), ##__VA_ARGS__)
+#else
+#define DebugLog(msg, ...)
+#endif
/*
@@ -34,7 +44,10 @@
Region
XCreateRegion(void)
{
- return (Region) HIShapeCreateMutable();
+ Region region = (Region) HIShapeCreateMutable();
+ DebugLog("Created region: total regions = %d\n", ++totalRegions);
+ RetainRegion(region);
+ return region;
}
/*
@@ -59,7 +72,8 @@ XDestroyRegion(
Region r)
{
if (r) {
- CFRelease(r);
+ DebugLog("Destroyed region: total regions = %d\n", --totalRegions);
+ ReleaseRegion(r);
}
return Success;
}
@@ -320,7 +334,7 @@ TkpBuildRegionFromAlphaData(
/*
*----------------------------------------------------------------------
*
- * TkpRetainRegion --
+ * RetainRegion --
*
* Increases reference count of region.
*
@@ -333,17 +347,18 @@ TkpBuildRegionFromAlphaData(
*----------------------------------------------------------------------
*/
-void
-TkpRetainRegion(
+static void
+RetainRegion(
Region r)
{
CFRetain(r);
+ DebugLog("Retained region: total count is %d\n", ++totalRegionRetainCount);
}
/*
*----------------------------------------------------------------------
*
- * TkpReleaseRegion --
+ * ReleaseRegion --
*
* Decreases reference count of region.
*
@@ -356,11 +371,12 @@ TkpRetainRegion(
*----------------------------------------------------------------------
*/
-void
-TkpReleaseRegion(
+static void
+ReleaseRegion(
Region r)
{
CFRelease(r);
+ DebugLog("Released region: total count is %d\n", --totalRegionRetainCount);
}
/*
@@ -463,7 +479,7 @@ XOffsetRegion(
*----------------------------------------------------------------------
*
* TkMacOSXHIShapeCreateEmpty, TkMacOSXHIShapeCreateMutableWithRect,
- * TkMacOSXHIShapeSetWithShape, TkMacOSXHIShapeSetWithRect,
+ * TkMacOSXHIShapeSetWithShape,
* TkMacOSHIShapeDifferenceWithRect, TkMacOSHIShapeUnionWithRect,
* TkMacOSHIShapeUnion --
*
@@ -502,22 +518,6 @@ TkMacOSXHIShapeSetWithShape(
return result;
}
-#if 0
-OSStatus
-TkMacOSXHIShapeSetWithRect(
- HIMutableShapeRef inShape,
- const CGRect *inRect)
-{
- OSStatus result;
- HIShapeRef rgn = HIShapeCreateWithRect(inRect);
-
- result = TkMacOSXHIShapeSetWithShape(inShape, rgn);
- CFRelease(rgn);
-
- return result;
-}
-#endif
-
OSStatus
TkMacOSHIShapeDifferenceWithRect(
HIMutableShapeRef inShape,
diff --git a/macosx/tkMacOSXScale.c b/macosx/tkMacOSXScale.c
index 2e33622..2bbd795 100644
--- a/macosx/tkMacOSXScale.c
+++ b/macosx/tkMacOSXScale.c
@@ -149,8 +149,6 @@ TkpDisplayScale(
MacScale *macScalePtr = clientData;
Rect r;
WindowRef windowRef;
- CGrafPtr destPort, savePort;
- Boolean portChanged;
MacDrawable *macDraw;
SInt32 initialValue, minValue, maxValue;
UInt16 numTicks;
@@ -179,7 +177,7 @@ TkpDisplayScale(
Tcl_DStringAppend(&buf, scalePtr->command, -1);
Tcl_DStringAppend(&buf, " ", -1);
Tcl_DStringAppend(&buf, string, -1);
- result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
Tcl_DStringFree(&buf);
if (result != TCL_OK) {
Tcl_AddErrorInfo(interp, "\n (command executed by scale)");
@@ -215,11 +213,8 @@ TkpDisplayScale(
* Set up port for drawing Macintosh control.
*/
- macDraw = (MacDrawable *) Tk_WindowId(tkwin);
- destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin));
- windowRef = TkMacOSXDrawableWindow(Tk_WindowId(tkwin));
- portChanged = QDSwapPort(destPort, &savePort);
- TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin));
+ macDraw = (MacDrawable *)Tk_WindowId(tkwin);
+ windowRef = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));
/*
* Create Macintosh control.
@@ -293,9 +288,6 @@ TkpDisplayScale(
HiliteControl(macScalePtr->scaleHandle, 0);
Draw1Control(macScalePtr->scaleHandle);
- if (portChanged) {
- QDSwapPort(savePort, NULL);
- }
done:
scalePtr->flags &= ~REDRAW_ALL;
}
@@ -327,14 +319,10 @@ TkpScaleElement(
ControlPartCode part;
Point where;
Rect bounds;
- CGrafPtr destPort, savePort;
- Boolean portChanged;
#ifdef TK_MAC_DEBUG_SCALE
TkMacOSXDbgMsg("TkpScaleElement");
#endif
- destPort = TkMacOSXGetDrawablePort(Tk_WindowId(scalePtr->tkwin));
- portChanged = QDSwapPort(destPort, &savePort);
/*
* All of the calculations in this procedure mirror those in
@@ -346,10 +334,6 @@ TkpScaleElement(
where.v = y + bounds.top;
part = TestControl(macScalePtr->scaleHandle, where);
- if (portChanged) {
- QDSwapPort(savePort, NULL);
- }
-
#ifdef TK_MAC_DEBUG_SCALE
fprintf (stderr,"ScalePart %d, pos ( %d %d )\n", part, where.h, where.v );
#endif
@@ -401,8 +385,6 @@ MacScaleEventProc(
Point where;
Rect bounds;
int part;
- CGrafPtr destPort, savePort;
- Boolean portChanged;
#ifdef TK_MAC_DEBUG_SCALE
fprintf(stderr,"MacScaleEventProc\n" );
@@ -414,14 +396,6 @@ MacScaleEventProc(
* control was hit and act accordingly.
*/
- destPort = TkMacOSXGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin));
- portChanged = QDSwapPort(destPort, &savePort);
- TkMacOSXSetUpClippingRgn(Tk_WindowId(macScalePtr->info.tkwin));
-
- TkMacOSXWinBounds((TkWindow *) macScalePtr->info.tkwin, &bounds);
- where.h = eventPtr->xbutton.x + bounds.left;
- where.v = eventPtr->xbutton.y + bounds.top;
-#ifdef TK_MAC_DEBUG_SCALE
TkMacOSXDbgMsg("calling TestControl");
#endif
part = TestControl(macScalePtr->scaleHandle, where);
@@ -447,10 +421,6 @@ MacScaleEventProc(
*/
TkGenerateButtonEventForXPointer(Tk_WindowId(macScalePtr->info.tkwin));
-
- if (portChanged) {
- QDSwapPort(savePort, NULL);
- }
}
/*
diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c
index a49ec55..3149b15 100644
--- a/macosx/tkMacOSXScrlbr.c
+++ b/macosx/tkMacOSXScrlbr.c
@@ -174,8 +174,8 @@ static void drawMacScrollbar(
MacScrollbar *msPtr,
CGContextRef context)
{
- MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
- NSView *view = TkMacOSXDrawableView(macWin);
+ Drawable d = Tk_WindowId(scrollPtr->tkwin);
+ NSView *view = TkMacOSXGetNSViewForDrawable(d);
CGPathRef path;
CGPoint inner[2], outer[2], thumbOrigin;
CGSize thumbSize;
@@ -258,12 +258,12 @@ TkpDisplayScrollbar(
return;
}
- MacDrawable *macWin = (MacDrawable *) winPtr->window;
- NSView *view = TkMacOSXDrawableView(macWin);
+ MacDrawable *macWin = (MacDrawable *)winPtr->window;
+ NSView *view = TkMacOSXGetNSViewForDrawable(macWin);
if ((view == NULL)
|| (macWin->flags & TK_DO_NOT_DRAW)
- || !TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
+ || !TkMacOSXSetupDrawingContext((Drawable)macWin, NULL, &dc)) {
return;
}
@@ -316,7 +316,7 @@ TkpDisplayScrollbar(
if (SNOW_LEOPARD_STYLE) {
HIThemeDrawTrack(&msPtr->info, 0, dc.context,
kHIThemeOrientationInverted);
- } else if ([NSApp macMinorVersion] <= 8) {
+ } else if ([NSApp macOSVersion] <= 100800) {
HIThemeDrawTrack(&msPtr->info, 0, dc.context,
kHIThemeOrientationNormal);
} else {
@@ -377,7 +377,7 @@ TkpComputeScrollbarGeometry(
scrollPtr->highlightWidth = 0;
}
scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
- if ([NSApp macMinorVersion] == 6) {
+ if ([NSApp macOSVersion] == 100600) {
scrollPtr->arrowLength = scrollPtr->width;
} else {
scrollPtr->arrowLength = 0;
@@ -590,12 +590,12 @@ UpdateControlValues(
{
MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
Tk_Window tkwin = scrollPtr->tkwin;
- MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
+ MacDrawable *macWin = (MacDrawable *)Tk_WindowId(scrollPtr->tkwin);
double dViewSize;
HIRect contrlRect;
short width, height;
- NSView *view = TkMacOSXDrawableView(macWin);
+ NSView *view = TkMacOSXGetNSViewForDrawable(macWin);
CGFloat viewHeight = [view bounds].size.height;
NSRect frame;
@@ -662,7 +662,7 @@ UpdateControlValues(
*
* ScrollbarEvent --
*
- * This procedure is invoked in response to <ButtonPress>,
+ * This procedure is invoked in response to <Button>,
* <ButtonRelease>, <EnterNotify>, and <LeaveNotify> events. The
* Scrollbar appearance is modified for each event.
*
diff --git a/macosx/tkMacOSXSend.c b/macosx/tkMacOSXSend.c
index 71a86df..8cc00d3 100644
--- a/macosx/tkMacOSXSend.c
+++ b/macosx/tkMacOSXSend.c
@@ -3,7 +3,7 @@
*
* This file provides procedures that implement the "send" command,
* allowing commands to be passed from interpreter to interpreter. This
- * current implementation for the Mac has most functionality stubed out.
+ * current implementation for the Mac has most functionality stubbed out.
*
* The current plan, which we have not had time to implement, is for the
* first Wish app to create a gestalt of type 'WIsH'. This gestalt will
diff --git a/macosx/tkMacOSXServices.c b/macosx/tkMacOSXServices.c
index 974fec1..6e1a9a1 100644
--- a/macosx/tkMacOSXServices.c
+++ b/macosx/tkMacOSXServices.c
@@ -20,12 +20,10 @@
static int
ServicesEventProc(
- Tcl_Event *event,
- int flags)
+ TCL_UNUSED(Tcl_Event *),
+ TCL_UNUSED(int))
{
TkMainInfo *info = TkGetMainInfoList();
- (void)event;
- (void)flags;
Tcl_GlobalEval(info->interp, "::tk::mac::PerformService");
return 1;
@@ -143,9 +141,8 @@ ServicesEventProc(
int
TkMacOSXServices_Init(
- Tcl_Interp *dummy)
+ TCL_UNUSED(Tcl_Interp *))
{
- (void)dummy;
/*
* Initialize an instance of TkService and register it with the NSApp.
*/
diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c
index 611afd7..d2979f6 100644
--- a/macosx/tkMacOSXSubwindows.c
+++ b/macosx/tkMacOSXSubwindows.c
@@ -14,6 +14,7 @@
#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"
#include "tkMacOSXWm.h"
+#include "tkMacOSXConstants.h"
/*
#ifdef TK_MAC_DEBUG
@@ -38,7 +39,7 @@ static void NotifyVisibility(TkWindow *winPtr, XEvent *eventPtr);
*
* XDestroyWindow --
*
- * Dealocates the given X Window.
+ * Deallocates the given X Window.
*
* Results:
* The window id is returned.
@@ -51,11 +52,10 @@ static void NotifyVisibility(TkWindow *winPtr, XEvent *eventPtr);
int
XDestroyWindow(
- Display *display, /* Display. */
+ TCL_UNUSED(Display *), /* Display. */
Window window) /* Window. */
{
- MacDrawable *macWin = (MacDrawable *) window;
- (void)display;
+ MacDrawable *macWin = (MacDrawable *)window;
/*
* Remove any dangling pointers that may exist if the window we are
@@ -69,7 +69,7 @@ XDestroyWindow(
if (!Tk_IsTopLevel(macWin->winPtr)) {
TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
if (macWin->winPtr->parentPtr != NULL) {
- TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr);
+ TkMacOSXInvalClipRgns((Tk_Window)macWin->winPtr->parentPtr);
}
if (macWin->visRgn) {
CFRelease(macWin->visRgn);
@@ -120,14 +120,18 @@ XDestroyWindow(
*
* XMapWindow --
*
- * Map the given X Window to the screen. See X window documentation for
- * more details.
+ * This X11 stub maps the given X11 Window but does not update any of
+ * the Tk structures describing the window. Tk applications should
+ * never call this directly, but it is called by Tk_MapWindow and
+ * Tk_WmMapWindow.
*
* Results:
- * None.
+ * Returns Success or BadWindow.
*
* Side effects:
- * The subwindow or toplevel may appear on the screen.
+ * The subwindow or toplevel may appear on the screen. VisibilityNotify
+ * events are generated.
+ *
*
*----------------------------------------------------------------------
*/
@@ -137,10 +141,13 @@ XMapWindow(
Display *display, /* Display. */
Window window) /* Window. */
{
- MacDrawable *macWin = (MacDrawable *) window;
+ if (!window) {
+ return BadWindow;
+ }
+ MacDrawable *macWin = (MacDrawable *)window;
TkWindow *winPtr = macWin->winPtr;
- NSWindow *win = TkMacOSXDrawableWindow(window);
- XEvent event;
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);
+ static Bool initialized = NO;
/*
* Under certain situations it's possible for this function to be called
@@ -155,9 +162,9 @@ XMapWindow(
}
display->request++;
- winPtr->flags |= TK_MAPPED;
if (Tk_IsTopLevel(winPtr)) {
if (!Tk_IsEmbedded(winPtr)) {
+ TKContentView *view = [win contentView];
/*
* We want to activate Tk when a toplevel is mapped but we must not
@@ -169,12 +176,14 @@ XMapWindow(
TkMacOSXApplyWindowAttributes(winPtr, win);
[win setExcludedFromWindowsMenu:NO];
- [NSApp activateIgnoringOtherApps:NO];
- [[win contentView] setNeedsDisplay:YES];
- if ([win canBecomeKeyWindow]) {
- [win makeKeyAndOrderFront:NSApp];
- } else {
- [win orderFrontRegardless];
+ [NSApp activateIgnoringOtherApps:initialized];
+ [view addTkDirtyRect: [view bounds]];
+ if (initialized) {
+ if ([win canBecomeKeyWindow]) {
+ [win makeKeyAndOrderFront:NSApp];
+ } else {
+ [win orderFrontRegardless];
+ }
}
} else {
TkWindow *contWinPtr = TkpGetOtherWindow(winPtr);
@@ -184,25 +193,10 @@ XMapWindow(
* the window.
*/
- TkMacOSXInvalClipRgns((Tk_Window) contWinPtr);
+ TkMacOSXInvalClipRgns((Tk_Window)contWinPtr);
TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
}
-
- TkMacOSXInvalClipRgns((Tk_Window) winPtr);
-
- /*
- * We only need to send the MapNotify event for toplevel windows.
- */
-
- event.xany.serial = LastKnownRequestProcessed(display);
- event.xany.send_event = False;
- event.xany.display = display;
-
- event.xmap.window = window;
- event.xmap.type = MapNotify;
- event.xmap.event = window;
- event.xmap.override_redirect = winPtr->atts.override_redirect;
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ TkMacOSXInvalClipRgns((Tk_Window)winPtr);
} else {
/*
@@ -210,24 +204,33 @@ XMapWindow(
* and redisplay the window.
*/
- TkMacOSXInvalClipRgns((Tk_Window) winPtr->parentPtr);
+ TkMacOSXInvalClipRgns((Tk_Window)winPtr->parentPtr);
}
- if ([NSApp isDrawing]) {
- [[win contentView] setNeedsRedisplay:YES];
- } else {
- [[win contentView] setNeedsDisplay:YES];
+ /*
+ * Mark the toplevel as needing to be redrawn, unless the window is being
+ * mapped while drawing is taking place.
+ */
+
+ TKContentView *view = [win contentView];
+ if (view != [NSView focusView]) {
+ [view addTkDirtyRect:[view bounds]];
}
/*
* Generate VisibilityNotify events for window and all mapped children.
*/
- event.xany.send_event = False;
- event.xany.display = display;
- event.xvisibility.type = VisibilityNotify;
- event.xvisibility.state = VisibilityUnobscured;
- NotifyVisibility(winPtr, &event);
+ if (initialized) {
+ XEvent event;
+ event.xany.send_event = False;
+ event.xany.display = display;
+ event.xvisibility.type = VisibilityNotify;
+ event.xvisibility.state = VisibilityUnobscured;
+ NotifyVisibility(winPtr, &event);
+ } else {
+ initialized = YES;
+ }
return Success;
}
@@ -270,11 +273,13 @@ NotifyVisibility(
*
* XUnmapWindow --
*
- * Unmap the given X Window to the screen. See X window documentation for
- * more details.
+ * This X11 stub maps the given X11 Window but does not update any of
+ * The Tk structures describing the window. Tk applications should
+ * never call this directly, but it is called by Tk_UnmapWindow and
+ * Tk_WmUnmapWindow.
*
* Results:
- * None.
+ * Always returns Success or BadWindow.
*
* Side effects:
* The subwindow or toplevel may be removed from the screen.
@@ -287,33 +292,22 @@ XUnmapWindow(
Display *display, /* Display. */
Window window) /* Window. */
{
- MacDrawable *macWin = (MacDrawable *) window;
+ MacDrawable *macWin = (MacDrawable *)window;
TkWindow *winPtr = macWin->winPtr;
TkWindow *parentPtr = winPtr->parentPtr;
- NSWindow *win = TkMacOSXDrawableWindow(window);
- XEvent event;
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(window);
+ if (!window) {
+ return BadWindow;
+ }
display->request++;
if (Tk_IsTopLevel(winPtr)) {
if (!Tk_IsEmbedded(winPtr) &&
winPtr->wmInfoPtr->hints.initial_state!=IconicState) {
[win orderOut:nil];
+ [win setExcludedFromWindowsMenu:YES];
}
- TkMacOSXInvalClipRgns((Tk_Window) winPtr);
-
- /*
- * We only need to send the UnmapNotify event for toplevel windows.
- */
-
- event.xany.serial = LastKnownRequestProcessed(display);
- event.xany.send_event = False;
- event.xany.display = display;
-
- event.xunmap.type = UnmapNotify;
- event.xunmap.window = window;
- event.xunmap.event = window;
- event.xunmap.from_configure = false;
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ TkMacOSXInvalClipRgns((Tk_Window)winPtr);
} else {
/*
* Rebuild the visRgn clip region for the parent so it will be allowed
@@ -323,17 +317,15 @@ XUnmapWindow(
if (parentPtr && parentPtr->privatePtr->visRgn) {
TkMacOSXInvalidateViewRegion(
- TkMacOSXDrawableView(parentPtr->privatePtr),
+ TkMacOSXGetNSViewForDrawable(parentPtr->privatePtr),
parentPtr->privatePtr->visRgn);
}
- TkMacOSXInvalClipRgns((Tk_Window) parentPtr);
+ TkMacOSXInvalClipRgns((Tk_Window)parentPtr);
TkMacOSXUpdateClipRgn(parentPtr);
}
- winPtr->flags &= ~TK_MAPPED;
- if ([NSApp isDrawing]) {
- [[win contentView] setNeedsRedisplay:YES];
- } else {
- [[win contentView] setNeedsDisplay:YES];
+ TKContentView *view = [win contentView];
+ if (view != [NSView focusView]) {
+ [view addTkDirtyRect:[view bounds]];
}
return Success;
}
@@ -362,19 +354,23 @@ XResizeWindow(
unsigned int width,
unsigned int height)
{
- MacDrawable *macWin = (MacDrawable *) window;
+ MacDrawable *macWin = (MacDrawable *)window;
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
- NSWindow *w = macWin->winPtr->wmInfoPtr->window;
+ TKWindow *w = (TKWindow *)macWin->winPtr->wmInfoPtr->window;
if (w) {
- NSRect r = [w contentRectForFrameRect:[w frame]];
+ if ([w styleMask] & NSFullScreenWindowMask) {
+ [w tkLayoutChanged];
+ } else {
+ NSRect r = [w contentRectForFrameRect:[w frame]];
- r.origin.y += r.size.height - height;
- r.size.width = width;
- r.size.height = height;
- [w setFrame:[w frameRectForContentRect:r] display:YES];
+ r.origin.y += r.size.height - height;
+ r.size.width = width;
+ r.size.height = height;
+ [w setFrame:[w frameRectForContentRect:r] display:NO];
+ }
}
} else {
MoveResizeWindow(macWin);
@@ -407,7 +403,7 @@ XMoveResizeWindow(
unsigned int width,
unsigned int height)
{
- MacDrawable *macWin = (MacDrawable *) window;
+ MacDrawable *macWin = (MacDrawable *)window;
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
@@ -430,7 +426,7 @@ XMoveResizeWindow(
X + XOff, TkMacOSXZeroScreenHeight() - Y - YOff - Height,
Width, Height);
- [w setFrame:[w frameRectForContentRect:r] display:YES];
+ [w setFrame:[w frameRectForContentRect:r] display:NO];
}
} else {
MoveResizeWindow(macWin);
@@ -460,7 +456,7 @@ XMoveWindow(
Window window, /* Window. */
int x, int y)
{
- MacDrawable *macWin = (MacDrawable *) window;
+ MacDrawable *macWin = (MacDrawable *)window;
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
@@ -498,7 +494,7 @@ MoveResizeWindow(
{
int deltaX = 0, deltaY = 0, parentBorderwidth = 0;
MacDrawable *macParent = NULL;
- NSWindow *macWindow = TkMacOSXDrawableWindow((Drawable) macWin);
+ NSWindow *macWindow = TkMacOSXGetNSWindowForDrawable((Drawable)macWin);
/*
* Find the Parent window, for an embedded window it will be its container.
@@ -535,7 +531,7 @@ MoveResizeWindow(
if (macWindow) {
TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW);
if (macParent) {
- TkMacOSXInvalClipRgns((Tk_Window) macParent->winPtr);
+ TkMacOSXInvalClipRgns((Tk_Window)macParent->winPtr);
}
}
UpdateOffsets(macWin->winPtr, deltaX, deltaY);
@@ -603,7 +599,7 @@ XRaiseWindow(
Display *display, /* Display. */
Window window) /* Window. */
{
- MacDrawable *macWin = (MacDrawable *) window;
+ MacDrawable *macWin = (MacDrawable *)window;
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
@@ -637,7 +633,7 @@ XLowerWindow(
Display *display, /* Display. */
Window window) /* Window. */
{
- MacDrawable *macWin = (MacDrawable *) window;
+ MacDrawable *macWin = (MacDrawable *)window;
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
@@ -673,11 +669,10 @@ XConfigureWindow(
Display *display, /* Display. */
Window w, /* Window. */
unsigned int value_mask,
- XWindowChanges *values)
+ TCL_UNUSED(XWindowChanges *))
{
- MacDrawable *macWin = (MacDrawable *) w;
+ MacDrawable *macWin = (MacDrawable *)w;
TkWindow *winPtr = macWin->winPtr;
- (void)values;
display->request++;
@@ -698,17 +693,11 @@ XConfigureWindow(
*/
if (value_mask & CWStackMode) {
- NSView *view = TkMacOSXDrawableView(macWin);
- Rect bounds;
- NSRect r;
+ NSView *view = TkMacOSXGetNSViewForDrawable(macWin);
if (view) {
- 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 setNeedsDisplayInRect:r];
+ TkMacOSXInvalClipRgns((Tk_Window)winPtr->parentPtr);
+ TkpRedrawWidget((Tk_Window)winPtr);
}
}
@@ -827,7 +816,7 @@ TkMacOSXUpdateClipRgn(
/*
* Clip away the area of any windows that may obscure this window.
- * For a non-toplevel window, first, clip to the parents visible
+ * For a non-toplevel window, first, clip to the parent's visible
* clip region. Second, clip away any siblings that are higher in
* the stacking order. For an embedded toplevel, just clip to the
* container's visible clip region. Remember, we only allow one
@@ -856,15 +845,6 @@ TkMacOSXUpdateClipRgn(
TkMacOSXUpdateClipRgn(win2Ptr);
ChkErr(HIShapeIntersect,
win2Ptr->privatePtr->aboveVisRgn, rgn, rgn);
- } else if (tkMacOSXEmbedHandler != NULL) {
- Region r = XCreateRegion();
- HIShapeRef visRgn;
-
- tkMacOSXEmbedHandler->getClipProc((Tk_Window) winPtr, r);
- visRgn = TkMacOSXGetNativeRegion(r);
- ChkErr(HIShapeIntersect, visRgn, rgn, rgn);
- CFRelease(visRgn);
- TkpReleaseRegion(r);
}
/*
@@ -988,13 +968,13 @@ TkMacOSXVisableClipRgn(
static OSStatus
InvalViewRect(
int msg,
- HIShapeRef rgn,
+ TCL_UNUSED(HIShapeRef),
const CGRect *rect,
void *ref)
{
static CGAffineTransform t;
- NSView *view = ref;
- (void)rgn;
+ TKContentView *view = ref;
+ NSRect dirtyRect;
if (!view) {
return paramErr;
@@ -1005,8 +985,8 @@ InvalViewRect(
NSHeight([view bounds]));
break;
case kHIShapeEnumerateRect:
- [view setNeedsDisplayInRect:NSRectFromCGRect(
- CGRectApplyAffineTransform(*rect, t))];
+ dirtyRect = NSRectFromCGRect(CGRectApplyAffineTransform(*rect, t));
+ [view addTkDirtyRect:dirtyRect];
break;
}
return noErr;
@@ -1052,16 +1032,17 @@ TkMacOSXInvalidateWindow(
if (macWin->flags & TK_CLIP_INVALID) {
TkMacOSXUpdateClipRgn(macWin->winPtr);
}
- TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(macWin),
+ TkMacOSXInvalidateViewRegion(TkMacOSXGetNSViewForDrawable(macWin),
(flag == TK_WINDOW_ONLY) ? macWin->visRgn : macWin->aboveVisRgn);
}
/*
*----------------------------------------------------------------------
*
- * TkMacOSXDrawableWindow --
+ * TkMacOSXGetNSWindowForDrawable --
*
- * This function returns the NSWindow for a given X drawable.
+ * This function returns the NSWindow for a given X drawable, if the
+ * drawable is a window. If the drawable is a pixmap it returns nil.
*
* Results:
* A NSWindow, or nil for off screen pixmaps.
@@ -1072,11 +1053,11 @@ TkMacOSXInvalidateWindow(
*----------------------------------------------------------------------
*/
-NSWindow *
-TkMacOSXDrawableWindow(
+void *
+Tk_MacOSXGetNSWindowForDrawable(
Drawable drawable)
{
- MacDrawable *macWin = (MacDrawable *) drawable;
+ MacDrawable *macWin = (MacDrawable *)drawable;
NSWindow *result = nil;
if (!macWin || macWin->flags & TK_IS_PIXMAP) {
@@ -1092,50 +1073,25 @@ TkMacOSXDrawableWindow(
TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
if (contWinPtr) {
- result = TkMacOSXDrawableWindow((Drawable) contWinPtr->privatePtr);
+ result = TkMacOSXGetNSWindowForDrawable((Drawable)contWinPtr->privatePtr);
}
}
return result;
}
-
-void *
-TkMacOSXDrawable(
- Drawable drawable)
-{
- return TkMacOSXDrawableWindow(drawable);
-}
/*
*----------------------------------------------------------------------
*
- * TkMacOSXGetDrawablePort --
- *
- * This function returns the Graphics Port for a given X drawable.
- *
- * Results:
- * NULL.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void *
-TkMacOSXGetDrawablePort(
- Drawable drawable)
-{
- (void)drawable;
-
- return NULL;
-}
-
-/*
- *----------------------------------------------------------------------
+ * TkMacOSXGetNSViewForDrawable/TkMacOSXGetRootControl --
*
- * TkMacOSXDrawableView --
+ * The function name TkMacOSXGetRootControl is being preserved only
+ * because it exists in a stubs table. Nobody knows what it means to
+ * get a "RootControl". The macro TkMacOSXGetNSViewForDrawable calls
+ * this function and should always be used rather than directly using
+ * the obscure official name of this function.
*
- * This function returns the NSView for a given X drawable.
+ * It returns the NSView for a given X drawable in the case that the
+ * drawable is a window. If the drawable is a pixmap it returns nil.
*
* Results:
* A NSView* or nil.
@@ -1146,14 +1102,15 @@ TkMacOSXGetDrawablePort(
*----------------------------------------------------------------------
*/
-NSView *
-TkMacOSXDrawableView(
- MacDrawable *macWin)
+void *
+TkMacOSXGetRootControl(
+ Drawable drawable)
{
- NSView *result = nil;
+ void *result = NULL;
+ MacDrawable *macWin = (MacDrawable *)drawable;
if (!macWin) {
- result = nil;
+ result = NULL;
} else if (!macWin->toplevel) {
result = macWin->view;
} else if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
@@ -1162,7 +1119,7 @@ TkMacOSXDrawableView(
TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
if (contWinPtr) {
- result = TkMacOSXDrawableView(contWinPtr->privatePtr);
+ result = TkMacOSXGetRootControl((Drawable)contWinPtr->privatePtr);
}
}
return result;
@@ -1171,33 +1128,6 @@ TkMacOSXDrawableView(
/*
*----------------------------------------------------------------------
*
- * TkMacOSXGetRootControl --
- *
- * This function returns the NSView for a given X drawable.
- *
- * Results:
- * A NSView* .
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void *
-TkMacOSXGetRootControl(
- Drawable drawable)
-{
- /*
- * will probably need to fix this up for embedding
- */
-
- return TkMacOSXDrawableView((MacDrawable *) drawable);
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TkMacOSXInvalClipRgns --
*
* This function invalidates the clipping regions for a given window and
@@ -1258,7 +1188,7 @@ TkMacOSXInvalClipRgns(
childPtr = winPtr->childList;
while (childPtr) {
if (!Tk_IsTopLevel(childPtr)) {
- TkMacOSXInvalClipRgns((Tk_Window) childPtr);
+ TkMacOSXInvalClipRgns((Tk_Window)childPtr);
}
childPtr = childPtr->nextPtr;
}
@@ -1271,7 +1201,7 @@ TkMacOSXInvalClipRgns(
childPtr = TkpGetOtherWindow(winPtr);
if (childPtr) {
- TkMacOSXInvalClipRgns((Tk_Window) childPtr);
+ TkMacOSXInvalClipRgns((Tk_Window)childPtr);
}
/*
@@ -1285,7 +1215,7 @@ TkMacOSXInvalClipRgns(
*
* TkMacOSXWinBounds --
*
- * Given a Tk window this function determines the windows bounds in
+ * Given a Tk window this function determines the window's bounds in
* relation to the Macintosh window's coordinate system. This is also the
* same coordinate system as the Tk toplevel window in which this window
* is contained.
@@ -1294,7 +1224,7 @@ TkMacOSXInvalClipRgns(
* None.
*
* Side effects:
- * None.
+ * Fills in a Rect.
*
*----------------------------------------------------------------------
*/
@@ -1317,16 +1247,15 @@ TkMacOSXWinBounds(
*
* TkMacOSXWinCGBounds --
*
- * Given a Tk window this function determines the windows bounds in
- * relation to the Macintosh window's coordinate system. This is also the
- * same coordinate system as the Tk toplevel window in which this window
- * is contained.
+ * Given a Tk window this function determines the window's bounds in
+ * the coordinate system of the Tk toplevel window in which this window
+ * is contained. This fills in a CGRect struct.
*
* Results:
* None.
*
* Side effects:
- * None.
+ * Fill in a CGRect.
*
*----------------------------------------------------------------------
*/
@@ -1341,6 +1270,39 @@ TkMacOSXWinCGBounds(
bounds->size.width = winPtr->changes.width;
bounds->size.height = winPtr->changes.height;
}
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXWinNSBounds --
+ *
+ * Given a Tk window this function determines the window's bounds in
+ * the coordinate system of the TKContentView in which this Tk window
+ * is contained, which has the origin at the lower left corner. This
+ * fills in an NSRect struct and requires the TKContentView as a
+ * parameter
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Fills in an NSRect.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXWinNSBounds(
+ TkWindow *winPtr,
+ NSView *view,
+ NSRect *bounds)
+{
+ bounds->size.width = winPtr->changes.width;
+ bounds->size.height = winPtr->changes.height;
+ bounds->origin.x = winPtr->privatePtr->xOff;
+ bounds->origin.y = ([view bounds].size.height -
+ bounds->size.height -
+ winPtr->privatePtr->yOff);
+}
/*
*----------------------------------------------------------------------
@@ -1421,13 +1383,12 @@ UpdateOffsets(
Pixmap
Tk_GetPixmap(
Display *display, /* Display for new pixmap (can be null). */
- Drawable d, /* Drawable where pixmap will be used (ignored). */
+ TCL_UNUSED(Drawable), /* Drawable where pixmap will be used (ignored). */
int width, /* Dimensions of pixmap. */
int height,
int depth) /* Bits per pixel for pixmap. */
{
MacDrawable *macPix;
- (void)d;
if (display != NULL) {
display->request++;
@@ -1470,7 +1431,7 @@ Tk_FreePixmap(
Display *display, /* Display. */
Pixmap pixmap) /* Pixmap to destroy */
{
- MacDrawable *macPix = (MacDrawable *) pixmap;
+ MacDrawable *macPix = (MacDrawable *)pixmap;
display->request++;
if (macPix->context) {
diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c
index 2d22824..4ded4de 100644
--- a/macosx/tkMacOSXTest.c
+++ b/macosx/tkMacOSXTest.c
@@ -14,6 +14,8 @@
#include "tkMacOSXPrivate.h"
#include "tkMacOSXConstants.h"
+#include "tkMacOSXWm.h"
+
/*
* Forward declarations of procedures defined later in this file:
@@ -24,9 +26,11 @@ static int DebuggerObjCmd (ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
#endif
static int PressButtonObjCmd (ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *const objv[]);
+ int objc, Tcl_Obj *const *objv);
static int InjectKeyEventObjCmd (ClientData dummy, Tcl_Interp *interp,
- int objc, Tcl_Obj *const objv[]);
+ int objc, Tcl_Obj *const *objv);
+static int MenuBarHeightObjCmd (ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
/*
@@ -59,7 +63,7 @@ TkplatformtestInit(
#endif
Tcl_CreateObjCommand(interp, "pressbutton", PressButtonObjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "injectkeyevent", InjectKeyEventObjCmd, NULL, NULL);
-
+ Tcl_CreateObjCommand(interp, "menubarheight", MenuBarHeightObjCmd, NULL, NULL);
return TCL_OK;
}
@@ -96,21 +100,48 @@ DebuggerObjCmd(
/*
*----------------------------------------------------------------------
*
+ * MenuBarHeightObjCmd --
+ *
+ * This procedure calls [NSMenu menuBarHeight] and returns the result
+ * as an integer. Windows can never be placed to overlap the MenuBar,
+ * so tests need to be aware of its size.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+MenuBarHeightObjCmd(
+ TCL_UNUSED(void *), /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ TCL_UNUSED(int), /* Not used. */
+ TCL_UNUSED(Tcl_Obj *const *)) /* Not used. */
+{
+ static int height = 0;
+ if (height == 0) {
+ height = (int) [[NSApp mainMenu] menuBarHeight];
+ }
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(height));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* 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.
+ * should write a log message recording that it has being run.
*
* Results:
- * 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].
+ * Returns true if and only if the NSView of the drawable is the
+ * current focusView, which on 10.14 and newer systems can only be the
+ * case when within [NSView drawRect].
*
* Side effects:
* None
@@ -118,11 +149,23 @@ DebuggerObjCmd(
*----------------------------------------------------------------------
*/
MODULE_SCOPE Bool
-TkTestLogDisplay(void) {
- if ([NSApp macMinorVersion] >= 14) {
- return [NSApp isDrawing];
+TkTestLogDisplay(
+ Drawable drawable)
+{
+ MacDrawable *macWin = (MacDrawable *)drawable;
+ NSWindow *win = nil;
+ if (macWin->toplevel && macWin->toplevel->winPtr &&
+ macWin->toplevel->winPtr->wmInfoPtr &&
+ macWin->toplevel->winPtr->wmInfoPtr->window) {
+ win = macWin->toplevel->winPtr->wmInfoPtr->window;
+ } else if (macWin->winPtr && macWin->winPtr->wmInfoPtr &&
+ macWin->winPtr->wmInfoPtr->window) {
+ win = macWin->winPtr->wmInfoPtr->window;
+ }
+ if (win) {
+ return ([win contentView] == [NSView focusView]);
} else {
- return ![NSApp isDrawing];
+ return True;
}
}
@@ -132,9 +175,11 @@ TkTestLogDisplay(void) {
* 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.
+ * 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. These events have
+ * their unused context property set to 1 as a signal indicating that they
+ * should not be ignored by [NSApp tkProcessMouseEvent].
*
* Results:
* A standard Tcl result.
@@ -147,19 +192,19 @@ TkTestLogDisplay(void) {
static int
PressButtonObjCmd(
- ClientData dummy,
+ TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
- int x = 0, y = 0, i, value, wNum;
+ int x = 0, y = 0, i, value;
+ NSInteger signal = -1;
CGPoint pt;
NSPoint loc;
NSEvent *motion, *press, *release;
NSArray *screens = [NSScreen screens];
CGFloat ScreenHeight = 0;
enum {X=1, Y};
- (void)dummy;
if (screens && [screens count]) {
ScreenHeight = [[screens objectAtIndex:0] frame].size.height;
@@ -187,15 +232,20 @@ PressButtonObjCmd(
pt.x = loc.x = x;
pt.y = y;
loc.y = ScreenHeight - y;
- wNum = 0;
+
+ /*
+ * We set the window number and the eventNumber to -1 as a signal to
+ * processMouseEvent.
+ */
+
CGWarpMouseCursorPosition(pt);
motion = [NSEvent mouseEventWithType:NSMouseMoved
location:loc
modifierFlags:0
timestamp:GetCurrentEventTime()
- windowNumber:wNum
+ windowNumber:signal
context:nil
- eventNumber:0
+ eventNumber:signal
clickCount:1
pressure:0.0];
[NSApp postEvent:motion atStart:NO];
@@ -203,9 +253,9 @@ PressButtonObjCmd(
location:loc
modifierFlags:0
timestamp:GetCurrentEventTime()
- windowNumber:wNum
+ windowNumber:signal
context:nil
- eventNumber:1
+ eventNumber:signal
clickCount:1
pressure:0.0];
[NSApp postEvent:press atStart:NO];
@@ -213,18 +263,18 @@ PressButtonObjCmd(
location:loc
modifierFlags:0
timestamp:GetCurrentEventTime()
- windowNumber:wNum
+ windowNumber:signal
context:nil
- eventNumber:2
+ eventNumber:signal
clickCount:1
- pressure:0.0];
+ pressure:-1.0];
[NSApp postEvent:release atStart:NO];
return TCL_OK;
}
static int
InjectKeyEventObjCmd(
- ClientData dummy,
+ TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
@@ -241,7 +291,6 @@ InjectKeyEventObjCmd(
NSEvent *keyEvent;
NSUInteger type;
MacKeycode macKC;
- (void)dummy;
if (objc < 3) {
wrongArgs:
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index 71e687b..30a2d57 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -30,17 +30,17 @@
* Declaration of functions used only in this file
*/
-static int GenerateUpdates(HIShapeRef updateRgn,
- CGRect *updateBounds, TkWindow *winPtr);
+static int GenerateUpdates(
+ CGRect *updateBounds, TkWindow *winPtr);
static int GenerateActivateEvents(TkWindow *winPtr,
int activeFlag);
-static void DoWindowActivate(ClientData clientData);
#pragma mark TKApplication(TKWindowEvent)
-#ifdef TK_MAC_DEBUG_NOTIFICATIONS
-extern NSString *NSWindowWillOrderOnScreenNotification;
extern NSString *NSWindowDidOrderOnScreenNotification;
+extern NSString *NSWindowWillOrderOnScreenNotification;
+
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
extern NSString *NSWindowDidOrderOffScreenNotification;
#endif
@@ -90,15 +90,12 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
height = bounds.size.height - wmPtr->yInParent;
flags |= TK_SIZE_CHANGED;
}
- if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
- /*
- * Propagate geometry changes immediately.
- */
-
- flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
- }
+ /*
+ * Propagate geometry changes immediately.
+ */
- TkGenWMConfigureEvent((Tk_Window) winPtr, x, y, width, height, flags);
+ flags |= TK_MACOSX_HANDLE_EVENT_IMMEDIATELY;
+ TkGenWMConfigureEvent((Tk_Window)winPtr, x, y, width, height, flags);
}
}
@@ -114,25 +111,21 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
if (winPtr) {
winPtr->wmInfoPtr->hints.initial_state =
TkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState;
- Tk_MapWindow((Tk_Window) winPtr);
- if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
+ Tk_MapWindow((Tk_Window)winPtr);
- /*
- * Process all Tk events generated by Tk_MapWindow().
- */
+ /*
+ * Process all Tk events generated by Tk_MapWindow().
+ */
- while (Tcl_ServiceEvent(0)) {}
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
+ while (Tcl_ServiceEvent(0)) {}
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
- /*
- * NSWindowDidDeminiaturizeNotification is received after
- * NSWindowDidBecomeKeyNotification, so activate manually
- */
+ /*
+ * NSWindowDidDeminiaturizeNotification is received after
+ * NSWindowDidBecomeKeyNotification, so activate manually
+ */
- GenerateActivateEvents(winPtr, 1);
- } else {
- Tcl_DoWhenIdle(DoWindowActivate, winPtr);
- }
+ GenerateActivateEvents(winPtr, 1);
}
}
@@ -154,6 +147,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
willUseFullScreenContentSize:(NSSize)proposedSize
{
(void)window;
+
/*
* 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
@@ -188,7 +182,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
- Tk_UnmapWindow((Tk_Window) winPtr);
+ Tk_UnmapWindow((Tk_Window)winPtr);
}
}
@@ -200,7 +194,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
- TkGenWMDestroyEvent((Tk_Window) winPtr);
+ TkGenWMDestroyEvent((Tk_Window)winPtr);
}
/*
@@ -211,33 +205,45 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
return (winPtr ? NO : YES);
}
-#ifdef TK_MAC_DEBUG_NOTIFICATIONS
-
-- (void) windowDragStart: (NSNotification *) notification
+- (void) windowBecameVisible: (NSNotification *) notification
{
- TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
-}
+ NSWindow *window = [notification object];
+ TkWindow *winPtr = TkMacOSXGetTkWindow(window);
+ if (winPtr) {
+ TKContentView *view = [window contentView];
-- (void) windowLiveResize: (NSNotification *) notification
-{
- TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
- //BOOL start = [[notification name] isEqualToString:NSWindowWillStartLiveResizeNotification];
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
+ if (@available(macOS 10.15, *)) {
+ [view viewDidChangeEffectiveAppearance];
+ }
+#endif
+ [view addTkDirtyRect:[view bounds]];
+ Tcl_CancelIdleCall(TkMacOSXDrawAllViews, NULL);
+ Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL);
+ }
}
- (void) windowMapped: (NSNotification *) notification
{
- TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
- //Tk_MapWindow((Tk_Window) winPtr);
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
}
}
-- (void) windowBecameVisible: (NSNotification *) notification
+#ifdef TK_MAC_DEBUG_NOTIFICATIONS
+
+- (void) windowDragStart: (NSNotification *) notification
+{
+ TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+}
+
+- (void) windowLiveResize: (NSNotification *) notification
{
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
+ //BOOL start = [[notification name] isEqualToString:NSWindowWillStartLiveResizeNotification];
}
- (void) windowUnmapped: (NSNotification *) notification
@@ -247,7 +253,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
- //Tk_UnmapWindow((Tk_Window) winPtr);
+ //Tk_UnmapWindow((Tk_Window)winPtr);
}
}
@@ -266,6 +272,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
observe(NSWindowDidResizeNotification, windowBoundsChanged:);
observe(NSWindowDidDeminiaturizeNotification, windowExpanded:);
observe(NSWindowDidMiniaturizeNotification, windowCollapsed:);
+ observe(NSWindowWillOrderOnScreenNotification, windowMapped:);
+ observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:);
#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 1070)
observe(NSWindowDidEnterFullScreenNotification, windowEnteredFullScreen:);
@@ -276,8 +284,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
observe(NSWindowWillMoveNotification, windowDragStart:);
observe(NSWindowWillStartLiveResizeNotification, windowLiveResize:);
observe(NSWindowDidEndLiveResizeNotification, windowLiveResize:);
- observe(NSWindowWillOrderOnScreenNotification, windowMapped:);
- observe(NSWindowDidOrderOnScreenNotification, windowBecameVisible:);
observe(NSWindowDidOrderOffScreenNotification, windowUnmapped:);
#endif
#undef observe
@@ -394,26 +400,53 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
/*
*----------------------------------------------------------------------
*
- * TkpAppIsDrawing --
+ * TkpWillDrawWidget --
*
* 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.
+ * being run inside of the drawRect method. If not, it may be desirable
+ * for the display procedure to simply clear the REDRAW_PENDING flag
+ * and return. The widget can be recorded in order to schedule a
+ * redraw, via and Expose event, from within drawRect.
+ *
+ * This is also 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;
+ * True if called from the drawRect method of a TKContentView with
+ * tkwin NULL or pointing to a widget in the current focusView.
*
* Side effects:
- * None
+ * Currently none. One day the tkwin parameter may be recorded to
+ * handle redrawing the widget later.
*
*----------------------------------------------------------------------
*/
-MODULE_SCOPE Bool
-TkpAppIsDrawing(void) {
- return [NSApp isDrawing];
+int
+TkpWillDrawWidget(Tk_Window tkwin) {
+ int result;
+ if (tkwin) {
+ TkWindow *winPtr = (TkWindow *)tkwin;
+ TKContentView *view = (TKContentView *)TkMacOSXGetNSViewForDrawable(
+ (Drawable)winPtr->privatePtr);
+ result = ([NSApp isDrawing] && view == [NSView focusView]);
+#if 0
+ printf("TkpWillDrawWidget: %s %d %d \n", Tk_PathName(tkwin),
+ [NSApp isDrawing], (view == [NSView focusView]));
+ if (!result) {
+ NSRect dirtyRect;
+ TkMacOSXWinNSBounds(winPtr, view, &dirtyRect);
+ printf("TkpAppCanDraw: dirtyRect for %s is %s\n",
+ Tk_PathName(tkwin),
+ NSStringFromRect(dirtyRect).UTF8String);
+ [view addTkDirtyRect:dirtyRect];
+ }
+#endif
+ } else {
+ result = [NSApp isDrawing];
+ }
+ return result;
}
/*
@@ -421,55 +454,39 @@ TkpAppIsDrawing(void) {
*
* GenerateUpdates --
*
- * Given a Macintosh update region and a Tk window this function geneates
+ * Given an update rectangle and a Tk window, this function generates
* an X Expose event for the window if it meets the update region. The
- * function will then recursivly have each damaged window generate Expose
+ * function will then recursively have each damaged window generate Expose
* events for its child windows.
*
* Results:
* True if event(s) are generated - false otherwise.
*
* Side effects:
- * Additional events may be place on the Tk event queue.
+ * Additional events may be placed on the Tk event queue.
*
*----------------------------------------------------------------------
*/
static int
GenerateUpdates(
- HIShapeRef updateRgn,
CGRect *updateBounds,
TkWindow *winPtr)
{
TkWindow *childPtr;
XEvent event;
CGRect bounds, damageBounds;
- HIShapeRef boundsRgn, damageRgn;
TkMacOSXWinCGBounds(winPtr, &bounds);
if (!CGRectIntersectsRect(bounds, *updateBounds)) {
return 0;
}
- if (!HIShapeIntersectsRect(updateRgn, &bounds)) {
- return 0;
- }
/*
- * Compute the bounding box of the area that the damage occured in.
+ * Compute the bounding box of the area that the damage occurred in.
*/
- boundsRgn = HIShapeCreateWithRect(&bounds);
- damageRgn = HIShapeCreateIntersection(updateRgn, boundsRgn);
- if (HIShapeIsEmpty(damageRgn)) {
- CFRelease(damageRgn);
- CFRelease(boundsRgn);
- return 0;
- }
- HIShapeGetBounds(damageRgn, &damageBounds);
-
- CFRelease(damageRgn);
- CFRelease(boundsRgn);
-
+ damageBounds = CGRectIntersection(bounds, *updateBounds);
event.xany.serial = LastKnownRequestProcessed(Tk_Display(winPtr));
event.xany.send_event = false;
event.xany.window = Tk_WindowId(winPtr);
@@ -483,7 +500,7 @@ GenerateUpdates(
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
#ifdef TK_MAC_DEBUG_DRAWING
- TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
+ TKLog(@"Exposed %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
event.xexpose.y, event.xexpose.width, event.xexpose.height);
#endif
@@ -496,7 +513,7 @@ GenerateUpdates(
if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
continue;
}
- GenerateUpdates(updateRgn, updateBounds, childPtr);
+ GenerateUpdates(updateBounds, childPtr);
}
/*
@@ -506,7 +523,7 @@ GenerateUpdates(
if (Tk_IsContainer(winPtr)) {
childPtr = TkpGetOtherWindow(winPtr);
if (childPtr != NULL && Tk_IsMapped(childPtr)) {
- GenerateUpdates(updateRgn, updateBounds, childPtr);
+ GenerateUpdates(updateBounds, childPtr);
}
/*
@@ -520,58 +537,6 @@ GenerateUpdates(
/*
*----------------------------------------------------------------------
*
- * GenerateActivateEvents --
- *
- * Given a Macintosh window activate event this function generates all the
- * X Activate events needed by Tk.
- *
- * Results:
- * True if event(s) are generated - false otherwise.
- *
- * Side effects:
- * Additional events may be place on the Tk event queue.
- *
- *----------------------------------------------------------------------
- */
-
-int
-GenerateActivateEvents(
- TkWindow *winPtr,
- int activeFlag)
-{
- TkGenerateActivateEvents(winPtr, activeFlag);
- if (activeFlag || ![NSApp isActive]) {
- TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
- }
- return true;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DoWindowActivate --
- *
- * Idle handler that calls GenerateActivateEvents().
- *
- * Results:
- * None.
- *
- * Side effects:
- * Additional events may be place on the Tk event queue.
- *
- *----------------------------------------------------------------------
- */
-
-void
-DoWindowActivate(
- ClientData clientData)
-{
- GenerateActivateEvents(clientData, 1);
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TkMacOSXGenerateFocusEvent --
*
* Given a Macintosh window activate event this function generates all
@@ -581,12 +546,12 @@ DoWindowActivate(
* True if event(s) are generated - false otherwise.
*
* Side effects:
- * Additional events may be place on the Tk event queue.
+ * Additional events may be placed on the Tk event queue.
*
*----------------------------------------------------------------------
*/
-MODULE_SCOPE int
+static int
TkMacOSXGenerateFocusEvent(
TkWindow *winPtr, /* Root X window for event. */
int activeFlag)
@@ -628,6 +593,35 @@ TkMacOSXGenerateFocusEvent(
/*
*----------------------------------------------------------------------
*
+ * GenerateActivateEvents --
+ *
+ * Given a Macintosh window activate event this function generates all the
+ * X Activate events needed by Tk.
+ *
+ * Results:
+ * True if event(s) are generated - false otherwise.
+ *
+ * Side effects:
+ * Additional events may be placed on the Tk event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+GenerateActivateEvents(
+ TkWindow *winPtr,
+ int activeFlag)
+{
+ TkGenerateActivateEvents(winPtr, activeFlag);
+ if (activeFlag || ![NSApp isActive]) {
+ TkMacOSXGenerateFocusEvent(winPtr, activeFlag);
+ }
+ return true;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkGenWMConfigureEvent --
*
* Generate a ConfigureNotify event for Tk. Depending on the value of flag
@@ -739,7 +733,7 @@ TkGenWMConfigureEvent(
/*
* Now set up the changes structure. Under X we wait for the
- * ConfigureNotify to set these values. On the Mac we know imediatly that
+ * ConfigureNotify to set these values. On the Mac we know immediately that
* this is what we want - so we just set them. However, we need to make
* sure the windows clipping region is marked invalid so the change is
* visible to the subwindow.
@@ -830,7 +824,7 @@ TkWmProtocolEventProc(
if (result != TCL_OK) {
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (command for \"%s\" window manager protocol)",
- Tk_GetAtomName((Tk_Window) winPtr, protocol)));
+ Tk_GetAtomName((Tk_Window)winPtr, protocol)));
Tcl_BackgroundException(interp, result);
}
Tcl_Release(interp);
@@ -844,8 +838,8 @@ TkWmProtocolEventProc(
* message then just destroy the window.
*/
- if (protocol == Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW")) {
- Tk_DestroyWindow((Tk_Window) winPtr);
+ if (protocol == Tk_InternAtom((Tk_Window)winPtr, "WM_DELETE_WINDOW")) {
+ Tk_DestroyWindow((Tk_Window)winPtr);
}
}
@@ -919,43 +913,32 @@ 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.
- */
+@implementation TKContentView(TKWindowEvent)
-static void
-RedisplayView(
- ClientData clientdata)
+- (void) addTkDirtyRect: (NSRect) rect
{
- NSView *view = (NSView *) clientdata;
-
- /*
- * Make sure that we are not trying to displaying a view that no longer
- * exists. Must call [NSApp windows] because [NSApp orderedWindows] excludes
- * floating/utility windows and other window panels.
- */
-
- for (NSWindow *w in [NSApp windows]) {
- if ([w contentView] == view) {
- [view setNeedsDisplay:YES];
- break;
- }
- }
+ _tkNeedsDisplay = YES;
+ _tkDirtyRect = NSUnionRect(_tkDirtyRect, rect);
+ [NSApp setNeedsToDraw:YES];
}
-@implementation TKContentView(TKWindowEvent)
+- (void) clearTkDirtyRect
+{
+ _tkNeedsDisplay = NO;
+ _tkDirtyRect = NSZeroRect;
+ [NSApp setNeedsToDraw:NO];
+}
- (void) drawRect: (NSRect) rect
{
- const NSRect *rectsBeingDrawn;
- NSInteger rectsBeingDrawnCount;
(void)rect;
#ifdef TK_MAC_DEBUG_DRAWING
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
- if (winPtr) fprintf(stderr, "drawRect: drawing %s\n",
- Tk_PathName(winPtr));
+ if (winPtr) {
+ fprintf(stderr, "drawRect: drawing %s in %s\n",
+ Tk_PathName(winPtr), NSStringFromRect(rect).UTF8String);
+ }
#endif
/*
@@ -964,37 +947,16 @@ RedisplayView(
*/
if ([NSApp isDrawing]) {
- if ([NSApp macMinorVersion] > 13) {
+ if ([NSApp macOSVersion] > 101300) {
TKLog(@"WARNING: a recursive call to drawRect was aborted.");
}
return;
}
[NSApp setIsDrawing: YES];
-
- [self getRectsBeingDrawn:&rectsBeingDrawn count:&rectsBeingDrawnCount];
- CGFloat height = [self bounds].size.height;
- HIMutableShapeRef drawShape = HIShapeCreateMutable();
-
- while (rectsBeingDrawnCount--) {
- CGRect r = NSRectToCGRect(*rectsBeingDrawn++);
-
-#ifdef TK_MAC_DEBUG_DRAWING
- fprintf(stderr, "drawRect: %dx%d@(%d,%d)\n", (int)r.size.width,
- (int)r.size.height, (int)r.origin.x, (int)r.origin.y);
-#endif
-
- r.origin.y = height - (r.origin.y + r.size.height);
- HIShapeUnionWithRect(drawShape, &r);
- }
- [self generateExposeEvents:(HIShapeRef)drawShape];
- CFRelease(drawShape);
- [NSApp setIsDrawing: NO];
-
- if ([self needsRedisplay]) {
- [self setNeedsRedisplay:NO];
- Tcl_DoWhenIdle(RedisplayView, self);
- }
+ [self clearTkDirtyRect];
+ [self generateExposeEvents:rect];
+ [NSApp setIsDrawing:NO];
#ifdef TK_MAC_DEBUG_DRAWING
fprintf(stderr, "drawRect: done.\n");
@@ -1006,7 +968,7 @@ RedisplayView(
[super setFrameSize: newsize];
NSWindow *w = [self window];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
- Tk_Window tkwin = (Tk_Window) winPtr;
+ Tk_Window tkwin = (Tk_Window)winPtr;
if (![self inLiveResize] &&
[w respondsToSelector: @selector (tkLayoutChanged)]) {
@@ -1051,13 +1013,14 @@ RedisplayView(
TkMacOSXUpdateClipRgn(winPtr);
/*
- * Generate and process expose events to redraw the window.
+ * Generate and process expose events to redraw the window. To avoid
+ * crashes, only do this if we are being called from drawRect. See
+ * ticket [1fa8c3ed8d].
*/
- HIRect bounds = NSRectToCGRect([self bounds]);
- HIShapeRef shape = HIShapeCreateWithRect(&bounds);
- [self generateExposeEvents: shape];
- [w displayIfNeeded];
+ if([NSApp isDrawing] || [self inLiveResize]) {
+ [self generateExposeEvents: [self bounds]];
+ }
/*
* Finally, unlock the main autoreleasePool.
@@ -1074,11 +1037,11 @@ RedisplayView(
* pending idle events are processed so the drawing will actually take place.
*/
-- (void) generateExposeEvents: (HIShapeRef) shape
+- (void) generateExposeEvents: (NSRect) rect
{
unsigned long serial;
- CGRect updateBounds;
int updatesNeeded;
+ CGRect updateBounds;
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
ClientData oldArg;
Tk_RestrictProc *oldProc;
@@ -1087,26 +1050,25 @@ RedisplayView(
}
/*
- * Generate Tk Expose events.
+ * Generate Tk Expose events. All of these events will share the same
+ * serial number.
*/
- HIShapeGetBounds(shape, &updateBounds);
-
- /*
- * All of these events will share the same serial number.
- */
-
- serial = LastKnownRequestProcessed(Tk_Display(winPtr));
- updatesNeeded = GenerateUpdates(shape, &updateBounds, winPtr);
-
+ updateBounds = NSRectToCGRect(rect);
+ updateBounds.origin.y = ([self bounds].size.height - updateBounds.origin.y
+ - updateBounds.size.height);
+ updatesNeeded = GenerateUpdates(&updateBounds, winPtr);
if (updatesNeeded) {
+ serial = LastKnownRequestProcessed(Tk_Display(winPtr));
+
/*
- * First process all of the Expose events.
+ * Use the ExposeRestrictProc to process only the expose events. This
+ * will create idle drawing tasks, which we handle before we return.
*/
oldProc = Tk_RestrictEvents(ExposeRestrictProc, UINT2PTR(serial), &oldArg);
- while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {};
+ while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {};
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
/*
@@ -1118,51 +1080,104 @@ RedisplayView(
* effect.)
*
* Fortunately, Tk schedules all drawing to be done while Tcl is idle.
- * So we can do the drawing by processing all of the idle events that
- * were created when the expose events were processed.
+ * So to run any display procs which were scheduled by the expose
+ * events we process all idle events before returning.
*/
+
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
}
}
/*
- * 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.
+ * In macOS 10.14 and later this method is called when a user changes between
+ * light and dark mode or changes the accent color. The implementation
+ * generates two virtual events. The first is either <<LightAqua>> or
+ * <<DarkAqua>>, depending on the view's current effective appearance. The
+ * second is <<AppearnceChanged>> and has a data string describing the
+ * effective appearance of the view and the current accent and highlight
+ * colors.
*/
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
+
+static const char *const accentNames[] = {
+ "Graphite",
+ "Red",
+ "Orange",
+ "Yellow",
+ "Green",
+ "Blue",
+ "Purple",
+ "Pink"
+};
+
- (void) viewDidChangeEffectiveAppearance
{
- XVirtualEvent event;
- int x, y;
- NSWindow *w = [self window];
- TkWindow *winPtr = TkMacOSXGetTkWindow(w);
- Tk_Window tkwin = (Tk_Window) winPtr;
+ Tk_Window tkwin = (Tk_Window)TkMacOSXGetTkWindow([self window]);
+ if (!tkwin) {
+ return;
+ }
+ NSAppearanceName effectiveAppearanceName = [[self effectiveAppearance] name];
+ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
+ static const char *defaultColor = NULL;
+
+ if (effectiveAppearanceName == NSAppearanceNameAqua) {
+ Tk_SendVirtualEvent(tkwin, "LightAqua", NULL);
+ } else if (effectiveAppearanceName == NSAppearanceNameDarkAqua) {
+ Tk_SendVirtualEvent(tkwin, "DarkAqua", NULL);
+ }
+ if ([NSApp macOSVersion] < 101500) {
+
+ /*
+ * Mojave cannot handle the KVO shenanigans that we need for the
+ * highlight and accent color notifications.
+ */
- if (!winPtr) {
return;
}
- bzero(&event, sizeof(XVirtualEvent));
- event.type = VirtualEvent;
- event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
- event.send_event = false;
- event.display = Tk_Display(tkwin);
- event.event = Tk_WindowId(tkwin);
- event.root = XRootWindow(Tk_Display(tkwin), 0);
- event.subwindow = None;
- event.time = TkpGetMS();
- XQueryPointer(NULL, winPtr->window, NULL, NULL,
- &event.x_root, &event.y_root, &x, &y, &event.state);
- Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
- event.same_screen = true;
- if (TkMacOSXInDarkMode(tkwin)) {
- event.name = Tk_GetUid("DarkAqua");
- } else {
- event.name = Tk_GetUid("LightAqua");
+ if (!defaultColor) {
+ defaultColor = [NSApp macOSVersion] < 110000 ? "Blue" : "Multicolor";
+ preferences = [[NSUserDefaults standardUserDefaults] retain];
+
+ /*
+ * AppKit calls this method when the user changes the Accent Color
+ * but not when the user changes the Highlight Color. So we register
+ * to receive KVO notifications for Highlight Color as well.
+ */
+
+ [preferences addObserver:self
+ forKeyPath:@"AppleHighlightColor"
+ options:NSKeyValueObservingOptionNew
+ context:NULL];
}
- Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
+ NSString *accent = [preferences stringForKey:@"AppleAccentColor"];
+ NSArray *words = [[preferences stringForKey:@"AppleHighlightColor"]
+ componentsSeparatedByString: @" "];
+ NSString *highlight = [words count] > 3 ? [words objectAtIndex:3] : nil;
+ const char *accentName = accent ? accentNames[1 + accent.intValue] : defaultColor;
+ const char *highlightName = highlight ? highlight.UTF8String: defaultColor;
+ char data[256];
+ snprintf(data, 256, "Appearance %s Accent %s Highlight %s",
+ effectiveAppearanceName.UTF8String, accentName,
+ highlightName);
+ Tk_SendVirtualEvent(tkwin, "AppearanceChanged", Tcl_NewStringObj(data, -1));
}
+- (void)observeValueForKeyPath:(NSString *)keyPath
+ ofObject:(id)object
+ change:(NSDictionary *)change
+ context:(void *)context
+{
+ NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
+ if (object == preferences && [keyPath isEqualToString:@"AppleHighlightColor"]) {
+ if (@available(macOS 10.14, *)) {
+ [self viewDidChangeEffectiveAppearance];
+ }
+ }
+}
+
+#endif
+
/*
* This is no-op on 10.7 and up because Apple has removed this widget, but we
* are leaving it here for backwards compatibility.
@@ -1176,7 +1191,7 @@ RedisplayView(
XVirtualEvent event;
int x, y;
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
- Tk_Window tkwin = (Tk_Window) winPtr;
+ Tk_Window tkwin = (Tk_Window)winPtr;
(void)sender;
if (!winPtr){
@@ -1199,12 +1214,10 @@ RedisplayView(
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}
-- (BOOL) isOpaque
-{
- NSWindow *w = [self window];
- return (w && (([w styleMask] & NSTexturedBackgroundWindowMask) ||
- ![w isOpaque]) ? NO : YES);
-}
+/*
+ * On Catalina this is never called and drawRect clips to the rect that
+ * is passed to it by AppKit.
+ */
- (BOOL) wantsDefaultClipping
{
@@ -1223,7 +1236,8 @@ RedisplayView(
- (void) keyDown: (NSEvent *) theEvent
{
- (void)theEvent;
+ (void)theEvent;
+
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
@@ -1231,7 +1245,7 @@ RedisplayView(
/*
* When the services menu is opened this is called for each Responder in
- * the Responder chain until a service provider is found. The TkContentView
+ * 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.
*/
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index f24b8d4..77da97d 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.c
@@ -183,7 +183,7 @@ static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin);
static const Tk_GeomMgr wmMgrType = {
"wm", /* name */
TopLevelReqProc, /* requestProc */
- NULL, /* lostSlaveProc */
+ NULL, /* lostContentProc */
};
/*
@@ -193,13 +193,6 @@ static const Tk_GeomMgr wmMgrType = {
static int tkMacOSXWmAttrNotifyVal = 0;
/*
- * Hash table for Mac Window -> TkWindow mapping.
- */
-
-static Tcl_HashTable windowTable;
-static int windowHashInit = false;
-
-/*
* Forward declarations for procedures defined in this file:
*/
@@ -320,7 +313,7 @@ static int WmWinAppearance(Tcl_Interp *interp, TkWindow *winPtr,
static void ApplyWindowAttributeFlagChanges(TkWindow *winPtr,
NSWindow *macWindow, UInt64 oldAttributes,
int oldFlags, int create, int initial);
-static void ApplyMasterOverrideChanges(TkWindow *winPtr,
+static void ApplyContainerOverrideChanges(TkWindow *winPtr,
NSWindow *macWindow);
static void GetMinSize(TkWindow *winPtr, int *minWidthPtr,
int *minHeightPtr);
@@ -360,11 +353,21 @@ static void RemoveTransient(TkWindow *winPtr);
#pragma mark -
-#pragma mark TKWindow(TKWm)
+@implementation TKPanel: NSPanel
+@synthesize tkWindow = _tkWindow;
+@end
+
+@implementation TKDrawerWindow: NSWindow
+@synthesize tkWindow = _tkWindow;
+@end
@implementation TKWindow: NSWindow
+@synthesize mouseInResizeArea = _mouseInResizeArea;
+@synthesize tkWindow = _tkWindow;
@end
+#pragma mark TKWindow(TKWm)
+
@implementation TKWindow(TKWm)
/*
@@ -523,7 +526,7 @@ static void
SetWindowSizeLimits(
TkWindow *winPtr)
{
- NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ NSWindow *macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
WmInfo *wmPtr = winPtr->wmInfoPtr;
int minWidth, minHeight, maxWidth, maxHeight, base;
@@ -671,7 +674,7 @@ TkWmNewWindow(
wmPtr->reparent = None;
wmPtr->titleUid = NULL;
wmPtr->iconName = NULL;
- wmPtr->master = NULL;
+ wmPtr->container = NULL;
wmPtr->hints.flags = InputHint | StateHint;
wmPtr->hints.input = True;
wmPtr->hints.initial_state = NormalState;
@@ -729,7 +732,7 @@ TkWmNewWindow(
* detect size and position changes caused by window managers.
*/
- Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask,
+ Tk_CreateEventHandler((Tk_Window)winPtr, StructureNotifyMask,
TopLevelEventProc, winPtr);
/*
@@ -737,7 +740,75 @@ TkWmNewWindow(
* window manager.
*/
- Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0);
+ Tk_ManageGeometry((Tk_Window)winPtr, &wmMgrType, NULL);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXHandleMapOrUnmap --
+ *
+ * The mechanism used by a geometry manager to propogate the information
+ * about which of its content widgets are mapped is to call Tk_MapWindow
+ * or Tk_UnmapNotify. Those functions generate MapNotify or UnmapNotify
+ * events and then handle them immediately. Other platforms use
+ * Tk_HandleEvent to do this. But that does not work correctly on macOS
+ * due to the fact that the calls to Tk_MapNotify or Tk_UnmapNotify can
+ * occur in display procedures which are being run in the drawRect method
+ * of a TKContentView. The events will be processed after drawRect
+ * returns, but they need to be processed immediately in some cases.
+
+ * This function operates as a macOS alternative to Tk_HandleEvent, for
+ * processing MapNotify or UnmapNotify events only. It is called by
+ * Tk_MapWindow, Tk_UnmapWindow, TkWmMapWindow and TkWmUnmapWindow.
+ * Rather than using Tk_HandleEvent it installs a filter which restricts
+ * to the MapNotify or UnmapNotify events, it queues the event and then
+ * processes window events with the filter installed. This allows the
+ * event to be handled immediately even from within the drawRect method.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Handles a MapNotify or UnMapNotify event.
+ *
+ *----------------------------------------------------------------------
+ */
+static Tk_RestrictAction
+MapUnmapRestrictProc(
+ TCL_UNUSED(void*),
+ XEvent *eventPtr)
+{
+ return (eventPtr->type==MapNotify || eventPtr->type==UnmapNotify ?
+ TK_PROCESS_EVENT : TK_DEFER_EVENT);
+}
+
+MODULE_SCOPE
+void TkMacOSXHandleMapOrUnmap(
+ Tk_Window tkwin,
+ XEvent *event)
+{
+ ClientData oldArg;
+ Tk_RestrictProc *oldProc;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ const Tk_GeomMgr *geomMgrPtr = winPtr->geomMgrPtr;
+
+ /*
+ * Sadly, this approach does not work with the "text" geometry manager.
+ * The mysterious unexplained crash elicited by textDisp-5.2 occurs. So we
+ * have to check for the "text" manager and revert to using Tk_HandleEvent
+ * in that case. Hopefully this can be removed when the revised text
+ * widget is in place.
+ */
+
+ if (geomMgrPtr && strcmp(geomMgrPtr->name, "text") == 0) {
+ Tk_HandleEvent(event);
+ return;
+ }
+ oldProc = Tk_RestrictEvents(MapUnmapRestrictProc, NULL, &oldArg);
+ Tk_QueueWindowEvent(event, TCL_QUEUE_TAIL);
+ while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}
+ Tk_RestrictEvents(oldProc, oldArg, &oldArg);
}
/*
@@ -769,6 +840,8 @@ TkWmMapWindow(
* mapped. */
{
WmInfo *wmPtr = winPtr->wmInfoPtr;
+ XEvent event;
+
if (wmPtr->flags & WM_NEVER_MAPPED) {
/*
* Create the underlying Mac window for this Tk window.
@@ -784,7 +857,7 @@ TkWmMapWindow(
* Generate configure event when we first map the window.
*/
- TkGenWMConfigureEvent((Tk_Window) winPtr, wmPtr->x, wmPtr->y, -1, -1,
+ TkGenWMConfigureEvent((Tk_Window)winPtr, wmPtr->x, wmPtr->y, -1, -1,
TK_LOCATION_CHANGED);
/*
@@ -832,10 +905,19 @@ TkWmMapWindow(
wmPtr->flags &= ~WM_ABOUT_TO_MAP;
/*
- * Map the window.
+ * Map the window and process a MapNotify event for it.
*/
+ winPtr->flags |= TK_MAPPED;
XMapWindow(winPtr->display, winPtr->window);
+ event.xany.serial = LastKnownRequestProcessed(winPtr->display);
+ event.xany.send_event = False;
+ event.xany.display = winPtr->display;
+ event.xmap.window = winPtr->window;
+ event.xmap.type = MapNotify;
+ event.xmap.event = winPtr->window;
+ event.xmap.override_redirect = winPtr->atts.override_redirect;
+ TkpHandleMapOrUnmap((Tk_Window)winPtr, &event);
}
/*
@@ -860,7 +942,18 @@ TkWmUnmapWindow(
TkWindow *winPtr) /* Top-level window that's about to be
* unmapped. */
{
+ XEvent event;
+
+ event.xany.serial = LastKnownRequestProcessed(winPtr->display);
+ event.xany.send_event = False;
+ event.xany.display = winPtr->display;
+ event.xunmap.type = UnmapNotify;
+ event.xunmap.window = winPtr->window;
+ event.xunmap.event = winPtr->window;
+ event.xunmap.from_configure = false;
+ winPtr->flags &= ~TK_MAPPED;
XUnmapWindow(winPtr->display, winPtr->window);
+ TkpHandleMapOrUnmap((Tk_Window)winPtr, &event);
}
/*
@@ -885,19 +978,19 @@ TkWmDeadWindow(
TkWindow *winPtr) /* Top-level window that's being deleted. */
{
WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
- NSWindow *ourNSWindow;
+ TKWindow *deadNSWindow;
if (wmPtr == NULL) {
return;
}
/*
- *If the dead window is a transient, remove it from the master's list.
+ *If the dead window is a transient, remove it from the container's list.
*/
RemoveTransient(winPtr);
- Tk_ManageGeometry((Tk_Window) winPtr, NULL, NULL);
- Tk_DeleteEventHandler((Tk_Window) winPtr, StructureNotifyMask,
+ Tk_ManageGeometry((Tk_Window)winPtr, NULL, NULL);
+ Tk_DeleteEventHandler((Tk_Window)winPtr, StructureNotifyMask,
TopLevelEventProc, winPtr);
if (wmPtr->hints.flags & IconPixmapHint) {
Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap);
@@ -912,11 +1005,11 @@ TkWmDeadWindow(
ckfree(wmPtr->leaderName);
}
if (wmPtr->icon != NULL) {
- wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
+ wmPtr2 = ((TkWindow *)wmPtr->icon)->wmInfoPtr;
wmPtr2->iconFor = NULL;
}
if (wmPtr->iconFor != NULL) {
- wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr;
+ wmPtr2 = ((TkWindow *)wmPtr->iconFor)->wmInfoPtr;
wmPtr2->icon = NULL;
wmPtr2->hints.flags &= ~IconWindowHint;
}
@@ -943,11 +1036,11 @@ TkWmDeadWindow(
for (Transient *transientPtr = wmPtr->transientPtr;
transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
TkWindow *winPtr2 = transientPtr->winPtr;
- TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
+ TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);
- if (masterPtr == winPtr) {
+ if (containerPtr == winPtr) {
wmPtr2 = winPtr2->wmInfoPtr;
- wmPtr2->master = NULL;
+ wmPtr2->container = NULL;
}
}
@@ -964,27 +1057,27 @@ TkWmDeadWindow(
* the parent. Then close and release the NSWindow.
*/
- ourNSWindow = wmPtr->window;
- if (ourNSWindow && !Tk_IsEmbedded(winPtr)) {
- NSWindow *parent = [ourNSWindow parentWindow];
- TkMacOSXUnregisterMacWindow(ourNSWindow);
+ deadNSWindow = (TKWindow *)wmPtr->window;
+ if (deadNSWindow && !Tk_IsEmbedded(winPtr)) {
+ NSWindow *parent = [deadNSWindow parentWindow];
+ [deadNSWindow setTkWindow:None];
if (winPtr->window) {
- ((MacDrawable *) winPtr->window)->view = nil;
+ ((MacDrawable *)winPtr->window)->view = nil;
}
wmPtr->window = NULL;
if (parent) {
- [parent removeChildWindow:ourNSWindow];
+ [parent removeChildWindow:deadNSWindow];
}
#if DEBUG_ZOMBIES > 1
{
- const char *title = [[ourNSWindow title] UTF8String];
+ const char *title = [[deadNSWindow title] UTF8String];
if (title == nil) {
title = "unnamed window";
}
fprintf(stderr, ">>>> Closing <%s>. Count is: %lu\n", title,
- [ourNSWindow retainCount]);
+ [deadNSWindow retainCount]);
}
#endif
@@ -1011,7 +1104,7 @@ TkWmDeadWindow(
wmPtr2 = winPtr2->wmInfoPtr;
isOnScreen = (wmPtr2->hints.initial_state != IconicState &&
wmPtr2->hints.initial_state != WithdrawnState);
- if (w != ourNSWindow && isOnScreen && [w canBecomeKeyWindow]) {
+ if (w != deadNSWindow && isOnScreen && [w canBecomeKeyWindow]) {
[w makeKeyAndOrderFront:NSApp];
break;
}
@@ -1021,12 +1114,12 @@ TkWmDeadWindow(
* Prevent zombies on systems with a TouchBar.
*/
- if (ourNSWindow == [NSApp keyWindow]) {
+ if (deadNSWindow == [NSApp keyWindow]) {
[NSApp _setKeyWindow:nil];
[NSApp _setMainWindow:nil];
}
- [ourNSWindow close];
- [ourNSWindow release];
+ [deadNSWindow close];
+ [deadNSWindow release];
[NSApp _resetAutoreleasePool];
#if DEBUG_ZOMBIES > 1
@@ -1094,7 +1187,7 @@ Tk_WmObjCmd(
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- Tk_Window tkwin = (Tk_Window) clientData;
+ Tk_Window tkwin = (Tk_Window)clientData;
static const char *const optionStrings[] = {
"aspect", "attributes", "client", "colormapwindows",
"command", "deiconify", "focusmodel", "forget",
@@ -1433,7 +1526,7 @@ WmSetAttribute(
oldFlags, 1, 0);
[macWindow setBackgroundColor:boolean ? [NSColor clearColor] : nil];
[macWindow setOpaque:!boolean];
- TkMacOSXInvalidateWindow((MacDrawable *) winPtr->window,
+ TkMacOSXInvalidateWindow((MacDrawable *)winPtr->window,
TK_PARENT_WINDOW);
}
break;
@@ -1529,12 +1622,12 @@ WmAttributesCmd(
NSWindow *macWindow;
if (winPtr->window == None) {
- Tk_MakeWindowExist((Tk_Window) winPtr);
+ Tk_MakeWindowExist((Tk_Window)winPtr);
}
if (!TkMacOSXHostToplevelExists(winPtr)) {
TkMacOSXMakeRealWindowExist(winPtr);
}
- macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
if (objc == 3) { /* wm attributes $win */
Tcl_Obj *result = Tcl_NewObj();
@@ -1663,7 +1756,7 @@ WmColormapwindowsCmd(
return TCL_ERROR;
}
if (objc == 3) {
- Tk_MakeWindowExist((Tk_Window) winPtr);
+ Tk_MakeWindowExist((Tk_Window)winPtr);
resultObj = Tcl_NewObj();
for (i = 0; i < wmPtr->cmapCount; i++) {
if ((i == (wmPtr->cmapCount-1))
@@ -1671,7 +1764,7 @@ WmColormapwindowsCmd(
break;
}
Tcl_ListObjAppendElement(NULL, resultObj,
- TkNewWindowObj((Tk_Window) wmPtr->cmapList[i]));
+ Tk_NewWindowObj((Tk_Window)wmPtr->cmapList[i]));
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
@@ -1691,7 +1784,7 @@ WmColormapwindowsCmd(
gotToplevel = 1;
}
if (winPtr2->window == None) {
- Tk_MakeWindowExist((Tk_Window) winPtr2);
+ Tk_MakeWindowExist((Tk_Window)winPtr2);
}
cmapList[i] = winPtr2;
}
@@ -1710,7 +1803,7 @@ WmColormapwindowsCmd(
wmPtr->cmapCount = windowObjc;
/*
- * On the Macintosh all of this is just an excercise in compatability as
+ * On the Macintosh all of this is just an excercise in compatibility as
* we don't support colormaps. If we did they would be installed here.
*/
@@ -1800,13 +1893,12 @@ WmDeiconifyCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
WmInfo *wmPtr = winPtr->wmInfoPtr;
- NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "window");
return TCL_ERROR;
}
-
if (wmPtr->iconFor != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't deiconify %s: it is an icon for %s",
@@ -1825,27 +1917,27 @@ WmDeiconifyCmd(
ZoomState : NormalState);
[win setExcludedFromWindowsMenu:NO];
TkMacOSXApplyWindowAttributes(winPtr, win);
- [win orderFront:nil];
+ [win orderFront:NSApp];
if (wmPtr->icon) {
Tk_UnmapWindow((Tk_Window)wmPtr->icon);
}
/*
* If this window has a transient, the transient must also be deiconified if
- * it was withdrawn by the master.
+ * it was withdrawn by the container.
*/
for (Transient *transientPtr = wmPtr->transientPtr;
transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
TkWindow *winPtr2 = transientPtr->winPtr;
WmInfo *wmPtr2 = winPtr2->wmInfoPtr;
- TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
+ TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);
- if (masterPtr == winPtr) {
+ if (containerPtr == winPtr) {
if ((wmPtr2->hints.initial_state == WithdrawnState) &&
- ((transientPtr->flags & WITHDRAWN_BY_MASTER) != 0)) {
+ ((transientPtr->flags & WITHDRAWN_BY_CONTAINER) != 0)) {
TkpWmSetState(winPtr2, NormalState);
- transientPtr->flags &= ~WITHDRAWN_BY_MASTER;
+ transientPtr->flags &= ~WITHDRAWN_BY_CONTAINER;
}
}
}
@@ -1932,7 +2024,7 @@ WmForgetCmd(
TCL_UNUSED(int), /* Number of arguments. */
TCL_UNUSED(Tcl_Obj *const *)) /* Argument objects. */
{
- Tk_Window frameWin = (Tk_Window) winPtr;
+ Tk_Window frameWin = (Tk_Window)winPtr;
if (Tk_IsTopLevel(frameWin)) {
MacDrawable *macWin;
@@ -1940,7 +2032,7 @@ WmForgetCmd(
Tk_MakeWindowExist(frameWin);
Tk_MakeWindowExist((Tk_Window)winPtr->parentPtr);
- macWin = (MacDrawable *) winPtr->window;
+ macWin = (MacDrawable *)winPtr->window;
TkFocusJoin(winPtr);
Tk_UnmapWindow(frameWin);
@@ -1951,7 +2043,7 @@ WmForgetCmd(
macWin->flags &= ~TK_HOST_EXISTS;
TkWmDeadWindow(winPtr);
- RemapWindows(winPtr, (MacDrawable *) winPtr->parentPtr->window);
+ RemapWindows(winPtr, (MacDrawable *)winPtr->parentPtr->window);
/*
* Make sure wm no longer manages this window
@@ -2008,7 +2100,7 @@ WmFrameCmd(
}
window = wmPtr->reparent;
if (window == None) {
- window = Tk_WindowId((Tk_Window) winPtr);
+ window = Tk_WindowId((Tk_Window)winPtr);
}
sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)window);
Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
@@ -2041,7 +2133,7 @@ WmGeometryCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
WmInfo *wmPtr = winPtr->wmInfoPtr;
- NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);
char xSign = '+', ySign = '+';
int width, height, x = wmPtr->x, y= wmPtr->y;
char *argv3;
@@ -2167,7 +2259,7 @@ WmGridCmd(
errorMsg = "heightInc can't be <= 0";
goto error;
}
- Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc,
+ Tk_SetGrid((Tk_Window)winPtr, reqWidth, reqHeight, widthInc,
heightInc);
}
wmPtr->flags |= WM_UPDATE_SIZE_HINTS;
@@ -2288,12 +2380,12 @@ WmIconbitmapCmd(
}
str = Tcl_GetStringFromObj(objv[3], &len);
if (winPtr->window == None) {
- Tk_MakeWindowExist((Tk_Window) winPtr);
+ Tk_MakeWindowExist((Tk_Window)winPtr);
}
if (!TkMacOSXHostToplevelExists(winPtr)) {
TkMacOSXMakeRealWindowExist(winPtr);
}
- if (WmSetAttribute(winPtr, TkMacOSXDrawableWindow(winPtr->window), interp,
+ if (WmSetAttribute(winPtr, TkMacOSXGetNSWindowForDrawable(winPtr->window), interp,
WMATT_TITLEPATH, objv[3]) == TCL_OK) {
if (!len) {
if (wmPtr->hints.icon_pixmap != None) {
@@ -2303,7 +2395,7 @@ WmIconbitmapCmd(
wmPtr->hints.flags &= ~IconPixmapHint;
}
} else {
- pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, Tk_GetUid(str));
+ pixmap = Tk_GetBitmap(interp, (Tk_Window)winPtr, Tk_GetUid(str));
if (pixmap == None) {
return TCL_ERROR;
}
@@ -2344,27 +2436,27 @@ WmIconifyCmd(
return TCL_ERROR;
}
- if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
+ if (Tk_Attributes((Tk_Window)winPtr)->override_redirect) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't iconify \"%s\": override-redirect flag is set",
winPtr->pathName));
Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "OVERRIDE_REDIRECT",
NULL);
return TCL_ERROR;
- } else if (wmPtr->master != NULL) {
+ } else if (wmPtr->container != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't iconify \"%s\": it is a transient", winPtr->pathName));
Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "TRANSIENT", NULL);
return TCL_ERROR;
} else if (wmPtr->iconFor != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't iconify %s: it is an icon for %s",
+ "can't iconify \"%s\": it is an icon for \"%s\"",
winPtr->pathName, Tk_PathName(wmPtr->iconFor)));
Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "ICON", NULL);
return TCL_ERROR;
} else if (winPtr->flags & TK_EMBEDDED) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't iconify %s: it is an embedded window",
+ "can't iconify \"%s\": it is an embedded window",
winPtr->pathName));
Tcl_SetErrorCode(interp, "TK", "WM", "ICONIFY", "EMBEDDED", NULL);
return TCL_ERROR;
@@ -2377,17 +2469,17 @@ WmIconifyCmd(
/*
* If this window has a transient the transient must be withdrawn when
- * the master is iconified.
+ * the container is iconified.
*/
for (Transient *transientPtr = wmPtr->transientPtr;
transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
TkWindow *winPtr2 = transientPtr->winPtr;
- TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
- if (masterPtr == winPtr &&
+ TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);
+ if (containerPtr == winPtr &&
winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
TkpWmSetState(winPtr2, WithdrawnState);
- transientPtr->flags |= WITHDRAWN_BY_MASTER;
+ transientPtr->flags |= WITHDRAWN_BY_CONTAINER;
}
}
@@ -2582,7 +2674,7 @@ WmIconphotoCmd(
Tk_SizeOfImage(tk_icon, &width, &height);
if (width != 0 && height != 0) {
- newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon,
+ newIcon = TkMacOSXGetNSImageFromTkImage(winPtr->display, tk_icon,
width, height);
}
Tk_FreeImage(tk_icon);
@@ -2690,7 +2782,7 @@ WmIconwindowCmd(
if (objc == 3) {
if (wmPtr->icon != NULL) {
- Tcl_SetObjResult(interp, TkNewWindowObj(wmPtr->icon));
+ Tcl_SetObjResult(interp, Tk_NewWindowObj(wmPtr->icon));
}
return TCL_OK;
}
@@ -2698,7 +2790,7 @@ WmIconwindowCmd(
if (*Tcl_GetString(objv[3]) == '\0') {
wmPtr->hints.flags &= ~IconWindowHint;
if (wmPtr->icon != NULL) {
- wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr;
+ wmPtr2 = ((TkWindow *)wmPtr->icon)->wmInfoPtr;
wmPtr2->iconFor = NULL;
wmPtr2->hints.initial_state = WithdrawnState;
}
@@ -2715,7 +2807,7 @@ WmIconwindowCmd(
NULL);
return TCL_ERROR;
}
- wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr;
+ wmPtr2 = ((TkWindow *)tkwin2)->wmInfoPtr;
if (wmPtr2->iconFor != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s is already an icon for %s",
@@ -2726,7 +2818,7 @@ WmIconwindowCmd(
if (wmPtr->icon != NULL) {
TkWindow *oldIcon = (TkWindow *)wmPtr->icon;
WmInfo *wmPtr3 = oldIcon->wmInfoPtr;
- NSWindow *win = TkMacOSXDrawableWindow(oldIcon->window);
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(oldIcon->window);
/*
* The old icon should be withdrawn.
@@ -2741,7 +2833,7 @@ WmIconwindowCmd(
wmPtr->hints.icon_window = Tk_WindowId(tkwin2);
wmPtr->hints.flags |= IconWindowHint;
wmPtr->icon = tkwin2;
- wmPtr2->iconFor = (Tk_Window) winPtr;
+ wmPtr2->iconFor = (Tk_Window)winPtr;
if (!(wmPtr2->flags & WM_NEVER_MAPPED)) {
/*
* If the window is in normal or zoomed state, the icon should be
@@ -2782,11 +2874,11 @@ WmManageCmd(
TCL_UNUSED(int), /* Number of arguments. */
TCL_UNUSED(Tcl_Obj *const *)) /* Argument objects. */
{
- Tk_Window frameWin = (Tk_Window) winPtr;
+ Tk_Window frameWin = (Tk_Window)winPtr;
WmInfo *wmPtr = winPtr->wmInfoPtr;
if (!Tk_IsTopLevel(frameWin)) {
- MacDrawable *macWin = (MacDrawable *) winPtr->window;
+ MacDrawable *macWin = (MacDrawable *)winPtr->window;
if (!Tk_IsManageable(frameWin)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
@@ -2801,8 +2893,8 @@ WmManageCmd(
if (wmPtr == NULL) {
TkWmNewWindow(winPtr);
if (winPtr->window == None) {
- Tk_MakeWindowExist((Tk_Window) winPtr);
- macWin = (MacDrawable *) winPtr->window;
+ Tk_MakeWindowExist((Tk_Window)winPtr);
+ macWin = (MacDrawable *)winPtr->window;
}
}
wmPtr = winPtr->wmInfoPtr;
@@ -2956,7 +3048,7 @@ WmOverrideredirectCmd(
{
int flag;
XSetWindowAttributes atts;
- TKWindow *win = (TKWindow *)TkMacOSXDrawableWindow(winPtr->window);
+ TKWindow *win = (TKWindow *)TkMacOSXGetNSWindowForDrawable(winPtr->window);
if ((objc != 3) && (objc != 4)) {
Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
@@ -2964,8 +3056,8 @@ WmOverrideredirectCmd(
}
if (objc == 3) {
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
- Tk_Attributes((Tk_Window) winPtr)->override_redirect != 0));
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
+ Tk_Attributes((Tk_Window) winPtr)->override_redirect));
return TCL_OK;
}
@@ -2973,8 +3065,8 @@ WmOverrideredirectCmd(
return TCL_ERROR;
}
atts.override_redirect = flag ? True : False;
- Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
- ApplyMasterOverrideChanges(winPtr, win);
+ Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts);
+ ApplyContainerOverrideChanges(winPtr, win);
return TCL_OK;
}
@@ -3096,7 +3188,7 @@ WmProtocolCmd(
return TCL_OK;
}
- protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3]));
+ protocol = Tk_InternAtom((Tk_Window)winPtr, Tcl_GetString(objv[3]));
if (objc == 4) {
/*
* Return the command to handle a given protocol.
@@ -3336,7 +3428,7 @@ WmStackorderCmd(
resultObj = Tcl_NewObj();
for (windowPtr = windows; *windowPtr ; windowPtr++) {
Tcl_ListObjAppendElement(NULL, resultObj,
- TkNewWindowObj((Tk_Window) *windowPtr));
+ Tk_NewWindowObj((Tk_Window)*windowPtr));
}
Tcl_SetObjResult(interp, resultObj);
ckfree(windows);
@@ -3456,14 +3548,14 @@ WmStateCmd(
if (objc == 4) {
if (wmPtr->iconFor != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't change state of %s: it is an icon for %s",
+ "can't change state of \"%s\": it is an icon for \"%s\"",
Tcl_GetString(objv[2]), Tk_PathName(wmPtr->iconFor)));
Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "ICON", NULL);
return TCL_ERROR;
}
if (winPtr->flags & TK_EMBEDDED) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't change state of %s: it is an embedded window",
+ "can't change state of \"%s\": it is an embedded window",
winPtr->pathName));
Tcl_SetErrorCode(interp, "TK", "WM", "STATE", "EMBEDDED", NULL);
return TCL_ERROR;
@@ -3485,7 +3577,7 @@ WmStateCmd(
break;
case OPT_ICONIC:
- if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) {
+ if (Tk_Attributes((Tk_Window)winPtr)->override_redirect) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't iconify \"%s\": override-redirect flag is set",
winPtr->pathName));
@@ -3493,7 +3585,7 @@ WmStateCmd(
"OVERRIDE_REDIRECT", NULL);
return TCL_ERROR;
}
- if (wmPtr->master != NULL) {
+ if (wmPtr->container != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't iconify \"%s\": it is a transient",
winPtr->pathName));
@@ -3610,37 +3702,37 @@ WmTransientCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
WmInfo *wmPtr = winPtr->wmInfoPtr;
- Tk_Window master;
- TkWindow *masterPtr, *w;
+ Tk_Window container;
+ TkWindow *containerPtr, *w;
WmInfo *wmPtr2;
Transient *transient;
if ((objc != 3) && (objc != 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "window ?master?");
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?window?");
return TCL_ERROR;
}
if (objc == 3) {
- if (wmPtr->master != NULL) {
+ if (wmPtr->container != NULL) {
Tcl_SetObjResult(interp,
- Tcl_NewStringObj(Tk_PathName(wmPtr->master), -1));
+ Tcl_NewStringObj(Tk_PathName(wmPtr->container), -1));
}
return TCL_OK;
}
if (*Tcl_GetString(objv[3]) == '\0') {
RemoveTransient(winPtr);
} else {
- if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
+ if (TkGetWindowFromObj(interp, tkwin, objv[3], &container) != TCL_OK) {
return TCL_ERROR;
}
- masterPtr = (TkWindow*) master;
- while (!Tk_TopWinHierarchy(masterPtr)) {
+ containerPtr = (TkWindow*) container;
+ while (!Tk_TopWinHierarchy(containerPtr)) {
/*
- * Ensure that the master window is actually a Tk toplevel.
+ * Ensure that the container window is actually a Tk toplevel.
*/
- masterPtr = masterPtr->parentPtr;
+ containerPtr = containerPtr->parentPtr;
}
- Tk_MakeWindowExist((Tk_Window)masterPtr);
+ Tk_MakeWindowExist((Tk_Window)containerPtr);
if (wmPtr->iconFor != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
@@ -3650,7 +3742,7 @@ WmTransientCmd(
return TCL_ERROR;
}
- wmPtr2 = masterPtr->wmInfoPtr;
+ wmPtr2 = containerPtr->wmInfoPtr;
/*
* Under some circumstances, wmPtr2 is NULL here.
@@ -3658,25 +3750,25 @@ WmTransientCmd(
if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "can't make \"%s\" a master: it is an icon for %s",
+ "can't make \"%s\" a container: it is an icon for %s",
Tcl_GetString(objv[3]), Tk_PathName(wmPtr2->iconFor)));
Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "ICON", NULL);
return TCL_ERROR;
}
- for (w = masterPtr; w != NULL && w->wmInfoPtr != NULL;
- w = (TkWindow *)w->wmInfoPtr->master) {
+ for (w = containerPtr; w != NULL && w->wmInfoPtr != NULL;
+ w = (TkWindow *)w->wmInfoPtr->container) {
if (w == winPtr) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "setting \"%s\" as master creates a transient/master cycle",
- Tk_PathName(masterPtr)));
+ "can't set \"%s\" as container: would cause management loop",
+ Tk_PathName(containerPtr)));
Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
return TCL_ERROR;
}
}
/*
- * Add the transient to the master's list, if it not already there.
+ * Add the transient to the container's list, if it not already there.
*/
for (transient = wmPtr2->transientPtr;
@@ -3691,19 +3783,19 @@ WmTransientCmd(
}
/*
- * If the master is withdrawn or iconic then withdraw the transient.
+ * If the container is withdrawn or iconic then withdraw the transient.
*/
if ((wmPtr2->hints.initial_state == WithdrawnState ||
wmPtr2->hints.initial_state == IconicState) &&
wmPtr->hints.initial_state != WithdrawnState) {
TkpWmSetState(winPtr, WithdrawnState);
- transient->flags |= WITHDRAWN_BY_MASTER;
+ transient->flags |= WITHDRAWN_BY_CONTAINER;
}
- wmPtr->master = (Tk_Window) masterPtr;
+ wmPtr->container = (Tk_Window)containerPtr;
}
- ApplyMasterOverrideChanges(winPtr, NULL);
+ ApplyContainerOverrideChanges(winPtr, NULL);
return TCL_OK;
}
@@ -3712,15 +3804,15 @@ WmTransientCmd(
*
* RemoveTransient --
*
- * Clears the transient's master record and removes the transient from the
- * master's list.
+ * Clears the transient's container record and removes the transient from the
+ * container's list.
*
* Results:
* None
*
* Side effects:
- * References to a master are removed from the transient's wmInfo
- * structure and references to the transient are removed from its master's
+ * References to a container are removed from the transient's wmInfo
+ * structure and references to the transient are removed from its container's
* wmInfo.
*
*----------------------------------------------------------------------
@@ -3731,18 +3823,18 @@ RemoveTransient(
TkWindow *winPtr)
{
WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2;
- TkWindow *masterPtr;
+ TkWindow *containerPtr;
Transient *transPtr, *temp;
- if (wmPtr == NULL || wmPtr->master == NULL) {
+ if (wmPtr == NULL || wmPtr->container == NULL) {
return;
}
- masterPtr = (TkWindow *)wmPtr->master;
- wmPtr2 = masterPtr->wmInfoPtr;
+ containerPtr = (TkWindow *)wmPtr->container;
+ wmPtr2 = containerPtr->wmInfoPtr;
if (wmPtr2 == NULL) {
return;
}
- wmPtr->master = NULL;
+ wmPtr->container= NULL;
transPtr = wmPtr2->transientPtr;
while (transPtr != NULL) {
if (transPtr->winPtr != winPtr) {
@@ -3806,10 +3898,6 @@ WmWithdrawCmd(
TkpWmSetState(winPtr, WithdrawnState);
- NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
- [win orderOut:NSApp];
- [win setExcludedFromWindowsMenu:YES];
-
/*
* If this window has a transient, the transient must also be withdrawn.
*/
@@ -3817,12 +3905,12 @@ WmWithdrawCmd(
for (Transient *transientPtr = wmPtr->transientPtr;
transientPtr != NULL; transientPtr = transientPtr->nextPtr) {
TkWindow *winPtr2 = transientPtr->winPtr;
- TkWindow *masterPtr = (TkWindow *) TkGetTransientMaster(winPtr2);
+ TkWindow *containerPtr = (TkWindow *)TkMacOSXGetContainer(winPtr2);
- if (masterPtr == winPtr &&
+ if (containerPtr == winPtr &&
winPtr2->wmInfoPtr->hints.initial_state != WithdrawnState) {
TkpWmSetState(winPtr2, WithdrawnState);
- transientPtr->flags |= WITHDRAWN_BY_MASTER;
+ transientPtr->flags |= WITHDRAWN_BY_CONTAINER;
}
}
@@ -3879,7 +3967,7 @@ Tk_SetGrid(
int widthInc, int heightInc)/* Pixel increments corresponding to a change
* of one grid unit. */
{
- TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *winPtr = (TkWindow *)tkwin;
WmInfo *wmPtr;
/*
@@ -3973,7 +4061,7 @@ Tk_UnsetGrid(
Tk_Window tkwin) /* Token for window that is currently
* controlling gridding. */
{
- TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *winPtr = (TkWindow *)tkwin;
WmInfo *wmPtr;
/*
@@ -4046,14 +4134,14 @@ TopLevelEventProc(
Tk_ErrorHandler handler = Tk_CreateErrorHandler(winPtr->display,
-1, -1, -1, NULL, NULL);
- Tk_DestroyWindow((Tk_Window) winPtr);
+ Tk_DestroyWindow((Tk_Window)winPtr);
Tk_DeleteErrorHandler(handler);
}
if (wmTracing) {
TkMacOSXDbgMsg("TopLevelEventProc: %s deleted", winPtr->pathName);
}
} else if (eventPtr->type == ReparentNotify) {
- Tcl_Panic("recieved unwanted reparent event");
+ Tcl_Panic("received unwanted reparent event");
}
}
@@ -4080,7 +4168,7 @@ TopLevelReqProc(
TCL_UNUSED(void *), /* Not used. */
Tk_Window tkwin) /* Information about window. */
{
- TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *winPtr = (TkWindow *)tkwin;
WmInfo *wmPtr;
wmPtr = winPtr->wmInfoPtr;
@@ -4260,7 +4348,7 @@ UpdateGeometryInfo(
wmPtr->x = wmPtr->y = 0;
wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y);
- Tk_GeometryRequest((Tk_Window) contWinPtr, width, height);
+ Tk_GeometryRequest((Tk_Window)contWinPtr, width, height);
}
return;
}
@@ -4513,7 +4601,7 @@ Tk_GetRootCoords(
int *yPtr) /* Where to store y-displacement of (0,0). */
{
int x, y;
- TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *winPtr = (TkWindow *)tkwin;
/*
* Search back through this window's parents all the way to a top-level
@@ -4535,27 +4623,6 @@ Tk_GetRootCoords(
otherPtr = TkpGetOtherWindow(winPtr);
if (otherPtr == NULL) {
- if (tkMacOSXEmbedHandler->getOffsetProc != NULL) {
- Point theOffset;
-
- /*
- * We do not require that the changes.x & changes.y for a
- * non-Tk master window be kept up to date. So we first
- * subtract off the possibly bogus values that have been
- * added on at the top of this pass through the loop, and
- * then call out to the getOffsetProc to give us the
- * correct offset.
- */
-
- x -= winPtr->changes.x + winPtr->changes.border_width;
- y -= winPtr->changes.y + winPtr->changes.border_width;
-
- tkMacOSXEmbedHandler->getOffsetProc((Tk_Window) winPtr,
- &theOffset);
-
- x += theOffset.h;
- y += theOffset.v;
- }
break;
}
@@ -4677,10 +4744,10 @@ Tk_CoordsToWindow(
}
winPtr = nextPtr;
}
- if (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr) {
+ if (winPtr->mainPtr != ((TkWindow *)tkwin)->mainPtr) {
return NULL;
}
- return (Tk_Window) winPtr;
+ return (Tk_Window)winPtr;
}
/*
@@ -4720,7 +4787,7 @@ Tk_TopCoordsToWindow(
int x, y; /* Coordinates in winPtr. */
Window *children; /* Children of winPtr, or NULL. */
- winPtr = (TkWindow *) tkwin;
+ winPtr = (TkWindow *)tkwin;
x = rootX;
y = rootY;
while (1) {
@@ -4773,7 +4840,7 @@ Tk_TopCoordsToWindow(
}
*newX = x;
*newY = y;
- return (Tk_Window) winPtr;
+ return (Tk_Window)winPtr;
}
/*
@@ -4874,7 +4941,7 @@ Tk_GetVRootGeometry(
int *heightPtr)
{
WmInfo *wmPtr;
- TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *winPtr = (TkWindow *)tkwin;
/*
* Find the top-level window for tkwin, and locate the window manager
@@ -4925,7 +4992,7 @@ Tk_MoveToplevelWindow(
Tk_Window tkwin, /* Window to move. */
int x, int y) /* New location for window (within parent). */
{
- TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *winPtr = (TkWindow *)tkwin;
WmInfo *wmPtr = winPtr->wmInfoPtr;
if (!(winPtr->flags & TK_TOP_LEVEL)) {
@@ -4995,7 +5062,7 @@ TkWmRestackToplevel(
wmPtr->hints.initial_state == WithdrawnState) {
return;
}
- macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
if (macWindow == nil) {
return;
}
@@ -5011,7 +5078,7 @@ TkWmRestackToplevel(
otherWmPtr->hints.initial_state == WithdrawnState) {
return;
}
- otherMacWindow = TkMacOSXDrawableWindow(otherPtr->window);
+ otherMacWindow = TkMacOSXGetNSWindowForDrawable(otherPtr->window);
if (otherMacWindow == nil) {
return;
}
@@ -5117,7 +5184,7 @@ TkWmAddToColormapWindows(
topPtr->wmInfoPtr->cmapCount = count+1;
/*
- * On the Macintosh all of this is just an excercise in compatability as
+ * On the Macintosh all of this is just an excercise in compatibility as
* we don't support colormaps. If we did they would be installed here.
*/
}
@@ -5353,20 +5420,20 @@ TkSetWMName(
}
NSString *title = [[NSString alloc] initWithUTF8String:titleUid];
- [TkMacOSXDrawableWindow(winPtr->window) setTitle:title];
+ [TkMacOSXGetNSWindowForDrawable(winPtr->window) setTitle:title];
[title release];
}
/*
*----------------------------------------------------------------------
*
- * TkGetTransientMaster --
+ * TkMacOSXGetContainer --
*
* If the passed window has the TRANSIENT_FOR property set this will
- * return the master window. Otherwise it will return None.
+ * return the container window. Otherwise it will return None.
*
* Results:
- * The master window or None.
+ * The container window or None.
*
* Side effects:
* None.
@@ -5375,11 +5442,11 @@ TkSetWMName(
*/
Tk_Window
-TkGetTransientMaster(
+TkMacOSXGetContainer(
TkWindow *winPtr)
{
if (winPtr->wmInfoPtr != NULL) {
- return (Tk_Window)winPtr->wmInfoPtr->master;
+ return (Tk_Window)winPtr->wmInfoPtr->container;
}
return NULL;
}
@@ -5389,7 +5456,8 @@ TkGetTransientMaster(
*
* TkMacOSXGetXWindow --
*
- * Returns the X window Id associated with the given NSWindow*.
+ * Stub function that returns the X window Id associated with the
+ * given NSWindow*.
*
* Results:
* The window id is returned. None is returned if not a Tk window.
@@ -5404,27 +5472,26 @@ Window
TkMacOSXGetXWindow(
void *macWinPtr)
{
- Tcl_HashEntry *hPtr;
-
- if (!macWinPtr || !windowHashInit) {
- return None;
+ Window window = None;
+ TKWindow *w = (TKWindow *)macWinPtr;
+ if ([w respondsToSelector: @selector (tkWindow)]) {
+ window = [w tkWindow];
}
- hPtr = Tcl_FindHashEntry(&windowTable, macWinPtr);
- if (hPtr == NULL) {
- return None;
- }
- return (Window) Tcl_GetHashValue(hPtr);
+ return window ? window : None;
}
/*
*----------------------------------------------------------------------
*
- * TkMacOSXGetTkWindow --
+ * Tk_MacOSXGetTkWindow --
*
- * Returns the TkWindow* associated with the given NSWindow*.
+ * Returns the Tk_Window associated with the given NSWindow*. This
+ * function is a stub, so the NSWindow* parameter must be declared as
+ * void*.
*
* Results:
- * The TkWindow* returned. NULL is returned if not a Tk window.
+ * A Tk_Window, or NULL if the NSWindow is not associated with
+ * any Tk window.
*
* Side effects:
* None.
@@ -5432,15 +5499,17 @@ TkMacOSXGetXWindow(
*----------------------------------------------------------------------
*/
-TkWindow*
-TkMacOSXGetTkWindow(
- NSWindow *w)
+Tk_Window
+Tk_MacOSXGetTkWindow(
+ void *w)
{
- Window window = TkMacOSXGetXWindow(w);
+ Window window = None;
TkDisplay *dispPtr = TkGetDisplayList();
-
+ if ([(NSWindow *)w respondsToSelector: @selector (tkWindow)]) {
+ window = [(TKWindow *)w tkWindow];
+ }
return (window != None ?
- (TkWindow *)Tk_IdToWindow(dispPtr->display, window) : NULL);
+ Tk_IdToWindow(dispPtr->display, window) : NULL);
}
/*
@@ -5465,7 +5534,7 @@ MODULE_SCOPE int
TkMacOSXIsWindowZoomed(
TkWindow *winPtr)
{
- NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ NSWindow *macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
return [macWindow isZoomed];
}
@@ -5584,7 +5653,7 @@ TkUnsupported1ObjCmd(
}
return WmWinStyle(interp, winPtr, objc, objv);
case TKMWS_TABID:
- if ([NSApp macMinorVersion] < 12) {
+ if ([NSApp macOSVersion] < 101200) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"Tabbing identifiers did not exist until OSX 10.12.", -1));
Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "TABBINGID", NULL);
@@ -5596,7 +5665,7 @@ TkUnsupported1ObjCmd(
}
return WmWinTabbingId(interp, winPtr, objc, objv);
case TKMWS_APPEARANCE:
- if ([NSApp macMinorVersion] < 9) {
+ if ([NSApp macOSVersion] < 100900) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"Window appearances did not exist until OSX 10.9.", -1));
Tcl_SetErrorCode(interp, "TK", "WINDOWSTYLE", "APPEARANCE", NULL);
@@ -5606,7 +5675,7 @@ TkUnsupported1ObjCmd(
Tcl_WrongNumArgs(interp, 2, objv, "window ?appearancename?");
return TCL_ERROR;
}
- if (objc == 4 && [NSApp macMinorVersion] < 14) {
+ if (objc == 4 && [NSApp macOSVersion] < 101400) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"Window appearances cannot be changed before OSX 10.14.",
-1));
@@ -5620,7 +5689,7 @@ TkUnsupported1ObjCmd(
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
- TkMacOSXInDarkMode((Tk_Window) winPtr)));
+ TkMacOSXInDarkMode((Tk_Window)winPtr)));
return TCL_OK;
default:
return TCL_ERROR;
@@ -5847,13 +5916,14 @@ WmWinTabbingId(
#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101200)
Tcl_Obj *result = NULL;
NSString *idString;
- NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);
if (win) {
idString = win.tabbingIdentifier;
result = Tcl_NewStringObj(idString.UTF8String, [idString length]);
}
if (result == NULL) {
- NSLog(@"Failed to read tabbing identifier; try calling update idletasks before getting/setting the tabbing identifier of the window.");
+ NSLog(@"Failed to read tabbing identifier; try calling update idletasks"
+ " before getting/setting the tabbing identifier of the window.");
return TCL_OK;
}
Tcl_SetObjResult(interp, result);
@@ -5937,7 +6007,7 @@ WmWinAppearance(
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
const char *resultString = "unrecognized";
- NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);
if (win) {
appearance = win.appearance.name;
if (appearance == nil) {
@@ -6012,7 +6082,7 @@ TkpMakeMenuWindow(
* is always visible, e.g. as a floating
* menu. */
{
- TkWindow *winPtr = (TkWindow *) tkwin;
+ TkWindow *winPtr = (TkWindow *)tkwin;
if (transient) {
winPtr->wmInfoPtr->macClass = kSimpleWindowClass;
@@ -6049,13 +6119,13 @@ TkMacOSXMakeRealWindowExist(
WmInfo *wmPtr = winPtr->wmInfoPtr;
MacDrawable *macWin;
WindowClass macClass;
- Bool overrideRedirect = Tk_Attributes((Tk_Window) winPtr)->override_redirect;
+ Bool overrideRedirect = Tk_Attributes((Tk_Window)winPtr)->override_redirect;
if (TkMacOSXHostToplevelExists(winPtr)) {
return;
}
- macWin = (MacDrawable *) winPtr->window;
+ macWin = (MacDrawable *)winPtr->window;
/*
* If this is embedded, make sure its container's toplevel exists, then
@@ -6072,14 +6142,7 @@ TkMacOSXMakeRealWindowExist(
return;
}
- if (tkMacOSXEmbedHandler == NULL) {
- Tcl_Panic("TkMacOSXMakeRealWindowExist could not find container");
- }
- if (tkMacOSXEmbedHandler->containerExistProc &&
- tkMacOSXEmbedHandler->containerExistProc((Tk_Window) winPtr)
- != TCL_OK) {
- Tcl_Panic("ContainerExistProc could not make container");
- }
+ Tcl_Panic("TkMacOSXMakeRealWindowExist could not find container");
return;
/*
@@ -6116,16 +6179,18 @@ TkMacOSXMakeRealWindowExist(
NSUnifiedTitleAndToolbarWindowMask : 0) |
((attributes & kWindowSideTitlebarAttribute) ? 1 << 9 : 0) |
(attributes >> WM_NSMASK_SHIFT);
- Class winClass = (macClass == kDrawerWindowClass ? [NSDrawerWindow class] :
+ Class winClass = (macClass == kDrawerWindowClass ? [TKDrawerWindow class] :
(styleMask & (NSUtilityWindowMask|NSDocModalWindowMask|
- NSNonactivatingPanelMask|NSHUDWindowMask)) ? [NSPanel class] :
+ NSNonactivatingPanelMask|NSHUDWindowMask)) ? [TKPanel class] :
[TKWindow class]);
NSRect structureRect = [winClass frameRectForContentRect:NSZeroRect
styleMask:styleMask];
NSRect contentRect = NSMakeRect(5 - structureRect.origin.x,
TkMacOSXZeroScreenHeight() - (TkMacOSXZeroScreenTop() + 5 +
structureRect.origin.y + structureRect.size.height + 200), 200, 200);
- NSWindow *window = [[winClass alloc] initWithContentRect:contentRect
+ if (wmPtr->hints.initial_state == WithdrawnState) {
+ }
+ TKWindow *window = [[winClass alloc] initWithContentRect:contentRect
styleMask:styleMask backing:NSBackingStoreBuffered defer:YES];
if (!window) {
Tcl_Panic("couldn't allocate new Mac window");
@@ -6138,7 +6203,7 @@ TkMacOSXMakeRealWindowExist(
[window setAcceptsMouseMovedEvents:YES];
[window setReleasedWhenClosed:NO];
if (styleMask & NSUtilityWindowMask) {
- [(NSPanel*)window setFloatingPanel:YES];
+ [(TKPanel*)window setFloatingPanel:YES];
}
if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) &&
!(styleMask & NSDocModalWindowMask)) {
@@ -6158,115 +6223,59 @@ TkMacOSXMakeRealWindowExist(
geometry.origin.y = TkMacOSXZeroScreenHeight() - (geometry.origin.y +
geometry.size.height);
[window setFrame:geometry display:YES];
- TkMacOSXRegisterOffScreenWindow((Window) macWin, window);
+ [window setTkWindow: (Window) macWin];
macWin->flags |= TK_HOST_EXISTS;
if (overrideRedirect) {
XSetWindowAttributes atts;
atts.override_redirect = True;
- Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts);
- ApplyMasterOverrideChanges(winPtr, NULL);
+ Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts);
+ ApplyContainerOverrideChanges(winPtr, NULL);
}
}
/*
*----------------------------------------------------------------------
*
- * TkpDisplayWindow --
+ * TkpRedrawWidget --
*
- * Mark the contentView of this window as needing display so the window
- * will be drawn by the window manager. If this is called within the
- * drawRect method, do nothing.
+ * Mark the bounding rectangle of this widget as needing display so the
+ * widget will be drawn by [NSView drawRect:]. If this is called within
+ * the drawRect method, do nothing.
*
* Results:
* None.
*
* Side effects:
- * The window's contentView is marked as needing display.
- *
- *----------------------------------------------------------------------
- */
-
-MODULE_SCOPE void
-TkpDisplayWindow(Tk_Window tkwin) {
- if (![NSApp isDrawing]) {
- TkWindow *winPtr = (TkWindow *) tkwin;
- NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);
-
- [[w contentView] setNeedsDisplay: YES];
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TkMacOSXRegisterOffScreenWindow --
- *
- * This function adds the passed in Off Screen Port to the hash table that
- * maps Mac windows to root X windows.
- *
- * Results:
- * None.
- *
- * Side effects:
- * An entry is added to the windowTable hash table.
+ * The widget's bounding rectangle is marked as dirty.
*
*----------------------------------------------------------------------
*/
void
-TkMacOSXRegisterOffScreenWindow(
- Window window, /* Window structure. */
- void *portPtr) /* Pointer to a Mac Window. */
-{
- Tcl_HashEntry *valueHashPtr;
- int isNew;
+TkpRedrawWidget(Tk_Window tkwin) {
+ TkWindow *winPtr = (TkWindow *)tkwin;
+ NSWindow *w;
+ Rect tkBounds;
+ NSRect bounds;
- if (!windowHashInit) {
- Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS);
- windowHashInit = true;
+ if ([NSApp isDrawing]) {
+ return;
}
- valueHashPtr = Tcl_CreateHashEntry(&windowTable, (char *) portPtr, &isNew);
- if (!isNew) {
- Tcl_Panic("Same macintosh window allocated twice!");
+ w = TkMacOSXGetNSWindowForDrawable(winPtr->window);
+ if (w) {
+ TKContentView *view = [w contentView];
+ TkMacOSXWinBounds(winPtr, &tkBounds);
+ bounds = NSMakeRect(tkBounds.left,
+ [view bounds].size.height - tkBounds.bottom,
+ tkBounds.right - tkBounds.left,
+ tkBounds.bottom - tkBounds.top);
+ [view setTkNeedsDisplay:YES];
+ [view setTkDirtyRect:bounds];
}
- Tcl_SetHashValue(valueHashPtr, window);
}
-/*
- *----------------------------------------------------------------------
- *
- * TkMacOSXUnregisterMacWindow --
- *
- * Given a macintosh port window, this function removes the association
- * between this window and the root X window that Tk cares about.
- *
- * Results:
- * None.
- *
- * Side effects:
- * An entry is removed from the windowTable hash table.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TkMacOSXUnregisterMacWindow(
- void *macWinPtr) /* Reference to a Mac Window */
-{
- Tcl_HashEntry *entryPtr;
-
- if (!windowHashInit) {
- Tcl_Panic("TkMacOSXUnregisterMacWindow: unmapping before inited");
- }
- entryPtr = Tcl_FindHashEntry(&windowTable, macWinPtr);
- if (!entryPtr) {
- TkMacOSXDbgMsg("Failed to find window %p", macWinPtr);
- } else {
- Tcl_DeleteHashEntry(entryPtr);
- }
-}
/*
*----------------------------------------------------------------------
@@ -6394,11 +6403,12 @@ TkpWmSetState(
return;
}
- macWin = TkMacOSXDrawableWindow(winPtr->window);
+ macWin = TkMacOSXGetNSWindowForDrawable(winPtr->window);
if (state == WithdrawnState) {
- Tk_UnmapWindow((Tk_Window) winPtr);
+ Tk_UnmapWindow((Tk_Window)winPtr);
} else if (state == IconicState) {
+
/*
* The window always gets unmapped. If we can show the icon version of
* the window we also collapse it.
@@ -6408,16 +6418,18 @@ TkpWmSetState(
![macWin isMiniaturized]) {
[macWin miniaturize:NSApp];
}
- Tk_UnmapWindow((Tk_Window) winPtr);
+ Tk_UnmapWindow((Tk_Window)winPtr);
} else if (state == NormalState || state == ZoomState) {
- Tk_MapWindow((Tk_Window) winPtr);
- if (macWin && ([macWin styleMask] & NSMiniaturizableWindowMask) &&
- [macWin isMiniaturized]) {
- [macWin deminiaturize:NSApp];
- }
- TkMacOSXZoomToplevel(macWin, state == NormalState ? inZoomIn :
- inZoomOut);
+ Tk_MapWindow((Tk_Window)winPtr);
+ [macWin deminiaturize:NSApp];
+ [macWin orderFront:NSApp];
+ TkMacOSXZoomToplevel(macWin, state == NormalState ? inZoomIn : inZoomOut);
}
+ /*
+ * Make sure windows are updated after the state change.
+ */
+
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
}
/*
@@ -6444,29 +6456,6 @@ TkpIsWindowFloating(
}
/*
- *----------------------------------------------------------------------
- *
- * TkMacOSXWindowClass --
- *
- * Returns OS X window class of window
- *
- * Results:
- * 1 or 0 depending on window's floating attribute.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-MODULE_SCOPE WindowClass
-TkMacOSXWindowClass(
- TkWindow *winPtr)
-{
- return winPtr->wmInfoPtr->macClass;
-}
-
-/*
*--------------------------------------------------------------
*
* TkMacOSXWindowOffset --
@@ -6590,7 +6579,7 @@ TkpChangeFocus(
}
if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)) {
- NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window);
TkWmRestackToplevel(winPtr, Above, NULL);
if (force) {
@@ -6645,7 +6634,7 @@ WmStackorderToplevelWrapperMap(
if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)
&& (winPtr->display == display)) {
hPtr = Tcl_CreateHashEntry(table,
- (char*) TkMacOSXDrawableWindow(winPtr->window), &newEntry);
+ (void *)TkMacOSXGetNSWindowForDrawable(winPtr->window), &newEntry);
Tcl_SetHashValue(hPtr, winPtr);
}
@@ -6724,8 +6713,8 @@ TkMacOSXApplyWindowAttributes(
WmInfo *wmPtr = winPtr->wmInfoPtr;
ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1);
- if (wmPtr->master != NULL || winPtr->atts.override_redirect) {
- ApplyMasterOverrideChanges(winPtr, macWindow);
+ if (wmPtr->container != NULL || winPtr->atts.override_redirect) {
+ ApplyContainerOverrideChanges(winPtr, macWindow);
}
}
@@ -6765,7 +6754,7 @@ ApplyWindowAttributeFlagChanges(
if (!create) {
return;
}
- Tk_MakeWindowExist((Tk_Window) winPtr);
+ Tk_MakeWindowExist((Tk_Window)winPtr);
}
if (!TkMacOSXHostToplevelExists(winPtr)) {
if (!create) {
@@ -6773,7 +6762,7 @@ ApplyWindowAttributeFlagChanges(
}
TkMacOSXMakeRealWindowExist(winPtr);
}
- macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
}
if ((changedAttributes & kWindowCloseBoxAttribute) || initial) {
[[macWindow standardWindowButton:NSWindowCloseButton]
@@ -6850,7 +6839,7 @@ ApplyWindowAttributeFlagChanges(
* after 10.10.
*/
-#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101000)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
if (!(macWindow.styleMask & NSUtilityWindowMask)) {
/*
* Exclude overrideredirect, transient, and "help"-styled
@@ -6858,12 +6847,11 @@ ApplyWindowAttributeFlagChanges(
*/
if ((winPtr->atts.override_redirect) ||
- (wmPtr->master != NULL) ||
+ (wmPtr->container != NULL) ||
(winPtr->wmInfoPtr->macClass == kHelpWindowClass)) {
b |= (NSWindowCollectionBehaviorCanJoinAllSpaces |
NSWindowCollectionBehaviorFullScreenAuxiliary);
} else {
- NSSize screenSize = [[macWindow screen] frame].size;
b |= NSWindowCollectionBehaviorFullScreenPrimary;
/*
@@ -6873,7 +6861,9 @@ ApplyWindowAttributeFlagChanges(
* window. To work around this we make the max size equal
* to the screen size. (For 10.11 and up, only)
*/
- if ([NSApp macMinorVersion] > 10) {
+
+ if (@available(macOS 10.11, *)) {
+ NSSize screenSize = [[macWindow screen] frame].size;
[macWindow setMaxFullScreenContentSize:screenSize];
}
}
@@ -6895,7 +6885,7 @@ ApplyWindowAttributeFlagChanges(
if ((wmPtr->flags & WM_TOPMOST) != (oldFlags & WM_TOPMOST)) {
[macWindow setLevel:(wmPtr->flags & WM_TOPMOST) ?
kCGUtilityWindowLevel : ([macWindow isKindOfClass:
- [NSPanel class]] && [macWindow isFloatingPanel] ?
+ [TKPanel class]] && [macWindow isFloatingPanel] ?
kCGFloatingWindowLevel : kCGNormalWindowLevel)];
}
@@ -6916,9 +6906,9 @@ ApplyWindowAttributeFlagChanges(
/*
*----------------------------------------------------------------------
*
- * ApplyMasterOverrideChanges --
+ * ApplyContainerOverrideChanges --
*
- * This procedure applies changes to override_redirect or master.
+ * This procedure applies changes to override_redirect or container.
*
* Results:
* None.
@@ -6930,7 +6920,7 @@ ApplyWindowAttributeFlagChanges(
*/
static void
-ApplyMasterOverrideChanges(
+ApplyContainerOverrideChanges(
TkWindow *winPtr,
NSWindow *macWindow)
{
@@ -6943,7 +6933,7 @@ ApplyMasterOverrideChanges(
if (!macWindow && winPtr->window != None &&
TkMacOSXHostToplevelExists(winPtr)) {
- macWindow = TkMacOSXDrawableWindow(winPtr->window);
+ macWindow = TkMacOSXGetNSWindowForDrawable(winPtr->window);
}
styleMask = [macWindow styleMask];
@@ -6957,20 +6947,20 @@ ApplyMasterOverrideChanges(
wmPtr->attributes = macClassAttrs[kSimpleWindowClass].defaultAttrs;
}
wmPtr->attributes |= kWindowNoActivatesAttribute;
- if ([NSApp macMinorVersion] == 6) {
+ if ([NSApp macOSVersion] == 100600) {
styleMask = 0;
} else {
styleMask &= ~NSTitledWindowMask;
}
} else {
if (wmPtr->macClass == kSimpleWindowClass &&
- oldAttributes == kWindowNoActivatesAttribute) {
+ (oldAttributes & kWindowNoActivatesAttribute)) {
wmPtr->macClass = kDocumentWindowClass;
wmPtr->attributes =
macClassAttrs[kDocumentWindowClass].defaultAttrs;
}
wmPtr->attributes &= ~kWindowNoActivatesAttribute;
- if ([NSApp macMinorVersion] == 6) {
+ if ([NSApp macOSVersion] == 100600) {
styleMask = NSTitledWindowMask |
NSClosableWindowMask |
NSMiniaturizableWindowMask |
@@ -6996,9 +6986,9 @@ ApplyMasterOverrideChanges(
[macWindow setExcludedFromWindowsMenu:YES];
[macWindow setStyleMask:styleMask];
if (wmPtr->hints.initial_state == NormalState) {
- [macWindow orderFront:nil];
+ [macWindow orderFront:NSApp];
}
- if (wmPtr->master != NULL) {
+ if (wmPtr->container != NULL) {
wmPtr->flags |= WM_TOPMOST;
} else {
wmPtr->flags &= ~WM_TOPMOST;
@@ -7014,24 +7004,24 @@ ApplyMasterOverrideChanges(
[macWindow setExcludedFromWindowsMenu:NO];
wmPtr->flags &= ~WM_TOPMOST;
}
- if (wmPtr->master != None) {
- TkWindow *masterWinPtr = (TkWindow *) wmPtr->master;
+ if (wmPtr->container != None) {
+ TkWindow *containerWinPtr = (TkWindow *)wmPtr->container;
- if (masterWinPtr && (masterWinPtr->window != None)
- && TkMacOSXHostToplevelExists(masterWinPtr)) {
- NSWindow *masterMacWin = TkMacOSXDrawableWindow(
- masterWinPtr->window);
+ if (containerWinPtr && (containerWinPtr->window != None)
+ && TkMacOSXHostToplevelExists(containerWinPtr)) {
+ NSWindow *containerMacWin = TkMacOSXGetNSWindowForDrawable(
+ containerWinPtr->window);
/*
* Try to add the transient window as a child window of the
- * master. A child NSWindow retains its relative position with
- * respect to the parent when the parent is moved. This is
- * pointless if the parent is offscreen, and adding a child to
- * an offscreen window causes the parent to be displayed as a
- * zombie. So we only do this if the parent is visible.
+ * container. A child NSWindow retains its relative position
+ * with respect to the parent when the parent is moved. This
+ * is pointless if the parent is offscreen, and adding a child
+ * to an offscreen window causes the parent to be displayed as
+ * a zombie. So we only do this if the parent is visible.
*/
- if (masterMacWin && [masterMacWin isVisible]
+ if (containerMacWin && [containerMacWin isVisible]
&& (winPtr->flags & TK_MAPPED)) {
/*
* If the transient is already a child of some other window,
@@ -7039,12 +7029,12 @@ ApplyMasterOverrideChanges(
*/
parentWindow = [macWindow parentWindow];
- if (parentWindow && parentWindow != masterMacWin) {
+ if (parentWindow && parentWindow != containerMacWin) {
[parentWindow removeChildWindow:macWindow];
}
-
- [masterMacWin addChildWindow:macWindow
- ordered:NSWindowAbove];
+ [macWindow orderFront:NSApp];
+ [containerMacWin addChildWindow:macWindow
+ ordered:NSWindowAbove];
}
}
} else {
@@ -7243,7 +7233,7 @@ RemapWindows(
*/
if (winPtr->window != None) {
- MacDrawable *macWin = (MacDrawable *) winPtr->window;
+ MacDrawable *macWin = (MacDrawable *)winPtr->window;
macWin->toplevel->referenceCount--;
macWin->toplevel = parentWin->toplevel;
@@ -7260,7 +7250,7 @@ RemapWindows(
for (childPtr = winPtr->childList; childPtr != NULL;
childPtr = childPtr->nextPtr) {
- RemapWindows(childPtr, (MacDrawable *) winPtr->window);
+ RemapWindows(childPtr, (MacDrawable *)winPtr->window);
}
}
diff --git a/macosx/tkMacOSXWm.h b/macosx/tkMacOSXWm.h
index 20bbb6d..c648292 100644
--- a/macosx/tkMacOSXWm.h
+++ b/macosx/tkMacOSXWm.h
@@ -37,7 +37,7 @@ typedef struct ProtocolHandler {
} 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.
+ * transient windows belonging to a given container.
*/
typedef struct Transient {
@@ -46,7 +46,7 @@ typedef struct Transient {
struct Transient *nextPtr;
} Transient;
-#define WITHDRAWN_BY_MASTER 0x1
+#define WITHDRAWN_BY_CONTAINER 0x1
/*
* A data structure of the following type holds window-manager-related
@@ -65,8 +65,8 @@ 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. */
- Tk_Window master; /* Master window for TRANSIENT_FOR property, or
- * None. */
+ Tk_Window container; /* Container window for TRANSIENT_FOR property,
+ * or None. */
XWMHints hints; /* Various pieces of information for window
* manager. */
char *leaderName; /* Path name of leader of window group
diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c
index 4912583..25d9f96 100644
--- a/macosx/tkMacOSXXStubs.c
+++ b/macosx/tkMacOSXXStubs.c
@@ -256,8 +256,8 @@ XkbOpenDisplay(
*/
screen->root = ROOT_ID;
screen->display = display;
- screen->black_pixel = 0x00000000 | PIXEL_MAGIC << 24;
- screen->white_pixel = 0x00FFFFFF | PIXEL_MAGIC << 24;
+ screen->black_pixel = 0x00000000;
+ screen->white_pixel = 0x00FFFFFF;
screen->ext_data = (XExtData *) &maxBounds;
screen->root_visual = (Visual *)ckalloc(sizeof(Visual));
@@ -308,7 +308,6 @@ XkbOpenDisplay(
return display;
}
-
/*
*----------------------------------------------------------------------
@@ -488,7 +487,7 @@ XGetGeometry(
unsigned int *border_width_return,
unsigned int *depth_return)
{
- TkWindow *winPtr = ((MacDrawable *) d)->winPtr;
+ TkWindow *winPtr = ((MacDrawable *)d)->winPtr;
display->request++;
*root_return = ROOT_ID;
@@ -500,7 +499,7 @@ XGetGeometry(
*border_width_return = winPtr->changes.border_width;
*depth_return = Tk_Depth(winPtr);
} else {
- CGSize size = ((MacDrawable *) d)->size;
+ CGSize size = ((MacDrawable *)d)->size;
*x_return = 0;
*y_return = 0;
*width_return = size.width;
@@ -878,8 +877,7 @@ XForceScreenSaver(
display->request++;
return Success;
}
-
-#if 0
+
int
XSetClipRectangles(
Display *d,
@@ -888,24 +886,22 @@ XSetClipRectangles(
int clip_y_origin,
XRectangle* rectangles,
int n,
- int ordering)
+ TCL_UNUSED(int))
{
- Region clipRgn = XCreateRegion();
+ TkRegion clipRgn = TkCreateRegion();
while (n--) {
- XRectangle rect = *rectangles;
+ XRectangle rect = *rectangles;
- rect.x += clip_x_origin;
- rect.y += clip_y_origin;
- XUnionRectWithRegion(&rect, clipRgn, clipRgn);
- rectangles++;
+ rect.x += clip_x_origin;
+ rect.y += clip_y_origin;
+ TkUnionRectWithRegion(&rect, clipRgn, clipRgn);
+ rectangles++;
}
- XSetRegion(d, gc, clipRgn);
- XDestroyRegion(clipRgn);
+ TkSetRegion(d, gc, clipRgn);
+ TkDestroyRegion(clipRgn);
return 1;
}
-#endif
-
/*
*----------------------------------------------------------------------
*
@@ -1084,7 +1080,7 @@ XSynchronize(
Display *display,
TCL_UNUSED(Bool))
{
- display->request++;
+ display->request++;
return NULL;
}
@@ -1190,7 +1186,7 @@ Tk_GetUserInactiveTime(
uint64_t time;
IOReturn result;
- regEntry = IOServiceGetMatchingService(kIOMasterPortDefault,
+ regEntry = IOServiceGetMatchingService(0,
IOServiceMatching("IOHIDSystem"));
if (regEntry == 0) {
diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c
index 72649f6..8437aa6 100644
--- a/macosx/ttkMacOSXTheme.c
+++ b/macosx/ttkMacOSXTheme.c
@@ -39,7 +39,7 @@
#define BEGIN_DRAWING(d) { \
TkMacOSXDrawingContext dc; \
- if (!TkMacOSXSetupDrawingContext((d), NULL, 1, &dc)) {return;}
+ if (!TkMacOSXSetupDrawingContext((d), NULL, &dc)) {return;}
#define END_DRAWING \
TkMacOSXRestoreDrawingContext(&dc);}
@@ -153,7 +153,7 @@ static inline CGRect BoxToRect(
Drawable d,
Ttk_Box b)
{
- MacDrawable *md = (MacDrawable *) d;
+ MacDrawable *md = (MacDrawable *)d;
CGRect rect;
rect.origin.y = b.y + md->yOff;
@@ -232,52 +232,51 @@ static CGRect NormalizeButtonBounds(
* support Dark Mode anyway.
*/
-static CGFloat windowBackground[4] = {
+static const CGFloat WINDOWBACKGROUND[4] = {
235.0 / 255, 235.0 / 255, 235.0 / 255, 1.0
};
-static CGFloat whiteRGBA[4] = {1.0, 1.0, 1.0, 1.0};
-static CGFloat blackRGBA[4] = {0.0, 0.0, 0.0, 1.0};
+static const CGFloat WHITERGBA[4] = {1.0, 1.0, 1.0, 1.0};
+static const CGFloat BLACKRGBA[4] = {0.0, 0.0, 0.0, 1.0};
/*----------------------------------------------------------------------
* GetBackgroundColor --
*
* Fills the array rgba with the color coordinates for a background color.
- * Start with the background color of a window's geometry master, or the
- * standard ttk window background if there is no master. If the contrast
- * parameter is nonzero, modify this color to be darker, for the aqua
- * appearance, or lighter for the DarkAqua appearance. This is primarily
- * used by the Fill and Background elements.
+ * Start with the background color of a window's geometry container, or
+ * the standard ttk window background if there is no container. If the
+ * contrast parameter is nonzero, modify this color to be darker, for the
+ * aqua appearance, or lighter for the DarkAqua appearance. This is
+ * primarily used by the Fill and Background elements.
*/
static void GetBackgroundColor(
- CGContextRef context,
+ TCL_UNUSED(CGContextRef),
Tk_Window tkwin,
int contrast,
CGFloat *rgba)
{
- TkWindow *winPtr = (TkWindow *) tkwin;
- TkWindow *masterPtr = (TkWindow *) TkGetGeomMaster(tkwin);
- (void)context;
+ TkWindow *winPtr = (TkWindow *)tkwin;
+ TkWindow *containerPtr = (TkWindow *)TkGetContainer(tkwin);
- while (masterPtr && masterPtr->privatePtr) {
- if (masterPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) {
+ while (containerPtr && containerPtr->privatePtr) {
+ if (containerPtr->privatePtr->flags & TTK_HAS_CONTRASTING_BG) {
break;
}
- masterPtr = (TkWindow *) TkGetGeomMaster(masterPtr);
+ containerPtr = (TkWindow *)TkGetContainer(containerPtr);
}
- if (masterPtr && masterPtr->privatePtr) {
+ if (containerPtr && containerPtr->privatePtr) {
for (int i = 0; i < 4; i++) {
- rgba[i] = masterPtr->privatePtr->fillRGBA[i];
+ rgba[i] = containerPtr->privatePtr->fillRGBA[i];
}
} else {
- if ([NSApp macMinorVersion] > 13) {
+ if ([NSApp macOSVersion] > 101300) {
NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
NSColor *windowColor = [[NSColor windowBackgroundColor]
colorUsingColorSpace: deviceRGB];
[windowColor getComponents: rgba];
} else {
for (int i = 0; i < 4; i++) {
- rgba[i] = windowBackground[i];
+ rgba[i] = WINDOWBACKGROUND[i];
}
}
}
@@ -304,9 +303,10 @@ static void GetBackgroundColor(
/*----------------------------------------------------------------------
- * +++ Single Arrow Buttons --
+ * +++ Single Arrow Images --
*
- * Used in ListHeaders and Comboboxes.
+ * Used in ListHeaders and Comboboxes as well as disclosure triangles in
+ * macOS 11.
*/
static void DrawDownArrow(
@@ -314,7 +314,7 @@ static void DrawDownArrow(
CGRect bounds,
CGFloat inset,
CGFloat size,
- CGFloat *rgba)
+ const CGFloat *rgba)
{
CGFloat x, y;
@@ -336,7 +336,7 @@ static void DrawUpArrow(
CGRect bounds,
CGFloat inset,
CGFloat size,
- CGFloat *rgba)
+ const CGFloat *rgba)
{
CGFloat x, y;
@@ -353,6 +353,48 @@ static void DrawUpArrow(
CGContextStrokePath(context);
}
+static void DrawClosedDisclosure(
+ CGContextRef context,
+ CGRect bounds,
+ CGFloat inset,
+ CGFloat size,
+ CGFloat *rgba)
+{
+ CGFloat x, y;
+
+ CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
+ CGContextSetLineWidth(context, 1.5);
+ x = bounds.origin.x + inset;
+ y = bounds.origin.y + trunc(bounds.size.height / 2);
+ CGContextBeginPath(context);
+ CGPoint arrow[3] = {
+ {x, y - size / 4 - 1}, {x + size / 2, y}, {x, y + size / 4 + 1}
+ };
+ CGContextAddLines(context, arrow, 3);
+ CGContextStrokePath(context);
+}
+
+static void DrawOpenDisclosure(
+ CGContextRef context,
+ CGRect bounds,
+ CGFloat inset,
+ CGFloat size,
+ CGFloat *rgba)
+{
+ CGFloat x, y;
+
+ CGContextSetRGBStrokeColor(context, rgba[0], rgba[1], rgba[2], rgba[3]);
+ CGContextSetLineWidth(context, 1.5);
+ x = bounds.origin.x + inset;
+ y = bounds.origin.y + trunc(bounds.size.height / 2);
+ CGContextBeginPath(context);
+ CGPoint arrow[3] = {
+ {x, y - size / 4}, {x + size / 2, y + size / 2}, {x + size, y - size / 4}
+ };
+ CGContextAddLines(context, arrow, 3);
+ CGContextStrokePath(context);
+}
+
/*----------------------------------------------------------------------
* +++ Double Arrow Buttons --
*
@@ -364,7 +406,7 @@ static void DrawUpDownArrows(
CGRect bounds,
CGFloat inset,
CGFloat size,
- CGFloat *rgba)
+ const CGFloat *rgba)
{
CGFloat x, y;
@@ -502,10 +544,13 @@ static void SolidFillRoundedRectangle(
NSColor *color)
{
CGPathRef path;
- CHECK_RADIUS(radius, bounds)
- CGContextSetFillColorWithColor(context, CGCOLOR(color));
+ CHECK_RADIUS(radius, bounds)
path = CGPathCreateWithRoundedRect(bounds, radius, radius, NULL);
+ if (!path) {
+ return;
+ }
+ CGContextSetFillColorWithColor(context, CGCOLOR(color));
CGContextBeginPath(context);
CGContextAddPath(context, path);
CGContextFillPath(context);
@@ -548,7 +593,7 @@ static void DrawListHeader(
* So we have to query the Apple window manager.
*/
- NSWindow *win = TkMacOSXDrawableWindow(Tk_WindowId(tkwin));
+ NSWindow *win = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));
CGFloat *bgRGBA = [win isKeyWindow] ? activeBgRGBA : inactiveBgRGBA;
CGFloat x = bounds.origin.x, y = bounds.origin.y;
CGFloat w = bounds.size.width, h = bounds.size.height;
@@ -588,9 +633,9 @@ static void DrawListHeader(
arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16;
arrowBounds.size.width = 16;
if (state & TTK_STATE_ALTERNATE) {
- DrawUpArrow(context, arrowBounds, 3, 8, blackRGBA);
+ DrawUpArrow(context, arrowBounds, 3, 8, BLACKRGBA);
} else if (state & TTK_STATE_SELECTED) {
- DrawDownArrow(context, arrowBounds, 3, 8, blackRGBA);
+ DrawDownArrow(context, arrowBounds, 3, 8, BLACKRGBA);
}
}
}
@@ -712,9 +757,9 @@ static void DrawDarkButton(
darkSelectedGradient, 2);
}
if (kind == kThemePopupButton) {
- DrawUpDownArrows(context, arrowBounds, 3, 7, whiteRGBA);
+ DrawUpDownArrows(context, arrowBounds, 3, 7, WHITERGBA);
} else {
- DrawDownArrow(context, arrowBounds, 4, 8, whiteRGBA);
+ DrawDownArrow(context, arrowBounds, 4, 8, WHITERGBA);
}
}
@@ -773,7 +818,7 @@ static void DrawDarkIncDecButton(
darkSelectedGradient, 2);
CGContextRestoreGState(context);
}
- DrawUpDownArrows(context, bounds, 3, 5, whiteRGBA);
+ DrawUpDownArrows(context, bounds, 3, 5, WHITERGBA);
HighlightButtonBorder(context, bounds);
}
@@ -1040,14 +1085,13 @@ static void DrawDarkTab(
static void DrawDarkSeparator(
CGRect bounds,
CGContextRef context,
- Tk_Window tkwin)
+ TCL_UNUSED(Tk_Window))
{
static CGFloat fill[4] = {1.0, 1.0, 1.0, 0.3};
NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
NSColor *fillColor = [NSColor colorWithColorSpace: deviceRGB
components: fill
count:4];
- (void)tkwin;
CGContextSetFillColorWithColor(context, CGCOLOR(fillColor));
CGContextFillRect(context, bounds);
@@ -1167,20 +1211,19 @@ static void DrawDarkFrame(
static void DrawDarkListHeader(
CGRect bounds,
CGContextRef context,
- Tk_Window tkwin,
+ TCL_UNUSED(Tk_Window),
int state)
{
NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
NSColor *stroke;
- (void)tkwin;
CGContextSetStrokeColorSpace(context, deviceRGB.CGColorSpace);
CGFloat x = bounds.origin.x, y = bounds.origin.y;
CGFloat w = bounds.size.width, h = bounds.size.height;
- CGPoint top[2] = {{x, y}, {x + w, y}};
- CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
- CGPoint separator[2] = {{x + w, y + 3}, {x + w, y + h - 3}};
+ CGPoint top[2] = {{x, y + 1}, {x + w, y + 1}};
+ CGPoint bottom[2] = {{x, y + h}, {x + w, y + h}};
+ CGPoint separator[2] = {{x + w - 1, y + 3}, {x + w - 1, y + h - 3}};
CGContextSaveGState(context);
CGContextSetShouldAntialias(context, false);
stroke = [NSColor colorWithColorSpace: deviceRGB
@@ -1202,9 +1245,9 @@ static void DrawDarkListHeader(
arrowBounds.origin.x = bounds.origin.x + bounds.size.width - 16;
arrowBounds.size.width = 16;
if (state & TTK_STATE_ALTERNATE) {
- DrawUpArrow(context, arrowBounds, 3, 8, whiteRGBA);
+ DrawUpArrow(context, arrowBounds, 3, 8, WHITERGBA);
} else if (state & TTK_STATE_SELECTED) {
- DrawDownArrow(context, arrowBounds, 3, 8, whiteRGBA);
+ DrawDownArrow(context, arrowBounds, 3, 8, WHITERGBA);
}
}
}
@@ -1412,7 +1455,7 @@ static void ButtonElementDraw(
} else if (info.kind == kThemePushButton &&
(state & TTK_STATE_PRESSED)) {
bounds.size.height += 2;
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
GradientFillRoundedRectangle(dc.context, bounds, 4,
pressedPushButtonGradient, 2);
}
@@ -1606,7 +1649,7 @@ static void PaneElementDraw(
bounds.origin.y -= kThemeMetricTabFrameOverlap;
bounds.size.height += kThemeMetricTabFrameOverlap;
BEGIN_DRAWING(d)
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
DrawGroupBox(bounds, dc.context, tkwin);
} else {
HIThemeTabPaneDrawInfo info = {
@@ -1665,7 +1708,7 @@ static void GroupElementDraw(
CGRect bounds = BoxToRect(d, b);
BEGIN_DRAWING(d)
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
DrawGroupBox(bounds, dc.context, tkwin);
} else {
const HIThemeGroupBoxDrawInfo info = {
@@ -1705,7 +1748,7 @@ static Ttk_ElementOptionSpec EntryElementOptions[] = {
offsetof(EntryElement, backgroundObj), ENTRY_DEFAULT_BACKGROUND},
{"-fieldbackground", TK_OPTION_BORDER,
offsetof(EntryElement, fieldbackgroundObj), ENTRY_DEFAULT_BACKGROUND},
- {0}
+ {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};
static void EntryElementSize(
@@ -1788,7 +1831,7 @@ static void EntryElementDraw(
}
BEGIN_DRAWING(d)
if (backgroundPtr == NULL) {
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
background = [NSColor textBackgroundColor];
CGContextSetFillColorWithColor(dc.context, CGCOLOR(background));
} else {
@@ -1866,7 +1909,7 @@ static void ComboboxElementDraw(
if (TkMacOSXInDarkMode(tkwin)) {
bounds.size.height += 1;
DrawDarkButton(bounds, info.kind, state, dc.context);
- } else if ([NSApp macMinorVersion] > 8) {
+ } else if ([NSApp macOSVersion] > 100800) {
if ((state & TTK_STATE_BACKGROUND) &&
!(state & TTK_STATE_DISABLED)) {
NSColor *background = [NSColor textBackgroundColor];
@@ -2065,7 +2108,7 @@ static Ttk_ElementOptionSpec TrackElementOptions[] = {
{"-to", TK_OPTION_DOUBLE, offsetof(TrackElement, toObj), NULL},
{"-value", TK_OPTION_DOUBLE, offsetof(TrackElement, valueObj), NULL},
{"-orient", TK_OPTION_STRING, offsetof(TrackElement, orientObj), NULL},
- {0, 0, 0, NULL}
+ {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};
static void TrackElementSize(
void *clientData,
@@ -2094,6 +2137,7 @@ static void TrackElementDraw(
TrackElement *elem = elementRecord;
Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;
double from = 0, to = 100, value = 0, factor;
+ CGRect bounds;
TtkGetOrientFromObj(NULL, elem->orientObj, &orientation);
Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from);
@@ -2101,10 +2145,16 @@ static void TrackElementDraw(
Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value);
factor = RangeToFactor(to);
+ /*
+ * HIThemeTrackDrawInfo uses 2-byte alignment; assigning to a separate
+ * bounds variable avoids UBSan (-fsanitize=alignment) complaints.
+ */
+
+ bounds = BoxToRect(d, b);
HIThemeTrackDrawInfo info = {
.version = 0,
.kind = data->kind,
- .bounds = BoxToRect(d, b),
+ .bounds = bounds,
.min = from * factor,
.max = to * factor,
.value = value * factor,
@@ -2126,7 +2176,7 @@ static void TrackElementDraw(
}
BEGIN_DRAWING(d)
if (TkMacOSXInDarkMode(tkwin)) {
- CGRect bounds = BoxToRect(d, b);
+ bounds = BoxToRect(d, b);
NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB
components: darkTrack
@@ -2205,7 +2255,7 @@ static Ttk_ElementOptionSpec PbarElementOptions[] = {
offsetof(PbarElement, phaseObj), "0"},
{"-mode", TK_OPTION_STRING,
offsetof(PbarElement, modeObj), "determinate"},
- {0, 0, 0, 0}
+ {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};
static void PbarElementSize(
TCL_UNUSED(void *),
@@ -2233,6 +2283,7 @@ static void PbarElementDraw(
Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL;
int phase = 0;
double value = 0, maximum = 100, factor;
+ CGRect bounds;
TtkGetOrientFromObj(NULL, pbar->orientObj, &orientation);
Tcl_GetDoubleFromObj(NULL, pbar->valueObj, &value);
@@ -2240,13 +2291,19 @@ static void PbarElementDraw(
Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase);
factor = RangeToFactor(maximum);
+ /*
+ * HIThemeTrackDrawInfo uses 2-byte alignment; assigning to a separate
+ * bounds variable avoids UBSan (-fsanitize=alignment) complaints.
+ */
+
+ bounds = BoxToRect(d, b);
HIThemeTrackDrawInfo info = {
.version = 0,
.kind =
(!strcmp("indeterminate",
Tcl_GetString(pbar->modeObj)) && value) ?
kThemeIndeterminateBar : kThemeProgressBar,
- .bounds = BoxToRect(d, b),
+ .bounds = bounds,
.min = 0,
.max = maximum * factor,
.value = value * factor,
@@ -2259,7 +2316,7 @@ static void PbarElementDraw(
BEGIN_DRAWING(d)
if (TkMacOSXInDarkMode(tkwin)) {
- CGRect bounds = BoxToRect(d, b);
+ bounds = BoxToRect(d, b);
NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB
components: darkTrack
@@ -2295,7 +2352,7 @@ typedef struct
static Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
{"-orient", TK_OPTION_STRING,
offsetof(ScrollbarElement, orientObj), "horizontal"},
- {0, 0, 0, 0}
+ {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};
static void TroughElementSize(
TCL_UNUSED(void *),
@@ -2313,12 +2370,12 @@ static void TroughElementSize(
ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness);
if (orientation == TTK_ORIENT_HORIZONTAL) {
*minHeight = thickness;
- if ([NSApp macMinorVersion] > 7) {
+ if ([NSApp macOSVersion] > 100700) {
*paddingPtr = Ttk_MakePadding(4, 4, 4, 3);
}
} else {
*minWidth = thickness;
- if ([NSApp macMinorVersion] > 7) {
+ if ([NSApp macOSVersion] > 100700) {
*paddingPtr = Ttk_MakePadding(4, 4, 3, 4);
}
}
@@ -2363,7 +2420,7 @@ static void TroughElementDraw(
components: rgba
count: 4];
BEGIN_DRAWING(d)
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
CGContextSetFillColorWithColor(dc.context, CGCOLOR(troughColor));
} else {
ChkErr(HIThemeSetFill, kThemeBrushDocumentWindowBackground, NULL,
@@ -2426,7 +2483,7 @@ static void ThumbElementDraw(
* draw the thumb directly.
*/
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
CGRect thumbBounds = BoxToRect(d, b);
NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
NSColor *thumbColor;
@@ -2452,7 +2509,7 @@ static void ThumbElementDraw(
END_DRAWING
} else {
double thumbSize, trackSize, visibleSize, factor, fraction;
- MacDrawable *macWin = (MacDrawable *) Tk_WindowId(tkwin);
+ MacDrawable *macWin = (MacDrawable *)Tk_WindowId(tkwin);
CGRect troughBounds = {{macWin->xOff, macWin->yOff},
{Tk_Width(tkwin), Tk_Height(tkwin)}};
@@ -2486,7 +2543,7 @@ static void ThumbElementDraw(
visibleSize = (thumbSize / trackSize) * factor;
info.max = factor - visibleSize;
info.trackInfo.scrollbar.viewsize = visibleSize;
- if ([NSApp macMinorVersion] < 8 ||
+ if ([NSApp macOSVersion] < 100800 ||
orientation == TTK_ORIENT_HORIZONTAL) {
info.value = factor * fraction;
} else {
@@ -2524,7 +2581,7 @@ static void ArrowElementSize(
int *minHeight,
TCL_UNUSED(Ttk_Padding *))
{
- if ([NSApp macMinorVersion] < 8) {
+ if ([NSApp macOSVersion] < 100800) {
*minHeight = *minWidth = 14;
} else {
*minHeight = *minWidth = -1;
@@ -2708,7 +2765,7 @@ static void FillElementDraw(
{
CGRect bounds = BoxToRect(d, b);
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
NSColor *bgColor;
CGFloat fill[4];
@@ -2813,7 +2870,7 @@ typedef struct {
static Ttk_ElementOptionSpec FieldElementOptions[] = {
{"-fieldbackground", TK_OPTION_BORDER,
offsetof(FieldElement, backgroundObj), "white"},
- {NULL, 0, 0, NULL}
+ {NULL, TK_OPTION_BOOLEAN, 0, NULL}
};
static void FieldElementDraw(
@@ -2880,7 +2937,7 @@ static void TreeAreaElementSize (
* widget expects the heading to be the same height as a row.
*/
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
paddingPtr->top = 4;
}
}
@@ -2900,7 +2957,7 @@ static void TreeHeaderElementSize(
int *minHeight,
Ttk_Padding *paddingPtr)
{
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
*minHeight = 24;
} else {
ButtonElementSize(clientData, elementRecord, tkwin, minWidth,
@@ -2927,7 +2984,7 @@ static void TreeHeaderElementDraw(
};
BEGIN_DRAWING(d)
- if ([NSApp macMinorVersion] > 8) {
+ if ([NSApp macOSVersion] > 100800) {
/*
* Compensate for the padding added in TreeHeaderElementSize, so
@@ -3002,8 +3059,21 @@ static void DisclosureElementDraw(
};
BEGIN_DRAWING(d)
- ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
+ if ([NSApp macOSVersion] >= 110000) {
+ CGFloat rgba[4];
+ NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace];
+ NSColor *stroke = [[NSColor textColor]
+ colorUsingColorSpace: deviceRGB];
+ [stroke getComponents: rgba];
+ if (state & TTK_TREEVIEW_STATE_OPEN) {
+ DrawOpenDisclosure(dc.context, bounds, 2, 8, rgba);
+ } else {
+ DrawClosedDisclosure(dc.context, bounds, 2, 12, rgba);
+ }
+ } else {
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
NULL);
+ }
END_DRAWING
}
}
@@ -3053,20 +3123,20 @@ TTK_LAYOUT("TCombobox",
/* Notebook tabs -- no focus ring */
TTK_LAYOUT("Tab",
TTK_GROUP("Notebook.tab", TTK_FILL_BOTH,
- TTK_GROUP("Notebook.padding", TTK_EXPAND | TTK_FILL_BOTH,
- TTK_NODE("Notebook.label", TTK_EXPAND | TTK_FILL_BOTH))))
+ TTK_GROUP("Notebook.padding", TTK_FILL_BOTH,
+ TTK_NODE("Notebook.label", TTK_FILL_BOTH))))
/* Spinbox -- buttons 2px to the right of the field. */
TTK_LAYOUT("TSpinbox",
TTK_GROUP("Spinbox.buttons", TTK_PACK_RIGHT,
TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP | TTK_STICK_E)
TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM | TTK_STICK_E))
- TTK_GROUP("Spinbox.field", TTK_EXPAND | TTK_FILL_X,
- TTK_NODE("Spinbox.textarea", TTK_EXPAND | TTK_FILL_X)))
+ TTK_GROUP("Spinbox.field", TTK_FILL_X,
+ TTK_NODE("Spinbox.textarea", TTK_FILL_X)))
/* Progress bars -- track only */
TTK_LAYOUT("TProgressbar",
- TTK_NODE("Progressbar.track", TTK_EXPAND | TTK_FILL_BOTH))
+ TTK_NODE("Progressbar.track", TTK_FILL_BOTH))
/* Treeview -- no border. */
TTK_LAYOUT("Treeview",
@@ -3091,15 +3161,13 @@ TTK_LAYOUT("Item",
TTK_LAYOUT("Vertical.TScrollbar",
TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y,
- TTK_NODE("Vertical.Scrollbar.thumb",
- TTK_PACK_TOP | TTK_EXPAND | TTK_FILL_BOTH)
+ TTK_NODE("Vertical.Scrollbar.thumb", TTK_FILL_BOTH)
TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM)
TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_BOTTOM)))
TTK_LAYOUT("Horizontal.TScrollbar",
TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X,
- TTK_NODE("Horizontal.Scrollbar.thumb",
- TTK_PACK_LEFT | TTK_EXPAND | TTK_FILL_BOTH)
+ TTK_NODE("Horizontal.Scrollbar.thumb", TTK_FILL_BOTH)
TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT)
TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_RIGHT)))