Import Tk 8.6.11

This commit is contained in:
Steve Dower
2021-03-30 00:54:10 +01:00
parent 42c69189d9
commit 070b8750b0
403 changed files with 21608 additions and 16269 deletions

24
macosx/Credits.html.in Normal file
View File

@@ -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>

View File

@@ -25,6 +25,7 @@ EXTRA_CONFIGURE_ARGS ?=
EXTRA_MAKE_ARGS ?=
INSTALL_PATH ?= /Library/Frameworks
TCL_INSTALL_PATH ?= ${INSTALL_PATH}/Tcl.framework
APPLICATION_INSTALL_PATH ?= /Applications/Utilities
PREFIX ?= /usr/local
BINDIR ?= ${PREFIX}/bin
@@ -43,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
@@ -107,7 +120,7 @@ TCL_VERSION := ${VERSION}
wish := wish
WISH = wish${VERSION}
BUILD_TARGET := all tktest
BUILD_TARGET := binaries libraries tktest
INSTALL_TARGET := install
ifneq ($(wildcard $(subst ${space},\ ,${TCL_BUILD_DIR})/tclConfig.sh),)
@@ -115,7 +128,7 @@ TCL_DIR := ${TCL_BUILD_DIR}
TCL_FRAMEWORK_DIR := ${TCL_BUILD_DIR}/..
MAKE_VARS :=
else
TCL_DIR := ${TCL_FRAMEWORK_DIR}/Tcl.framework
TCL_DIR := ${TCL_INSTALL_PATH}
TCL_EXE := ${TCLSH_DIR}/tclsh${TCL_VERSION}
MAKE_VARS := TCL_EXE
export DYLD_FRAMEWORK_PATH := ${TCL_FRAMEWORK_DIR}
@@ -210,8 +223,14 @@ 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_)
@@ -227,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
@@ -236,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" && \
@@ -271,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}

View File

@@ -275,9 +275,9 @@ but rather refers to the context in which the color should be used.
Tk now provides the following semantic colors as system colors:
systemTextColor, systemTextBackgroundColor, systemSelectedTextColor,
systemSelectedTextBackgroundColor, systemControlTextColor,
systemDisabledControlTextColor, systemLabelColor, and
systemControlAccentColor. All of these except the last two were
present in OSX 10.0 (and those two are simulated in systems where they
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
@@ -455,6 +455,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 +676,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
~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -1411,7 +1411,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>"; };
@@ -3078,7 +3078,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 */,

View File

@@ -1411,7 +1411,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>"; };
@@ -3078,7 +3078,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 */,

68
macosx/configure vendored
View File

@@ -2287,7 +2287,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
TK_VERSION=8.6
TK_MAJOR_VERSION=8
TK_MINOR_VERSION=6
TK_PATCH_LEVEL=".10"
TK_PATCH_LEVEL=".11"
VERSION=${TK_VERSION}
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
@@ -2432,10 +2432,6 @@ $as_echo "loading" >&6; }
$as_echo "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; }
fi
# eval is required to do the TCL_DBGX substitution
eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
# If the TCL_BIN_DIR is the build directory (not the install directory),
# then set the common variable name to the value of the build variables.
# For example, the variable TCL_LIB_SPEC will be set to the value
@@ -2469,12 +2465,6 @@ $as_echo "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; }
esac
fi
# eval is required to do the TCL_DBGX substitution
eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
@@ -4286,14 +4276,6 @@ else
tcl_ok=yes
fi
if test "${enable_shared+set}" = set; then
enableval="$enable_shared"
tcl_ok=$enableval
else
tcl_ok=yes
fi
if test "$tcl_ok" = "yes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5
$as_echo "shared" >&6; }
@@ -4607,7 +4589,7 @@ fi
if test "$GCC" = yes; then :
CFLAGS_OPTIMIZE=-O2
CFLAGS_WARNING="-Wall"
CFLAGS_WARNING="-Wall -Wpointer-arith"
else
@@ -4875,7 +4857,7 @@ fi
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
;;
CYGWIN_*|MINGW32*)
CYGWIN_*|MINGW32_*|MSYS_*)
SHLIB_CFLAGS=""
SHLIB_LD='${CC} -shared'
SHLIB_SUFFIX=".dll"
@@ -4886,7 +4868,7 @@ fi
CC_SEARCH_FLAGS=""
LD_SEARCH_FLAGS=""
TCL_NEEDS_EXP_FILE=1
TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a'
TCL_EXPORT_FILE_SUFFIX='${VERSION}.dll.a'
SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Cygwin version of gcc" >&5
$as_echo_n "checking for Cygwin version of gcc... " >&6; }
@@ -5092,7 +5074,7 @@ fi
SHLIB_LD='${CC} -shared'
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
;;
@@ -5182,7 +5164,7 @@ esac
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
;;
@@ -5200,7 +5182,7 @@ esac
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
if test "$GCC" = yes; then :
@@ -5237,7 +5219,7 @@ esac
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
@@ -5277,7 +5259,7 @@ fi
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
if test "`uname -m`" = "alpha"; then :
@@ -5344,8 +5326,8 @@ fi
LD_FLAGS="-Wl,--export-dynamic"
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
;;
MP-RAS-02*)
@@ -5385,7 +5367,7 @@ fi
DL_LIBS=""
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}'
@@ -5413,7 +5395,7 @@ fi
LDFLAGS="$LDFLAGS -export-dynamic"
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
if test "${TCL_THREADS}" = "1"; then :
@@ -5433,11 +5415,10 @@ fi
SHLIB_SUFFIX=".so"
DL_OBJS="tclLoadDl.o"
DL_LIBS=""
LDFLAGS=""
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
if test "${TCL_THREADS}" = "1"; then :
@@ -5640,6 +5621,7 @@ fi
$as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h
tcl_cv_cc_visibility_hidden=yes
fi
CC_SEARCH_FLAGS=""
@@ -5830,7 +5812,7 @@ fi
DL_LIBS=""
if test $doRpath = yes; then :
CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
if test "$GCC" = yes; then :
@@ -6233,7 +6215,7 @@ fi
case $system in
AIX-*) ;;
BSD/OS*) ;;
CYGWIN_*|MINGW32_*) ;;
CYGWIN_*|MINGW32_*|MSYS_*) ;;
IRIX*) ;;
NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
Darwin-*) ;;
@@ -6263,7 +6245,7 @@ fi
if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then :
LIB_SUFFIX=${SHARED_LIB_SUFFIX}
MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${LDFLAGS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}'
if test "${SHLIB_SUFFIX}" = ".dll"; then :
INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;'
@@ -6404,7 +6386,6 @@ else
fi
# FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT.
DBGX=""
if test "$tcl_ok" = "no"; then
CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)'
LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)'
@@ -7384,7 +7365,7 @@ else
int
main ()
{
struct passwd pwd; pwd.pw_gecos;
struct passwd pwd; (void)pwd.pw_gecos;
;
return 0;
}
@@ -8668,8 +8649,12 @@ $as_echo "static library" >&6; }
echo "$LDFLAGS " | grep -q -- '-prebind ' && TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -seg1addr 0xb000000'
TK_SHLIB_LD_EXTRAS="${TK_SHLIB_LD_EXTRAS}"' -sectcreate __TEXT __info_plist Tk-Info.plist'
EXTRA_WISH_LIBS='-sectcreate __TEXT __info_plist Wish-Info.plist'
EXTRA_WISH_LIBS=${EXTRA_WISH_LIBS}' -sectcreate __TEXT __credits_html Credits.html'
if test "${SHARED_BUILD}" = "0"; then
EXTRA_WISH_LIBS=${EXTRA_WISH_LIBS}' -ObjC'
fi
EXTRA_APP_CC_SWITCHES="${EXTRA_APP_CC_SWITCHES}"' -mdynamic-no-pic'
ac_config_files="$ac_config_files Tk-Info.plist:../macosx/Tk-Info.plist.in Wish-Info.plist:../macosx/Wish-Info.plist.in"
ac_config_files="$ac_config_files Tk-Info.plist:../macosx/Tk-Info.plist.in Wish-Info.plist:../macosx/Wish-Info.plist.in Credits.html:../macosx/Credits.html.in"
for l in ${LOCALES}; do CFBUNDLELOCALIZATIONS="${CFBUNDLELOCALIZATIONS}<string>$l</string>"; done
TK_YEAR="`date +%Y`"
@@ -8703,6 +8688,7 @@ $as_echo "#define TK_FRAMEWORK 1" >>confdefs.h
EXTRA_INSTALL="install-private-headers html-tk"
EXTRA_BUILD_HTML='@ln -fs contents.htm "$(HTML_INSTALL_DIR)"/TkTOC.html'
EXTRA_INSTALL_BINARIES='@echo "Installing Info.plist to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Tk-Info.plist "$(LIB_INSTALL_DIR)/Resources/Info.plist"'
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Credits.html to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && $(INSTALL_DATA) Credits.html "$(LIB_INSTALL_DIR)/Resources"'
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing license.terms to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA) "$(TOP_DIR)/license.terms" "$(LIB_INSTALL_DIR)/Resources"'
if test $tk_aqua = yes; then
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Images to $(LIB_INSTALL_DIR)/Resources/" && $(INSTALL_DATA_DIR) "$(LIB_INSTALL_DIR)/Resources" && for i in Tk.tiff Tk.icns; do $(INSTALL_DATA) "$(MAC_OSX_DIR)/$$i" "$(LIB_INSTALL_DIR)/Resources"; done'
@@ -8712,6 +8698,7 @@ $as_echo "#define TK_FRAMEWORK 1" >>confdefs.h
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.icns to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA_DIR) "$(BIN_INSTALL_DIR)/../Resources"'
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Tk.icns" "$(BIN_INSTALL_DIR)/../Resources/Wish.icns"'
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Wish.sdef to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA) "$(MAC_OSX_DIR)/Wish.sdef" "$(BIN_INSTALL_DIR)/../Resources"'
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Installing Credits.html to $(BIN_INSTALL_DIR)/../Resources" && $(INSTALL_DATA) Credits.html "$(BIN_INSTALL_DIR)/../Resources"'
fi
EXTRA_INSTALL_BINARIES="$EXTRA_INSTALL_BINARIES"' && echo "Finalizing Tk.framework" && rm -f "$(LIB_INSTALL_DIR)/../Current" && ln -s "$(VERSION)" "$(LIB_INSTALL_DIR)/../Current" && for f in "$(LIB_FILE)" tkConfig.sh Resources Headers PrivateHeaders; do rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/Current/$$f" "$(LIB_INSTALL_DIR)/../.."; done && f="$(STUB_LIB_FILE)" && rm -f "$(LIB_INSTALL_DIR)/../../$$f" && ln -s "Versions/$(VERSION)/$$f" "$(LIB_INSTALL_DIR)/../.."'
# Don't use AC_DEFINE for the following as the framework version define
@@ -9525,6 +9512,7 @@ do
"tkConfig.h") CONFIG_HEADERS="$CONFIG_HEADERS tkConfig.h:../unix/tkConfig.h.in" ;;
"Tk-Info.plist") CONFIG_FILES="$CONFIG_FILES Tk-Info.plist:../macosx/Tk-Info.plist.in" ;;
"Wish-Info.plist") CONFIG_FILES="$CONFIG_FILES Wish-Info.plist:../macosx/Wish-Info.plist.in" ;;
"Credits.html") CONFIG_FILES="$CONFIG_FILES Credits.html:../macosx/Credits.html.in" ;;
"Tk.framework") CONFIG_COMMANDS="$CONFIG_COMMANDS Tk.framework" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile:../unix/Makefile.in" ;;
"tkConfig.sh") CONFIG_FILES="$CONFIG_FILES tkConfig.sh:../unix/tkConfig.sh.in" ;;

View File

@@ -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, TkRegion rgn);
typedef void (Tk_MacOSXEmbedGetClipProc) (Tk_Window window, void *rgn);
typedef void (Tk_MacOSXEmbedGetOffsetInParentProc) (Tk_Window window, void *ulCorner);
#include "tkPlatDecls.h"

View File

@@ -44,7 +44,7 @@ static BuiltInIcon builtInIcons[] = {
{"stop", kAlertStopIcon},
{"note", kAlertNoteIcon},
{"caution", kAlertCautionIcon},
{NULL}
{NULL, 0}
};
#define builtInIconSize 32
@@ -100,7 +100,7 @@ TkpDefineNativeBitmaps(void)
name = Tk_GetUid(builtInPtr->name);
predefHashPtr = Tcl_CreateHashEntry(tablePtr, name, &isNew);
if (isNew) {
TkPredefBitmap *predefPtr = ckalloc(sizeof(TkPredefBitmap));
TkPredefBitmap *predefPtr = (TkPredefBitmap *)ckalloc(sizeof(TkPredefBitmap));
predefPtr->source = UINT2PTR(builtInPtr->iconType);
predefPtr->width = builtInIconSize;
@@ -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];
@@ -180,7 +178,7 @@ TkpCreateNativeBitmap(
NSImage *iconImage = [[NSWorkspace sharedWorkspace]
iconForFileType: iconUTI];
CGSize size = CGSizeMake(builtInIconSize, builtInIconSize);
Pixmap pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));
Pixmap pixmap = PixmapFromImage(display, iconImage, size);
return pixmap;
}
@@ -317,7 +315,6 @@ TkpGetNativeAppBitmap(
OSType iconType;
if (OSTypeFromString(name, &iconType) == TCL_OK) {
NSString *iconUTI = OSTYPE_TO_UTI(iconType);
printf("Found image for UTI %s\n", iconUTI.UTF8String);
NSImage *iconImage = [[NSWorkspace sharedWorkspace]
iconForFileType: iconUTI];
pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size));
@@ -344,7 +341,7 @@ TkpGetNativeAppBitmap(
int
TkMacOSXIconBitmapObjCmd(
ClientData clientData, /* Unused. */
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
@@ -399,7 +396,7 @@ TkMacOSXIconBitmapObjCmd(
}
}
#endif
ib.value = ckalloc(len + 1);
ib.value = (char *)ckalloc(len + 1);
strcpy(ib.value, value);
if (!iconBitmapTable.buckets) {
Tcl_InitHashTable(&iconBitmapTable, TCL_STRING_KEYS);
@@ -409,7 +406,7 @@ TkMacOSXIconBitmapObjCmd(
iconBitmap = Tcl_GetHashValue(hPtr);
ckfree(iconBitmap->value);
} else {
iconBitmap = ckalloc(sizeof(IconBitmap));
iconBitmap = (IconBitmap *)ckalloc(sizeof(IconBitmap));
Tcl_SetHashValue(hPtr, iconBitmap);
}
*iconBitmap = ib;

View File

@@ -95,6 +95,8 @@ static void PulseDefaultButtonProc(ClientData clientData);
const Tk_ClassProcs tkpButtonProcs = {
sizeof(Tk_ClassProcs), /* size */
TkButtonWorldChanged, /* worldChangedProc */
NULL,
NULL
};
static int bCount;
@@ -143,7 +145,7 @@ TkButton *
TkpCreateButton(
Tk_Window tkwin)
{
MacButton *macButtonPtr = ckalloc(sizeof(MacButton));
MacButton *macButtonPtr = (MacButton *)ckalloc(sizeof(MacButton));
Tk_CreateEventHandler(tkwin, ActivateMask,
ButtonEventProc, macButtonPtr);
@@ -186,22 +188,12 @@ TkpDisplayButton(
DrawParams* dpPtr = &macButtonPtr->drawParams;
int needhighlight = 0;
if (butPtr->flags & BUTTON_DELETED) {
return;
}
butPtr->flags &= ~REDRAW_PENDING;
if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
return;
}
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 {
@@ -332,39 +324,40 @@ TkpComputeButtonGeometry(
haveText = 1;
}
if (haveImage && haveText) { /* Image and Text */
switch ((enum compound) butPtr->compound) {
case COMPOUND_TOP:
case COMPOUND_BOTTOM:
/*
* Image is above or below text.
*/
if (haveImage) {
if (haveText) { /* Image and Text */
switch ((enum compound) butPtr->compound) {
case COMPOUND_TOP:
case COMPOUND_BOTTOM:
/*
* Image is above or below text.
*/
height += txtHeight + butPtr->padY;
width = (width > txtWidth ? width : txtWidth);
break;
case COMPOUND_LEFT:
case COMPOUND_RIGHT:
/*
* Image is left or right of text.
*/
height += txtHeight + butPtr->padY;
width = (width > txtWidth ? width : txtWidth);
break;
case COMPOUND_LEFT:
case COMPOUND_RIGHT:
/*
* Image is left or right of text.
*/
width += txtWidth + 2*butPtr->padX;
height = (height > txtHeight ? height : txtHeight);
break;
case COMPOUND_CENTER:
/*
* Image and text are superimposed.
*/
width += txtWidth + 2*butPtr->padX;
height = (height > txtHeight ? height : txtHeight);
break;
case COMPOUND_CENTER:
/*
* Image and text are superimposed.
*/
width = (width > txtWidth ? width : txtWidth);
height = (height > txtHeight ? height : txtHeight);
break;
default:
break;
width = (width > txtWidth ? width : txtWidth);
height = (height > txtHeight ? height : txtHeight);
break;
default:
break;
}
}
width += butPtr->indicatorSpace;
} else if (haveImage) { /* Image only */
/* Image with or without text */
width = butPtr->width > 0 ? butPtr->width : width + butPtr->indicatorSpace;
height = butPtr->height > 0 ? butPtr->height : height;
if (butPtr->type == TYPE_BUTTON) {
@@ -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) {
@@ -465,7 +458,7 @@ DrawButtonImageAndText(
pixmap = (Pixmap) Tk_WindowId(tkwin);
if (butPtr->image != None) {
if (butPtr->image != NULL) {
Tk_SizeOfImage(butPtr->image, &width, &height);
haveImage = 1;
} else if (butPtr->bitmap != None) {
@@ -481,7 +474,7 @@ DrawButtonImageAndText(
}
haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
if (haveImage && haveText) { /* Image and Text */
if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { /* Image and Text */
int x, y;
switch ((enum compound) butPtr->compound) {
@@ -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 */
@@ -751,7 +744,7 @@ TkMacOSXDrawButton(
ButtonBackgroundDrawCB(&cntrRect, mbPtr, 32, true);
if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, &dc)) {
return;
}
@@ -784,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;
}
@@ -812,10 +805,10 @@ 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;
@@ -864,12 +857,12 @@ 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;
@@ -1047,7 +1040,14 @@ TkMacOSXComputeButtonParams(
if (drawinfo->state != kThemeStatePressed) {
drawinfo->adornment |= kThemeAdornmentDefault;
}
if (!mbPtr->defaultPulseHandler) {
/*
* Older macOS systems (10.9 and earlier) use an animation to
* indicate the active button. This is simulated by redrawing
* the button periodically.
*/
if (!mbPtr->defaultPulseHandler && ([NSApp macOSVersion] <= 100900)) {
mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(
PULSE_TIMER_MSECS, PulseDefaultButtonProc, butPtr);
}
@@ -1177,6 +1177,13 @@ PulseDefaultButtonProc(ClientData clientData)
MacButton *mbPtr = clientData;
TkpDisplayButton(clientData);
/*
* Fix 40ada90762: any idle calls to TkpDisplayButton need to be canceled
* in case the button is destroyed and has its data freed before the idle
* event is handled (DestroyButton only cancels calls when REDRAW_PENDING
* is set, which is not the case after calling TkpDisplayButton directly).
*/
Tcl_CancelIdleCall(TkpDisplayButton, clientData);
mbPtr->defaultPulseHandler = Tcl_CreateTimerHandler(
PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData);
}

View File

@@ -35,7 +35,9 @@ static Tk_Window clipboardOwner = NULL;
targetPtr->type == dispPtr->utf8Atom) {
for (TkClipboardBuffer *cbPtr = targetPtr->firstBufferPtr;
cbPtr; cbPtr = cbPtr->nextPtr) {
NSString *s = TclUniToNSString(cbPtr->buffer, cbPtr->length);
NSString *s = [[TKNSString alloc]
initWithTclUtfBytes:cbPtr->buffer
length:cbPtr->length];
[string appendString:s];
[s release];
}
@@ -135,26 +137,19 @@ TkSelGetSelection(
string = [pb stringForType:type];
}
if (string) {
/*
* Encode the string using the encoding which is used in Tcl
* when TCL_UTF_MAX = 3. This replaces each UTF-16 surrogate with
* a 3-byte sequence generated using the UTF-8 algorithm. (Even
* though UTF-8 does not allow encoding surrogates, the algorithm
* does produce a 3-byte sequence.)
*/
char *bytes = NSStringToTclUni(string, NULL);
result = proc(clientData, interp, bytes);
if (bytes) {
ckfree(bytes);
if (target == dispPtr->utf8Atom) {
result = proc(clientData, interp, string.UTF8String);
} else if (target == XA_STRING) {
const char *latin1 = [string
cStringUsingEncoding:NSISOLatin1StringEncoding];
result = proc(clientData, interp, latin1);
}
}
} else {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s selection doesn't exist or form \"%s\" not defined",
Tk_GetAtomName(tkwin, selection),
Tk_GetAtomName(tkwin, target)));
"%s selection doesn't exist or form \"%s\" not defined",
Tk_GetAtomName(tkwin, selection),
Tk_GetAtomName(tkwin, target)));
Tcl_SetErrorCode(interp, "TK", "SELECTION", "EXISTS", NULL);
}
return result;
@@ -182,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();
@@ -242,8 +237,8 @@ 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];
@@ -271,7 +266,7 @@ TkSelUpdateClipboard(
void
TkSelEventProc(
Tk_Window tkwin, /* Window for which event was targeted. */
register XEvent *eventPtr) /* X event: either SelectionClear,
XEvent *eventPtr) /* X event: either SelectionClear,
* SelectionRequest, or SelectionNotify. */
{
if (eventPtr->type == SelectionClear) {
@@ -299,7 +294,7 @@ TkSelEventProc(
void
TkSelPropProc(
register XEvent *eventPtr) /* X PropertyChange event. */
TCL_UNUSED(XEvent *)) /* X PropertyChange event. */
{
}

File diff suppressed because it is too large Load Diff

264
macosx/tkMacOSXColor.h Normal file
View File

@@ -0,0 +1,264 @@
#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.*/
HIText, /* A HITheme text color. */
HIBackground, /* A HITheme background 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 systemColorMap. */
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 },
{"ButtonText", HIText, kThemeTextColorPushButtonActive, NULL, 0, NULL },
{"MenuActiveText", HIText, kThemeTextColorMenuItemSelected, NULL, 0, NULL },
{"MenuDisabled", HIText, kThemeTextColorMenuItemDisabled, NULL, 0, NULL },
{"MenuText", HIText, kThemeTextColorMenuItemActive, NULL, 0, NULL },
{"BlackText", HIText, kThemeTextColorBlack, NULL, 0, NULL },
{"DialogActiveText", HIText, kThemeTextColorDialogActive, NULL, 0, NULL },
{"DialogInactiveText", HIText, kThemeTextColorDialogInactive, NULL, 0, NULL },
{"AlertActiveText", HIText, kThemeTextColorAlertActive, NULL, 0, NULL },
{"AlertInactiveText", HIText, kThemeTextColorAlertInactive, NULL, 0, NULL },
{"ModelessDialogActiveText", HIText, kThemeTextColorModelessDialogActive, NULL, 0, NULL },
{"ModelessDialogInactiveText", HIText, kThemeTextColorModelessDialogInactive, NULL, 0, NULL },
{"WindowHeaderActiveText", HIText, kThemeTextColorWindowHeaderActive, NULL, 0, NULL },
{"WindowHeaderInactiveText", HIText, kThemeTextColorWindowHeaderInactive, NULL, 0, NULL },
{"PlacardActiveText", HIText, kThemeTextColorPlacardActive, NULL, 0, NULL },
{"PlacardInactiveText", HIText, kThemeTextColorPlacardInactive, NULL, 0, NULL },
{"PlacardPressedText", HIText, kThemeTextColorPlacardPressed, NULL, 0, NULL },
{"PushButtonActiveText", HIText, kThemeTextColorPushButtonActive, NULL, 0, NULL },
{"PushButtonInactiveText", HIText, kThemeTextColorPushButtonInactive, NULL, 0, NULL },
{"PushButtonPressedText", HIText, kThemeTextColorPushButtonPressed, NULL, 0, NULL },
{"BevelButtonActiveText", HIText, kThemeTextColorBevelButtonActive, NULL, 0, NULL },
{"BevelButtonInactiveText", HIText, kThemeTextColorBevelButtonInactive, NULL, 0, NULL },
{"BevelButtonPressedText", HIText, kThemeTextColorBevelButtonPressed, NULL, 0, NULL },
{"PopupButtonActiveText", HIText, kThemeTextColorPopupButtonActive, NULL, 0, NULL },
{"PopupButtonInactiveText", HIText, kThemeTextColorPopupButtonInactive, NULL, 0, NULL },
{"PopupButtonPressedText", HIText, kThemeTextColorPopupButtonPressed, NULL, 0, NULL },
{"IconLabelText", HIText, kThemeTextColorIconLabel, NULL, 0, NULL },
{"ListViewText", HIText, kThemeTextColorListView, NULL, 0, NULL },
{"DocumentWindowTitleActiveText", HIText, kThemeTextColorDocumentWindowTitleActive, NULL, 0, NULL },
{"DocumentWindowTitleInactiveText", HIText, kThemeTextColorDocumentWindowTitleInactive, NULL, 0, NULL },
{"MovableModalWindowTitleActiveText", HIText, kThemeTextColorMovableModalWindowTitleActive, NULL, 0, NULL },
{"MovableModalWindowTitleInactiveText", HIText, kThemeTextColorMovableModalWindowTitleInactive, NULL, 0, NULL },
{"UtilityWindowTitleActiveText", HIText, kThemeTextColorUtilityWindowTitleActive, NULL, 0, NULL },
{"UtilityWindowTitleInactiveText", HIText, kThemeTextColorUtilityWindowTitleInactive, NULL, 0, NULL },
{"PopupWindowTitleActiveText", HIText, kThemeTextColorPopupWindowTitleActive, NULL, 0, NULL },
{"PopupWindowTitleInactiveText", HIText, kThemeTextColorPopupWindowTitleInactive, NULL, 0, NULL },
{"RootMenuActiveText", HIText, kThemeTextColorRootMenuActive, NULL, 0, NULL },
{"RootMenuSelectedText", HIText, kThemeTextColorRootMenuSelected, NULL, 0, NULL },
{"RootMenuDisabledText", HIText, kThemeTextColorRootMenuDisabled, NULL, 0, NULL },
{"MenuItemActiveText", HIText, kThemeTextColorMenuItemActive, NULL, 0, NULL },
{"MenuItemSelectedText", HIText, kThemeTextColorMenuItemSelected, NULL, 0, NULL },
{"MenuItemDisabledText", HIText, kThemeTextColorMenuItemDisabled, NULL, 0, NULL },
{"PopupLabelActiveText", HIText, kThemeTextColorPopupLabelActive, NULL, 0, NULL },
{"PopupLabelInactiveText", HIText, kThemeTextColorPopupLabelInactive, NULL, 0, NULL },
{"TabFrontActiveText", HIText, kThemeTextColorTabFrontActive, NULL, 0, NULL },
{"TabNonFrontActiveText", HIText, kThemeTextColorTabNonFrontActive, NULL, 0, NULL },
{"TabNonFrontPressedText", HIText, kThemeTextColorTabNonFrontPressed, NULL, 0, NULL },
{"TabFrontInactiveText", HIText, kThemeTextColorTabFrontInactive, NULL, 0, NULL },
{"TabNonFrontInactiveText", HIText, kThemeTextColorTabNonFrontInactive, NULL, 0, NULL },
{"IconLabelSelectedText", HIText, kThemeTextColorIconLabelSelected, NULL, 0, NULL },
{"BevelButtonStickyActiveText", HIText, kThemeTextColorBevelButtonStickyActive, NULL, 0, NULL },
{"BevelButtonStickyInactiveText", HIText, kThemeTextColorBevelButtonStickyInactive, NULL, 0, NULL },
{"NotificationText", HIText, kThemeTextColorNotification, NULL, 0, NULL },
{"SystemDetailText", HIText, kThemeTextColorSystemDetail, NULL, 0, NULL },
{"PlacardBackground", HIBackground, kThemeBackgroundPlacard, NULL, 0, NULL },
{"WindowHeaderBackground", HIBackground, kThemeBackgroundWindowHeader, NULL, 0, NULL },
{"ListViewWindowHeaderBackground", HIBackground, kThemeBackgroundListViewWindowHeader, NULL, 0, NULL },
{"MetalBackground", HIBackground, kThemeBackgroundMetal, NULL, 0, NULL },
{"SecondaryGroupBoxBackground", HIBackground, kThemeBackgroundSecondaryGroupBox, NULL, 0, NULL },
{"TabPaneBackground", HIBackground, kThemeBackgroundTabPane, NULL, 0, NULL },
{"WhiteText", HIText, kThemeTextColorWhite, NULL, 0, NULL },
{"Black", HIBrush, kThemeBrushBlack, NULL, 0, NULL },
{"White", HIBrush, kThemeBrushWhite, 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. */
{"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 },
{"UnemphasizedSelectedTextBackgroundColor", 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:
*/

View File

@@ -19,6 +19,10 @@
#define NSFullScreenWindowMask (1 << 14)
#endif
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
typedef NSInteger NSModalResponse;
#endif
/*
* Let's raise a glass for the project manager who improves our lives by
* generating deprecation warnings about pointless changes of the names
@@ -98,10 +102,18 @@
#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

View File

@@ -54,131 +54,131 @@ struct CursorName {
#define MacXCursorData(n) ((id)tkMacOSXXCursors[TK_MAC_XCURSOR_##n])
static const struct CursorName cursorNames[] = {
{"none", NONE, nil},
{"arrow", SELECTOR, @"arrowCursor"},
{"top_left_arrow", SELECTOR, @"arrowCursor"},
{"left_ptr", SELECTOR, @"arrowCursor"},
{"copyarrow", SELECTOR, @"dragCopyCursor", @"_copyDragCursor"},
{"aliasarrow", SELECTOR, @"dragLinkCursor", @"_linkDragCursor"},
{"contextualmenuarrow", SELECTOR, @"contextualMenuCursor"},
{"movearrow", SELECTOR, @"_moveCursor"},
{"ibeam", SELECTOR, @"IBeamCursor"},
{"text", SELECTOR, @"IBeamCursor"},
{"xterm", SELECTOR, @"IBeamCursor"},
{"cross", SELECTOR, @"crosshairCursor"},
{"crosshair", SELECTOR, @"crosshairCursor"},
{"cross-hair", SELECTOR, @"crosshairCursor"},
{"tcross", SELECTOR, @"crosshairCursor"},
{"hand", SELECTOR, @"openHandCursor"},
{"openhand", SELECTOR, @"openHandCursor"},
{"closedhand", SELECTOR, @"closedHandCursor"},
{"fist", SELECTOR, @"closedHandCursor"},
{"pointinghand", SELECTOR, @"pointingHandCursor"},
{"resize", SELECTOR, @"arrowCursor"},
{"resizeleft", SELECTOR, @"resizeLeftCursor"},
{"resizeright", SELECTOR, @"resizeRightCursor"},
{"resizeleftright", SELECTOR, @"resizeLeftRightCursor"},
{"resizeup", SELECTOR, @"resizeUpCursor"},
{"resizedown", SELECTOR, @"resizeDownCursor"},
{"resizeupdown", SELECTOR, @"resizeUpDownCursor"},
{"resizebottomleft", SELECTOR, @"_bottomLeftResizeCursor"},
{"resizetopleft", SELECTOR, @"_topLeftResizeCursor"},
{"resizebottomright", SELECTOR, @"_bottomRightResizeCursor"},
{"resizetopright", SELECTOR, @"_topRightResizeCursor"},
{"notallowed", SELECTOR, @"operationNotAllowedCursor"},
{"poof", SELECTOR, @"disappearingItemCursor"},
{"wait", SELECTOR, @"busyButClickableCursor"},
{"spinning", SELECTOR, @"busyButClickableCursor"},
{"countinguphand", SELECTOR, @"busyButClickableCursor"},
{"countingdownhand", SELECTOR, @"busyButClickableCursor"},
{"countingupanddownhand", SELECTOR, @"busyButClickableCursor"},
{"none", NONE, nil, nil, {0, 0}},
{"arrow", SELECTOR, @"arrowCursor", nil, {0, 0}},
{"top_left_arrow", SELECTOR, @"arrowCursor", nil, {0, 0}},
{"left_ptr", SELECTOR, @"arrowCursor", nil, {0, 0}},
{"copyarrow", SELECTOR, @"dragCopyCursor", @"_copyDragCursor", {0, 0}},
{"aliasarrow", SELECTOR, @"dragLinkCursor", @"_linkDragCursor", {0, 0}},
{"contextualmenuarrow", SELECTOR, @"contextualMenuCursor", nil, {0, 0}},
{"movearrow", SELECTOR, @"_moveCursor", nil, {0, 0}},
{"ibeam", SELECTOR, @"IBeamCursor", nil, {0, 0}},
{"text", SELECTOR, @"IBeamCursor", nil, {0, 0}},
{"xterm", SELECTOR, @"IBeamCursor", nil, {0, 0}},
{"cross", SELECTOR, @"crosshairCursor", nil, {0, 0}},
{"crosshair", SELECTOR, @"crosshairCursor", nil, {0, 0}},
{"cross-hair", SELECTOR, @"crosshairCursor", nil, {0, 0}},
{"tcross", SELECTOR, @"crosshairCursor", nil, {0, 0}},
{"hand", SELECTOR, @"openHandCursor", nil, {0, 0}},
{"openhand", SELECTOR, @"openHandCursor", nil, {0, 0}},
{"closedhand", SELECTOR, @"closedHandCursor", nil, {0, 0}},
{"fist", SELECTOR, @"closedHandCursor", nil, {0, 0}},
{"pointinghand", SELECTOR, @"pointingHandCursor", nil, {0, 0}},
{"resize", SELECTOR, @"arrowCursor", nil, {0, 0}},
{"resizeleft", SELECTOR, @"resizeLeftCursor", nil, {0, 0}},
{"resizeright", SELECTOR, @"resizeRightCursor", nil, {0, 0}},
{"resizeleftright", SELECTOR, @"resizeLeftRightCursor", nil, {0, 0}},
{"resizeup", SELECTOR, @"resizeUpCursor", nil, {0, 0}},
{"resizedown", SELECTOR, @"resizeDownCursor", nil, {0, 0}},
{"resizeupdown", SELECTOR, @"resizeUpDownCursor", nil, {0, 0}},
{"resizebottomleft", SELECTOR, @"_bottomLeftResizeCursor", nil, {0, 0}},
{"resizetopleft", SELECTOR, @"_topLeftResizeCursor", nil, {0, 0}},
{"resizebottomright", SELECTOR, @"_bottomRightResizeCursor", nil, {0, 0}},
{"resizetopright", SELECTOR, @"_topRightResizeCursor", nil, {0, 0}},
{"notallowed", SELECTOR, @"operationNotAllowedCursor", nil, {0, 0}},
{"poof", SELECTOR, @"disappearingItemCursor", nil, {0, 0}},
{"wait", SELECTOR, @"busyButClickableCursor", nil, {0, 0}},
{"spinning", SELECTOR, @"busyButClickableCursor", nil, {0, 0}},
{"countinguphand", SELECTOR, @"busyButClickableCursor", nil, {0, 0}},
{"countingdownhand", SELECTOR, @"busyButClickableCursor", nil, {0, 0}},
{"countingupanddownhand", SELECTOR, @"busyButClickableCursor", nil, {0, 0}},
{"help", IMAGENAMED, @"NSHelpCursor", nil, {8, 8}},
// {"hand", IMAGEBITMAP, MacCursorData(hand)},
{"bucket", IMAGEBITMAP, MacCursorData(bucket)},
{"cancel", IMAGEBITMAP, MacCursorData(cancel)},
// {"resize", IMAGEBITMAP, MacCursorData(resize)},
{"eyedrop", IMAGEBITMAP, MacCursorData(eyedrop)},
{"eyedrop-full", IMAGEBITMAP, MacCursorData(eyedrop_full)},
{"zoom-in", IMAGEBITMAP, MacCursorData(zoom_in)},
{"zoom-out", IMAGEBITMAP, MacCursorData(zoom_out)},
{"X_cursor", IMAGEBITMAP, MacXCursorData(X_cursor)},
// {"arrow", IMAGEBITMAP, MacXCursorData(arrow)},
{"based_arrow_down", IMAGEBITMAP, MacXCursorData(based_arrow_down)},
{"based_arrow_up", IMAGEBITMAP, MacXCursorData(based_arrow_up)},
{"boat", IMAGEBITMAP, MacXCursorData(boat)},
{"bogosity", IMAGEBITMAP, MacXCursorData(bogosity)},
{"bottom_left_corner", IMAGEBITMAP, MacXCursorData(bottom_left_corner)},
{"bottom_right_corner", IMAGEBITMAP, MacXCursorData(bottom_right_corner)},
{"bottom_side", IMAGEBITMAP, MacXCursorData(bottom_side)},
{"bottom_tee", IMAGEBITMAP, MacXCursorData(bottom_tee)},
{"box_spiral", IMAGEBITMAP, MacXCursorData(box_spiral)},
{"center_ptr", IMAGEBITMAP, MacXCursorData(center_ptr)},
{"circle", IMAGEBITMAP, MacXCursorData(circle)},
{"clock", IMAGEBITMAP, MacXCursorData(clock)},
{"coffee_mug", IMAGEBITMAP, MacXCursorData(coffee_mug)},
// {"cross", IMAGEBITMAP, MacXCursorData(cross)},
{"cross_reverse", IMAGEBITMAP, MacXCursorData(cross_reverse)},
// {"crosshair", IMAGEBITMAP, MacXCursorData(crosshair)},
{"diamond_cross", IMAGEBITMAP, MacXCursorData(diamond_cross)},
{"dot", IMAGEBITMAP, MacXCursorData(dot)},
{"dotbox", IMAGEBITMAP, MacXCursorData(dotbox)},
{"double_arrow", IMAGEBITMAP, MacXCursorData(double_arrow)},
{"draft_large", IMAGEBITMAP, MacXCursorData(draft_large)},
{"draft_small", IMAGEBITMAP, MacXCursorData(draft_small)},
{"draped_box", IMAGEBITMAP, MacXCursorData(draped_box)},
{"exchange", IMAGEBITMAP, MacXCursorData(exchange)},
{"fleur", IMAGEBITMAP, MacXCursorData(fleur)},
{"gobbler", IMAGEBITMAP, MacXCursorData(gobbler)},
{"gumby", IMAGEBITMAP, MacXCursorData(gumby)},
{"hand1", IMAGEBITMAP, MacXCursorData(hand1)},
{"hand2", IMAGEBITMAP, MacXCursorData(hand2)},
{"heart", IMAGEBITMAP, MacXCursorData(heart)},
{"icon", IMAGEBITMAP, MacXCursorData(icon)},
{"iron_cross", IMAGEBITMAP, MacXCursorData(iron_cross)},
// {"left_ptr", IMAGEBITMAP, MacXCursorData(left_ptr)},
{"left_side", IMAGEBITMAP, MacXCursorData(left_side)},
{"left_tee", IMAGEBITMAP, MacXCursorData(left_tee)},
{"leftbutton", IMAGEBITMAP, MacXCursorData(leftbutton)},
{"ll_angle", IMAGEBITMAP, MacXCursorData(ll_angle)},
{"lr_angle", IMAGEBITMAP, MacXCursorData(lr_angle)},
{"man", IMAGEBITMAP, MacXCursorData(man)},
{"middlebutton", IMAGEBITMAP, MacXCursorData(middlebutton)},
{"mouse", IMAGEBITMAP, MacXCursorData(mouse)},
{"pencil", IMAGEBITMAP, MacXCursorData(pencil)},
{"pirate", IMAGEBITMAP, MacXCursorData(pirate)},
{"plus", IMAGEBITMAP, MacXCursorData(plus)},
{"question_arrow", IMAGEBITMAP, MacXCursorData(question_arrow)},
{"right_ptr", IMAGEBITMAP, MacXCursorData(right_ptr)},
{"right_side", IMAGEBITMAP, MacXCursorData(right_side)},
{"right_tee", IMAGEBITMAP, MacXCursorData(right_tee)},
{"rightbutton", IMAGEBITMAP, MacXCursorData(rightbutton)},
{"rtl_logo", IMAGEBITMAP, MacXCursorData(rtl_logo)},
{"sailboat", IMAGEBITMAP, MacXCursorData(sailboat)},
{"sb_down_arrow", IMAGEBITMAP, MacXCursorData(sb_down_arrow)},
{"sb_h_double_arrow", IMAGEBITMAP, MacXCursorData(sb_h_double_arrow)},
{"sb_left_arrow", IMAGEBITMAP, MacXCursorData(sb_left_arrow)},
{"sb_right_arrow", IMAGEBITMAP, MacXCursorData(sb_right_arrow)},
{"sb_up_arrow", IMAGEBITMAP, MacXCursorData(sb_up_arrow)},
{"sb_v_double_arrow", IMAGEBITMAP, MacXCursorData(sb_v_double_arrow)},
{"shuttle", IMAGEBITMAP, MacXCursorData(shuttle)},
{"sizing", IMAGEBITMAP, MacXCursorData(sizing)},
{"spider", IMAGEBITMAP, MacXCursorData(spider)},
{"spraycan", IMAGEBITMAP, MacXCursorData(spraycan)},
{"star", IMAGEBITMAP, MacXCursorData(star)},
{"target", IMAGEBITMAP, MacXCursorData(target)},
// {"tcross", IMAGEBITMAP, MacXCursorData(tcross)},
// {"top_left_arrow", IMAGEBITMAP, MacXCursorData(top_left_arrow)},
{"top_left_corner", IMAGEBITMAP, MacXCursorData(top_left_corner)},
{"top_right_corner", IMAGEBITMAP, MacXCursorData(top_right_corner)},
{"top_side", IMAGEBITMAP, MacXCursorData(top_side)},
{"top_tee", IMAGEBITMAP, MacXCursorData(top_tee)},
{"trek", IMAGEBITMAP, MacXCursorData(trek)},
{"ul_angle", IMAGEBITMAP, MacXCursorData(ul_angle)},
{"umbrella", IMAGEBITMAP, MacXCursorData(umbrella)},
{"ur_angle", IMAGEBITMAP, MacXCursorData(ur_angle)},
{"watch", IMAGEBITMAP, MacXCursorData(watch)},
// {"xterm", IMAGEBITMAP, MacXCursorData(xterm)},
{NULL}
// {"hand", IMAGEBITMAP, MacCursorData(hand), nil, {0, 0}},
{"bucket", IMAGEBITMAP, MacCursorData(bucket), nil, {0, 0}},
{"cancel", IMAGEBITMAP, MacCursorData(cancel), nil, {0, 0}},
// {"resize", IMAGEBITMAP, MacCursorData(resize), nil, {0, 0}},
{"eyedrop", IMAGEBITMAP, MacCursorData(eyedrop), nil, {0, 0}},
{"eyedrop-full", IMAGEBITMAP, MacCursorData(eyedrop_full), nil, {0, 0}},
{"zoom-in", IMAGEBITMAP, MacCursorData(zoom_in), nil, {0, 0}},
{"zoom-out", IMAGEBITMAP, MacCursorData(zoom_out), nil, {0, 0}},
{"X_cursor", IMAGEBITMAP, MacXCursorData(X_cursor), nil, {0, 0}},
// {"arrow", IMAGEBITMAP, MacXCursorData(arrow), nil, {0, 0}},
{"based_arrow_down", IMAGEBITMAP, MacXCursorData(based_arrow_down), nil, {0, 0}},
{"based_arrow_up", IMAGEBITMAP, MacXCursorData(based_arrow_up), nil, {0, 0}},
{"boat", IMAGEBITMAP, MacXCursorData(boat), nil, {0, 0}},
{"bogosity", IMAGEBITMAP, MacXCursorData(bogosity), nil, {0, 0}},
{"bottom_left_corner", IMAGEBITMAP, MacXCursorData(bottom_left_corner), nil, {0, 0}},
{"bottom_right_corner", IMAGEBITMAP, MacXCursorData(bottom_right_corner), nil, {0, 0}},
{"bottom_side", IMAGEBITMAP, MacXCursorData(bottom_side), nil, {0, 0}},
{"bottom_tee", IMAGEBITMAP, MacXCursorData(bottom_tee), nil, {0, 0}},
{"box_spiral", IMAGEBITMAP, MacXCursorData(box_spiral), nil, {0, 0}},
{"center_ptr", IMAGEBITMAP, MacXCursorData(center_ptr), nil, {0, 0}},
{"circle", IMAGEBITMAP, MacXCursorData(circle), nil, {0, 0}},
{"clock", IMAGEBITMAP, MacXCursorData(clock), nil, {0, 0}},
{"coffee_mug", IMAGEBITMAP, MacXCursorData(coffee_mug), nil, {0, 0}},
// {"cross", IMAGEBITMAP, MacXCursorData(cross), nil, {0, 0}},
{"cross_reverse", IMAGEBITMAP, MacXCursorData(cross_reverse), nil, {0, 0}},
// {"crosshair", IMAGEBITMAP, MacXCursorData(crosshair), nil, {0, 0}},
{"diamond_cross", IMAGEBITMAP, MacXCursorData(diamond_cross), nil, {0, 0}},
{"dot", IMAGEBITMAP, MacXCursorData(dot), nil, {0, 0}},
{"dotbox", IMAGEBITMAP, MacXCursorData(dotbox), nil, {0, 0}},
{"double_arrow", IMAGEBITMAP, MacXCursorData(double_arrow), nil, {0, 0}},
{"draft_large", IMAGEBITMAP, MacXCursorData(draft_large), nil, {0, 0}},
{"draft_small", IMAGEBITMAP, MacXCursorData(draft_small), nil, {0, 0}},
{"draped_box", IMAGEBITMAP, MacXCursorData(draped_box), nil, {0, 0}},
{"exchange", IMAGEBITMAP, MacXCursorData(exchange), nil, {0, 0}},
{"fleur", IMAGEBITMAP, MacXCursorData(fleur), nil, {0, 0}},
{"gobbler", IMAGEBITMAP, MacXCursorData(gobbler), nil, {0, 0}},
{"gumby", IMAGEBITMAP, MacXCursorData(gumby), nil, {0, 0}},
{"hand1", IMAGEBITMAP, MacXCursorData(hand1), nil, {0, 0}},
{"hand2", IMAGEBITMAP, MacXCursorData(hand2), nil, {0, 0}},
{"heart", IMAGEBITMAP, MacXCursorData(heart), nil, {0, 0}},
{"icon", IMAGEBITMAP, MacXCursorData(icon), nil, {0, 0}},
{"iron_cross", IMAGEBITMAP, MacXCursorData(iron_cross), nil, {0, 0}},
// {"left_ptr", IMAGEBITMAP, MacXCursorData(left_ptr), nil, {0, 0}},
{"left_side", IMAGEBITMAP, MacXCursorData(left_side), nil, {0, 0}},
{"left_tee", IMAGEBITMAP, MacXCursorData(left_tee), nil, {0, 0}},
{"leftbutton", IMAGEBITMAP, MacXCursorData(leftbutton), nil, {0, 0}},
{"ll_angle", IMAGEBITMAP, MacXCursorData(ll_angle), nil, {0, 0}},
{"lr_angle", IMAGEBITMAP, MacXCursorData(lr_angle), nil, {0, 0}},
{"man", IMAGEBITMAP, MacXCursorData(man), nil, {0, 0}},
{"middlebutton", IMAGEBITMAP, MacXCursorData(middlebutton), nil, {0, 0}},
{"mouse", IMAGEBITMAP, MacXCursorData(mouse), nil, {0, 0}},
{"pencil", IMAGEBITMAP, MacXCursorData(pencil), nil, {0, 0}},
{"pirate", IMAGEBITMAP, MacXCursorData(pirate), nil, {0, 0}},
{"plus", IMAGEBITMAP, MacXCursorData(plus), nil, {0, 0}},
{"question_arrow", IMAGEBITMAP, MacXCursorData(question_arrow), nil, {0, 0}},
{"right_ptr", IMAGEBITMAP, MacXCursorData(right_ptr), nil, {0, 0}},
{"right_side", IMAGEBITMAP, MacXCursorData(right_side), nil, {0, 0}},
{"right_tee", IMAGEBITMAP, MacXCursorData(right_tee), nil, {0, 0}},
{"rightbutton", IMAGEBITMAP, MacXCursorData(rightbutton), nil, {0, 0}},
{"rtl_logo", IMAGEBITMAP, MacXCursorData(rtl_logo), nil, {0, 0}},
{"sailboat", IMAGEBITMAP, MacXCursorData(sailboat), nil, {0, 0}},
{"sb_down_arrow", IMAGEBITMAP, MacXCursorData(sb_down_arrow), nil, {0, 0}},
{"sb_h_double_arrow", IMAGEBITMAP, MacXCursorData(sb_h_double_arrow), nil, {0, 0}},
{"sb_left_arrow", IMAGEBITMAP, MacXCursorData(sb_left_arrow), nil, {0, 0}},
{"sb_right_arrow", IMAGEBITMAP, MacXCursorData(sb_right_arrow), nil, {0, 0}},
{"sb_up_arrow", IMAGEBITMAP, MacXCursorData(sb_up_arrow), nil, {0, 0}},
{"sb_v_double_arrow", IMAGEBITMAP, MacXCursorData(sb_v_double_arrow), nil, {0, 0}},
{"shuttle", IMAGEBITMAP, MacXCursorData(shuttle), nil, {0, 0}},
{"sizing", IMAGEBITMAP, MacXCursorData(sizing), nil, {0, 0}},
{"spider", IMAGEBITMAP, MacXCursorData(spider), nil, {0, 0}},
{"spraycan", IMAGEBITMAP, MacXCursorData(spraycan), nil, {0, 0}},
{"star", IMAGEBITMAP, MacXCursorData(star), nil, {0, 0}},
{"target", IMAGEBITMAP, MacXCursorData(target), nil, {0, 0}},
// {"tcross", IMAGEBITMAP, MacXCursorData(tcross), nil, {0, 0}},
// {"top_left_arrow", IMAGEBITMAP, MacXCursorData(top_left_arrow), nil, {0, 0}},
{"top_left_corner", IMAGEBITMAP, MacXCursorData(top_left_corner), nil, {0, 0}},
{"top_right_corner", IMAGEBITMAP, MacXCursorData(top_right_corner), nil, {0, 0}},
{"top_side", IMAGEBITMAP, MacXCursorData(top_side), nil, {0, 0}},
{"top_tee", IMAGEBITMAP, MacXCursorData(top_tee), nil, {0, 0}},
{"trek", IMAGEBITMAP, MacXCursorData(trek), nil, {0, 0}},
{"ul_angle", IMAGEBITMAP, MacXCursorData(ul_angle), nil, {0, 0}},
{"umbrella", IMAGEBITMAP, MacXCursorData(umbrella), nil, {0, 0}},
{"ur_angle", IMAGEBITMAP, MacXCursorData(ur_angle), nil, {0, 0}},
{"watch", IMAGEBITMAP, MacXCursorData(watch), nil, {0, 0}},
// {"xterm", IMAGEBITMAP, MacXCursorData(xterm), nil, {0, 0}},
{NULL, 0, nil, nil, {0, 0}}
};
/*
@@ -271,7 +271,7 @@ FindCursorByName(
break;
case IMAGEBITMAP: {
unsigned char *bitmap = (unsigned char *)(cursorNames[idx].id1);
NSBitmapImageRep *bitmapImageRep = NULL;
NSBitmapImageRep *bitmapImageRep = nil;
CGImageRef img = NULL, mask = NULL, maskedImg = NULL;
static const CGFloat decodeWB[] = {1, 0};
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(
@@ -312,6 +312,7 @@ FindCursorByName(
if (bitmapImageRep) {
image = [[NSImage alloc] initWithSize:NSMakeSize(pix, pix)];
[image addRepresentation:bitmapImageRep];
[image setTemplate:YES];
[bitmapImageRep release];
}
@@ -374,7 +375,7 @@ 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. */
{
@@ -389,7 +390,7 @@ TkGetCursorByName(
if (Tcl_SplitList(interp, string, &argc, &argv) == TCL_OK) {
if (argc) {
macCursorPtr = ckalloc(sizeof(TkMacOSXCursor));
macCursorPtr = (TkMacOSXCursor *)ckalloc(sizeof(TkMacOSXCursor));
macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr;
macCursorPtr->macCursor = nil;
macCursorPtr->type = 0;
@@ -428,13 +429,15 @@ 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. */
{
return NULL;
}
@@ -463,7 +466,7 @@ TkpFreeCursor(
TkMacOSXCursor *macCursorPtr = (TkMacOSXCursor *) cursorPtr;
[macCursorPtr->macCursor release];
macCursorPtr->macCursor = NULL;
macCursorPtr->macCursor = nil;
if (macCursorPtr == gCurrentCursor) {
gCurrentCursor = NULL;
}

View File

@@ -64,7 +64,7 @@ TkMacOSXGetNamedDebugSymbol(
for (i = 0; i < n; i++) {
if (module && *module) {
/* Find image with given module name */
char *name;
const char *name;
const char *path = _dyld_get_image_name(i);
if (!path) {

View File

@@ -42,10 +42,11 @@
#define ACTIVE_FG "systemTextColor"
#define SELECT_BG "systemSelectedTextBackgroundColor"
#define SELECT_FG "systemSelectedTextColor"
#define INACTIVE_SELECT_BG "systemSelectedTextBackgroundColor"
#define INACTIVE_SELECT_BG "systemUnemphasizedSelectedTextBackgroundColor"
#define TROUGH "#c3c3c3"
#define INDICATOR "#b03060"
#define DISABLED "#a3a3a3"
#define IGNORED "#abcdef"
/*
* Defaults for labels, buttons, checkbuttons, and radiobuttons:
@@ -88,19 +89,9 @@
#define DEF_BUTTON_ON_VALUE "1"
#define DEF_BUTTON_TRISTATE_VALUE ""
#define DEF_BUTTON_OVER_RELIEF ""
//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
//#define DEF_BUTTON_PADX "12"
//#define DEF_BUTTON_PADX_NOCM "1"
//#else
#define DEF_BUTTON_PADX "1"
//#endif
#define DEF_LABCHKRAD_PADX "1"
//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
//#define DEF_BUTTON_PADY "3"
//#define DEF_BUTTON_PADY_NOCM "1"
//#else
#define DEF_BUTTON_PADY "1"
//#endif
#define DEF_LABCHKRAD_PADY "1"
#define DEF_BUTTON_RELIEF "flat"
#define DEF_LABCHKRAD_RELIEF "flat"
@@ -307,23 +298,23 @@
* Defaults for menus overall:
*/
#define DEF_MENU_ACTIVE_BG_COLOR "systemMenuActive"
#define DEF_MENU_ACTIVE_BG_MONO BLACK
#define DEF_MENU_ACTIVE_BG_COLOR IGNORED
#define DEF_MENU_ACTIVE_BG_MONO 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_BG_COLOR "systemMenu"
#define DEF_MENU_BG_MONO WHITE
#define DEF_MENU_ACTIVE_FG_COLOR IGNORED
#define DEF_MENU_ACTIVE_FG_MONO IGNORED
#define DEF_MENU_BG_COLOR "#000001" /* Detects custom bg. */
#define DEF_MENU_BG_MONO IGNORED
#define DEF_MENU_BORDER_WIDTH "0"
#define DEF_MENU_CURSOR "arrow"
#define DEF_MENU_DISABLED_FG_COLOR "systemMenuDisabled"
#define DEF_MENU_DISABLED_FG_COLOR IGNORED
#define DEF_MENU_DISABLED_FG_MONO ""
#define DEF_MENU_FONT "menu" /* special: see tkMacOSXMenu.c */
#define DEF_MENU_FG "systemMenuText"
#define DEF_MENU_FG "#010000" /* Detects custom 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 IGNORED
#define DEF_MENU_SELECT_MONO IGNORED
#define DEF_MENU_TAKE_FOCUS "0"
#define DEF_MENU_TEAROFF "0"
#define DEF_MENU_TEAROFF_CMD NULL

View File

@@ -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;
@@ -198,19 +202,24 @@ getFileURL(
@implementation TKApplication(TKDialog)
- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url {
(void)sender;
(void)url;
return YES;
}
- (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url {
(void)sender; (void)url;
}
- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError {
(void)sender; (void)url;
*outError = nil;
return YES;
}
- (void) tkFilePanelDidEnd: (NSSavePanel *) panel
returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
returnCode: (NSModalResponse) returnCode
contextInfo: (void *) contextInfo
{
FilePanelCallbackInfo *callbackInfo = contextInfo;
@@ -232,7 +241,7 @@ getFileURL(
callbackInfo->cmdObj, &objc, &objv);
if (result == TCL_OK && objc) {
tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
tmpv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
tmpv[objc] = resultObj;
TkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,
@@ -245,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
@@ -270,7 +279,7 @@ getFileURL(
callbackInfo->cmdObj, &objc, &objv);
if (result == TCL_OK && objc) {
tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
tmpv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
tmpv[objc] = resultObj;
TkBackgroundEvalObjv(callbackInfo->interp, objc + 1, tmpv,
@@ -293,7 +302,6 @@ getFileURL(
- (void)selectFormat:(id)sender {
NSPopUpButton *button = (NSPopUpButton *)sender;
filterInfo.fileTypeIndex = [button indexOfSelectedItem];
if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) {
[openpanel setAllowsOtherFileTypes:YES];
@@ -343,21 +351,50 @@ static NSInteger showOpenSavePanel(
{
NSInteger modalReturnCode;
if (parent && ![parent attachedSheet] && [NSApp macMinorVersion] < 15) {
if (parent && ![parent attachedSheet]) {
[panel beginSheetModalForWindow:parent
completionHandler:^(NSInteger returnCode) {
completionHandler:^(NSModalResponse returnCode) {
[NSApp tkFilePanelDidEnd:panel
returnCode:returnCode
contextInfo:callbackInfo ];
}];
modalReturnCode = callbackInfo->cmdObj ? modalOther :
[NSApp runModalForWindow:panel];
/*
* 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;
}
/*
@@ -654,8 +691,6 @@ Tk_GetOpenFileObjCmd(
NSInteger modalReturnCode = modalError;
BOOL parentIsKey = NO;
[openpanel setDelegate:NSApp];
for (i = 1; i < objc; i += 2) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings,
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
@@ -725,7 +760,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];
@@ -763,6 +798,7 @@ Tk_GetOpenFileObjCmd(
[label setBezeled:NO];
[label setDrawsBackground:NO];
[popupButton addItemsWithTitles:filterInfo.fileTypeLabels];
[popupButton setTarget:NSApp];
[popupButton setAction:@selector(selectFormat:)];
[accessoryView addSubview:label];
[accessoryView addSubview:popupButton];
@@ -804,7 +840,7 @@ Tk_GetOpenFileObjCmd(
}
Tcl_IncrRefCount(cmdObj);
}
callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
callbackInfo->cmdObj = cmdObj;
callbackInfo->interp = interp;
callbackInfo->multiple = multiple;
@@ -814,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;
@@ -866,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 = @"";
@@ -913,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;
@@ -928,8 +964,6 @@ Tk_GetSaveFileObjCmd(
NSInteger modalReturnCode = modalError;
BOOL parentIsKey = NO;
[savepanel setDelegate:NSApp];
for (i = 1; i < objc; i += 2) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings,
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
@@ -1050,8 +1084,8 @@ Tk_GetSaveFileObjCmd(
[popupButton addItemsWithTitles:filterInfo.fileTypeLabels];
[popupButton selectItemAtIndex:filterInfo.fileTypeIndex];
[popupButton setTarget:NSApp];
[popupButton setAction:@selector(saveFormat:)];
[accessoryView addSubview:label];
[accessoryView addSubview:popupButton];
@@ -1082,7 +1116,7 @@ Tk_GetSaveFileObjCmd(
}
Tcl_IncrRefCount(cmdObj);
}
callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
callbackInfo->cmdObj = cmdObj;
callbackInfo->interp = interp;
callbackInfo->multiple = 0;
@@ -1102,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;
@@ -1157,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;
@@ -1171,8 +1205,6 @@ Tk_ChooseDirectoryObjCmd(
NSInteger modalReturnCode = modalError;
BOOL parentIsKey = NO;
[panel setDelegate:NSApp];
for (i = 1; i < objc; i += 2) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i], chooseOptionStrings,
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
@@ -1233,7 +1265,7 @@ Tk_ChooseDirectoryObjCmd(
}
Tcl_IncrRefCount(cmdObj);
}
callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo));
callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
callbackInfo->cmdObj = cmdObj;
callbackInfo->interp = interp;
callbackInfo->multiple = 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,7 +1336,7 @@ TkAboutDlg(void)
int
TkMacOSXStandardAboutPanelObjCmd(
ClientData clientData, /* Unused. */
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
@@ -1368,7 +1345,7 @@ TkMacOSXStandardAboutPanelObjCmd(
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
TkAboutDlg();
[NSApp orderFrontStandardAboutPanel:nil];
return TCL_OK;
}
@@ -1395,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;
@@ -1529,11 +1506,11 @@ Tk_MessageBoxObjCmd(
}
Tcl_IncrRefCount(cmdObj);
}
callbackInfo = ckalloc(sizeof(AlertCallbackInfo));
callbackInfo = (AlertCallbackInfo *)ckalloc(sizeof(AlertCallbackInfo));
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
@@ -1630,6 +1607,7 @@ enum FontchooserOption {
- (void) changeFont: (id) sender
{
NSFontManager *fm = [NSFontManager sharedFontManager];
(void)sender;
if ([fm currentFontAction] == NSViaPanelFontAction) {
NSFont *font = [fm convertFont:fontPanelFont];
@@ -1653,14 +1631,16 @@ enum FontchooserOption {
}
}
- (NSUInteger) validModesForFontPanel: (NSFontPanel *) fontPanel
- (NSUInteger) validModesForFontPanel: (NSFontPanel *)fontPanel
{
(void)fontPanel;
return (NSFontPanelStandardModesMask & ~NSFontPanelAllEffectsModeMask) |
NSFontPanelUnderlineEffectModeMask |
NSFontPanelStrikethroughEffectModeMask;
}
- (void) windowDidOrderOffScreen: (NSNotification *) notification
- (void) windowDidOrderOffScreen: (NSNotification *)notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
@@ -1684,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.
*
*----------------------------------------------------------------------
*/
@@ -1718,7 +1698,7 @@ FontchooserEvent(
result = Tcl_ListObjGetElements(fontchooserInterp,
fcdPtr->cmdObj, &objc, &objv);
if (result == TCL_OK) {
tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
tmpv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
tmpv[objc] = fontObj;
TkBackgroundEvalObjv(fontchooserInterp, objc + 1, tmpv,
@@ -1760,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);
}
@@ -1981,14 +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);
if (fcdPtr->parent == None) {
fcdPtr->parent = (Tk_Window) clientData;
fcdPtr->parent = (Tk_Window)clientData;
Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask,
FontchooserParentEventHandler, fcdPtr);
}
@@ -2027,10 +2007,10 @@ FontchooserShowCmd(
static int
FontchooserHideCmd(
ClientData clientData, /* 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];
@@ -2129,9 +2109,9 @@ DeleteFontchooserData(
MODULE_SCOPE int
TkInitFontchooser(
Tcl_Interp *interp,
ClientData clientData)
TCL_UNUSED(void *))
{
FontchooserData *fcdPtr = ckalloc(sizeof(FontchooserData));
FontchooserData *fcdPtr = (FontchooserData *)ckalloc(sizeof(FontchooserData));
bzero(fcdPtr, sizeof(FontchooserData));
Tcl_SetAssocData(interp, "::tk::fontchooser", DeleteFontchooserData,

File diff suppressed because it is too large Load Diff

View File

@@ -446,7 +446,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");
@@ -853,7 +853,7 @@ ContainerEventProc(
* Here we are following unix, by destroying the container.
*/
Tk_DestroyWindow((Tk_Window) winPtr);
Tk_DestroyWindow((Tk_Window)winPtr);
}
Tk_DeleteErrorHandler(errHandler);
}
@@ -902,8 +902,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);
}
@@ -1048,10 +1048,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);

View File

@@ -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);

View File

@@ -104,43 +104,8 @@ enum {
return processedEvent;
}
@end
#pragma mark -
/*
*----------------------------------------------------------------------
*
* TkMacOSXFlushWindows --
*
* This routine is a stub called by XSync, which is called during the Tk
* update command. The language specification does not require that the
* update command be synchronous but many of the tests 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.
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
if (Tk_GetNumMainWindows() == 0) {
return;
}
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){}
for (NSWindow *w in [NSApp orderedWindows]) {
[w display];
}
}
/*
* Local Variables:
* mode: objc

View File

@@ -18,6 +18,8 @@
#include "tkMacOSXInt.h"
#endif
MODULE_SCOPE void TkMacOSXFlushWindows(void);
/*
* Currently nothing needs to be declared here.
*/
#endif

View File

@@ -56,25 +56,25 @@ struct SystemFontMapEntry {
#define ThemeFont(n, ...) { kTheme##n##Font, "system" #n "Font", ##__VA_ARGS__ }
static const struct SystemFontMapEntry systemFontMap[] = {
ThemeFont(System, "TkDefaultFont", "TkIconFont"),
ThemeFont(EmphasizedSystem, "TkCaptionFont"),
ThemeFont(EmphasizedSystem, "TkCaptionFont", NULL),
ThemeFont(SmallSystem, "TkHeadingFont", "TkTooltipFont"),
ThemeFont(SmallEmphasizedSystem),
ThemeFont(Application, "TkTextFont"),
ThemeFont(Label, "TkSmallCaptionFont"),
ThemeFont(Views),
ThemeFont(MenuTitle),
ThemeFont(MenuItem, "TkMenuFont"),
ThemeFont(MenuItemMark),
ThemeFont(MenuItemCmdKey),
ThemeFont(WindowTitle),
ThemeFont(PushButton),
ThemeFont(UtilityWindowTitle),
ThemeFont(AlertHeader),
ThemeFont(Toolbar),
ThemeFont(MiniSystem),
{ kThemeSystemFontDetail, "systemDetailSystemFont" },
{ kThemeSystemFontDetailEmphasized, "systemDetailEmphasizedSystemFont" },
{ -1, NULL }
ThemeFont(SmallEmphasizedSystem, NULL, NULL),
ThemeFont(Application, "TkTextFont", NULL),
ThemeFont(Label, "TkSmallCaptionFont", NULL),
ThemeFont(Views, NULL, NULL),
ThemeFont(MenuTitle, NULL, NULL),
ThemeFont(MenuItem, "TkMenuFont", NULL),
ThemeFont(MenuItemMark, NULL, NULL),
ThemeFont(MenuItemCmdKey, NULL, NULL),
ThemeFont(WindowTitle, NULL, NULL),
ThemeFont(PushButton, NULL, NULL),
ThemeFont(UtilityWindowTitle, NULL, NULL),
ThemeFont(AlertHeader, NULL, NULL),
ThemeFont(Toolbar, NULL, NULL),
ThemeFont(MiniSystem, NULL, NULL),
{ kThemeSystemFontDetail, "systemDetailSystemFont", NULL, NULL },
{ kThemeSystemFontDetailEmphasized, "systemDetailEmphasizedSystemFont", NULL, NULL },
{ -1, NULL, NULL, NULL }
};
#undef ThemeFont
@@ -93,155 +93,89 @@ 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:
/*
*---------------------------------------------------------------------------
*
* TclUniToNSString --
*
* When Tcl is compiled with TCL_UTF_MAX = 3 (the default for 8.6) it cannot
* deal directly with UTF-8 encoded non-BMP characters, since their UTF-8
* encoding requires 4 bytes.
*
* As a workaround, these versions of Tcl encode non-BMP characters as a string
* of length 6 in which the high and low UTF-16 surrogates have been encoded
* using the UTF-8 algorithm. The UTF-8 encoding does not allow encoding
* surrogates, so these 6-byte strings are not valid UTF-8, and hence Apple's
* NString class will refuse to instantiate an NSString from the 6-byte
* encoding. This function allows creating an NSString from a C-string which
* has been encoded using this scheme.
*
* Results:
* An NSString, which may be nil.
*
* Side effects:
* None.
*---------------------------------------------------------------------------
* To avoid an extra copy, a TKNSString object wraps a Tcl_DString with an
* NSString that uses the DString's buffer as its character buffer. It can be
* constructed from a Tcl_DString and it has a DString property that handles
* converting from an NSString to a Tcl_DString.
*/
MODULE_SCOPE NSString*
TclUniToNSString(
const char *source,
int numBytes)
@implementation TKNSString
- (instancetype)initWithTclUtfBytes:(const void *)bytes
length:(NSUInteger)len
{
NSString *string = [[NSString alloc] initWithBytesNoCopy:(void *)source
length:numBytes
encoding:NSUTF8StringEncoding
freeWhenDone:NO];
if (!string) {
const unichar *characters = ckalloc(numBytes*sizeof(unichar));
const char *in = source;
unichar *out = (unichar *) characters;
while (in < source + numBytes) {
in += Tcl_UtfToUniChar(in, out++);
self = [self init];
if (self) {
Tcl_DStringInit(&_ds);
Tcl_UtfToUniCharDString(bytes, len, &_ds);
_string = [[NSString alloc]
initWithCharactersNoCopy:(unichar *)Tcl_DStringValue(&_ds)
length:Tcl_DStringLength(&_ds)>>1
freeWhenDone:NO];
self.UTF8String = _string.UTF8String;
}
return self;
}
- (instancetype)initWithString:(NSString *)aString
{
self = [self init];
if (self) {
_string = [[NSString alloc] initWithString:aString];
_UTF8String = _string.UTF8String;
}
return self;
}
- (void)dealloc
{
Tcl_DStringFree(&_ds);
[_string release];
[super dealloc];
}
- (NSUInteger)length
{
return _string.length;
}
- (unichar)characterAtIndex:(NSUInteger)index
{
return [_string characterAtIndex:index];
}
- (Tcl_DString)DString
{
if ( _ds.string == NULL) {
/*
* The DString has not been initialized. Construct it from
* our string's unicode characters.
*/
char *p;
NSUInteger index;
Tcl_DStringInit(&_ds);
Tcl_DStringSetLength(&_ds, 3 * [_string length]);
p = Tcl_DStringValue(&_ds);
for (index = 0; index < [_string length]; index++) {
p += Tcl_UniCharToUtf([_string characterAtIndex: index], p);
}
string = [[NSString alloc] initWithCharacters:characters
length:(out - characters)];
ckfree(characters);
Tcl_DStringSetLength(&_ds, p - Tcl_DStringValue(&_ds));
}
return string;
return _ds;
}
/*
*---------------------------------------------------------------------------
*
* TclUniAtIndex --
*
* Write a sequence of bytes up to length 6 which is an encoding of a UTF-16
* character in an NSString. Also record the unicode code point of the character.
* this may be a non-BMP character constructed by reading two surrogates from
* the NSString.
*
* Results:
* Returns the number of bytes written.
*
* Side effects:
* Bytes are written to the char array referenced by the pointer uni and
* the unicode code point is written to the integer referenced by the
* pointer code.
*
*/
MODULE_SCOPE int
TclUniAtIndex(
NSString *string,
int index,
char *uni,
unsigned int *code)
{
char *ptr = uni;
UniChar uniChar = [string characterAtIndex: index];
if (CFStringIsSurrogateHighCharacter(uniChar)) {
UniChar lowChar = [string characterAtIndex: ++index];
*code = CFStringGetLongCharacterForSurrogatePair(
uniChar, lowChar);
ptr += Tcl_UniCharToUtf(uniChar, ptr);
ptr += Tcl_UniCharToUtf(lowChar, ptr);
return ptr - uni;
} else {
*code = (int) uniChar;
[[string substringWithRange: NSMakeRange(index, 1)]
getCString: uni
maxLength: XMaxTransChars
encoding: NSUTF8StringEncoding];
return strlen(uni);
}
}
/*
*---------------------------------------------------------------------------
*
* NSStringToTclUni --
*
* Encodes the unicode string represented by an NSString object with the
* internal encoding that Tcl uses when TCL_UTF_MAX = 3. This encoding
* is similar to UTF-8 except that non-BMP characters are encoded as two
* successive 3-byte sequences which are constructed from UTF-16 surrogates
* by applying the UTF-8 algorithm. Even though the UTF-8 encoding does not
* allow encoding surrogates, the algorithm does produce a well-defined
* 3-byte sequence.
*
* Results:
* Returns a pointer to a null-terminated byte array which encodes the
* NSString.
*
* Side effects:
* Memory is allocated to hold the byte array, which must be freed with
* ckalloc. If the pointer numBytes is not NULL the number of non-null
* bytes written to the array is stored in the integer it references.
*/
MODULE_SCOPE char*
NSStringToTclUni(
NSString *string,
int *numBytes)
{
unsigned int code;
int i;
char *ptr, *bytes = ckalloc(6*[string length] + 1);
ptr = bytes;
if (ptr) {
for (i = 0; i < [string length]; i++) {
ptr += TclUniAtIndex(string, i, ptr, &code);
if (code > 0xffff){
i++;
}
}
*ptr = '\0';
}
if (numBytes) {
*numBytes = ptr - bytes;
}
return bytes;
}
#ifndef __clang__
@synthesize UTF8String = _UTF8String;
@synthesize DString = _ds;
#endif
@end
#define GetNSFontTraitsFromTkFontAttributes(faPtr) \
((faPtr)->weight == TK_FW_BOLD ? NSBoldFontMask : NSUnboldFontMask) | \
@@ -514,7 +448,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;
@@ -613,7 +547,7 @@ 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;
@@ -632,7 +566,7 @@ TkpGetNativeFont(
ctFont = CTFontCreateUIFontForLanguage(
HIThemeGetUIFontType(themeFontId), 0, NULL);
if (ctFont) {
fontPtr = ckalloc(sizeof(MacFont));
fontPtr = (MacFont *)ckalloc(sizeof(MacFont));
InitFont((NSFont*) ctFont, NULL, fontPtr);
}
@@ -700,7 +634,7 @@ TkpGetFontFromAttributes(
Tcl_Panic("Could not determine NSFont from TkFontAttributes");
}
if (tkFontPtr == NULL) {
fontPtr = ckalloc(sizeof(MacFont));
fontPtr = (MacFont *)ckalloc(sizeof(MacFont));
} else {
fontPtr = (MacFont *) tkFontPtr;
TkpDeleteFont(tkFontPtr);
@@ -762,7 +696,7 @@ 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];
@@ -835,7 +769,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 */
@@ -986,7 +920,7 @@ TkpMeasureCharsInContext(
if (maxLength > 32767) {
maxLength = 32767;
}
string = TclUniToNSString((const char *)source, numBytes);
string = [[TKNSString alloc] initWithTclUtfBytes:source length:numBytes];
if (!string) {
length = 0;
fit = rangeLength;
@@ -1098,7 +1032,7 @@ TkpMeasureCharsInContext(
[attributedString release];
[string release];
length = ceil(width - offset);
fit = (Tcl_UtfAtIndex(source, index) - source) - rangeStart;
fit = (TkUtfAtIndex(source, index) - source) - rangeStart;
done:
#ifdef TK_MAC_DEBUG_FONTS
TkMacOSXDbgMsg("measure: source=\"%s\" range=\"%.*s\" maxLength=%d "
@@ -1122,7 +1056,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.
@@ -1151,7 +1085,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);
}
@@ -1174,7 +1108,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);
}
@@ -1219,13 +1153,13 @@ TkpDrawCharsInContext(
* whole (not just the range) string when
* drawing. */
{
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
@@ -1240,71 +1174,77 @@ 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;
NSMutableDictionary *attributes;
NSAttributedString *attributedString;
CTTypesetterRef typesetter;
CFIndex start, len;
CTLineRef line;
MacDrawable *macWin = (MacDrawable *) drawable;
CFIndex start, length;
CTLineRef line, full=nil;
MacDrawable *macWin = (MacDrawable *)drawable;
TkMacOSXDrawingContext drawingContext;
CGContextRef context;
CGColorRef fg;
NSFont *nsFont;
CGAffineTransform t;
int h;
CGFloat width, height, textX = (CGFloat) x, textY = (CGFloat) y;
if (rangeStart < 0 || rangeLength <= 0 ||
rangeStart + rangeLength > numBytes ||
!TkMacOSXSetupDrawingContext(drawable, gc, 1, &drawingContext)) {
if (rangeStart < 0 || rangeLength <= 0 ||
rangeStart + rangeLength > numBytes ||
!TkMacOSXSetupDrawingContext(drawable, gc, &drawingContext)) {
return;
}
string = TclUniToNSString((const char *)source, numBytes);
string = [[TKNSString alloc] initWithTclUtfBytes:source length:numBytes];
if (!string) {
return;
}
context = drawingContext.context;
fg = TkMacOSXCreateCGColor(gc, gc->foreground);
TkSetMacColor(gc->foreground, &fg);
attributes = [fontPtr->nsAttributes mutableCopy];
[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];
typesetter = CTTypesetterCreateWithAttributedString(
(CFAttributedStringRef)attributedString);
x += macWin->xOff;
y += macWin->yOff;
h = drawingContext.portBounds.size.height;
y = h - y;
t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, h);
textX += (CGFloat) macWin->xOff;
textY += (CGFloat) macWin->yOff;
height = drawingContext.portBounds.size.height;
textY = height - textY;
t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, height);
if (angle != 0.0) {
t = CGAffineTransformTranslate(CGAffineTransformRotate(
CGAffineTransformTranslate(t, x, y), angle*PI/180.0), -x, -y);
t = CGAffineTransformTranslate(
CGAffineTransformRotate(
CGAffineTransformTranslate(t, textX, textY), angle*PI/180.0),
-textX, -textY);
}
CGContextConcatCTM(context, t);
CGContextSetTextPosition(context, x, y);
start = Tcl_NumUtfChars(source, rangeStart);
len = Tcl_NumUtfChars(source, rangeStart + rangeLength);
length = Tcl_NumUtfChars(source, rangeStart + rangeLength) - start;
line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, length));
if (start > 0) {
CGRect clipRect = CGRectInfinite, startBounds;
line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start));
startBounds = CTLineGetImageBounds(line, context);
CFRelease(line);
clipRect.origin.x = startBounds.origin.x + startBounds.size.width;
CGContextClipToRect(context, clipRect);
/*
* We are only drawing part of the string. To compute the x coordinate
* of the part we are drawing we subtract its typographical length from
* the typographical length of the full string. This accounts for the
* kerning after the initial part of the string.
*/
full = CTTypesetterCreateLine(typesetter, CFRangeMake(0, start + length));
width = CTLineGetTypographicBounds(full, NULL, NULL, NULL);
CFRelease(full);
textX += (width - CTLineGetTypographicBounds(line, NULL, NULL, NULL));
}
line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, len));
CGContextSetTextPosition(context, textX, textY);
CTLineDraw(line, context);
CFRelease(line);
CFRelease(typesetter);
@@ -1382,8 +1322,8 @@ 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. */
{
return 0;
}
@@ -1422,8 +1362,8 @@ TkMacOSXFontDescriptionForNSFontAndNSFontAttributes(
NSStrikethroughStyleAttributeName];
objv[i++] = Tcl_NewStringObj(familyName, -1);
objv[i++] = Tcl_NewIntObj([nsFont pointSize]);
#define S(s) Tcl_NewStringObj(STRINGIFY(s),(int)(sizeof(STRINGIFY(s))-1))
objv[i++] = Tcl_NewWideIntObj([nsFont pointSize]);
#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)] &&

View File

@@ -39,6 +39,7 @@ typedef struct AppleEventInfo {
const char *procedure;
Tcl_DString command;
NSAppleEventDescriptor *replyEvent; /* Only used for DoScriptText. */
int retryCount;
} AppleEventInfo;
/*
@@ -67,6 +68,11 @@ static const char *scriptTextProc = "::tk::mac::DoScriptText";
[self handleQuitApplicationEvent:Nil withReplyEvent:Nil];
}
- (void) superTerminate: (id) sender
{
[super terminate:nil];
}
- (void) preferences: (id) sender
{
[self handleShowPreferencesEvent:Nil withReplyEvent:Nil];
@@ -148,6 +154,7 @@ static const char *scriptTextProc = "::tk::mac::DoScriptText";
AEKeyword keyword;
Tcl_DString pathName;
/*
* Do nothing if we don't have an interpreter.
*/
@@ -215,7 +222,13 @@ static const char *scriptTextProc = "::tk::mac::DoScriptText";
AEInfo->interp = _eventInterp;
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
@@ -232,7 +245,8 @@ static const char *scriptTextProc = "::tk::mac::DoScriptText";
AEInfo->interp = _eventInterp;
AEInfo->procedure = printDocProc;
AEInfo->replyEvent = nil;
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
AEInfo->retryCount = 0;
ProcessAppleEvent((ClientData)AEInfo);
}
- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
@@ -293,7 +307,8 @@ static const char *scriptTextProc = "::tk::mac::DoScriptText";
AEInfo->interp = _eventInterp;
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,
@@ -309,6 +324,7 @@ static const char *scriptTextProc = "::tk::mac::DoScriptText";
if (noErr == AEGetParamPtr(theDesc, keyDirectObject,
typeUTF8Text, &type,
data, actual, NULL)) {
data[actual] = '\0';
AppleEventInfo *AEInfo = ckalloc(sizeof(AppleEventInfo));
Tcl_DString *scriptTextCommand = &AEInfo->command;
Tcl_DStringInit(scriptTextCommand);
@@ -316,12 +332,13 @@ static const char *scriptTextProc = "::tk::mac::DoScriptText";
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);
} else {
AEInfo->replyEvent = nil;
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
ProcessAppleEvent((ClientData)AEInfo);
}
}
}
@@ -342,7 +359,8 @@ static const char *scriptTextProc = "::tk::mac::DoScriptText";
AEInfo->interp = _eventInterp;
AEInfo->procedure = launchURLProc;
AEInfo->replyEvent = nil;
Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo);
AEInfo->retryCount = 0;
ProcessAppleEvent((ClientData)AEInfo);
}
@end
@@ -377,15 +395,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;
@@ -400,7 +433,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);
}
@@ -534,13 +570,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);
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...
*/

View File

@@ -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,6 +15,10 @@
#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
@@ -128,141 +132,6 @@ TkMacOSXCreateCGImageWithXImage(
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 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;
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 = 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;
}
/*
*----------------------------------------------------------------------
*
@@ -300,7 +169,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.
@@ -316,13 +189,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;
@@ -332,12 +210,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;
@@ -345,7 +223,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;
@@ -353,12 +231,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);
}
/*
@@ -463,13 +342,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;
@@ -542,13 +414,13 @@ XPutImage(
int dest_x, /* Destination X & Y. */
int dest_y,
unsigned int width, /* Same width & height for both */
unsigned int height) /* distination and source. */
unsigned int height) /* destination 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) {
@@ -564,17 +436,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,
@@ -607,6 +470,454 @@ TkPutImage(
return XPutImage(display, d, gc, image, src_x, src_y, dest_x, dest_y, width, height);
}
/*
*----------------------------------------------------------------------
*
* 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 = nil;
NSView *view = nil;
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) != nil) {
/*
* 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,
unsigned long plane_mask,
int format)
{
NSBitmapImageRep* bitmapRep = nil;
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

View File

@@ -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] = "";
@@ -28,12 +27,20 @@ static char tkLibPath[PATH_MAX + 1] = "";
static char scriptPath[PATH_MAX + 1] = "";
/*
* Forward declarations...
*/
static int TkMacOSXGetAppPathCmd(ClientData cd, Tcl_Interp *ip,
int objc, Tcl_Obj *const objv[]);
#pragma mark TKApplication(TKInit)
@implementation TKApplication
@synthesize poolLock = _poolLock;
@synthesize macMinorVersion = _macMinorVersion;
@synthesize macOSVersion = _macOSVersion;
@synthesize isDrawing = _isDrawing;
@synthesize needsToDraw = _needsToDraw;
@end
/*
@@ -75,7 +82,7 @@ static char scriptPath[PATH_MAX + 1] = "";
#define observe(n, s) \
[nc addObserver:self selector:@selector(s) name:(n) object:nil]
observe(NSApplicationDidBecomeActiveNotification, applicationActivate:);
observe(NSApplicationDidResignActiveNotification, applicationDeactivate:);
observe(NSApplicationWillResignActiveNotification, applicationDeactivate:);
observe(NSApplicationDidUnhideNotification, applicationShowHide:);
observe(NSApplicationDidHideNotification, applicationShowHide:);
observe(NSApplicationDidChangeScreenParametersNotification, displayChanged:);
@@ -85,6 +92,7 @@ static char scriptPath[PATH_MAX + 1] = "";
-(void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
(void)aNotification;
/*
* Initialize notifications.
@@ -95,16 +103,16 @@ static char scriptPath[PATH_MAX + 1] = "";
#endif
[self _setupWindowNotifications];
[self _setupApplicationNotifications];
}
/*
* Construct the menu bar.
*/
_defaultMainMenu = nil;
[self _setupMenus];
-(void)applicationDidFinishLaunching:(NSNotification *)notification
{
(void)notification;
/*
* Initialize event processing.
*/
/*
* Initialize event processing.
*/
TkMacOSXInitAppleEvents(_eventInterp);
/*
@@ -112,22 +120,24 @@ static char scriptPath[PATH_MAX + 1] = "";
*/
TkMacOSXUseAntialiasedText(_eventInterp, -1);
TkMacOSXInitCGDrawing(_eventInterp, TRUE, 0);
}
-(void)applicationDidFinishLaunching:(NSNotification *)notification
{
/*
* Construct the menu bar.
*/
_defaultMainMenu = nil;
[self _setupMenus];
/*
* It is not safe to force activation of the NSApp until this method is
* called. Activating too early can cause the menu bar to be unresponsive.
* The call to activateIgnoringOtherApps was moved here to avoid this.
* However, with the release of macOS 10.15 (Catalina) this was no longer
* sufficient. (See ticket bf93d098d7.) Apparently apps were being
* activated automatically, and this was sometimes being done too early.
* As a workaround we deactivate and then reactivate the app, even though
* Apple says that "Normally, you shouldnt invoke this method".
* However, with the release of macOS 10.15 (Catalina) that was no longer
* sufficient. (See ticket bf93d098d7.) The call to setActivationPolicy
* needed to be moved into this function as well.
*/
[NSApp deactivate];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp activateIgnoringOtherApps: YES];
/*
@@ -136,7 +146,7 @@ static char scriptPath[PATH_MAX + 1] = "";
*/
[NSApp _lockAutoreleasePool];
while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS| TCL_DONT_WAIT)) {}
while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT)) {}
[NSApp _unlockAutoreleasePool];
}
@@ -156,15 +166,18 @@ static char scriptPath[PATH_MAX + 1] = "";
/*
* 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.
@@ -178,12 +191,6 @@ static char scriptPath[PATH_MAX + 1] = "";
[self setDelegate:self];
/*
* Make sure we are allowed to open windows.
*/
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
/*
* If no icon has been set from an Info.plist file, use the Wish icon from
* the Tk framework.
@@ -265,6 +272,80 @@ static char scriptPath[PATH_MAX + 1] = "";
*----------------------------------------------------------------------
*/
/*
* 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)
@@ -272,15 +353,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.
@@ -290,7 +371,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.
@@ -306,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.
@@ -331,20 +405,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];
/*
@@ -371,36 +445,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));
/*
* Only show the console if we don't have a startup script and
* tcl_interactive hasn't been set already.
*/
if (Tcl_GetStartupScript(NULL) == NULL) {
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 (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {
return TCL_ERROR;
}
} else if (stdinIsNullish) {
/*
* 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.
*/
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
}
/*
* 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);
}
/*
@@ -410,8 +508,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);
}
@@ -425,7 +561,9 @@ TkpInit(
TkMacOSXStandardAboutPanelObjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "::tk::mac::iconBitmap",
TkMacOSXIconBitmapObjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath", TkMacOSXGetAppPath, NULL, NULL);
Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath",
TkMacOSXGetAppPathCmd, NULL, NULL);
return TCL_OK;
}
@@ -465,11 +603,11 @@ TkpGetAppName(
}
Tcl_DStringAppend(namePtr, name, -1);
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXGetAppPath --
* TkMacOSXGetAppPathCmd --
*
* Returns the path of the Wish application bundle.
*
@@ -481,42 +619,39 @@ TkpGetAppName(
*
*----------------------------------------------------------------------
*/
int TkMacOSXGetAppPath(
ClientData cd,
Tcl_Interp *ip,
int objc,
Tcl_Obj *const objv[])
static int
TkMacOSXGetAppPathCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
CFURLRef mainBundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());
/*
* Get the application path URL and convert it to a string path reference.
*/
CFURLRef mainBundleURL = CFBundleCopyBundleURL(CFBundleGetMainBundle());
CFStringRef appPath =
CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);
/*
* Convert the URL reference into a string reference.
*/
/*
* Convert (and copy) the string reference into a Tcl result.
*/
CFStringRef appPath = CFURLCopyFileSystemPath(mainBundleURL, kCFURLPOSIXPathStyle);
/*
* Get the system encoding method.
*/
CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
/*
* Convert the string reference into a C string.
*/
char *path = (char *) CFStringGetCStringPtr(appPath, encodingMethod);
Tcl_SetResult(ip, path, NULL);
CFRelease(mainBundleURL);
CFRelease(appPath);
return TCL_OK;
Tcl_SetObjResult(interp, Tcl_NewStringObj(
CFStringGetCStringPtr(appPath, CFStringGetSystemEncoding()), -1));
CFRelease(mainBundleURL);
CFRelease(appPath);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
@@ -583,7 +718,7 @@ TkMacOSXDefaultStartupScript(void)
CFURLRef scriptFldrURL;
char startupScript[PATH_MAX + 1];
if (CFURLGetFileSystemRepresentation (appMainURL, true,
if (CFURLGetFileSystemRepresentation(appMainURL, true,
(unsigned char *) startupScript, PATH_MAX)) {
Tcl_SetStartupScript(Tcl_NewStringObj(startupScript,-1), NULL);
scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent(NULL,
@@ -620,56 +755,17 @@ 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);
if (!addr) {
(void) dlerror(); /* Clear dlfcn error state */
}
return addr;
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXGetStringObjFromCFString --
*
* Get a string object from a CFString as efficiently as possible.
*
* Results:
* New string object or NULL if conversion failed.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE Tcl_Obj*
TkMacOSXGetStringObjFromCFString(
CFStringRef str)
{
Tcl_Obj *obj = NULL;
const char *c = CFStringGetCStringPtr(str, kCFStringEncodingUTF8);
if (c) {
obj = Tcl_NewStringObj(c, -1);
} else {
CFRange all = CFRangeMake(0, CFStringGetLength(str));
CFIndex len;
if (CFStringGetBytes(str, all, kCFStringEncodingUTF8, 0, false, NULL,
0, &len) > 0 && len < INT_MAX) {
obj = Tcl_NewObj();
Tcl_SetObjLength(obj, len);
CFStringGetBytes(str, all, kCFStringEncodingUTF8, 0, false,
(UInt8*) obj->bytes, len, NULL);
}
}
return obj;
}
/*
* Local Variables:
* mode: objc

View File

@@ -116,21 +116,6 @@ typedef struct {
MODULE_SCOPE TkMacOSXEmbedHandler *tkMacOSXEmbedHandler;
/*
* GC CGColorRef cache for tkMacOSXColor.c
*/
typedef struct {
unsigned long cachedForeground;
CGColorRef cachedForegroundColor;
unsigned long cachedBackground;
CGColorRef cachedBackgroundColor;
} TkpGCCache;
MODULE_SCOPE TkpGCCache *TkpGetGCCache(GC gc);
MODULE_SCOPE void TkpInitGCCache(GC gc);
MODULE_SCOPE void TkpFreeGCCache(GC gc);
/*
* Undef compatibility platform types defined above.
*/
@@ -180,7 +165,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
@@ -191,19 +176,10 @@ MODULE_SCOPE void TkpFreeGCCache(GC gc);
*/
MODULE_SCOPE void TkMacOSXDefaultStartupScript(void);
#if 0
MODULE_SCOPE int XSetClipRectangles(Display *d, GC gc, int clip_x_origin,
int clip_y_origin, XRectangle* rectangles, int n, int ordering);
#endif
MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x,
int y, int width, int height);
MODULE_SCOPE void TkpRetainRegion(TkRegion r);
MODULE_SCOPE void TkpReleaseRegion(TkRegion r);
MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
MODULE_SCOPE Bool TkpAppIsDrawing(void);
MODULE_SCOPE void TkpDisplayWindow(Tk_Window tkwin);
MODULE_SCOPE Bool TkTestLogDisplay(void);
MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin);
MODULE_SCOPE Bool TkTestLogDisplay(Drawable drawable);
/*
* Include the stubbed internal platform-specific API.

View File

@@ -7,7 +7,7 @@
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright (c) 2012 Adrian Robert.
* Copyright 2015-2019 Marc Culler.
* Copyright 2015-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,28 +16,29 @@
#include "tkMacOSXPrivate.h"
#include "tkMacOSXInt.h"
#include "tkMacOSXConstants.h"
#include "tkMacOSXWm.h"
/*
* See tkMacOSXPrivate.h for macros related to key event processing.
*/
/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_KEYBOARD
#endif
*/
#define NS_KEYLOG 0
static Tk_Window keyboardGrabWinPtr = NULL;
/* Current keyboard grab window. */
static NSWindow *keyboardGrabNSWindow = nil;
/* NSWindow for the current keyboard grab
* window. */
#define NS_KEYLOG 0
#define XEVENT_MOD_MASK (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask)
static Tk_Window keyboardGrabWinPtr = NULL; /* Current keyboard grab window. */
static NSWindow *keyboardGrabNSWindow = nil; /* Its underlying NSWindow.*/
static NSModalSession modalSession = nil;
static BOOL processingCompose = NO;
static Tk_Window composeWin = NULL;
static int caret_x = 0, caret_y = 0, caret_height = 0;
static unsigned short releaseCode;
static void setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state);
static unsigned isFunctionKey(unsigned int code);
static void setupXEvent(XEvent *xEvent, Tk_Window tkwin, NSUInteger modifiers);
static void setXEventPoint(XEvent *xEvent, Tk_Window tkwin, NSWindow *w);
static NSUInteger textInputModifiers;
#pragma mark TKApplication(TKKeyEvent)
@@ -48,233 +49,226 @@ static unsigned isFunctionKey(unsigned int code);
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
NSWindow *w;
NSWindow *w = [theEvent window];
TkWindow *winPtr = TkMacOSXGetTkWindow(w), *grabWinPtr, *focusWinPtr;
Tk_Window tkwin = (Tk_Window)winPtr;
NSEventType type = [theEvent type];
NSUInteger virtual = [theEvent keyCode];
NSUInteger modifiers = ([theEvent modifierFlags] &
NSDeviceIndependentModifierFlagsMask);
NSUInteger len = 0;
BOOL repeat = NO;
unsigned short keyCode = [theEvent keyCode];
NSString *characters = nil, *charactersIgnoringModifiers = nil;
XEvent xEvent;
MacKeycode macKC;
UniChar keychar = 0;
Bool can_input_text, has_modifiers = NO, use_text_input = NO;
static NSUInteger savedModifiers = 0;
static NSMutableArray *nsEvArray;
static NSMutableArray *nsEvArray = nil;
if (nsEvArray == nil) {
nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
processingCompose = NO;
}
w = [theEvent window];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
XEvent xEvent;
if (!winPtr) {
return theEvent;
}
/*
* Control-Tab and Control-Shift-Tab are used to switch tabs in a tabbed
* window. We do not want to generate an Xevent for these since that might
* cause the deselected tab to be reactivated.
* If a local grab is in effect, key events for windows in the
* grabber's application are redirected to the grabber. Key events
* for other applications are delivered normally. If a global
* grab is in effect all key events are redirected to the grabber.
*/
if (keyCode == 48 && (modifiers & NSControlKeyMask) == NSControlKeyMask) {
return theEvent;
}
switch (type) {
case NSKeyUp:
/*Fix for bug #1ba71a86bb: key release firing on key press.*/
setupXEvent(&xEvent, w, 0);
xEvent.xany.type = KeyRelease;
xEvent.xkey.keycode = releaseCode;
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
case NSKeyDown:
repeat = [theEvent isARepeat];
characters = [theEvent characters];
charactersIgnoringModifiers = [theEvent charactersIgnoringModifiers];
len = [charactersIgnoringModifiers length];
case NSFlagsChanged:
#if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1
TKLog(@"-[%@(%p) %s] r=%d mods=%u '%@' '%@' code=%u c=%d %@ %d", [self class], self, _cmd, repeat, modifiers, characters, charactersIgnoringModifiers, keyCode,([charactersIgnoringModifiers length] == 0) ? 0 : [charactersIgnoringModifiers characterAtIndex: 0], w, type);
#endif
break;
default:
return theEvent; /* Unrecognized key event. */
grabWinPtr = winPtr->dispPtr->grabWinPtr;
if (grabWinPtr) {
if (winPtr->dispPtr->grabFlags || /* global grab */
grabWinPtr->mainPtr == winPtr->mainPtr){ /* same application */
winPtr =winPtr->dispPtr->focusPtr;
tkwin = (Tk_Window)winPtr;
}
}
/*
* Create an Xevent to add to the Tk queue.
* Extract the unicode character from KeyUp and KeyDown events.
*/
if (!processingCompose) {
unsigned int state = 0;
if (modifiers & NSAlphaShiftKeyMask) {
state |= LockMask;
}
if (modifiers & NSShiftKeyMask) {
state |= ShiftMask;
}
if (modifiers & NSControlKeyMask) {
state |= ControlMask;
}
if (modifiers & NSCommandKeyMask) {
state |= Mod1Mask; /* command key */
}
if (modifiers & NSAlternateKeyMask) {
state |= Mod2Mask; /* option key */
}
if (modifiers & NSNumericPadKeyMask) {
state |= Mod3Mask;
}
if (modifiers & NSFunctionKeyMask) {
state |= Mod4Mask;
}
/*
* Key events are only received for the front Window on the Macintosh. So
* to build an XEvent we look up the Tk window associated to the Front
* window.
*/
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
if (tkwin) {
TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;
if (type == NSKeyUp || type == NSKeyDown) {
if ([[theEvent characters] length] > 0) {
keychar = [[theEvent characters] characterAtIndex:0];
/*
* If a local grab is in effect, key events for windows in the
* grabber's application are redirected to the grabber. Key events
* for other applications are delivered normally. If a global
* grab is in effect all key events are redirected to the grabber.
* Currently, real keys always send BMP characters, but who knows?
*/
if (grabWinPtr) {
if (winPtr->dispPtr->grabFlags || /* global grab */
grabWinPtr->mainPtr == winPtr->mainPtr){ /* same appl. */
tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
}
if (CFStringIsSurrogateHighCharacter(keychar)) {
UniChar lowChar = [[theEvent characters] characterAtIndex:1];
keychar = CFStringGetLongCharacterForSurrogatePair(
keychar, lowChar);
}
} else {
tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
}
if (!tkwin) {
TkMacOSXDbgMsg("tkwin == NULL");
return theEvent; /* Give up. No window for this event. */
}
/*
* If it's a function key, or we have modifiers other than Shift or
* Alt, pass it straight to Tk. Otherwise we'll send for input
* processing.
*/
/*
* This is a dead key, such as Option-e, so it should go to the
* TextInputClient.
*/
int code = (len == 0) ? 0 :
[charactersIgnoringModifiers characterAtIndex: 0];
if (type != NSKeyDown || isFunctionKey(code)
|| (len > 0 && state & (ControlMask | Mod1Mask | Mod3Mask | Mod4Mask))) {
XEvent xEvent;
setupXEvent(&xEvent, w, state);
if (type == NSFlagsChanged) {
if (savedModifiers > modifiers) {
xEvent.xany.type = KeyRelease;
} else {
xEvent.xany.type = KeyPress;
}
/*
* Use special '-1' to signify a special keycode to our
* platform specific code in tkMacOSXKeyboard.c. This is rather
* like what happens on Windows.
*/
xEvent.xany.send_event = -1;
/*
* Set keycode (which was zero) to the changed modifier
*/
xEvent.xkey.keycode = (modifiers ^ savedModifiers);
} else {
if (type == NSKeyUp || repeat) {
xEvent.xany.type = KeyRelease;
} else {
xEvent.xany.type = KeyPress;
}
if ([characters length] > 0) {
xEvent.xkey.keycode = (keyCode << 16) |
(UInt16) [characters characterAtIndex:0];
if (![characters getCString:xEvent.xkey.trans_chars
maxLength:XMaxTransChars encoding:NSUTF8StringEncoding]) {
/* prevent SF bug 2907388 (crash on some composite chars) */
//PENDING: we might not need this anymore
TkMacOSXDbgMsg("characters too long");
return theEvent;
}
}
if (repeat) {
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
xEvent.xany.type = KeyPress;
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
}
}
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
savedModifiers = modifiers;
return theEvent;
} /* if this is a function key or has modifiers */
} /* if not processing compose */
if (type == NSKeyDown) {
if (NS_KEYLOG) {
TKLog(@"keyDown: %s compose sequence.\n",
processingCompose == YES ? "Continue" : "Begin");
use_text_input = YES;
}
/*
* Call the interpretKeyEvents method to interpret composition key
* strokes. When it detects a complete composition sequence it will
* call our implementation of insertText: replacementRange, which
* generates a key down XEvent with the appropriate character. In IME
* when multiple characters have the same composition sequence and the
* chosen character is not the default it may be necessary to hit the
* enter key multiple times before the character is accepted and
* rendered. We send enter key events until inputText has cleared
* the processingCompose flag.
* Apple uses 0x10 for unrecognized keys.
*/
processingCompose = YES;
while(processingCompose) {
if (keychar == 0x10) {
keychar = UNKNOWN_KEYCHAR;
}
#if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1
TKLog(@"-[%@(%p) %s] repeat=%d mods=%x char=%x code=%lu c=%d type=%d",
[self class], self, _cmd,
(type == NSKeyDown) && [theEvent isARepeat], modifiers, keychar,
virtual, w, type);
#endif
}
/*
* Build a skeleton XEvent. We need to build it here, even if we will not
* send it, so we can pass it to TkFocusKeyEvent to determine whether the
* target widget can input text.
*/
setupXEvent(&xEvent, tkwin, modifiers);
has_modifiers = xEvent.xkey.state & XEVENT_MOD_MASK;
focusWinPtr = TkFocusKeyEvent(winPtr, &xEvent);
if (focusWinPtr == NULL) {
TKContentView *contentView = [w contentView];
/*
* This NSEvent is being sent to a window which does not have focus.
* This could mean, for example, that the user deactivated the Tk app
* while the NSTextInputClient's popup character selection window was
* still open. We attempt to abandon any ongoing composition operation
* and discard the event.
*/
[contentView cancelComposingText];
return theEvent;
}
can_input_text = ((focusWinPtr->flags & TK_CAN_INPUT_TEXT) != 0);
#if (NS_KEYLOG)
TKLog(@"keyDown: %s compose sequence.\n",
processingCompose == YES ? "Continue" : "Begin");
#endif
/*
* Decide whether this event should be processed with the NSTextInputClient
* protocol.
*/
if (processingCompose ||
(type == NSKeyDown && can_input_text && !has_modifiers &&
IS_PRINTABLE(keychar))
) {
use_text_input = YES;
}
/*
* If we are processing this KeyDown event as an NSTextInputClient we do
* not queue an XEvent. We pass the NSEvent to our interpretKeyEvents
* method. When the composition sequence is complete, the callback method
* insertText: replacementRange will be called. That method generates a
* keyPress XEvent with the selected character.
*/
if (use_text_input) {
textInputModifiers = modifiers;
/*
* In IME the Enter key is used to terminate a composition sequence.
* When there are multiple choices of input text available, and the
* user's selected choice is not the default, it may be necessary to
* hit the Enter key multiple times before the text is accepted and
* rendered (See ticket 39de9677aa]). So when sending an Enter key
* during composition, we continue sending Enter keys until the
* inputText method has cleared the processingCompose flag.
*/
if (processingCompose && [theEvent keyCode] == 36) {
[nsEvArray addObject: theEvent];
while(processingCompose) {
[[w contentView] interpretKeyEvents: nsEvArray];
}
[nsEvArray removeObject: theEvent];
} else {
[nsEvArray addObject: theEvent];
[[w contentView] interpretKeyEvents: nsEvArray];
[nsEvArray removeObject: theEvent];
if ([theEvent keyCode] != 36) {
break;
}
}
return theEvent;
}
savedModifiers = modifiers;
/*
* We are not handling this event as an NSTextInputClient, so we need to
* finish constructing the XEvent and queue it.
*/
macKC.v.o_s = ((modifiers & NSShiftKeyMask ? INDEX_SHIFT : 0) |
(modifiers & NSAlternateKeyMask ? INDEX_OPTION : 0));
macKC.v.virtual = virtual;
switch (type) {
case NSFlagsChanged:
/*
* This XEvent is a simulated KeyPress or KeyRelease event for a
* modifier key. To determine the type, note that the highest bit
* where the flags differ is 1 if and only if it is a KeyPress. The
* modifiers are saved so we can detect the next flag change.
*/
xEvent.xany.type = modifiers > savedModifiers ? KeyPress : KeyRelease;
savedModifiers = modifiers;
/*
* Set the keychar to MOD_KEYCHAR as a signal to TkpGetKeySym (see
* tkMacOSXKeyboard.c) that this is a modifier key event.
*/
keychar = MOD_KEYCHAR;
break;
case NSKeyUp:
xEvent.xany.type = KeyRelease;
break;
case NSKeyDown:
xEvent.xany.type = KeyPress;
break;
default:
return theEvent; /* Unrecognized key event. */
}
macKC.v.keychar = keychar;
xEvent.xkey.keycode = macKC.uint;
setXEventPoint(&xEvent, tkwin, w);
/*
* Finally we can queue the XEvent, inserting a KeyRelease before a
* repeated KeyPress.
*/
if (type == NSKeyDown && [theEvent isARepeat]) {
xEvent.xany.type = KeyRelease;
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
xEvent.xany.type = KeyPress;
}
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
return theEvent;
}
@end
@implementation TKContentView
-(id)init {
self = [super init];
if (self) {
_needsRedisplay = NO;
}
return self;
}
@synthesize tkDirtyRect = _tkDirtyRect;
@synthesize tkNeedsDisplay = _tkNeedsDisplay;
/*
* Implementation of the NSTextInputClient protocol.
@@ -282,15 +276,18 @@ static unsigned isFunctionKey(unsigned int code);
/* [NSTextInputClient inputText: replacementRange:] is called by
* interpretKeyEvents when a composition sequence is complete. It is also
* called when we delete over working text. In that case the call is followed
* called when we delete working text. In that case the call is followed
* immediately by doCommandBySelector: deleteBackward:
*/
- (void)insertText: (id)aString
replacementRange: (NSRange)repRange
{
int i, len;
int i, len, state;
XEvent xEvent;
NSString *str;
NSString *str, *keystr, *lower;
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
Tk_Window tkwin = (Tk_Window)winPtr;
Bool sendingIMEText = NO;
str = ([aString isKindOfClass: [NSAttributedString class]]) ?
[aString string] : aString;
@@ -300,13 +297,12 @@ static unsigned isFunctionKey(unsigned int code);
TKLog(@"insertText '%@'\tlen = %d", aString, len);
}
processingCompose = NO;
/*
* Clear any working text.
*/
if (privateWorkingText != nil) {
sendingIMEText = YES;
[self deleteWorkingText];
}
@@ -314,7 +310,8 @@ static unsigned isFunctionKey(unsigned int code);
* Insert the string as a sequence of keystrokes.
*/
setupXEvent(&xEvent, [self window], 0);
setupXEvent(&xEvent, tkwin, textInputModifiers);
setXEventPoint(&xEvent, tkwin, [self window]);
xEvent.xany.type = KeyPress;
/*
@@ -325,37 +322,54 @@ static unsigned isFunctionKey(unsigned int code);
*/
if (repRange.location == 0) {
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
Tk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;
TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
}
/*
* Next we generate an XEvent for each unicode character in our string.
* This string could contain non-BMP characters, for example if the
* emoji palette was used.
*
* NSString uses UTF-16 internally, which means that a non-BMP character is
* represented by a sequence of two 16-bit "surrogates". In principle we
* could record this in the XEvent by setting the keycode to the 32-bit
* unicode code point and setting the trans_chars string to the 4-byte
* UTF-8 string for the non-BMP character. However, that will not work
* when TCL_UTF_MAX is set to 3, as is the case for Tcl 8.6. A workaround
* used internally by Tcl 8.6 is to encode each surrogate as a 3-byte
* sequence using the UTF-8 algorithm (ignoring the fact that the UTF-8
* encoding specification does not allow encoding UTF-16 surrogates).
* This gives a 6-byte encoding of the non-BMP character which we write into
* the trans_chars field of the XEvent.
* represented by a sequence of two 16-bit "surrogates". We record this in
* the XEvent by setting the low order 21-bits of the keycode to the UCS-32
* value value of the character and the virtual keycode in the high order
* byte to the special value NON_BMP.
*/
state = xEvent.xkey.state;
for (i = 0; i < len; i++) {
xEvent.xkey.nbytes = TclUniAtIndex(str, i, xEvent.xkey.trans_chars,
&xEvent.xkey.keycode);
if (xEvent.xkey.keycode > 0xffff){
i++;
UniChar keychar;
MacKeycode macKC = {0};
keychar = [str characterAtIndex:i];
macKC.v.keychar = keychar;
if (CFStringIsSurrogateHighCharacter(keychar)) {
UniChar lowChar = [str characterAtIndex:++i];
macKC.v.keychar = CFStringGetLongCharacterForSurrogatePair(
(UniChar)keychar, lowChar);
macKC.v.virtual = NON_BMP_VIRTUAL;
} else if (repRange.location == 0 || sendingIMEText) {
macKC.v.virtual = REPLACEMENT_VIRTUAL;
} else {
macKC.uint = TkMacOSXAddVirtual(macKC.uint);
xEvent.xkey.state |= INDEX2STATE(macKC.x.xvirtual);
}
keystr = [[NSString alloc] initWithCharacters:&keychar length:1];
lower = [keystr lowercaseString];
if (![keystr isEqual: lower]) {
macKC.v.o_s |= INDEX_SHIFT;
xEvent.xkey.state |= ShiftMask;
}
if (xEvent.xkey.state & Mod2Mask) {
macKC.v.o_s |= INDEX_OPTION;
}
xEvent.xkey.keycode = macKC.uint;
xEvent.xany.type = KeyPress;
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
xEvent.xkey.state = state;
}
releaseCode = (UInt16) [str characterAtIndex: 0];
}
/*
@@ -379,13 +393,12 @@ static unsigned isFunctionKey(unsigned int code);
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;
str = ([aString isKindOfClass: [NSAttributedString class]]) ?
[aString string] : aString;
if (focusWin) {
/*
@@ -416,10 +429,10 @@ static unsigned isFunctionKey(unsigned int code);
*/
TkSendVirtualEvent(focusWin, "TkStartIMEMarkedText", NULL);
processingCompose = YES;
temp = [str copy];
[self insertText: temp replacementRange:repRange];
privateWorkingText = temp;
processingCompose = YES;
TkSendVirtualEvent(focusWin, "TkEndIMEMarkedText", NULL);
}
@@ -428,7 +441,6 @@ static unsigned isFunctionKey(unsigned int code);
return privateWorkingText != nil;
}
- (NSRange)markedRange
{
NSRange rng = privateWorkingText != nil
@@ -441,15 +453,6 @@ static unsigned isFunctionKey(unsigned int code);
return rng;
}
- (void)cancelComposingText
{
if (NS_KEYLOG) {
TKLog(@"cancelComposingText");
}
[self deleteWorkingText];
processingCompose = NO;
}
- (void)unmarkText
{
if (NS_KEYLOG) {
@@ -459,7 +462,6 @@ static unsigned isFunctionKey(unsigned int code);
processingCompose = NO;
}
/*
* Called by the system to get a position for popup character selection windows
* such as a Character Palette, or a selection menu for IME.
@@ -496,7 +498,7 @@ static unsigned isFunctionKey(unsigned int code);
processingCompose = NO;
if (aSelector == @selector (deleteBackward:)) {
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
Tk_Window focusWin = (Tk_Window)winPtr->dispPtr->focusPtr;
TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
}
}
@@ -543,7 +545,6 @@ static unsigned isFunctionKey(unsigned int code);
}
/* End of NSTextInputClient implementation. */
@synthesize needsRedisplay = _needsRedisplay;
@end
@@ -573,6 +574,16 @@ static unsigned isFunctionKey(unsigned int code);
}
}
}
- (void)cancelComposingText
{
if (NS_KEYLOG) {
TKLog(@"cancelComposingText");
}
[self deleteWorkingText];
processingCompose = NO;
}
@end
/*
@@ -580,21 +591,29 @@ static unsigned isFunctionKey(unsigned int code);
*/
static void
setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
setupXEvent(XEvent *xEvent, Tk_Window tkwin, NSUInteger modifiers)
{
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
unsigned int state = 0;
Display *display = Tk_Display(tkwin);
if (!winPtr) {
if (tkwin == NULL) {
return;
}
if (modifiers) {
state = (modifiers & NSAlphaShiftKeyMask ? LockMask : 0) |
(modifiers & NSShiftKeyMask ? ShiftMask : 0) |
(modifiers & NSControlKeyMask ? ControlMask : 0) |
(modifiers & NSCommandKeyMask ? Mod1Mask : 0) |
(modifiers & NSAlternateKeyMask ? Mod2Mask : 0) |
(modifiers & NSNumericPadKeyMask ? Mod3Mask : 0) |
(modifiers & NSFunctionKeyMask ? Mod4Mask : 0) ;
}
memset(xEvent, 0, sizeof(XEvent));
xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
xEvent->xany.serial = LastKnownRequestProcessed(display);
xEvent->xany.display = Tk_Display(tkwin);
xEvent->xany.window = Tk_WindowId(tkwin);
xEvent->xkey.root = XRootWindow(Tk_Display(tkwin), 0);
xEvent->xkey.root = XRootWindow(display, 0);
xEvent->xkey.time = TkpGetMS();
xEvent->xkey.state = state;
xEvent->xkey.same_screen = true;
@@ -602,6 +621,41 @@ setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
* because of the memset() above. */
}
static void
setXEventPoint(
XEvent *xEvent,
Tk_Window tkwin,
NSWindow *w)
{
TkWindow *winPtr = (TkWindow *) tkwin;
NSPoint local = [w mouseLocationOutsideOfEventStream];
NSPoint global = [w tkConvertPointToScreen: local];
int win_x, win_y;
if (Tk_IsEmbedded(winPtr)) {
TkWindow *contPtr = TkpGetOtherWindow(winPtr);
if (Tk_IsTopLevel(contPtr)) {
local.x -= contPtr->wmInfoPtr->xInParent;
local.y -= contPtr->wmInfoPtr->yInParent;
} else {
TkWindow *topPtr = TkMacOSXGetHostToplevel(winPtr)->winPtr;
local.x -= (topPtr->wmInfoPtr->xInParent + contPtr->changes.x);
local.y -= (topPtr->wmInfoPtr->yInParent + contPtr->changes.y);
}
} else if (winPtr->wmInfoPtr != NULL) {
local.x -= winPtr->wmInfoPtr->xInParent;
local.y -= winPtr->wmInfoPtr->yInParent;
}
tkwin = Tk_TopCoordsToWindow(tkwin, local.x, local.y, &win_x, &win_y);
local.x = win_x;
local.y = win_y;
global.y = TkMacOSXZeroScreenHeight() - global.y;
xEvent->xbutton.x = local.x;
xEvent->xbutton.y = local.y;
xEvent->xbutton.x_root = global.x;
xEvent->xbutton.y_root = global.y;
}
#pragma mark -
/*
@@ -633,8 +687,8 @@ XGrabKeyboard(
TkWindow *captureWinPtr = (TkWindow *) TkpGetCapture();
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) {
@@ -706,15 +760,22 @@ TkMacOSXGetModalSession(void)
*
* Tk_SetCaretPos --
*
* This enables correct placement of the XIM caret. This is called by
* widgets to indicate their cursor placement, and the caret location is
* used by TkpGetString to place the XIM caret.
* 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 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
* text by setting the TK_CAN_INPUT_TEXT flag.
*
* Results:
* None
*
* Side effects:
* None
* Sets the CAN_INPUT_TEXT flag on the widget passed as tkwin. May update
* the display's caret structure as well as the static variables caret_x,
* caret_y and caret_height.
*
*----------------------------------------------------------------------
*/
@@ -726,27 +787,40 @@ Tk_SetCaretPos(
int y,
int height)
{
TkCaret *caretPtr = &(((TkWindow *) tkwin)->dispPtr->caret);
TkWindow *winPtr = (TkWindow *) tkwin;
TkCaret *caretPtr = &(winPtr->dispPtr->caret);
NSWindow *w = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));
/*
* Prevent processing anything if the values haven't changed. Windows only
* has one display, so we can do this with statics.
* Register this widget as being capable of text input, so we know we
* should process (appropriate) key events for this window with the
* NSTextInputClient protocol.
*/
if ((caretPtr->winPtr == ((TkWindow *) tkwin))
&& (caretPtr->x == x) && (caretPtr->y == y)) {
winPtr->flags |= TK_CAN_INPUT_TEXT;
if (w && ![w isKeyWindow]) {
return;
}
if ((caretPtr->winPtr == winPtr
&& caretPtr->x == x) && (caretPtr->y == y)) {
return;
}
caretPtr->winPtr = ((TkWindow *) tkwin);
/*
* Update the display's caret information.
*/
caretPtr->winPtr = winPtr;
caretPtr->x = x;
caretPtr->y = y;
caretPtr->height = height;
/*
* As in Windows, adjust to the toplevel to get the coords right.
* Record the caret geometry in static variables for use when processing
* key events. We use the TKContextView coordinate system for this.
*/
caret_height = height;
while (!Tk_IsTopLevel(tkwin)) {
x += Tk_X(tkwin);
y += Tk_Y(tkwin);
@@ -755,94 +829,8 @@ Tk_SetCaretPos(
return;
}
}
/*
* But adjust for fact that NS uses flipped view.
*/
y = Tk_Height(tkwin) - y;
caret_x = x;
caret_y = y;
caret_height = height;
}
static unsigned convert_ns_to_X_keysym[] =
{
NSHomeFunctionKey, 0x50,
NSLeftArrowFunctionKey, 0x51,
NSUpArrowFunctionKey, 0x52,
NSRightArrowFunctionKey, 0x53,
NSDownArrowFunctionKey, 0x54,
NSPageUpFunctionKey, 0x55,
NSPageDownFunctionKey, 0x56,
NSEndFunctionKey, 0x57,
NSBeginFunctionKey, 0x58,
NSSelectFunctionKey, 0x60,
NSPrintFunctionKey, 0x61,
NSExecuteFunctionKey, 0x62,
NSInsertFunctionKey, 0x63,
NSUndoFunctionKey, 0x65,
NSRedoFunctionKey, 0x66,
NSMenuFunctionKey, 0x67,
NSFindFunctionKey, 0x68,
NSHelpFunctionKey, 0x6A,
NSBreakFunctionKey, 0x6B,
NSF1FunctionKey, 0xBE,
NSF2FunctionKey, 0xBF,
NSF3FunctionKey, 0xC0,
NSF4FunctionKey, 0xC1,
NSF5FunctionKey, 0xC2,
NSF6FunctionKey, 0xC3,
NSF7FunctionKey, 0xC4,
NSF8FunctionKey, 0xC5,
NSF9FunctionKey, 0xC6,
NSF10FunctionKey, 0xC7,
NSF11FunctionKey, 0xC8,
NSF12FunctionKey, 0xC9,
NSF13FunctionKey, 0xCA,
NSF14FunctionKey, 0xCB,
NSF15FunctionKey, 0xCC,
NSF16FunctionKey, 0xCD,
NSF17FunctionKey, 0xCE,
NSF18FunctionKey, 0xCF,
NSF19FunctionKey, 0xD0,
NSF20FunctionKey, 0xD1,
NSF21FunctionKey, 0xD2,
NSF22FunctionKey, 0xD3,
NSF23FunctionKey, 0xD4,
NSF24FunctionKey, 0xD5,
NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */
NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */
NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */
NSTabCharacter, 0x09,
0x19, 0x09, /* left tab->regular since pass shift */
NSCarriageReturnCharacter, 0x0D,
NSNewlineCharacter, 0x0D,
NSEnterCharacter, 0x8D,
0x1B, 0x1B /* escape */
};
static unsigned
isFunctionKey(
unsigned code)
{
const unsigned last_keysym = (sizeof(convert_ns_to_X_keysym)
/ sizeof(convert_ns_to_X_keysym[0]));
unsigned keysym;
for (keysym = 0; keysym < last_keysym; keysym += 2) {
if (code == convert_ns_to_X_keysym[keysym]) {
return 0xFF00 | convert_ns_to_X_keysym[keysym + 1];
}
}
return 0;
caret_y = Tk_Height(tkwin) - y;
}
/*

File diff suppressed because it is too large Load Diff

1308
macosx/tkMacOSXKeysyms.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -36,19 +36,19 @@
#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),
SPECIALMENU(window, WINDOWS),
{NULL}
{NULL, 0, 0}
};
#undef SPECIALMENU
#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),
@@ -58,13 +58,13 @@ static const struct {
MODIFIER(Command, NSCommandKeyMask),
MODIFIER(Cmd, NSCommandKeyMask),
MODIFIER(Meta, NSCommandKeyMask),
{NULL}
{NULL, 0, 0}
};
#undef MODIFIER
#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),
@@ -86,7 +86,7 @@ static const struct {
ACCEL(Help, NSHelpFunctionKey),
ACCEL(Power, 0x233d),
ACCEL(Eject, 0xf804),
{NULL}
{NULL, 0, 0}
};
#undef ACCEL
#undef sl
@@ -95,7 +95,6 @@ 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 +107,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
/*
@@ -259,12 +319,6 @@ static int ModifierCharWidth(Tk_Font tkfont);
if (menuPtr && mePtr) {
Tcl_Interp *interp = menuPtr->interp;
/*
* Add time for errors to fire if necessary. This is sub-optimal
* but avoids issues with Tcl/Cocoa event loop integration.
*/
//Tcl_Sleep(100);
Tcl_Preserve(interp);
Tcl_Preserve(menuPtr);
@@ -287,6 +341,8 @@ static int ModifierCharWidth(Tk_Font tkfont);
- (BOOL) menuHasKeyEquivalent: (NSMenu *) menu forEvent: (NSEvent *) event
target: (id *) target action: (SEL *) action
{
(void)menu;
/*
* Use lowercaseString when comparing keyEquivalents since the notion of
* a shifted upper case letter does not make much sense.
@@ -343,6 +399,8 @@ static int ModifierCharWidth(Tk_Font tkfont);
- (void) menuWillOpen: (NSMenu *) menu
{
(void)menu;
if (_tkMenu) {
//RecursivelyClearActiveMenu(_tkMenu);
GenerateMenuSelectEvent((TKMenu *)[self supermenu],
@@ -352,6 +410,8 @@ static int ModifierCharWidth(Tk_Font tkfont);
- (void) menuDidClose: (NSMenu *) menu
{
(void)menu;
if (_tkMenu) {
RecursivelyClearActiveMenu(_tkMenu);
}
@@ -359,6 +419,8 @@ static int ModifierCharWidth(Tk_Font tkfont);
- (void) menu: (NSMenu *) menu willHighlightItem: (NSMenuItem *) item
{
(void)menu;
if (_tkMenu) {
GenerateMenuSelectEvent(self, item);
}
@@ -367,6 +429,7 @@ static int ModifierCharWidth(Tk_Font tkfont);
- (void) menuNeedsUpdate: (NSMenu *) menu
{
TkMenu *menuPtr = (TkMenu *) _tkMenu;
(void)menu;
if (menuPtr) {
Tcl_Interp *interp = menuPtr->interp;
@@ -392,18 +455,31 @@ static int ModifierCharWidth(Tk_Font tkfont);
- (void) menuBeginTracking: (NSNotification *) notification
{
(void)notification;
#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();
}
- (void) menuEndTracking: (NSNotification *) notification
{
(void)notification;
#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();
}
@@ -610,7 +686,6 @@ TkpConfigureMenuEntry(
NSString *keyEquivalent = @"";
NSUInteger modifierMask = NSCommandKeyMask;
NSMenu *submenu = nil;
NSDictionary *attributes;
int imageWidth, imageHeight;
GC gc = (mePtr->textGC ? mePtr->textGC : mePtr->menuPtr->textGC);
Tcl_Obj *fontPtr = (mePtr->fontPtr ? mePtr->fontPtr :
@@ -618,7 +693,7 @@ TkpConfigureMenuEntry(
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,
@@ -626,12 +701,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];
}
[image setTemplate:YES];
}
[menuItem setImage:image];
if ((!image || mePtr->compound != COMPOUND_NONE) && mePtr->labelPtr &&
@@ -645,25 +717,50 @@ TkpConfigureMenuEntry(
}
}
[menuItem setTitle:title];
if (strcmp(Tcl_GetString(fontPtr), "menu") || gc->foreground != defaultFg
|| gc->background != defaultBg) {
attributes = TkMacOSXNSFontAttributesForFont(Tk_GetFontFromObj(
mePtr->menuPtr->tkwin, fontPtr));
if (gc->foreground != defaultFg || gc->background != defaultBg) {
NSColor *color = TkMacOSXGetNSColor(gc,
gc->foreground!=defaultFg? gc->foreground:gc->background);
attributes = [[attributes mutableCopy] autorelease];
[(NSMutableDictionary *) attributes setObject:color
forKey:NSForegroundColorAttributeName];
}
if (attributes) {
attributedTitle = [[[NSAttributedString alloc]
initWithString:title attributes:attributes] autorelease];
}
#if 0
/*
* The -background and -foreground options are now ignored in Aqua.
* See ticket [635167af14].
*/
NSDictionary fontAttributes = TkMacOSXNSFontAttributesForFont(
Tk_GetFontFromObj(mePtr->menuPtr->tkwin, fontPtr));
NSMutableDictionary *attributes = [fontAttributes mutableCopy];
static unsigned long defaultBg = 0, defaultFg = 0;
if (defaultBg == 0) {
tkColor *tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);
defaultBg = tkColPtr->color.pixel;
ckfree(tkColPtr);
}
if (defaultFg == 0) {
tkColor *tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);
defaultFg = tkColPtr->color.pixel;
ckfree(tkColPtr);
}
if (gc->foreground != defaultFg) {
NSColor *fgcolor = TkMacOSXGetNSColor(gc, gc->foreground);
[attributes setObject:fgcolor
forKey:NSForegroundColorAttributeName];
}
if (gc->background != defaultBg) {
NSColor *bgcolor = TkMacOSXGetNSColor(gc, gc->background);
[attributes setObject:bgcolor
forKey:NSBackgroundColorAttributeName];
}
#else
NSDictionary *attributes = TkMacOSXNSFontAttributesForFont(
Tk_GetFontFromObj(mePtr->menuPtr->tkwin, fontPtr));
#endif
attributedTitle = [[NSAttributedString alloc] initWithString:title
attributes:attributes];
[menuItem setAttributedTitle:attributedTitle];
[menuItem setEnabled:!(mePtr->state == ENTRY_DISABLED)];
[menuItem setEnabled:(mePtr->state != ENTRY_DISABLED)];
[menuItem setState:((mePtr->type == CHECK_BUTTON_ENTRY ||
mePtr->type == RADIO_BUTTON_ENTRY) && mePtr->indicatorOn &&
(mePtr->entryFlags & ENTRY_SELECTED) ? NSOnState : NSOffState)];
@@ -696,27 +793,17 @@ TkpConfigureMenuEntry(
if ([menuItem isEnabled]) {
/*
* This menuItem might have been previously disabled (XXX:
* track this), which would have disabled entries; we must
* re-enable the entries here.
* This menuItem might have been previously disabled which
* would have disabled all of its entries; we must re-enable the
* entries here. It is important to iterate though the Tk
* entries, not the NSMenuItems, since some NSMenuItems may
* have been added by the system. See [7185d26cf4].
*/
int i = 0;
NSArray *itemArray = [submenu itemArray];
for (NSMenuItem *item in itemArray) {
for (int i = 0; i < menuRefPtr->menuPtr->numEntries; i++) {
TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
/*
* Work around an apparent bug where itemArray can have
* more items than the menu's entries[] array.
*/
if (i >= (int) menuRefPtr->menuPtr->numEntries) {
break;
}
[item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
i++;
NSMenuItem *item = (NSMenuItem *) submePtr->platformEntryData;
[item setEnabled:(submePtr->state != ENTRY_DISABLED)];
}
}
}
@@ -785,7 +872,7 @@ TkpDestroyMenuEntry(
int
TkpPostMenu(
Tcl_Interp *interp, /* The interpreter this menu lives in */
TCL_UNUSED(Tcl_Interp *), /* The interpreter this menu lives in */
TkMenu *menuPtr, /* The menu we are posting */
int x, int y, /* The screen coordinates where the top left
* corner of the menu, or of the specified
@@ -809,7 +896,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;
}
@@ -882,7 +969,7 @@ TkpPostMenu(
int
TkpPostTearoffMenu(
Tcl_Interp *interp, /* The interpreter this menu lives in */
TCL_UNUSED(Tcl_Interp *), /* The interpreter this menu lives in */
TkMenu *menuPtr, /* The menu we are posting */
int x, int y, int index) /* The screen coordinates where the top left
* corner of the menu, or of the specified
@@ -1093,12 +1180,12 @@ CheckForSpecialMenu(
cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) {
if (cascadeEntryPtr->menuPtr->menuType == MENUBAR
&& cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin) {
TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr;
TkMenu *mainMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr;
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);
@@ -1145,18 +1232,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;
}
}
@@ -1380,14 +1467,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;
@@ -1613,8 +1700,6 @@ Tk_MacOSXTurnOffMenus(void)
void
TkpMenuInit(void)
{
TkColor *tkColPtr;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
#define observe(n, s) \
@@ -1624,13 +1709,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,
@@ -1691,8 +1769,8 @@ TkpMenuThreadInit(void)
void
TkpMenuNotifyToplevelCreate(
Tcl_Interp *interp, /* The interp the menu lives in. */
const char *menuName) /* The name of the menu to reconfigure. */
TCL_UNUSED(Tcl_Interp *), /* The interp the menu lives in. */
TCL_UNUSED(const char *)) /* The name of the menu to reconfigure. */
{
/*
* Nothing to do.
@@ -1720,8 +1798,8 @@ TkpMenuNotifyToplevelCreate(
void
TkpInitializeMenuBindings(
Tcl_Interp *interp, /* The interpreter to set. */
Tk_BindingTable bindingTable)
TCL_UNUSED(Tcl_Interp *), /* The interpreter to set. */
TCL_UNUSED(Tk_BindingTable))
/* The table to add to. */
{
/*
@@ -1761,30 +1839,34 @@ TkpComputeMenubarGeometry(
* TkpDrawMenuEntry --
*
* Draws the given menu entry at the given coordinates with the given
* attributes.
* attributes. This is a no-op on macOS since the menus are drawn by
* the Apple window manager, which also handles all events related to
* selecting menu items. This function is only called for tearoff
* menus, which are not supported on macOS but do get drawn as nearly
* invisible 1 pixel wide windows on macOS
*
* Results:
* None.
*
* Side effects:
* X Server commands are executed to display the menu entry.
* None
*
*----------------------------------------------------------------------
*/
void
TkpDrawMenuEntry(
TkMenuEntry *mePtr, /* The entry to draw */
Drawable d, /* What to draw into */
Tk_Font tkfont, /* Precalculated font for menu */
const Tk_FontMetrics *menuMetricsPtr,
TCL_UNUSED(TkMenuEntry *), /* The entry to draw */
TCL_UNUSED(Drawable), /* What to draw into */
TCL_UNUSED(Tk_Font), /* Precalculated font for menu */
TCL_UNUSED(const Tk_FontMetrics *),
/* Precalculated metrics for menu */
int x, /* X-coordinate of topleft of entry */
int y, /* Y-coordinate of topleft of entry */
int width, /* Width of the entry rectangle */
int height, /* Height of the current rectangle */
int strictMotif, /* Boolean flag */
int drawArrow) /* Whether or not to draw the cascade arrow
TCL_UNUSED(int), /* X-coordinate of topleft of entry */
TCL_UNUSED(int), /* Y-coordinate of topleft of entry */
TCL_UNUSED(int), /* Width of the entry rectangle */
TCL_UNUSED(int), /* Height of the current rectangle */
TCL_UNUSED(int), /* Boolean flag */
TCL_UNUSED(int)) /* Whether or not to draw the cascade arrow
* for cascade items. */
{
}
@@ -1833,7 +1915,7 @@ TkMacOSXPreprocessMenu(void)
int
TkMacOSXUseMenuID(
short macID) /* The id to take out of the table */
TCL_UNUSED(short)) /* The id to take out of the table */
{
return TCL_OK;
}
@@ -1856,8 +1938,8 @@ TkMacOSXUseMenuID(
int
TkMacOSXDispatchMenuEvent(
int menuID, /* The menu id of the menu we are invoking */
int index) /* The one-based index of the item that was
TCL_UNUSED(int), /* The menu id of the menu we are invoking */
TCL_UNUSED(int)) /* The one-based index of the item that was
* selected. */
{
return TCL_ERROR;

View File

@@ -76,6 +76,8 @@ static void DrawMenuButtonImageAndText(TkMenuButton *butPtr);
Tk_ClassProcs tkpMenubuttonClass = {
sizeof(Tk_ClassProcs), /* size */
TkMenuButtonWorldChanged, /* worldChangedProc */
NULL,
NULL
};
/*
@@ -133,7 +135,7 @@ TkMenuButton *
TkpCreateMenuButton(
Tk_Window tkwin)
{
MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton));
MacMenuButton *mbPtr = (MacMenuButton *)ckalloc(sizeof(MacMenuButton));
Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc, mbPtr);
mbPtr->flags = FIRST_DRAW;
@@ -178,13 +180,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.
*/
@@ -222,7 +217,7 @@ TkpDisplayMenuButton(
void
TkpDestroyMenuButton(
TkMenuButton *mbPtr)
TCL_UNUSED(TkMenuButton *))
{
}
@@ -246,7 +241,7 @@ TkpDestroyMenuButton(
void
TkpComputeMenuButtonGeometry(butPtr)
register TkMenuButton *butPtr; /* Widget record for menu button. */
TkMenuButton *butPtr; /* Widget record for menu button. */
{
int width, height, avgWidth, haveImage = 0, haveText = 0;
int txtWidth, txtHeight;
@@ -362,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.
@@ -393,7 +388,7 @@ DrawMenuButtonImageAndText(
DrawParams *dpPtr = &mbPtr->drawParams;
pixmap = (Pixmap) Tk_WindowId(tkwin);
if (butPtr->image != None) {
if (butPtr->image != NULL) {
Tk_SizeOfImage(butPtr->image, &width, &height);
haveImage = 1;
} else if (butPtr->bitmap != None) {
@@ -544,8 +539,7 @@ DrawMenuButtonImageAndText(
static void
TkMacOSXDrawMenuButton(
MacMenuButton *mbPtr, /* Mac menubutton. */
GC gc, /* The GC we are drawing into - needed for the bevel
* button */
TCL_UNUSED(GC), /* The GC we are drawing into - not used */
Pixmap pixmap) /* The pixmap we are drawing into - needed for the
* bevel button */
{
@@ -566,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;
}
@@ -597,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);
@@ -625,8 +619,8 @@ TkMacOSXDrawMenuButton(
static void
MenuButtonBackgroundDrawCB (
MacMenuButton *ptr,
SInt16 depth,
Boolean isColorDev)
TCL_UNUSED(SInt16),
TCL_UNUSED(Boolean))
{
TkMenuButton* butPtr = (TkMenuButton *) ptr;
Tk_Window tkwin = butPtr->tkwin;
@@ -658,11 +652,11 @@ MenuButtonBackgroundDrawCB (
static void
MenuButtonContentDrawCB (
ThemeButtonKind kind,
const HIThemeButtonDrawInfo *drawinfo,
TCL_UNUSED(ThemeButtonKind),
TCL_UNUSED(const HIThemeButtonDrawInfo *),
MacMenuButton *ptr,
SInt16 depth,
Boolean isColorDev)
TCL_UNUSED(SInt16),
TCL_UNUSED(Boolean))
{
TkMenuButton *butPtr = (TkMenuButton *) ptr;
Tk_Window tkwin = butPtr->tkwin;
@@ -709,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;
}
}

View File

@@ -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:
@@ -201,7 +201,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);
@@ -415,7 +415,7 @@ GenerateEditEvent(
if (!winPtr) {
return;
}
tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
tkwin = (Tk_Window)winPtr->dispPtr->focusPtr;
if (!tkwin) {
return;
}

View File

@@ -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,134 +53,164 @@ 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 = None, capture, target;
NSPoint local, global;
#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
switch (eventType) {
case NSMouseEntered:
case NSMouseExited:
case NSCursorUpdate:
case NSLeftMouseDown:
case NSLeftMouseUp:
case NSRightMouseDown:
case NSRightMouseUp:
case NSOtherMouseDown:
case NSOtherMouseUp:
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
case NSMouseMoved:
case NSTabletPoint:
case NSTabletProximity:
case NSScrollWheel:
break;
default: /* Unrecognized mouse event. */
return theEvent;
/*
* 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;
}
/*
* 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.
* Check if the event is located in the titlebar.
*/
if (eventWindow) {
local = [theEvent locationInWindow];
global = [eventWindow tkConvertPointToScreen: local];
tkwin = TkMacOSXGetCapture();
if (tkwin) {
winPtr = (TkWindow *) tkwin;
eventWindow = TkMacOSXDrawableWindow(winPtr->window);
if (eventWindow) {
local = [eventWindow tkConvertPointFromScreen: global];
} else {
return theEvent;
}
}
local.y = [eventWindow frame].size.height - local.y;
global.y = TkMacOSXZeroScreenHeight() - global.y;
} else {
/*
* If the event has no NSWindow, the location is in screen coordinates.
*/
global = [theEvent locationInWindow];
tkwin = TkMacOSXGetCapture();
if (tkwin) {
winPtr = (TkWindow *) tkwin;
eventWindow = TkMacOSXDrawableWindow(winPtr->window);
} else {
eventWindow = [NSApp mainWindow];
}
if (!eventWindow) {
return theEvent;
}
local = [eventWindow tkConvertPointFromScreen: global];
local.y = [eventWindow frame].size.height - local.y;
global.y = TkMacOSXZeroScreenHeight() - global.y;
inTitleBar = viewFrame.size.height < location.y;
}
/*
* If we still don't have a window, try using the toplevel that
* manages the NSWindow.
*/
if (!tkwin) {
winPtr = TkMacOSXGetTkWindow(eventWindow);
tkwin = (Tk_Window) winPtr;
}
if (!tkwin) {
/*
* We can't find a window for this event. We have to ignore it.
*/
#ifdef TK_MAC_DEBUG_EVENTS
TkMacOSXDbgMsg("tkwin == NULL");
button = [theEvent buttonNumber] + Button1;
switch (eventType) {
case NSRightMouseUp:
case NSOtherMouseUp:
buttonState &= ~TkGetButtonMask(button);
break;
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
case NSRightMouseDown:
case NSOtherMouseDown:
buttonState |= TkGetButtonMask(button);
break;
case NSMouseEntered:
if ([eventWindow respondsToSelector:@selector(mouseInResizeArea)] &&
!inTitleBar) {
[(TKWindow *)eventWindow setMouseInResizeArea:YES];
}
break;
case NSMouseExited:
if ([eventWindow respondsToSelector:@selector(mouseInResizeArea)]) {
[(TKWindow *)eventWindow setMouseInResizeArea:NO];
break;
}
case NSLeftMouseUp:
case NSLeftMouseDown:
case NSMouseMoved:
case NSScrollWheel:
#if 0
case NSCursorUpdate:
case NSTabletPoint:
case NSTabletProximity:
#endif
break;
default: /* This type of event is ignored. */
return theEvent;
}
/*
* Ignore the event if a local grab is in effect and the Tk event window is
* not in the grabber's subtree.
* Update the button state. We ignore left button presses that start a
* resize or occur in the title bar. See tickets [d72abe6b54] and
* [39cbacb9e8].
*/
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) {
if (eventType == NSLeftMouseDown) {
if ([eventWindow respondsToSelector:@selector(mouseInResizeArea)] &&
[(TKWindow *) eventWindow mouseInResizeArea]) {
/*
* 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.
*/
buttonState &= ~TkGetButtonMask(Button1);
return theEvent;
}
for (tkwin2 = tkEventWindow;
!Tk_IsTopLevel(tkwin2);
tkwin2 = Tk_Parent(tkwin2)) {
if (tkwin2 == (Tk_Window) grabWinPtr) {
break;
}
}
if (tkwin2 != (Tk_Window) grabWinPtr) {
if (inTitleBar) {
ignoredPresses++;
return theEvent;
}
validPresses++;
buttonState |= TkGetButtonMask(Button1);
}
if (eventType == NSLeftMouseUp) {
if (ignoredPresses > 0) {
ignoredPresses--;
} else if (validPresses > 0) {
validPresses--;
}
if (validPresses == 0) {
buttonState &= ~TkGetButtonMask(Button1);
}
}
/*
* Convert local from NSWindow flipped coordinates to the toplevel's
* coordinates.
* Find an appropriate NSWindow to attach to this event, and its
* associated Tk window.
*/
capture = TkMacOSXGetCapture();
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 (!winPtr) {
/*
* We couldn't find a Tk window for this event. We have to ignore it.
*/
#ifdef TK_MAC_DEBUG_EVENTS
TkMacOSXDbgMsg("Event received with no Tk window.");
#endif
return theEvent;
}
tkwin = (Tk_Window) winPtr;
/*
* 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)) {
@@ -196,43 +227,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);
/*
* Ignore the event if a local grab is in effect and the Tk 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;
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 = 0;
int button = [theEvent buttonNumber] + Button1;
EventRef eventRef = (EventRef)[theEvent eventRef];
UInt32 buttons;
OSStatus err = GetEventParameter(eventRef, kEventParamMouseChord,
typeUInt32, NULL, sizeof(UInt32), NULL, &buttons);
if (err == noErr) {
state |= (buttons & 0x1F) * Button1Mask;
} else if (button <= Button5) {
switch (eventType) {
case NSLeftMouseDown:
case NSRightMouseDown:
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDown:
state |= TkGetButtonMask(button);
break;
default:
break;
}
}
unsigned int state = buttonState;
NSUInteger modifiers = [theEvent modifierFlags];
if (modifiers & NSAlphaShiftKeyMask) {
@@ -260,32 +292,34 @@ 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;
int coarseDelta;
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];
if (delta != 0.0) {
@@ -312,34 +346,6 @@ enum {
#pragma mark -
/*
*----------------------------------------------------------------------
*
* 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);
}
/*
*----------------------------------------------------------------------
*
@@ -464,8 +470,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;
@@ -503,7 +509,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.
*
*----------------------------------------------------------------------
@@ -541,7 +547,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.
*
*----------------------------------------------------------------------
@@ -554,8 +560,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));
@@ -593,7 +599,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.
*
*----------------------------------------------------------------------
@@ -636,51 +642,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];
}
/*
@@ -708,8 +703,7 @@ TkpSetCapture(
while (winPtr && !Tk_IsTopLevel(winPtr)) {
winPtr = winPtr->parentPtr;
}
[NSEvent stopPeriodicEvents];
captureWinPtr = (Tk_Window) winPtr;
captureWinPtr = (Tk_Window)winPtr;
}
/*

View File

@@ -141,12 +141,57 @@ void DebugPrintQueue(void)
*/
- (void) sendEvent: (NSEvent *) theEvent
{
/*
* Workaround for an Apple bug. When an accented character is selected
* from an NSTextInputClient popup character viewer with the mouse, Apple
* sends an event of type NSAppKitDefined and subtype 21. If that event is
* sent up the responder chain it causes Apple to print a warning to the
* console log and, extremely obnoxiously, also to stderr, which says
* "Window move completed without beginning." Apparently they are sending
* the "move completed" event without having sent the "move began" event of
* subtype 20, and then announcing their error on our stderr. Also, of
* course, no movement is occurring. The popup is not movable and is just
* being closed. The bug has been reported to Apple. If they ever fix it,
* this block should be removed.
*/
# if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
if ([theEvent type] == NSAppKitDefined) {
static Bool aWindowIsMoving = NO;
switch([theEvent subtype]) {
case 20:
aWindowIsMoving = YES;
break;
case 21:
if (aWindowIsMoving) {
aWindowIsMoving = NO;
break;
} else {
// printf("Bug!!!!\n");
return;
}
default:
break;
}
}
#endif
[super sendEvent:theEvent];
[NSApp tkCheckPasteboard];
#ifdef TK_MAC_DEBUG_EVENTS
fprintf(stderr, "Sending event of type %d\n", (int)[theEvent type]);
DebugPrintQueue();
#endif
}
- (void) _runBackgroundLoop
{
while(Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_TIMER_EVENTS|TCL_DONT_WAIT)){
TkMacOSXDrawAllViews(NULL);
}
}
@end
@@ -166,15 +211,13 @@ void DebugPrintQueue(void)
*----------------------------------------------------------------------
*/
NSString *
static NSString *
GetRunLoopMode(NSModalSession modalSession)
{
NSString *runLoopMode = nil;
if (modalSession) {
runLoopMode = NSModalPanelRunLoopMode;
} else if (TkMacOSXGetCapture()) {
runLoopMode = NSEventTrackingRunLoopMode;
}
if (!runLoopMode) {
runLoopMode = [[NSRunLoop currentRunLoop] currentMode];
@@ -226,7 +269,6 @@ Tk_MacOSXSetupTkNotifier(void)
Tcl_CreateEventSource(TkMacOSXEventsSetupProc,
TkMacOSXEventsCheckProc, NULL);
TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
Tcl_SetServiceMode(TCL_SERVICE_ALL);
TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);
TclMacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode);
}
@@ -261,13 +303,93 @@ TkMacOSXNotifyExitHandler(
tsdPtr->initialized = 0;
}
/*
*----------------------------------------------------------------------
*
* 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 may 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.
@@ -277,18 +399,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(
ClientData clientData)
{
if (ticker) {
ticker = Tcl_CreateTimerHandler(TICK, Heartbeat, NULL);
}
}
static const Tcl_Time zeroBlockTime = { 0, 0 };
static void
TkMacOSXEventsSetupProc(
ClientData clientData,
int flags)
{
static Bool havePeriodicEvents = NO;
NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
/*
@@ -296,35 +433,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 heartbeat.
*/
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);
}
}
}
@@ -352,6 +493,7 @@ TkMacOSXEventsCheckProc(
int flags)
{
NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
int eventsFound = 0;
/*
* runloopMode will be nil if we are in a Tcl event loop.
@@ -390,17 +532,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 {
@@ -417,6 +561,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);
}
}
}

View File

@@ -1,7 +1,7 @@
/*
* tkMacOSXPort.h --
*
* This file is included by all of the Tk C files. It contains
* This file is included by all of the Tk C files. It contains
* information that may be configuration-dependent, such as
* #includes for system include files and a few other things.
*
@@ -17,14 +17,15 @@
#define _TKMACPORT
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <pwd.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/file.h>
#ifdef HAVE_SYS_SELECT_H
@@ -158,29 +159,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 TRANSPARENT_PIXEL 30
#define APPEARANCE_PIXEL 52
#define PIXEL_MAGIC ((unsigned char) 0x69)
#define TKPUTIMAGE_CAN_BLEND
/*
* 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 xcolor.c
*/
#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \
| (((p)->red >> 8) & 0xff)) << 8) \
| (((p)->green >> 8) & 0xff)) << 8) \
| (((p)->blue >> 8) & 0xff))
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))
/*
* Used by tkWindow.c
*/
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 */

View File

@@ -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.
@@ -19,6 +20,10 @@
#error Objective-C compiler required
#endif
#ifndef __clang__
#define instancetype id
#endif
#define TextStyle MacTextStyle
#import <ApplicationServices/ApplicationServices.h>
#import <Cocoa/Cocoa.h>
@@ -98,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, ...)
@@ -122,6 +127,74 @@
STRINGIFY(symbol)); \
}
/*
* The structure of a 32-bit XEvent keycode on macOS. It may be viewed as
* an unsigned int or as having either two or three bitfields.
*/
typedef struct keycode_v_t {
unsigned keychar: 22; /* UCS-32 character */
unsigned o_s: 2; /* State of Option and Shift keys. */
unsigned virtual: 8; /* 8-bit virtual keycode - identifies a key. */
} keycode_v;
typedef struct keycode_x_t {
unsigned keychar: 22; /* UCS-32 character */
unsigned xvirtual: 10; /* Combines o_s and virtual. This 10-bit integer
* is used as a key for looking up the character
* produced when pressing a key with a particular
* Shift and Option modifier state. */
} keycode_x;
typedef union MacKeycode_t {
unsigned int uint;
keycode_v v;
keycode_x x;
} MacKeycode;
/*
* Macros used in tkMacOSXKeyboard.c and tkMacOSXKeyEvent.c.
* Note that 0x7f is del and 0xF8FF is the Apple Logo character.
*/
#define ON_KEYPAD(virtual) ((virtual >= 0x41) && (virtual <= 0x5C))
#define IS_PRINTABLE(keychar) ((keychar >= 0x20) && (keychar != 0x7f) && \
((keychar < 0xF700) || keychar >= 0xF8FF))
/*
* An "index" is 2-bit bitfield showing the state of the Option and Shift
* keys. It is used as an index when building the keymaps and it
* is the value of the o_s bitfield of a keycode_v.
*/
#define INDEX_SHIFT 1
#define INDEX_OPTION 2
#define INDEX2STATE(index) ((index & INDEX_SHIFT ? ShiftMask : 0) | \
(index & INDEX_OPTION ? Mod2Mask : 0))
#define INDEX2CARBON(index) ((index & INDEX_SHIFT ? shiftKey : 0) | \
(index & INDEX_OPTION ? optionKey : 0))
#define STATE2INDEX(state) ((state & ShiftMask ? INDEX_SHIFT : 0) | \
(state & Mod2Mask ? INDEX_OPTION : 0))
/*
* Special values for the virtual bitfield. Actual virtual keycodes are < 128.
*/
#define NO_VIRTUAL 0xFF /* Not generated by a key or the NSText"InputClient. */
#define REPLACEMENT_VIRTUAL 0x80 /* A BMP char sent by the NSTextInputClient. */
#define NON_BMP_VIRTUAL 0x81 /* A non-BMP char sent by the NSTextInputClient. */
/*
* A special character is used in the keycode for simulated modifier KeyPress
* or KeyRelease XEvents. It is near the end of the private-use range but
* different from the UniChar 0xF8FF which Apple uses for their logo character.
* A different special character is used for keys, like the Menu key, which do
* not appear on Macintosh keyboards.
*/
#define MOD_KEYCHAR 0xF8FE
#define UNKNOWN_KEYCHAR 0xF8FD
/*
* Structure encapsulating current drawing environment.
*/
@@ -143,24 +216,15 @@ MODULE_SCOPE long tkMacOSXMacOSXVersion;
* Prototypes for TkMacOSXRegion.c.
*/
#if 0
MODULE_SCOPE void TkMacOSXEmtpyRegion(TkRegion r);
MODULE_SCOPE int TkMacOSXIsEmptyRegion(TkRegion r);
#endif
MODULE_SCOPE HIShapeRef TkMacOSXGetNativeRegion(TkRegion r);
MODULE_SCOPE void TkMacOSXSetWithNativeRegion(TkRegion r,
HIShapeRef rgn);
MODULE_SCOPE void TkMacOSXOffsetRegion(TkRegion r, short dx, short dy);
MODULE_SCOPE HIShapeRef TkMacOSXHIShapeCreateEmpty(void);
MODULE_SCOPE HIMutableShapeRef TkMacOSXHIShapeCreateMutableWithRect(
const CGRect *inRect);
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,
@@ -181,46 +245,31 @@ 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*)TkMacOSXDrawable(drawable))
#define TkMacOSXGetNSViewForDrawable(macWin) (NSView *)Tk_MacOSXGetNSViewForDrawable((Drawable)(macWin))
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 Tcl_Obj * TkMacOSXGetStringObjFromCFString(CFStringRef str);
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);
@@ -237,12 +286,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[]);
MODULE_SCOPE NSString* TclUniToNSString(const char *source, int numBytes);
MODULE_SCOPE int TclUniAtIndex(NSString *string, int index, char *uni,
unsigned int *code);
MODULE_SCOPE char* NSStringToTclUni(NSString *string, int *numBytes);
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
@@ -273,16 +323,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)
@@ -308,6 +363,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;
@@ -324,6 +380,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;
@@ -353,17 +410,22 @@ VISIBILITY_HIDDEN
{
@private
NSString *privateWorkingText;
Bool _needsRedisplay;
Bool _tkNeedsDisplay;
NSRect _tkDirtyRect;
}
@property Bool needsRedisplay;
@property Bool tkNeedsDisplay;
@property NSRect tkDirtyRect;
@end
@interface TKContentView(TKKeyEvent)
- (void) deleteWorkingText;
- (void) cancelComposingText;
@end
@interface TKContentView(TKWindowEvent)
- (void) generateExposeEvents: (HIShapeRef) shape;
- (void) addTkDirtyRect: (NSRect) rect;
- (void) clearTkDirtyRect;
- (void) generateExposeEvents: (NSRect) rect;
- (void) tkToolbarButton: (id) sender;
@end
@@ -374,16 +436,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
@@ -433,10 +519,54 @@ VISIBILITY_HIDDEN
- (void) setAppleMenu: (NSMenu *) menu;
@end
/*
* These methods are exposed because they are needed to prevent zombie windows
* on systems with a TouchBar. The TouchBar Key-Value observer holds a
* reference to the key window, which prevents deallocation of the key window
* when it is closed.
*/
@interface NSApplication(TkWm)
- (id) _setKeyWindow: (NSWindow *) window;
- (id) _setMainWindow: (NSWindow *) window;
@end
/*
*---------------------------------------------------------------------------
*
* TKNSString --
*
* When Tcl is compiled with TCL_UTF_MAX = 3 (the default for 8.6) it cannot
* deal directly with UTF-8 encoded non-BMP characters, since their UTF-8
* encoding requires 4 bytes. Instead, when using these versions of Tcl, Tk
* uses the CESU-8 encoding internally. This encoding is similar to UTF-8
* except that it allows encoding surrogate characters as 3-byte sequences
* using the same algorithm which UTF-8 uses for non-surrogates. This means
* that a non-BMP character is encoded as a string of length 6. Apple's
* NSString class does not provide a constructor which accepts a CESU-8 encoded
* byte sequence as initial data. So we add a new class which does provide
* such a constructor. It also has a DString property which is a DString whose
* string pointer is a byte sequence encoding the NSString with the current Tk
* encoding, namely UTF-8 if TCL_UTF_MAX >= 4 or CESU-8 if TCL_UTF_MAX = 3.
*
*---------------------------------------------------------------------------
*/
@interface TKNSString:NSString {
@private
Tcl_DString _ds;
NSString *_string;
const char *_UTF8String;
}
@property const char *UTF8String;
@property (readonly) Tcl_DString DString;
- (instancetype)initWithTclUtfBytes:(const void *)bytes
length:(NSUInteger)len;
@end
#endif /* _TKMACPRIV */
int TkMacOSXGetAppPath(ClientData cd, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]);
/*
* Local Variables:
* mode: objc

View File

@@ -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 @@
TkRegion
TkCreateRegion(void)
{
return (TkRegion) HIShapeCreateMutable();
TkRegion region = (TkRegion) HIShapeCreateMutable();
DebugLog("Created region: total regions = %d\n", ++totalRegions);
RetainRegion(region);
return region;
}
/*
@@ -59,7 +72,8 @@ TkDestroyRegion(
TkRegion r)
{
if (r) {
CFRelease(r);
DebugLog("Destroyed region: total regions = %d\n", --totalRegions);
ReleaseRegion(r);
}
return Success;
}
@@ -175,7 +189,7 @@ TkUnionRectWithRegion(
*----------------------------------------------------------------------
*/
int
static int
TkMacOSXIsEmptyRegion(
TkRegion r)
{
@@ -320,7 +334,7 @@ TkpBuildRegionFromAlphaData(
/*
*----------------------------------------------------------------------
*
* TkpRetainRegion --
* RetainRegion --
*
* Increases reference count of region.
*
@@ -333,17 +347,18 @@ TkpBuildRegionFromAlphaData(
*----------------------------------------------------------------------
*/
void
TkpRetainRegion(
static void
RetainRegion(
TkRegion 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(
TkRegion r)
{
CFRelease(r);
DebugLog("Released region: total count is %d\n", --totalRegionRetainCount);
}
/*
@@ -436,7 +452,7 @@ TkMacOSXSetWithNativeRegion(
/*
*----------------------------------------------------------------------
*
* TkMacOSXOffsetRegion --
* XOffsetRegion --
*
* Offsets region by given distances.
*
@@ -449,20 +465,21 @@ TkMacOSXSetWithNativeRegion(
*----------------------------------------------------------------------
*/
void
TkMacOSXOffsetRegion(
TkRegion r,
short dx,
short dy)
int
XOffsetRegion(
void *r,
int dx,
int dy)
{
ChkErr(HIShapeOffset, (HIMutableShapeRef) r, dx, dy);
return Success;
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXHIShapeCreateEmpty, TkMacOSXHIShapeCreateMutableWithRect,
* TkMacOSXHIShapeSetWithShape, TkMacOSXHIShapeSetWithRect,
* TkMacOSXHIShapeSetWithShape,
* TkMacOSHIShapeDifferenceWithRect, TkMacOSHIShapeUnionWithRect,
* TkMacOSHIShapeUnion --
*
@@ -501,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,

View File

@@ -76,7 +76,7 @@ TkScale *
TkpCreateScale(
Tk_Window tkwin)
{
MacScale *macScalePtr = ckalloc(sizeof(MacScale));
MacScale *macScalePtr = (MacScale *)ckalloc(sizeof(MacScale));
macScalePtr->scaleHandle = NULL;
if (scaleActionProc == NULL) {
@@ -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.
@@ -292,10 +287,6 @@ TkpDisplayScale(
SetControlVisibility(macScalePtr->scaleHandle, true, true);
HiliteControl(macScalePtr->scaleHandle, 0);
Draw1Control(macScalePtr->scaleHandle);
if (portChanged) {
QDSwapPort(savePort, NULL);
}
done:
scalePtr->flags &= ~REDRAW_ALL;
}
@@ -327,14 +318,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 +333,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,23 +384,11 @@ MacScaleEventProc(
Point where;
Rect bounds;
int part;
CGrafPtr destPort, savePort;
Boolean portChanged;
#ifdef TK_MAC_DEBUG_SCALE
fprintf(stderr,"MacScaleEventProc\n" );
#endif
/*
* To call Macintosh control routines we must have the port set to the
* window containing the control. We will then test which part of the
* control was hit and act accordingly.
*/
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;
@@ -447,10 +418,6 @@ MacScaleEventProc(
*/
TkGenerateButtonEventForXPointer(Tk_WindowId(macScalePtr->info.tkwin));
if (portChanged) {
QDSwapPort(savePort, NULL);
}
}
/*

View File

@@ -121,7 +121,7 @@ TkScrollbar *
TkpCreateScrollbar(
Tk_Window tkwin)
{
MacScrollbar *scrollPtr = ckalloc(sizeof(MacScrollbar));
MacScrollbar *scrollPtr = (MacScrollbar *)ckalloc(sizeof(MacScrollbar));
scrollPtr->troughGC = NULL;
scrollPtr->copyGC = NULL;
@@ -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;
@@ -246,9 +246,9 @@ void
TkpDisplayScrollbar(
ClientData clientData) /* Information about window. */
{
register TkScrollbar *scrollPtr = clientData;
TkScrollbar *scrollPtr = clientData;
MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
register Tk_Window tkwin = scrollPtr->tkwin;
Tk_Window tkwin = scrollPtr->tkwin;
TkWindow *winPtr = (TkWindow *) tkwin;
TkMacOSXDrawingContext dc;
@@ -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 {
@@ -354,7 +354,7 @@ TkpDisplayScrollbar(
extern void
TkpComputeScrollbarGeometry(
register TkScrollbar *scrollPtr)
TkScrollbar *scrollPtr)
/* Scrollbar whose geometry may have
* changed. */
{
@@ -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;
@@ -484,7 +484,7 @@ TkpDestroyScrollbar(
void
TkpConfigureScrollbar(
register TkScrollbar *scrollPtr)
TkScrollbar *scrollPtr)
{
/* empty */
}
@@ -509,7 +509,7 @@ TkpConfigureScrollbar(
int
TkpScrollbarPosition(
register TkScrollbar *scrollPtr,
TkScrollbar *scrollPtr,
/* Scrollbar widget record. */
int x, int y) /* Coordinates within scrollPtr's window. */
{
@@ -519,7 +519,7 @@ TkpScrollbarPosition(
*/
int length, width, tmp;
register const int inset = scrollPtr->inset;
const int inset = scrollPtr->inset;
if (scrollPtr->vertical) {
length = Tk_Height(scrollPtr->tkwin);
@@ -589,12 +589,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;

View File

@@ -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

View File

@@ -20,10 +20,11 @@
static int
ServicesEventProc(
Tcl_Event *event,
int flags)
TCL_UNUSED(Tcl_Event *),
TCL_UNUSED(int))
{
TkMainInfo *info = TkGetMainInfoList();
Tcl_GlobalEval(info->interp, "::tk::mac::PerformService");
return 1;
}
@@ -43,8 +44,8 @@ ServicesEventProc(
- (void) provideService:(NSPasteboard *)pboard
userData:(NSString *)data
error:(NSString **)error;
- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
types:(NSArray *)types;
- (BOOL) writeSelectionToPasteboard:(NSPasteboard *)pboard
types:(NSArray *)types;
@end
@@ -104,6 +105,8 @@ ServicesEventProc(
NSString *pboardString = nil, *pboardType = nil;
NSArray *types = [pboard types];
Tcl_Event *event;
(void)data;
(void)error;
/*
* Get a string from the private pasteboard and copy it to the general
@@ -123,7 +126,7 @@ ServicesEventProc(
[generalpasteboard declareTypes:[NSArray arrayWithObjects:pboardType, nil]
owner:nil];
[generalpasteboard setString:pboardString forType:pboardType];
event = ckalloc(sizeof(Tcl_Event));
event = (Tcl_Event *)ckalloc(sizeof(Tcl_Event));
event->proc = ServicesEventProc;
Tcl_QueueEvent((Tcl_Event *)event, TCL_QUEUE_TAIL);
}
@@ -137,7 +140,7 @@ ServicesEventProc(
int
TkMacOSXServices_Init(
Tcl_Interp *interp)
TCL_UNUSED(Tcl_Interp *))
{
/*
* Initialize an instance of TkService and register it with the NSApp.

View File

@@ -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,10 +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;
MacDrawable *macWin = (MacDrawable *)window;
/*
* Remove any dangling pointers that may exist if the window we are
@@ -68,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);
@@ -119,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.
*
*
*----------------------------------------------------------------------
*/
@@ -136,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
@@ -154,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
@@ -168,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);
@@ -183,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 {
/*
@@ -209,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;
}
@@ -269,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.
@@ -286,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
@@ -322,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;
}
@@ -361,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);
@@ -406,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)) {
@@ -429,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);
@@ -459,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)) {
@@ -497,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.
@@ -534,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);
@@ -602,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)) {
@@ -615,7 +612,6 @@ XRaiseWindow(
return Success;
}
#if 0
/*
*----------------------------------------------------------------------
*
@@ -632,23 +628,23 @@ XRaiseWindow(
*----------------------------------------------------------------------
*/
void
int
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)) {
TkWmRestackToplevel(macWin->winPtr, Below, NULL);
} else {
/*
/*
* TODO: this should generate damage
*/
}
return Success;
}
#endif
/*
*----------------------------------------------------------------------
@@ -673,9 +669,9 @@ 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;
display->request++;
@@ -697,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);
}
}
@@ -826,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
@@ -859,11 +849,11 @@ TkMacOSXUpdateClipRgn(
TkRegion r = TkCreateRegion();
HIShapeRef visRgn;
tkMacOSXEmbedHandler->getClipProc((Tk_Window) winPtr, r);
tkMacOSXEmbedHandler->getClipProc((Tk_Window)winPtr, r);
visRgn = TkMacOSXGetNativeRegion(r);
ChkErr(HIShapeIntersect, visRgn, rgn, rgn);
CFRelease(visRgn);
TkpReleaseRegion(r);
TkDestroyRegion(r);
}
/*
@@ -987,12 +977,13 @@ TkMacOSXVisableClipRgn(
static OSStatus
InvalViewRect(
int msg,
HIShapeRef rgn,
TCL_UNUSED(HIShapeRef),
const CGRect *rect,
void *ref)
{
static CGAffineTransform t;
NSView *view = ref;
TKContentView *view = ref;
NSRect dirtyRect;
if (!view) {
return paramErr;
@@ -1003,8 +994,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;
@@ -1050,14 +1041,14 @@ 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.
*
@@ -1070,11 +1061,11 @@ TkMacOSXInvalidateWindow(
*----------------------------------------------------------------------
*/
NSWindow *
TkMacOSXDrawableWindow(
void *
TkMacOSXDrawable(
Drawable drawable)
{
MacDrawable *macWin = (MacDrawable *) drawable;
MacDrawable *macWin = (MacDrawable *)drawable;
NSWindow *result = nil;
if (!macWin || macWin->flags & TK_IS_PIXMAP) {
@@ -1090,25 +1081,19 @@ 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.
* This function only exists because it is listed in the stubs table.
* It is useless.
*
* Results:
* NULL.
@@ -1121,7 +1106,7 @@ TkMacOSXDrawable(
void *
TkMacOSXGetDrawablePort(
Drawable drawable)
TCL_UNUSED(Drawable))
{
return NULL;
}
@@ -1129,9 +1114,16 @@ TkMacOSXGetDrawablePort(
/*
*----------------------------------------------------------------------
*
* TkMacOSXDrawableView --
* TkMacOSXGetNSViewForDrawable/TkMacOSXGetRootControl --
*
* This function returns the NSView for a given X drawable.
* 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.
*
* 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.
@@ -1142,53 +1134,27 @@ TkMacOSXGetDrawablePort(
*----------------------------------------------------------------------
*/
NSView *
TkMacOSXDrawableView(
MacDrawable *macWin)
{
NSView *result = nil;
if (!macWin) {
result = nil;
} else if (!macWin->toplevel) {
result = macWin->view;
} else if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
result = macWin->toplevel->view;
} else {
TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
if (contWinPtr) {
result = TkMacOSXDrawableView(contWinPtr->privatePtr);
}
}
return result;
}
/*
*----------------------------------------------------------------------
*
* 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
*/
void *result = NULL;
MacDrawable *macWin = (MacDrawable *)drawable;
return TkMacOSXDrawableView((MacDrawable *) drawable);
if (!macWin) {
result = NULL;
} else if (!macWin->toplevel) {
result = macWin->view;
} else if (!(macWin->toplevel->flags & TK_EMBEDDED)) {
result = macWin->toplevel->view;
} else {
TkWindow *contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr);
if (contWinPtr) {
result = TkMacOSXGetRootControl((Drawable)contWinPtr->privatePtr);
}
}
return result;
}
/*
@@ -1254,7 +1220,7 @@ TkMacOSXInvalClipRgns(
childPtr = winPtr->childList;
while (childPtr) {
if (!Tk_IsTopLevel(childPtr)) {
TkMacOSXInvalClipRgns((Tk_Window) childPtr);
TkMacOSXInvalClipRgns((Tk_Window)childPtr);
}
childPtr = childPtr->nextPtr;
}
@@ -1267,7 +1233,7 @@ TkMacOSXInvalClipRgns(
childPtr = TkpGetOtherWindow(winPtr);
if (childPtr) {
TkMacOSXInvalClipRgns((Tk_Window) childPtr);
TkMacOSXInvalClipRgns((Tk_Window)childPtr);
}
/*
@@ -1281,7 +1247,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.
@@ -1290,7 +1256,7 @@ TkMacOSXInvalClipRgns(
* None.
*
* Side effects:
* None.
* Fills in a Rect.
*
*----------------------------------------------------------------------
*/
@@ -1313,16 +1279,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.
*
*----------------------------------------------------------------------
*/
@@ -1337,6 +1302,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);
}
/*
*----------------------------------------------------------------------
@@ -1417,7 +1415,7 @@ 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. */
@@ -1427,7 +1425,7 @@ Tk_GetPixmap(
if (display != NULL) {
display->request++;
}
macPix = ckalloc(sizeof(MacDrawable));
macPix = (MacDrawable *)ckalloc(sizeof(MacDrawable));
macPix->winPtr = NULL;
macPix->xOff = 0;
macPix->yOff = 0;
@@ -1465,7 +1463,7 @@ Tk_FreePixmap(
Display *display, /* Display. */
Pixmap pixmap) /* Pixmap to destroy */
{
MacDrawable *macPix = (MacDrawable *) pixmap;
MacDrawable *macPix = (MacDrawable *)pixmap;
display->request++;
if (macPix->context) {

View File

@@ -14,6 +14,8 @@
#include "tkMacOSXPrivate.h"
#include "tkMacOSXConstants.h"
#include "tkMacOSXWm.h"
/*
* Forward declarations of procedures defined later in this file:
@@ -24,7 +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);
static int MenuBarHeightObjCmd (ClientData dummy, Tcl_Interp *interp,
int objc, Tcl_Obj *const *objv);
/*
@@ -56,7 +62,8 @@ TkplatformtestInit(
Tcl_CreateObjCommand(interp, "debugger", DebuggerObjCmd, NULL, NULL);
#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;
}
@@ -93,45 +100,86 @@ DebuggerObjCmd(
/*
*----------------------------------------------------------------------
*
* TkTestLogDisplay --
* MenuBarHeightObjCmd --
*
* The test image display procedure calls this to determine whether it
* should write a log message recording that it has being run. On OSX
* 10.14 and later, only calls to the display procedure which occur inside
* of the drawRect method should be logged, since those are the only ones
* which actually draw anything. On earlier systems the opposite is true.
* The calls from within the drawRect method are redundant, since the
* first time the display procedure is run it will do the drawing and that
* first call will usually not occur inside of drawRect.
*
* Results:
* On OSX 10.14 and later, returns true if and only if called from
* within [NSView drawRect]. On earlier systems returns false if
* and only if called from with [NSView drawRect].
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE Bool
TkTestLogDisplay(void) {
if ([NSApp macMinorVersion] >= 14) {
return [NSApp isDrawing];
} else {
return ![NSApp isDrawing];
}
}
/*
*----------------------------------------------------------------------
*
* PressButtonObjCmd --
*
* This Tcl command simulates a button press at a specific screen
* location. It injects NSEvents into the NSApplication event queue,
* as opposed to adding events to the Tcl queue as event generate
* would do. One application is for testing the grab command.
* 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_NewIntObj(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.
*
* Results:
* 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
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE Bool
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 True;
}
}
/*
*----------------------------------------------------------------------
*
* 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. 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.
@@ -142,15 +190,15 @@ TkTestLogDisplay(void) {
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static int
PressButtonObjCmd(
ClientData clientData,
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
int x, y, i, value, wNum;
int x = 0, y = 0, i, value;
NSInteger signal = -1;
CGPoint pt;
NSPoint loc;
NSEvent *motion, *press, *release;
@@ -184,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];
@@ -200,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];
@@ -210,16 +263,123 @@ 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(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
static const char *const optionStrings[] = {
"press", "release", "flagschanged", NULL};
NSUInteger types[3] = {NSKeyDown, NSKeyUp, NSFlagsChanged};
static const char *const argStrings[] = {
"-shift", "-control", "-option", "-command", "-function", "-x", "-y", NULL};
enum args {KEYEVENT_SHIFT, KEYEVENT_CONTROL, KEYEVENT_OPTION, KEYEVENT_COMMAND,
KEYEVENT_FUNCTION, KEYEVENT_X, KEYEVENT_Y};
int i, index, keysym, mods = 0, x = 0, y = 0;
NSString *chars = nil, *unmod = nil, *upper, *lower;
NSEvent *keyEvent;
NSUInteger type;
MacKeycode macKC;
if (objc < 3) {
wrongArgs:
Tcl_WrongNumArgs(interp, 1, objv, "option keysym ?arg?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
type = types[index];
if (Tcl_GetIntFromObj(interp, objv[2], &keysym) != TCL_OK) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"keysym must be an integer"));
Tcl_SetErrorCode(interp, "TK", "TEST", "INJECT", "KEYSYM", NULL);
return TCL_ERROR;
}
macKC.uint = XKeysymToKeycode(NULL, keysym);
for (i = 3; i < objc; i++) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i], argStrings,
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum args) index) {
case KEYEVENT_SHIFT:
mods |= NSShiftKeyMask;
break;
case KEYEVENT_CONTROL:
mods |= NSControlKeyMask;
break;
case KEYEVENT_OPTION:
mods |= NSAlternateKeyMask;
break;
case KEYEVENT_COMMAND:
mods |= NSCommandKeyMask;
break;
case KEYEVENT_FUNCTION:
mods |= NSFunctionKeyMask;
break;
case KEYEVENT_X:
if (++i >= objc) {
goto wrongArgs;
}
if (Tcl_GetIntFromObj(interp,objv[i], &x) != TCL_OK) {
return TCL_ERROR;
}
break;
case KEYEVENT_Y:
if (++i >= objc) {
goto wrongArgs;
}
if (Tcl_GetIntFromObj(interp,objv[i], &y) != TCL_OK) {
return TCL_ERROR;
}
break;
}
}
if (type != NSFlagsChanged) {
UniChar keychar = macKC.v.keychar;
chars = [[NSString alloc] initWithCharacters: &keychar length:1];
upper = [chars uppercaseString];
lower = [chars lowercaseString];
if (![upper isEqual: lower] && [chars isEqual: upper]) {
mods |= NSShiftKeyMask;
}
if (mods & NSShiftKeyMask) {
chars = upper;
unmod = lower;
macKC.v.o_s |= INDEX_SHIFT;
} else {
unmod = chars;
}
if (macKC.v.o_s & INDEX_OPTION) {
mods |= NSAlternateKeyMask;
}
}
keyEvent = [NSEvent keyEventWithType:type
location:NSMakePoint(x, y)
modifierFlags:mods
timestamp:GetCurrentEventTime()
windowNumber:0
context:nil
characters:chars
charactersIgnoringModifiers:unmod
isARepeat:NO
keyCode:macKC.v.virtual];
[NSApp postEvent:keyEvent atStart:NO];
return TCL_OK;
}
/*
* Local Variables:
* mode: objc

View File

@@ -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.
*/
/*
* Propagate geometry changes immediately.
*/
flags |= TK_MACOSX_HANDLE_EVENT_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,31 +111,29 @@ 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);
}
}
- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
defaultFrame:(NSRect)newFrame
{
(void)window;
/*
* This method needs to be implemented in order for [NSWindow isZoomed] to
* give the correct answer. But it suffices to always validate every
@@ -151,6 +146,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
- (NSSize)window:(NSWindow *)window
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
@@ -185,7 +182,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
Tk_UnmapWindow((Tk_Window) winPtr);
Tk_UnmapWindow((Tk_Window)winPtr);
}
}
@@ -197,7 +194,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
TkGenWMDestroyEvent((Tk_Window) winPtr);
TkGenWMDestroyEvent((Tk_Window)winPtr);
}
/*
@@ -208,6 +205,34 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
return (winPtr ? NO : YES);
}
- (void) windowBecameVisible: (NSNotification *) notification
{
NSWindow *window = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(window);
if (winPtr) {
TKContentView *view = [window contentView];
#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
{
NSWindow *w = [notification object];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}
}
}
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
- (void) windowDragStart: (NSNotification *) notification
@@ -221,22 +246,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
//BOOL start = [[notification name] isEqualToString:NSWindowWillStartLiveResizeNotification];
}
- (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);
}
}
- (void) windowBecameVisible: (NSNotification *) notification
{
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
}
- (void) windowUnmapped: (NSNotification *) notification
{
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
@@ -244,7 +253,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
if (winPtr) {
//Tk_UnmapWindow((Tk_Window) winPtr);
//Tk_UnmapWindow((Tk_Window)winPtr);
}
}
@@ -263,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:);
@@ -273,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
@@ -288,6 +297,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
- (void) applicationActivate: (NSNotification *) notification
{
(void)notification;
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
@@ -312,14 +323,33 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
- (void) applicationDeactivate: (NSNotification *) notification
{
(void)notification;
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
/*
* To prevent zombie windows on systems with a TouchBar, set the key window
* to nil if the current key window is not visible. This allows a closed
* Help or About window to be deallocated so it will not reappear as a
* zombie when the app is reactivated.
*/
NSWindow *keywindow = [NSApp keyWindow];
if (keywindow && ![keywindow isVisible]) {
[NSApp _setKeyWindow:nil];
[NSApp _setMainWindow:nil];
}
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender
hasVisibleWindows:(BOOL)flag
{
(void)sender;
(void)flag;
/*
* Allowing the default response means that withdrawn windows will get
* displayed on the screen with unresponsive title buttons. We don't
@@ -352,6 +382,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
- (void) displayChanged: (NSNotification *) notification
{
(void)notification;
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
@@ -368,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;
}
/*
@@ -395,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);
@@ -457,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
@@ -470,7 +513,7 @@ GenerateUpdates(
if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
continue;
}
GenerateUpdates(updateRgn, updateBounds, childPtr);
GenerateUpdates(updateBounds, childPtr);
}
/*
@@ -480,7 +523,7 @@ GenerateUpdates(
if (Tk_IsContainer(winPtr)) {
childPtr = TkpGetOtherWindow(winPtr);
if (childPtr != NULL && Tk_IsMapped(childPtr)) {
GenerateUpdates(updateRgn, updateBounds, childPtr);
GenerateUpdates(updateBounds, childPtr);
}
/*
@@ -491,58 +534,6 @@ GenerateUpdates(
return 1;
}
/*
*----------------------------------------------------------------------
*
* 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);
}
/*
*----------------------------------------------------------------------
*
@@ -555,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)
@@ -599,6 +590,35 @@ TkMacOSXGenerateFocusEvent(
return true;
}
/*
*----------------------------------------------------------------------
*
* 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;
}
/*
*----------------------------------------------------------------------
*
@@ -713,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.
@@ -804,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);
@@ -818,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);
}
}
@@ -887,47 +907,38 @@ ExposeRestrictProc(
static Tk_RestrictAction
ConfigureRestrictProc(
ClientData arg,
TCL_UNUSED(void *),
XEvent *eventPtr)
{
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.
*/
for (NSWindow *w in [NSApp orderedWindows]) {
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
/*
@@ -936,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");
@@ -978,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)]) {
@@ -1023,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.
@@ -1046,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;
@@ -1059,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);
/*
@@ -1090,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;
if (!winPtr) {
Tk_Window tkwin = (Tk_Window)TkMacOSXGetTkWindow([self window]);
if (!tkwin) {
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");
NSAppearanceName effectiveAppearanceName = [[self effectiveAppearance] name];
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
static const char *defaultColor = NULL;
if (effectiveAppearanceName == NSAppearanceNameAqua) {
TkSendVirtualEvent(tkwin, "LightAqua", NULL);
} else if (effectiveAppearanceName == NSAppearanceNameDarkAqua) {
TkSendVirtualEvent(tkwin, "DarkAqua", NULL);
}
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
if ([NSApp macOSVersion] < 101500) {
/*
* Mojave cannot handle the KVO shenanigans that we need for the
* highlight and accent color notifications.
*/
return;
}
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];
}
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);
TkSendVirtualEvent(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.
@@ -1148,7 +1191,9 @@ 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){
return;
}
@@ -1169,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
{
@@ -1193,6 +1236,8 @@ RedisplayView(
- (void) keyDown: (NSEvent *) theEvent
{
(void)theEvent;
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
@@ -1200,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.
*/

File diff suppressed because it is too large Load Diff

View File

@@ -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,6 +46,7 @@ typedef struct Transient {
struct Transient *nextPtr;
} Transient;
#define WITHDRAWN_BY_CONTAINER 0x1
#define WITHDRAWN_BY_MASTER 0x1
/*
@@ -65,8 +66,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

View File

@@ -201,8 +201,8 @@ TkpOpenDisplay(
}
}
display = ckalloc(sizeof(Display));
screen = ckalloc(sizeof(Screen));
display = (Display *)ckalloc(sizeof(Display));
screen = (Screen *)ckalloc(sizeof(Screen));
bzero(display, sizeof(Display));
bzero(screen, sizeof(Screen));
@@ -250,11 +250,11 @@ TkpOpenDisplay(
*/
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 = ckalloc(sizeof(Visual));
screen->root_visual = (Visual *)ckalloc(sizeof(Visual));
screen->root_visual->visualid = 0;
screen->root_visual->c_class = TrueColor;
screen->root_visual->red_mask = 0x00FF0000;
@@ -269,7 +269,7 @@ TkpOpenDisplay(
TkMacOSXDisplayChanged(display);
gMacDisplay = ckalloc(sizeof(TkDisplay));
gMacDisplay = (TkDisplay *)ckalloc(sizeof(TkDisplay));
/*
* This is the quickest way to make sure that all the *Init flags get
@@ -387,7 +387,7 @@ TkClipCleanup(
static XID
MacXIdAlloc(
Display *display) /* Display for which to allocate. */
TCL_UNUSED(Display *)) /* Display for which to allocate. */
{
static long int cur_id = 100;
/*
@@ -417,8 +417,8 @@ MacXIdAlloc(
static int
DefaultErrorHandler(
Display* display,
XErrorEvent* err_evt)
TCL_UNUSED(Display *),
TCL_UNUSED(XErrorEvent *))
{
/*
* This call should never be called. Tk replaces it with its own error
@@ -431,8 +431,8 @@ DefaultErrorHandler(
char *
XGetAtomName(
Display * display,
Atom atom)
Display *display,
TCL_UNUSED(Atom))
{
display->request++;
return NULL;
@@ -440,7 +440,7 @@ XGetAtomName(
XErrorHandler
XSetErrorHandler(
XErrorHandler handler)
TCL_UNUSED(XErrorHandler))
{
return DefaultErrorHandler;
}
@@ -448,7 +448,7 @@ XSetErrorHandler(
Window
XRootWindow(
Display *display,
int screen_number)
TCL_UNUSED(int))
{
display->request++;
return ROOT_ID;
@@ -466,7 +466,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;
@@ -478,7 +478,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;
@@ -491,14 +491,14 @@ XGetGeometry(
int
XChangeProperty(
Display* display,
Window w,
Atom property,
Atom type,
int format,
int mode,
_Xconst unsigned char* data,
int nelements)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(Atom),
TCL_UNUSED(Atom),
TCL_UNUSED(int),
TCL_UNUSED(int),
TCL_UNUSED(_Xconst unsigned char *),
TCL_UNUSED(int))
{
Debugger();
return Success;
@@ -506,9 +506,9 @@ XChangeProperty(
int
XSelectInput(
Display* display,
Window w,
long event_mask)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(long))
{
Debugger();
return Success;
@@ -516,40 +516,16 @@ XSelectInput(
int
XBell(
Display* display,
int percent)
TCL_UNUSED(Display *),
TCL_UNUSED(int))
{
NSBeep();
return Success;
}
#if 0
void
XSetWMNormalHints(
Display* display,
Window w,
XSizeHints* hints)
{
/*
* Do nothing. Shouldn't even be called.
*/
}
XSizeHints *
XAllocSizeHints(void)
{
/*
* Always return NULL. Tk code checks to see if NULL is returned & does
* nothing if it is.
*/
return NULL;
}
#endif
GContext
XGContextFromGC(
GC gc)
TCL_UNUSED(GC))
{
/*
* TODO: currently a no-op
@@ -560,11 +536,11 @@ XGContextFromGC(
Status
XSendEvent(
Display* display,
Window w,
Bool propagate,
long event_mask,
XEvent* event_send)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(Bool),
TCL_UNUSED(long),
TCL_UNUSED(XEvent *))
{
Debugger();
return 0;
@@ -572,56 +548,31 @@ XSendEvent(
int
XClearWindow(
Display* display,
Window w)
TCL_UNUSED(Display *),
TCL_UNUSED(Window))
{
return Success;
}
/*
int
XDrawPoint(
Display* display,
Drawable d,
GC gc,
int x,
int y)
{
return Success;
}
int
XDrawPoints(
Display* display,
Drawable d,
GC gc,
XPoint* points,
int npoints,
int mode)
{
return Success;
}
*/
int
XWarpPointer(
Display* display,
Window src_w,
Window dest_w,
int src_x,
int src_y,
unsigned int src_width,
unsigned int src_height,
int dest_x,
int dest_y)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(Window),
TCL_UNUSED(int),
TCL_UNUSED(int),
TCL_UNUSED(unsigned int),
TCL_UNUSED(unsigned int),
TCL_UNUSED(int),
TCL_UNUSED(int))
{
return Success;
}
int
XQueryColor(
Display* display,
Colormap colormap,
TCL_UNUSED(Display *),
TCL_UNUSED(Colormap),
XColor* def_in_out)
{
unsigned long p;
@@ -642,8 +593,8 @@ XQueryColor(
int
XQueryColors(
Display* display,
Colormap colormap,
TCL_UNUSED(Display *),
TCL_UNUSED(Colormap),
XColor* defs_in_out,
int ncolors)
{
@@ -667,14 +618,13 @@ XQueryColors(
}
int
XQueryTree(display, w, root_return, parent_return, children_return,
nchildren_return)
Display* display;
Window w;
Window* root_return;
Window* parent_return;
Window** children_return;
unsigned int* nchildren_return;
XQueryTree(
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(Window *),
TCL_UNUSED(Window *),
TCL_UNUSED(Window **),
TCL_UNUSED(unsigned int *))
{
return 0;
}
@@ -683,17 +633,17 @@ XQueryTree(display, w, root_return, parent_return, children_return,
int
XGetWindowProperty(
Display *display,
Window w,
Atom property,
long long_offset,
long long_length,
Bool delete,
Atom req_type,
TCL_UNUSED(Window),
TCL_UNUSED(Atom),
TCL_UNUSED(long),
TCL_UNUSED(long),
TCL_UNUSED(Bool),
TCL_UNUSED(Atom),
Atom *actual_type_return,
int *actual_format_return,
unsigned long *nitems_return,
unsigned long *bytes_after_return,
unsigned char ** prop_return)
TCL_UNUSED(unsigned char **))
{
display->request++;
*actual_type_return = None;
@@ -704,7 +654,7 @@ XGetWindowProperty(
int
XRefreshKeyboardMapping(
XMappingEvent *x)
TCL_UNUSED(XMappingEvent *))
{
/* used by tkXEvent.c */
Debugger();
@@ -714,8 +664,8 @@ XRefreshKeyboardMapping(
int
XSetIconName(
Display* display,
Window w,
const char *icon_name)
TCL_UNUSED(Window),
TCL_UNUSED(const char *))
{
/*
* This is a no-op, no icon name for Macs.
@@ -727,7 +677,7 @@ XSetIconName(
int
XForceScreenSaver(
Display* display,
int mode)
TCL_UNUSED(int))
{
/*
* This function is just a no-op. It is defined to reset the screen saver.
@@ -741,8 +691,8 @@ XForceScreenSaver(
void
Tk_FreeXId(
Display *display,
XID xid)
TCL_UNUSED(Display *),
TCL_UNUSED(XID))
{
/* no-op function needed for stubs implementation. */
}
@@ -750,14 +700,24 @@ Tk_FreeXId(
int
XSync(
Display *display,
Bool discard)
TCL_UNUSED(Bool))
{
TkMacOSXFlushWindows();
/*
* 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.
*/
while (Tcl_DoOneEvent(TCL_TIMER_EVENTS|TCL_DONT_WAIT)){}
display->request++;
return 0;
}
#if 0
int
XSetClipRectangles(
Display *d,
@@ -771,19 +731,17 @@ XSetClipRectangles(
TkRegion clipRgn = TkCreateRegion();
while (n--) {
XRectangle rect = *rectangles;
XRectangle rect = *rectangles;
rect.x += clip_x_origin;
rect.y += clip_y_origin;
TkUnionRectWithRegion(&rect, clipRgn, clipRgn);
rectangles++;
rect.x += clip_x_origin;
rect.y += clip_y_origin;
TkUnionRectWithRegion(&rect, clipRgn, clipRgn);
rectangles++;
}
TkSetRegion(d, gc, clipRgn);
TkDestroyRegion(clipRgn);
return 1;
}
#endif
/*
*----------------------------------------------------------------------
*
@@ -842,64 +800,64 @@ TkGetServerInfo(
int
XChangeWindowAttributes(
Display *display,
Window w,
unsigned long value_mask,
XSetWindowAttributes *attributes)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(unsigned long),
TCL_UNUSED(XSetWindowAttributes *))
{
return Success;
}
int
XSetWindowBackground(
Display *display,
Window window,
unsigned long value)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(unsigned long))
{
return Success;
}
int
XSetWindowBackgroundPixmap(
Display *display,
Window w,
Pixmap background_pixmap)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(Pixmap))
{
return Success;
}
int
XSetWindowBorder(
Display *display,
Window w,
unsigned long border_pixel)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(unsigned long))
{
return Success;
}
int
XSetWindowBorderPixmap(
Display *display,
Window w,
Pixmap border_pixmap)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(Pixmap))
{
return Success;
}
int
XSetWindowBorderWidth(
Display *display,
Window w,
unsigned int width)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(unsigned int))
{
return Success;
}
int
XSetWindowColormap(
Display *display,
Window w,
Colormap colormap)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(Colormap))
{
Debugger();
return Success;
@@ -907,25 +865,25 @@ XSetWindowColormap(
Status
XStringListToTextProperty(
char **list,
int count,
XTextProperty *text_prop_return)
TCL_UNUSED(char **),
TCL_UNUSED(int),
TCL_UNUSED(XTextProperty *))
{
Debugger();
return (Status) 0;
return Success;
}
void
XSetWMClientMachine(
Display *display,
Window w,
XTextProperty *text_prop)
TCL_UNUSED(Display *),
TCL_UNUSED(Window),
TCL_UNUSED(XTextProperty *))
{
Debugger();
}
XIC
XCreateIC(XIM xim, ...)
XCreateIC(TCL_UNUSED(XIM), ...)
{
Debugger();
return (XIC) 0;
@@ -943,16 +901,16 @@ XVisualIDFromVisual(
XAfterFunction
XSynchronize(
Display *display,
Bool onoff)
TCL_UNUSED(Bool))
{
display->request++;
display->request++;
return NULL;
}
#undef XUngrabServer
int
XUngrabServer(
Display *display)
TCL_UNUSED(Display *))
{
return 0;
}
@@ -969,7 +927,7 @@ XNoOp(
#undef XGrabServer
int
XGrabServer(
Display *display)
TCL_UNUSED(Display *))
{
return 0;
}
@@ -987,7 +945,7 @@ XFree(
#undef XFlush
int
XFlush(
Display *display)
TCL_UNUSED(Display *))
{
return 0;
}
@@ -1011,7 +969,7 @@ XFlush(
const char *
TkGetDefaultScreenName(
Tcl_Interp *interp, /* Not used. */
TCL_UNUSED(Tcl_Interp *),
const char *screenName) /* If NULL, use default string. */
{
if ((screenName == NULL) || (screenName[0] == '\0')) {
@@ -1038,7 +996,7 @@ TkGetDefaultScreenName(
long
Tk_GetUserInactiveTime(
Display *dpy)
TCL_UNUSED(Display *))
{
io_registry_entry_t regEntry;
CFMutableDictionaryRef props = NULL;
@@ -1047,7 +1005,7 @@ Tk_GetUserInactiveTime(
uint64_t time;
IOReturn result;
regEntry = IOServiceGetMatchingService(kIOMasterPortDefault,
regEntry = IOServiceGetMatchingService(0,
IOServiceMatching("IOHIDSystem"));
if (regEntry == 0) {
@@ -1104,7 +1062,7 @@ Tk_GetUserInactiveTime(
void
Tk_ResetUserInactiveTime(
Display *dpy)
TCL_UNUSED(Display *))
{
lastInactivityReset = TkpGetMS();
}

File diff suppressed because it is too large Load Diff