Imported Tk 8.6.9
This commit is contained in:
@@ -561,3 +561,12 @@ source and destination rectangles for the scrolling. The embedded
|
||||
windows are redrawn within the DisplayText function by some
|
||||
conditional code which is only used for macOS.
|
||||
|
||||
5.0 Virtual events on 10.14
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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.
|
||||
|
||||
@@ -42,5 +42,5 @@ TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION)
|
||||
TCL_PACKAGE_PATH = "$(LIBDIR)"
|
||||
TCL_DEFS = HAVE_TCL_CONFIG_H
|
||||
TK_LIBRARY = $(LIBDIR)/tk$(VERSION)
|
||||
TK_DEFS = HAVE_TK_CONFIG_H TCL_NO_DEPRECATED
|
||||
TK_DEFS = HAVE_TK_CONFIG_H
|
||||
VERSION = 8.6
|
||||
|
||||
127
macosx/configure
vendored
127
macosx/configure
vendored
@@ -2287,7 +2287,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
TK_VERSION=8.6
|
||||
TK_MAJOR_VERSION=8
|
||||
TK_MINOR_VERSION=6
|
||||
TK_PATCH_LEVEL=".8"
|
||||
TK_PATCH_LEVEL=".9"
|
||||
VERSION=${TK_VERSION}
|
||||
LOCALES="cs da de el en en_gb eo es fr hu it nl pl pt ru sv"
|
||||
|
||||
@@ -2376,11 +2376,13 @@ $as_echo "$as_me: WARNING: --with-tcl argument should refer to directory contain
|
||||
for i in `ls -d ${libdir} 2>/dev/null` \
|
||||
`ls -d ${exec_prefix}/lib 2>/dev/null` \
|
||||
`ls -d ${prefix}/lib 2>/dev/null` \
|
||||
`ls -d /usr/contrib/lib 2>/dev/null` \
|
||||
`ls -d /usr/local/lib 2>/dev/null` \
|
||||
`ls -d /usr/contrib/lib 2>/dev/null` \
|
||||
`ls -d /usr/pkg/lib 2>/dev/null` \
|
||||
`ls -d /usr/lib 2>/dev/null` \
|
||||
`ls -d /usr/lib64 2>/dev/null` \
|
||||
`ls -d /usr/local/lib/tcl8.6 2>/dev/null` \
|
||||
`ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \
|
||||
; do
|
||||
if test -f "$i/tclConfig.sh" ; then
|
||||
ac_cv_c_tclconfig="`(cd $i; pwd)`"
|
||||
@@ -4944,7 +4946,7 @@ $as_echo "$ac_cv_cygwin" >&6; }
|
||||
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
|
||||
SHLIB_CFLAGS="-fPIC"
|
||||
SHLIB_SUFFIX=".so"
|
||||
SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
|
||||
SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
|
||||
DL_OBJS="tclLoadDl.o"
|
||||
DL_LIBS="-lroot"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5
|
||||
@@ -5266,7 +5268,7 @@ fi
|
||||
# get rid of the warnings.
|
||||
#CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES"
|
||||
|
||||
SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
|
||||
SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared'
|
||||
DL_OBJS="tclLoadDl.o"
|
||||
DL_LIBS="-ldl"
|
||||
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
|
||||
@@ -5374,7 +5376,7 @@ fi
|
||||
SHLIB_CFLAGS="-fpic"
|
||||
;;
|
||||
esac
|
||||
SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
|
||||
SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
|
||||
SHLIB_SUFFIX=".so"
|
||||
DL_OBJS="tclLoadDl.o"
|
||||
DL_LIBS=""
|
||||
@@ -5401,7 +5403,7 @@ fi
|
||||
NetBSD-*)
|
||||
# NetBSD has ELF and can use 'cc -shared' to build shared libs
|
||||
SHLIB_CFLAGS="-fPIC"
|
||||
SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
|
||||
SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared'
|
||||
SHLIB_SUFFIX=".so"
|
||||
DL_OBJS="tclLoadDl.o"
|
||||
DL_LIBS=""
|
||||
@@ -5420,7 +5422,7 @@ fi
|
||||
|
||||
fi
|
||||
;;
|
||||
FreeBSD-*)
|
||||
DragonFly-*|FreeBSD-*)
|
||||
# This configuration from FreeBSD Ports.
|
||||
SHLIB_CFLAGS="-fPIC"
|
||||
SHLIB_LD="${CC} -shared"
|
||||
@@ -6236,7 +6238,7 @@ fi
|
||||
BSD/OS*) ;;
|
||||
CYGWIN_*|MINGW32_*) ;;
|
||||
IRIX*) ;;
|
||||
NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
|
||||
NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
|
||||
Darwin-*) ;;
|
||||
SCO_SV-3.2*) ;;
|
||||
*) SHLIB_CFLAGS="-fPIC" ;;
|
||||
@@ -6702,6 +6704,40 @@ $as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DIR64" >&5
|
||||
$as_echo_n "checking for DIR64... " >&6; }
|
||||
if ${tcl_cv_DIR64+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
struct dirent64 *p; DIR64 d = opendir64(".");
|
||||
p = readdir64(d); rewinddir64(d); closedir64(d);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
tcl_cv_DIR64=yes
|
||||
else
|
||||
tcl_cv_DIR64=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5
|
||||
$as_echo "$tcl_cv_DIR64" >&6; }
|
||||
if test "x${tcl_cv_DIR64}" = "xyes" ; then
|
||||
|
||||
$as_echo "#define HAVE_DIR64 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5
|
||||
$as_echo_n "checking for struct stat64... " >&6; }
|
||||
if ${tcl_cv_struct_stat64+:} false; then :
|
||||
@@ -7162,81 +7198,6 @@ $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
|
||||
fi
|
||||
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Under Solaris 2.4, strtod returns the wrong value for the
|
||||
# terminating character under some conditions. Check for this
|
||||
# and if the problem exists use a substitute procedure
|
||||
# "fixstrtod" (provided by Tcl) that corrects the error.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "strtod" "ac_cv_func_strtod"
|
||||
if test "x$ac_cv_func_strtod" = xyes; then :
|
||||
tcl_strtod=1
|
||||
else
|
||||
tcl_strtod=0
|
||||
fi
|
||||
|
||||
if test "$tcl_strtod" = 1; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris2.4/Tru64 strtod bugs" >&5
|
||||
$as_echo_n "checking for Solaris2.4/Tru64 strtod bugs... " >&6; }
|
||||
if ${tcl_cv_strtod_buggy+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
|
||||
if test "$cross_compiling" = yes; then :
|
||||
tcl_cv_strtod_buggy=buggy
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
extern double strtod();
|
||||
int main() {
|
||||
char *infString="Inf", *nanString="NaN", *spaceString=" ";
|
||||
char *term;
|
||||
double value;
|
||||
value = strtod(infString, &term);
|
||||
if ((term != infString) && (term[-1] == 0)) {
|
||||
exit(1);
|
||||
}
|
||||
value = strtod(nanString, &term);
|
||||
if ((term != nanString) && (term[-1] == 0)) {
|
||||
exit(1);
|
||||
}
|
||||
value = strtod(spaceString, &term);
|
||||
if (term == (spaceString+1)) {
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_run "$LINENO"; then :
|
||||
tcl_cv_strtod_buggy=ok
|
||||
else
|
||||
tcl_cv_strtod_buggy=buggy
|
||||
fi
|
||||
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
|
||||
conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_strtod_buggy" >&5
|
||||
$as_echo "$tcl_cv_strtod_buggy" >&6; }
|
||||
if test "$tcl_cv_strtod_buggy" = buggy; then
|
||||
case " $LIBOBJS " in
|
||||
*" fixstrtod.$ac_objext "* ) ;;
|
||||
*) LIBOBJS="$LIBOBJS fixstrtod.$ac_objext"
|
||||
;;
|
||||
esac
|
||||
|
||||
USE_COMPAT=1
|
||||
|
||||
$as_echo "#define strtod fixstrtod" >>confdefs.h
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check for various typedefs and provide substitutes if
|
||||
# they don't exist.
|
||||
|
||||
@@ -21,19 +21,16 @@
|
||||
#include "tkMacOSXFont.h"
|
||||
#include "tkMacOSXDebug.h"
|
||||
|
||||
|
||||
#define FIRST_DRAW 2
|
||||
#define ACTIVE 4
|
||||
|
||||
|
||||
/*
|
||||
* Default insets for controls
|
||||
* Extra padding used for computing the content size that should
|
||||
* be allowed when drawing the HITheme button.
|
||||
*/
|
||||
|
||||
#define DEF_INSET_LEFT 12
|
||||
#define DEF_INSET_RIGHT 12
|
||||
#define DEF_INSET_TOP 1
|
||||
#define DEF_INSET_BOTTOM 1
|
||||
#define HI_PADX 2
|
||||
#define HI_PADY 1
|
||||
|
||||
/*
|
||||
* Some defines used to control what type of control is drawn.
|
||||
@@ -318,9 +315,8 @@ TkpComputeButtonGeometry(
|
||||
Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength,
|
||||
butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
|
||||
|
||||
/*Remove extraneous padding around label widgets.*/
|
||||
txtWidth = butPtr->textWidth;
|
||||
txtHeight = butPtr->textHeight + DEF_INSET_BOTTOM + DEF_INSET_TOP;
|
||||
txtHeight = butPtr->textHeight;
|
||||
charWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
|
||||
Tk_GetFontMetrics(butPtr->tkfont, &fm);
|
||||
haveText = (txtWidth != 0 && txtHeight != 0);
|
||||
@@ -364,8 +360,7 @@ TkpComputeButtonGeometry(
|
||||
height = butPtr->height > 0 ? butPtr->height : height;
|
||||
|
||||
} else { /* Text only */
|
||||
/*Add four pixels of padding to width for text-only buttons to improve appearance.*/
|
||||
width = txtWidth + butPtr->indicatorSpace + 4;
|
||||
width = txtWidth + butPtr->indicatorSpace;
|
||||
height = txtHeight;
|
||||
if (butPtr->width > 0) {
|
||||
width = butPtr->width * charWidth;
|
||||
@@ -396,7 +391,7 @@ TkpComputeButtonGeometry(
|
||||
int paddingx = 0;
|
||||
int paddingy = 0;
|
||||
|
||||
tmpRect = CGRectMake(0, 0, width, height);
|
||||
tmpRect = CGRectMake(0, 0, width + 2*HI_PADX, height + 2*HI_PADY);
|
||||
|
||||
HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);
|
||||
/* If the content region has a minimum height, match it. */
|
||||
@@ -425,6 +420,9 @@ TkpComputeButtonGeometry(
|
||||
|
||||
width += butPtr->inset*2;
|
||||
height += butPtr->inset*2;
|
||||
if ([NSApp macMinorVersion] == 6) {
|
||||
width += 12;
|
||||
}
|
||||
|
||||
Tk_GeometryRequest(butPtr->tkwin, width, height);
|
||||
Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
|
||||
@@ -649,7 +647,7 @@ DrawButtonImageAndText(
|
||||
butPtr->textHeight, &x, &y);
|
||||
x += butPtr->indicatorSpace;
|
||||
Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout,
|
||||
x, y - DEF_INSET_BOTTOM, 0, -1);
|
||||
x, y, 0, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -786,19 +784,6 @@ TkMacOSXDrawButton(
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (mbPtr->btnkind == kThemePushButton) {
|
||||
/*
|
||||
* For some reason, pushbuttons get drawn a bit
|
||||
* too low, normally. Correct for this.
|
||||
*/
|
||||
if (cntrRect.size.height < 22) {
|
||||
cntrRect.origin.y -= 1;
|
||||
} else if (cntrRect.size.height < 23) {
|
||||
cntrRect.origin.y -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
hiinfo.version = 0;
|
||||
hiinfo.state = mbPtr->drawinfo.state;
|
||||
hiinfo.kind = mbPtr->btnkind;
|
||||
@@ -910,7 +895,10 @@ ButtonContentDrawCB (
|
||||
return;
|
||||
}
|
||||
|
||||
/*Overlay Tk elements over button native region: drawing elements within button boundaries/native region causes unpredictable metrics.*/
|
||||
/*
|
||||
* Overlay Tk elements over button native region: drawing elements
|
||||
* within button boundaries/native region causes unpredictable metrics.
|
||||
*/
|
||||
DrawButtonImageAndText( butPtr);
|
||||
}
|
||||
|
||||
@@ -1213,3 +1201,11 @@ PulseDefaultButtonProc(ClientData clientData)
|
||||
PULSE_TIMER_MSECS, PulseDefaultButtonProc, clientData);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 79
|
||||
* coding: utf-8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "tkMacOSXPrivate.h"
|
||||
#include "tkMacOSXConstants.h"
|
||||
#include "tkSelect.h"
|
||||
|
||||
static NSInteger changeCount = -1;
|
||||
@@ -70,10 +71,8 @@ static Tk_Window clipboardOwner = NULL;
|
||||
if (clipboardOwner && [[NSPasteboard generalPasteboard] changeCount] !=
|
||||
changeCount) {
|
||||
TkDisplay *dispPtr = TkGetDisplayList();
|
||||
|
||||
if (dispPtr) {
|
||||
XEvent event;
|
||||
|
||||
event.xany.type = SelectionClear;
|
||||
event.xany.serial = NextRequest(Tk_Display(clipboardOwner));
|
||||
event.xany.send_event = False;
|
||||
@@ -125,8 +124,10 @@ TkSelGetSelection(
|
||||
int result = TCL_ERROR;
|
||||
TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
|
||||
|
||||
if (dispPtr && selection == dispPtr->clipboardAtom && (target == XA_STRING
|
||||
|| target == dispPtr->utf8Atom)) {
|
||||
int haveExternalClip = ([[NSPasteboard generalPasteboard] changeCount] != changeCount);
|
||||
if (dispPtr && (haveExternalClip || dispPtr->clipboardActive)
|
||||
&& selection == dispPtr->clipboardAtom
|
||||
&& (target == XA_STRING || target == dispPtr->utf8Atom)) {
|
||||
NSString *string = nil;
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
NSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject:
|
||||
@@ -176,7 +177,6 @@ XSetSelectionOwner(
|
||||
clipboardOwner = owner ? Tk_IdToWindow(display, owner) : NULL;
|
||||
if (!dispPtr->clipboardActive) {
|
||||
NSPasteboard *pb = [NSPasteboard generalPasteboard];
|
||||
|
||||
changeCount = [pb declareTypes:[NSArray array] owner:NSApp];
|
||||
}
|
||||
}
|
||||
@@ -289,28 +289,6 @@ TkSelPropProc(
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkSuspendClipboard --
|
||||
*
|
||||
* Handle clipboard conversion as required by the suppend event.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The local scrap is moved to the global scrap.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
TkSuspendClipboard(void)
|
||||
{
|
||||
changeCount = [[NSPasteboard generalPasteboard] changeCount];
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
|
||||
@@ -41,3 +41,12 @@ TkpGetSystemDefault(
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 79
|
||||
* coding: utf-8
|
||||
* End:
|
||||
*/
|
||||
|
||||
121
macosx/tkMacOSXConstants.h
Normal file
121
macosx/tkMacOSXConstants.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* tkMacOSXConstants.h --
|
||||
*
|
||||
* Macros which map the names of NS constants used in the Tk code to
|
||||
* the new name that Apple came up with for subsequent versions of the
|
||||
* operating system. (Each new OS release seems to come with a new
|
||||
* naming convention for the same old constants.)
|
||||
*
|
||||
* Copyright (c) 2017 Marc Culler
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#ifndef _TKMACCONSTANTS
|
||||
#define _TKMACCONSTANTS
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
|
||||
#define NSFullScreenWindowMask (1 << 14)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Let's raise a glass for the project manager who improves our lives by
|
||||
* generating deprecation warnings about pointless changes of the names
|
||||
* of constants.
|
||||
*/
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
|
||||
#define kCTFontDefaultOrientation kCTFontOrientationDefault
|
||||
#define kCTFontVerticalOrientation kCTFontOrientationVertical
|
||||
#endif
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
|
||||
#define NSOKButton NSModalResponseOK
|
||||
#endif
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
|
||||
#define kCTFontUserFixedPitchFontType kCTFontUIFontUserFixedPitch
|
||||
#endif
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
||||
#define NSAppKitDefined NSEventTypeAppKitDefined
|
||||
#define NSApplicationDefined NSEventTypeApplicationDefined
|
||||
#define NSApplicationActivatedEventType NSEventSubtypeApplicationActivated
|
||||
#define NSApplicationDeactivatedEventType NSEventSubtypeApplicationDeactivated
|
||||
#define NSWindowExposedEventType NSEventSubtypeWindowExposed
|
||||
#define NSScreenChangedEventType NSEventSubtypeScreenChanged
|
||||
#define NSWindowMovedEventType NSEventSubtypeWindowMoved
|
||||
#define NSKeyUp NSEventTypeKeyUp
|
||||
#define NSKeyDown NSEventTypeKeyDown
|
||||
#define NSFlagsChanged NSEventTypeFlagsChanged
|
||||
#define NSLeftMouseDown NSEventTypeLeftMouseDown
|
||||
#define NSLeftMouseUp NSEventTypeLeftMouseUp
|
||||
#define NSRightMouseDown NSEventTypeRightMouseDown
|
||||
#define NSRightMouseUp NSEventTypeRightMouseUp
|
||||
#define NSLeftMouseDragged NSEventTypeLeftMouseDragged
|
||||
#define NSRightMouseDragged NSEventTypeRightMouseDragged
|
||||
#define NSMouseMoved NSEventTypeMouseMoved
|
||||
#define NSMouseEntered NSEventTypeMouseEntered
|
||||
#define NSMouseExited NSEventTypeMouseExited
|
||||
#define NSScrollWheel NSEventTypeScrollWheel
|
||||
#define NSOtherMouseDown NSEventTypeOtherMouseDown
|
||||
#define NSOtherMouseUp NSEventTypeOtherMouseUp
|
||||
#define NSOtherMouseDragged NSEventTypeOtherMouseDragged
|
||||
#define NSTabletPoint NSEventTypeTabletPoint
|
||||
#define NSTabletProximity NSEventTypeTabletProximity
|
||||
#define NSDeviceIndependentModifierFlagsMask NSEventModifierFlagDeviceIndependentFlagsMask
|
||||
#define NSCommandKeyMask NSEventModifierFlagCommand
|
||||
#define NSShiftKeyMask NSEventModifierFlagShift
|
||||
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
|
||||
#define NSAlternateKeyMask NSEventModifierFlagOption
|
||||
#define NSControlKeyMask NSEventModifierFlagControl
|
||||
#define NSNumericPadKeyMask NSEventModifierFlagNumericPad
|
||||
#define NSFunctionKeyMask NSEventModifierFlagFunction
|
||||
#define NSCursorUpdate NSEventTypeCursorUpdate
|
||||
#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground
|
||||
#define NSCompositeCopy NSCompositingOperationCopy
|
||||
#define NSWarningAlertStyle NSAlertStyleWarning
|
||||
#define NSInformationalAlertStyle NSAlertStyleInformational
|
||||
#define NSCriticalAlertStyle NSAlertStyleCritical
|
||||
#define NSCenterTextAlignment NSTextAlignmentCenter
|
||||
#define NSDeviceIndependentModifierFlagsMask NSEventModifierFlagDeviceIndependentFlagsMask
|
||||
#define NSCommandKeyMask NSEventModifierFlagCommand
|
||||
#define NSShiftKeyMask NSEventModifierFlagShift
|
||||
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
|
||||
#define NSAlternateKeyMask NSEventModifierFlagOption
|
||||
#define NSControlKeyMask NSEventModifierFlagControl
|
||||
#define NSNumericPadKeyMask NSEventModifierFlagNumericPad
|
||||
#define NSFunctionKeyMask NSEventModifierFlagFunction
|
||||
#define NSKeyUp NSEventTypeKeyUp
|
||||
#define NSKeyDown NSEventTypeKeyDown
|
||||
#define NSFlagsChanged NSEventTypeFlagsChanged
|
||||
#define NSAlphaShiftKeyMask NSEventModifierFlagCapsLock
|
||||
#define NSShiftKeyMask NSEventModifierFlagShift
|
||||
#define NSAnyEventMask NSEventMaskAny
|
||||
#define NSApplicationDefinedMask NSEventMaskApplicationDefined
|
||||
#define NSTexturedBackgroundWindowMask NSWindowStyleMaskTexturedBackground
|
||||
#define NSUtilityWindowMask NSWindowStyleMaskUtilityWindow
|
||||
#define NSNonactivatingPanelMask NSWindowStyleMaskNonactivatingPanel
|
||||
#define NSDocModalWindowMask NSWindowStyleMaskDocModalWindow
|
||||
#define NSHUDWindowMask NSWindowStyleMaskHUDWindow
|
||||
#define NSTitledWindowMask NSWindowStyleMaskTitled
|
||||
#define NSClosableWindowMask NSWindowStyleMaskClosable
|
||||
#define NSResizableWindowMask NSWindowStyleMaskResizable
|
||||
#define NSUnifiedTitleAndToolbarWindowMask NSWindowStyleMaskUnifiedTitleAndToolbar
|
||||
#define NSMiniaturizableWindowMask NSWindowStyleMaskMiniaturizable
|
||||
#define NSBorderlessWindowMask NSWindowStyleMaskBorderless
|
||||
#define NSFullScreenWindowMask NSWindowStyleMaskFullScreen
|
||||
#endif
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
|
||||
#define NSStringPboardType NSPasteboardTypeString
|
||||
#define NSOnState NSControlStateValueOn
|
||||
#define NSOffState NSControlStateValueOff
|
||||
// Now we are also changing names of methods!
|
||||
#define graphicsContextWithGraphicsPort graphicsContextWithCGContext
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -117,7 +117,7 @@ enum alertIconOptions {
|
||||
ICON_ERROR, ICON_INFO, ICON_QUESTION, ICON_WARNING
|
||||
};
|
||||
static const char *const alertButtonStrings[] = {
|
||||
"abort", "retry", "ignore", "ok", "cancel", "yes", "no", NULL
|
||||
"abort", "retry", "ignore", "ok", "cancel", "no", "yes", NULL
|
||||
};
|
||||
|
||||
static const NSString *const alertButtonNames[][3] = {
|
||||
@@ -147,8 +147,8 @@ static const short alertButtonIndexAndTypeToNativeButtonIndex[][7] = {
|
||||
[TYPE_OK] = {0, 0, 0, 1, 0, 0, 0},
|
||||
[TYPE_OKCANCEL] = {0, 0, 0, 1, 2, 0, 0},
|
||||
[TYPE_RETRYCANCEL] = {0, 1, 0, 0, 2, 0, 0},
|
||||
[TYPE_YESNO] = {0, 0, 0, 0, 0, 1, 2},
|
||||
[TYPE_YESNOCANCEL] = {0, 0, 0, 0, 3, 1, 2},
|
||||
[TYPE_YESNO] = {0, 0, 0, 0, 0, 2, 1},
|
||||
[TYPE_YESNOCANCEL] = {0, 0, 0, 0, 3, 2, 1},
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -161,8 +161,8 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {
|
||||
[TYPE_OK] = {3, 0, 0},
|
||||
[TYPE_OKCANCEL] = {3, 4, 0},
|
||||
[TYPE_RETRYCANCEL] = {1, 4, 0},
|
||||
[TYPE_YESNO] = {5, 6, 0},
|
||||
[TYPE_YESNOCANCEL] = {5, 6, 4},
|
||||
[TYPE_YESNO] = {6, 5, 0},
|
||||
[TYPE_YESNOCANCEL] = {6, 5, 4},
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -746,7 +746,7 @@ Tk_GetOpenFileObjCmd(
|
||||
/*
|
||||
* The -typevariable must be set to the selected file type, if the dialog was not cancelled
|
||||
*/
|
||||
NSInteger selectedFilterIndex = filterInfo.fileTypeIndex;
|
||||
NSUInteger selectedFilterIndex = filterInfo.fileTypeIndex;
|
||||
NSString *selectedFilter = NULL;
|
||||
if (filterInfo.userHasSelectedFilter) {
|
||||
selectedFilterIndex = filterInfo.fileTypeIndex;
|
||||
@@ -772,7 +772,7 @@ Tk_GetOpenFileObjCmd(
|
||||
selectedFilter = [filterInfo.fileTypeNames objectAtIndex:selectedFilterIndex];
|
||||
} else {
|
||||
// scan the list
|
||||
int i;
|
||||
NSUInteger i;
|
||||
for (i = 0; i < [filterInfo.fileTypeNames count]; i++) {
|
||||
if (filterCompatible(extension, i)) {
|
||||
selectedFilterIndex = i;
|
||||
@@ -1198,36 +1198,42 @@ TkAboutDlg(void)
|
||||
NSString *year = [dateFormatter stringFromDate:[NSDate date]];
|
||||
|
||||
[dateFormatter release];
|
||||
|
||||
NSMutableParagraphStyle *style =
|
||||
[[[NSParagraphStyle defaultParagraphStyle] mutableCopy]
|
||||
autorelease];
|
||||
|
||||
[style setAlignment:NSCenterTextAlignment];
|
||||
|
||||
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"Tcl & Tk", @"ApplicationName",
|
||||
@"Tcl " TCL_VERSION " & Tk " TK_VERSION, @"ApplicationVersion",
|
||||
@TK_PATCH_LEVEL, @"Version",
|
||||
image, @"ApplicationIcon",
|
||||
[NSString stringWithFormat:@"Copyright %1$C 1987-%2$@.", 0xA9,
|
||||
year], @"Copyright",
|
||||
[[[NSAttributedString alloc] initWithString:
|
||||
[NSString stringWithFormat:
|
||||
@"%1$C 1987-%2$@ Tcl Core Team." "\n\n"
|
||||
"%1$C 1989-%2$@ Contributors." "\n\n"
|
||||
"%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC." "\n\n"
|
||||
"%1$C 2014-%2$@ Marc Culler." "\n\n"
|
||||
"%1$C 2002-%2$@ 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:
|
||||
[NSDictionary dictionaryWithObject:style
|
||||
forKey:NSParagraphStyleAttributeName]] autorelease], @"Credits",
|
||||
nil];
|
||||
[NSApp orderFrontStandardAboutPanelWithOptions:options];
|
||||
|
||||
/*
|
||||
* 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];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1257,7 +1263,7 @@ TkMacOSXStandardAboutPanelObjCmd(
|
||||
Tcl_WrongNumArgs(interp, 1, objv, NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
[NSApp orderFrontStandardAboutPanelWithOptions:[NSDictionary dictionary]];
|
||||
TkAboutDlg();
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -1330,7 +1336,7 @@ Tk_MessageBoxObjCmd(
|
||||
|
||||
case ALERT_ICON:
|
||||
if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertIconStrings,
|
||||
sizeof(char *), "value", TCL_EXACT, &iconIndex) != TCL_OK) {
|
||||
sizeof(char *), "-icon value", TCL_EXACT, &iconIndex) != TCL_OK) {
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
@@ -1360,7 +1366,7 @@ Tk_MessageBoxObjCmd(
|
||||
|
||||
case ALERT_TYPE:
|
||||
if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertTypeStrings,
|
||||
sizeof(char *), "value", TCL_EXACT, &typeIndex) != TCL_OK) {
|
||||
sizeof(char *), "-type value", TCL_EXACT, &typeIndex) != TCL_OK) {
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
@@ -1376,7 +1382,7 @@ Tk_MessageBoxObjCmd(
|
||||
*/
|
||||
|
||||
if (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1],
|
||||
alertButtonStrings, sizeof(char *), "value", TCL_EXACT, &index) != TCL_OK) {
|
||||
alertButtonStrings, sizeof(char *), "-default value", TCL_EXACT, &index) != TCL_OK) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
#include "tkMacOSXDebug.h"
|
||||
#include "tkButton.h"
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
|
||||
#define GET_CGCONTEXT [[NSGraphicsContext currentContext] CGContext]
|
||||
#else
|
||||
#define GET_CGCONTEXT [[NSGraphicsContext currentContext] graphicsPort]
|
||||
#endif
|
||||
|
||||
/*
|
||||
#ifdef TK_MAC_DEBUG
|
||||
#define TK_MAC_DEBUG_DRAWING
|
||||
@@ -105,6 +111,25 @@ TkMacOSXInitCGDrawing(
|
||||
*
|
||||
* Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep.
|
||||
*
|
||||
* This is only used by XGetImage, which is never called. And this
|
||||
* implementation does not work correctly. Originally it relied on
|
||||
* [NSBitmapImageRep initWithFocusedViewRect:view_rect] which was
|
||||
* deprecated by Apple in OSX 10.14 and also required the use of other
|
||||
* deprecated functions such as [NSView lockFocus]. Apple's suggested
|
||||
* replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that
|
||||
* is what is being used here. However, that method only works when the
|
||||
* view has a valid CGContext, and a view is only guaranteed to have a
|
||||
* valid context during a call to [NSView drawRect]. To further
|
||||
* complicate matters, cacheDisplayInRect calls [NSView drawRect].
|
||||
* Essentially it is asking the view to draw a subrectangle of itself into
|
||||
* a special graphics context which is linked to the BitmapImageRep. But
|
||||
* our implementation of [NSView drawRect] does not allow recursive calls.
|
||||
* If called recursively it returns immediately without doing any drawing.
|
||||
* So the bottom line is that this function either returns a NULL pointer
|
||||
* or a black image. To make it useful would require a significant amount
|
||||
* of rewriting of the drawRect method. Perhaps the next release of OSX
|
||||
* will include some more helpful ways of doing this.
|
||||
*
|
||||
* Results:
|
||||
* Returns an NSBitmapRep representing the image of the given
|
||||
* rectangle of the given drawable. This object is retained.
|
||||
@@ -128,15 +153,16 @@ TkMacOSXBitmapRepFromDrawableRect(
|
||||
unsigned int height)
|
||||
{
|
||||
MacDrawable *mac_drawable = (MacDrawable *) drawable;
|
||||
CGContextRef cg_context=NULL;
|
||||
CGImageRef cg_image=NULL, sub_cg_image=NULL;
|
||||
NSBitmapImageRep *bitmap_rep=NULL;
|
||||
CGContextRef cg_context = NULL;
|
||||
CGImageRef cg_image=NULL, sub_cg_image = NULL;
|
||||
NSBitmapImageRep *bitmap_rep = NULL;
|
||||
NSView *view=NULL;
|
||||
if ( mac_drawable->flags & TK_IS_PIXMAP ) {
|
||||
|
||||
/*
|
||||
* This means that the MacDrawable is functioning as a
|
||||
* Tk Pixmap, so its view field is NULL.
|
||||
*/
|
||||
* This MacDrawable is a bitmap, so its view is NULL.
|
||||
*/
|
||||
|
||||
cg_context = TkMacOSXGetCGContextForDrawable(drawable);
|
||||
CGRect image_rect = CGRectMake(x, y, width, height);
|
||||
cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context);
|
||||
@@ -149,22 +175,32 @@ TkMacOSXBitmapRepFromDrawableRect(
|
||||
CGImageRelease(cg_image);
|
||||
}
|
||||
} else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) {
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
if ( [view lockFocusIfCanDraw] ) {
|
||||
bitmap_rep = [NSBitmapImageRep alloc];
|
||||
bitmap_rep = [bitmap_rep initWithFocusedViewRect:view_rect];
|
||||
[view unlockFocus];
|
||||
} else {
|
||||
TkMacOSXDbgMsg("Could not lock focus on view.");
|
||||
}
|
||||
/*
|
||||
* Attempt to copy from the view to a bitmapImageRep. If the view does
|
||||
* not have a valid CGContext, doing this will silently corrupt memory
|
||||
* and make a big mess. So, in that case, we mark the view as needing
|
||||
* display and return NULL.
|
||||
*/
|
||||
|
||||
if (view == [NSView focusView]) {
|
||||
bitmap_rep = [view bitmapImageRepForCachingDisplayInRect: view_rect];
|
||||
[bitmap_rep retain];
|
||||
[view cacheDisplayInRect:view_rect toBitmapImageRep:bitmap_rep];
|
||||
} else {
|
||||
TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap.");
|
||||
[view setNeedsDisplay:YES];
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
TkMacOSXDbgMsg("Invalid source drawable");
|
||||
}
|
||||
@@ -205,26 +241,24 @@ XCopyArea(
|
||||
MacDrawable *srcDraw = (MacDrawable *) src;
|
||||
NSBitmapImageRep *bitmap_rep = NULL;
|
||||
CGImageRef img = NULL;
|
||||
CGRect bounds, srcRect, dstRect;
|
||||
|
||||
display->request++;
|
||||
|
||||
if (!width || !height) {
|
||||
/* This happens all the time.
|
||||
TkMacOSXDbgMsg("Drawing of empty area requested");
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
|
||||
return;
|
||||
/*TkMacOSXDbgMsg("Failed to setup drawing context.");*/
|
||||
TkMacOSXDbgMsg("Failed to setup drawing context.");
|
||||
}
|
||||
|
||||
if ( dc.context ) {
|
||||
if (srcDraw->flags & TK_IS_PIXMAP) {
|
||||
img = TkMacOSXCreateCGImageWithDrawable(src);
|
||||
}else if (TkMacOSXDrawableWindow(src)) {
|
||||
bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src, src_x, src_y, width, height);
|
||||
bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src,
|
||||
src_x, src_y, width, height);
|
||||
if ( bitmap_rep ) {
|
||||
img = [bitmap_rep CGImage];
|
||||
}
|
||||
@@ -233,13 +267,12 @@ XCopyArea(
|
||||
}
|
||||
|
||||
if (img) {
|
||||
TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, gc->background,
|
||||
CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
|
||||
CGRectMake(src_x, src_y, width, height),
|
||||
CGRectMake(dest_x, dest_y, width, height));
|
||||
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.");
|
||||
}
|
||||
@@ -288,7 +321,7 @@ XCopyPlane(
|
||||
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"); */
|
||||
@@ -308,7 +341,7 @@ XCopyPlane(
|
||||
TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
|
||||
unsigned long imageBackground = gc->background;
|
||||
if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP){
|
||||
CGRect srcRect = CGRectMake(src_x, src_y, width, height);
|
||||
srcRect = CGRectMake(src_x, src_y, width, height);
|
||||
CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(clipPtr->value.pixmap);
|
||||
CGImageRef submask = CGImageCreateWithImageInRect(img, srcRect);
|
||||
CGRect rect = CGRectMake(dest_x, dest_y, width, height);
|
||||
@@ -333,10 +366,11 @@ XCopyPlane(
|
||||
CGImageRelease(submask);
|
||||
CGImageRelease(subimage);
|
||||
} else {
|
||||
TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, imageBackground,
|
||||
CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
|
||||
CGRectMake(src_x, src_y, width, height),
|
||||
CGRectMake(dest_x, dest_y, width, height));
|
||||
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 */
|
||||
@@ -440,10 +474,8 @@ TkMacOSXGetNSImageWithTkImage(
|
||||
int height)
|
||||
{
|
||||
Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);
|
||||
MacDrawable *macDraw = (MacDrawable *) pixmap;
|
||||
NSImage *nsImage;
|
||||
|
||||
macDraw->flags |= TK_USE_XIMAGE_ALPHA;
|
||||
Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);
|
||||
nsImage = CreateNSImageWithPixmap(pixmap, width, height);
|
||||
Tk_FreePixmap(display, pixmap);
|
||||
@@ -596,11 +628,13 @@ TkMacOSXDrawCGImage(
|
||||
}
|
||||
}
|
||||
dstBounds = CGRectOffset(dstBounds, macDraw->xOff, macDraw->yOff);
|
||||
|
||||
if (CGImageIsMask(image)) {
|
||||
/*CGContextSaveGState(context);*/
|
||||
if (macDraw->flags & TK_IS_BW_PIXMAP) {
|
||||
/* Set fill color to black, background comes from the context, or is transparent. */
|
||||
|
||||
/* Set fill color to black; background comes from the context,
|
||||
* or is transparent.
|
||||
*/
|
||||
|
||||
if (imageBackground != TRANSPARENT_PIXEL << 24) {
|
||||
CGContextClearRect(context, dstBounds);
|
||||
}
|
||||
@@ -1448,7 +1482,7 @@ TkMacOSXSetUpGraphicsPort(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
Bool
|
||||
TkMacOSXSetupDrawingContext(
|
||||
Drawable d,
|
||||
GC gc,
|
||||
@@ -1456,41 +1490,71 @@ TkMacOSXSetupDrawingContext(
|
||||
TkMacOSXDrawingContext *dcPtr)
|
||||
{
|
||||
MacDrawable *macDraw = ((MacDrawable*)d);
|
||||
int dontDraw = 0, isWin = 0;
|
||||
Bool canDraw = true;
|
||||
NSWindow *win = NULL;
|
||||
TkMacOSXDrawingContext dc = {};
|
||||
CGRect clipBounds;
|
||||
|
||||
dc.clipRgn = TkMacOSXGetClipRgn(d);
|
||||
if (!dontDraw) {
|
||||
ClipToGC(d, gc, &dc.clipRgn);
|
||||
dontDraw = dc.clipRgn ? HIShapeIsEmpty(dc.clipRgn) : 0;
|
||||
/*
|
||||
* If we are simulating drawing for tests, just return false.
|
||||
*/
|
||||
|
||||
if ([NSApp simulateDrawing]) {
|
||||
return false;
|
||||
}
|
||||
if (dontDraw) {
|
||||
|
||||
/*
|
||||
* If the drawable is not a pixmap and it has an associated
|
||||
* NSWindow then we know we are drawing to a window.
|
||||
*/
|
||||
|
||||
if (!(macDraw->flags & TK_IS_PIXMAP)) {
|
||||
win = TkMacOSXDrawableWindow(d);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that we have a non-empty clipping region.
|
||||
*/
|
||||
|
||||
dc.clipRgn = TkMacOSXGetClipRgn(d);
|
||||
ClipToGC(d, gc, &dc.clipRgn);
|
||||
if (dc.clipRgn && HIShapeIsEmpty(dc.clipRgn)) {
|
||||
canDraw = false;
|
||||
goto end;
|
||||
}
|
||||
if (useCG) {
|
||||
dc.context = TkMacOSXGetCGContextForDrawable(d);
|
||||
}
|
||||
if (!dc.context || !(macDraw->flags & TK_IS_PIXMAP)) {
|
||||
isWin = (TkMacOSXDrawableWindow(d) != nil);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we already have a CGContext, use it. Otherwise, if we
|
||||
* are drawing to a window then we can get one from the
|
||||
* window.
|
||||
*/
|
||||
|
||||
dc.context = TkMacOSXGetCGContextForDrawable(d);
|
||||
if (dc.context) {
|
||||
dc.portBounds = clipBounds = CGContextGetClipBoundingBox(dc.context);
|
||||
} else if (isWin) {
|
||||
} else if (win) {
|
||||
NSView *view = TkMacOSXDrawableView(macDraw);
|
||||
if (view) {
|
||||
if (view != [NSView focusView]) {
|
||||
dc.focusLocked = [view lockFocusIfCanDraw];
|
||||
dontDraw = !dc.focusLocked;
|
||||
} else {
|
||||
dontDraw = ![view canDraw];
|
||||
}
|
||||
if (dontDraw) {
|
||||
goto end;
|
||||
}
|
||||
[[view window] disableFlushWindow];
|
||||
|
||||
/*
|
||||
* We can only draw into the view when the current CGContext is
|
||||
* valid and belongs to the view. Validity can only be guaranteed
|
||||
* inside of a view's drawRect or setFrame methods. The isDrawing
|
||||
* attribute tells us whether we are being called from one of those
|
||||
* methods.
|
||||
*
|
||||
* If the CGContext is not valid, or belongs to a different View,
|
||||
* then we mark our view as needing display and return failure.
|
||||
* It should get drawn in a later call to drawRect.
|
||||
*/
|
||||
|
||||
if (view != [NSView focusView]) {
|
||||
[view setNeedsDisplay:YES];
|
||||
canDraw = false;
|
||||
goto end;
|
||||
}
|
||||
dc.view = view;
|
||||
dc.context = [[NSGraphicsContext currentContext] graphicsPort];
|
||||
dc.context = GET_CGCONTEXT;
|
||||
dc.portBounds = NSRectToCGRect([view bounds]);
|
||||
if (dc.clipRgn) {
|
||||
clipBounds = CGContextGetClipBoundingBox(dc.context);
|
||||
@@ -1503,14 +1567,17 @@ TkMacOSXSetupDrawingContext(
|
||||
Tcl_Panic("TkMacOSXSetupDrawingContext(): "
|
||||
"no context to draw into !");
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the drawing context.
|
||||
*/
|
||||
|
||||
if (dc.context) {
|
||||
CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
|
||||
.ty = dc.portBounds.size.height};
|
||||
dc.portBounds.origin.x += macDraw->xOff;
|
||||
dc.portBounds.origin.y += macDraw->yOff;
|
||||
if (!dc.focusLocked) {
|
||||
CGContextSaveGState(dc.context);
|
||||
}
|
||||
CGContextSaveGState(dc.context);
|
||||
CGContextSetTextDrawingMode(dc.context, kCGTextFill);
|
||||
CGContextConcatCTM(dc.context, t);
|
||||
if (dc.clipRgn) {
|
||||
@@ -1545,7 +1612,7 @@ TkMacOSXSetupDrawingContext(
|
||||
double w = gc->line_width;
|
||||
|
||||
TkMacOSXSetColorInContext(gc, gc->foreground, dc.context);
|
||||
if (isWin) {
|
||||
if (win) {
|
||||
CGContextSetPatternPhase(dc.context, CGSizeMake(
|
||||
dc.portBounds.size.width, dc.portBounds.size.height));
|
||||
}
|
||||
@@ -1583,13 +1650,21 @@ TkMacOSXSetupDrawingContext(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (dontDraw && dc.clipRgn) {
|
||||
#ifdef TK_MAC_DEBUG_DRAWING
|
||||
if (!canDraw && win != NULL) {
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(win);
|
||||
if (winPtr) fprintf(stderr, "Cannot draw in %s - postponing.\n",
|
||||
Tk_PathName(winPtr));
|
||||
}
|
||||
#endif
|
||||
if (!canDraw && dc.clipRgn) {
|
||||
CFRelease(dc.clipRgn);
|
||||
dc.clipRgn = NULL;
|
||||
}
|
||||
*dcPtr = dc;
|
||||
return !dontDraw;
|
||||
return canDraw;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1614,13 +1689,7 @@ TkMacOSXRestoreDrawingContext(
|
||||
{
|
||||
if (dcPtr->context) {
|
||||
CGContextSynchronize(dcPtr->context);
|
||||
[[dcPtr->view window] setViewsNeedDisplay:YES];
|
||||
[[dcPtr->view window] enableFlushWindow];
|
||||
if (dcPtr->focusLocked) {
|
||||
[dcPtr->view unlockFocus];
|
||||
} else {
|
||||
CGContextRestoreGState(dcPtr->context);
|
||||
}
|
||||
CGContextRestoreGState(dcPtr->context);
|
||||
}
|
||||
if (dcPtr->clipRgn) {
|
||||
CFRelease(dcPtr->clipRgn);
|
||||
@@ -1659,17 +1728,13 @@ TkMacOSXGetClipRgn(
|
||||
#ifdef TK_MAC_DEBUG_DRAWING
|
||||
TkMacOSXDbgMsg("%s", macDraw->winPtr->pathName);
|
||||
NSView *view = TkMacOSXDrawableView(macDraw);
|
||||
if ([view lockFocusIfCanDraw]) {
|
||||
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
|
||||
CGContextSaveGState(context);
|
||||
CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0,
|
||||
-1.0, 0.0, [view bounds].size.height));
|
||||
ChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context);
|
||||
CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1);
|
||||
CGContextEOFillPath(context);
|
||||
CGContextRestoreGState(context);
|
||||
[view unlockFocus];
|
||||
}
|
||||
CGContextSaveGState(context);
|
||||
CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0,
|
||||
-1.0, 0.0, [view bounds].size.height));
|
||||
ChkErr(HIShapeReplacePathInCGContext, macDraw->visRgn, context);
|
||||
CGContextSetRGBFillColor(context, 0.0, 1.0, 0.0, 0.1);
|
||||
CGContextEOFillPath(context);
|
||||
CGContextRestoreGState(context);
|
||||
#endif /* TK_MAC_DEBUG_DRAWING */
|
||||
}
|
||||
|
||||
@@ -1729,13 +1794,11 @@ TkpClipDrawableToRect(
|
||||
int width, int height)
|
||||
{
|
||||
MacDrawable *macDraw = (MacDrawable *) d;
|
||||
NSView *view = TkMacOSXDrawableView(macDraw);
|
||||
|
||||
if (macDraw->drawRgn) {
|
||||
CFRelease(macDraw->drawRgn);
|
||||
macDraw->drawRgn = NULL;
|
||||
}
|
||||
|
||||
if (width >= 0 && height >= 0) {
|
||||
CGRect clipRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff,
|
||||
width, height);
|
||||
@@ -1751,17 +1814,6 @@ TkpClipDrawableToRect(
|
||||
} else {
|
||||
macDraw->drawRgn = drawRgn;
|
||||
}
|
||||
if (view && view != [NSView focusView] && [view lockFocusIfCanDraw]) {
|
||||
clipRect.origin.y = [view bounds].size.height -
|
||||
(clipRect.origin.y + clipRect.size.height);
|
||||
NSRectClip(NSRectFromCGRect(clipRect));
|
||||
macDraw->flags |= TK_FOCUSED_VIEW;
|
||||
}
|
||||
} else {
|
||||
if (view && (macDraw->flags & TK_FOCUSED_VIEW)) {
|
||||
[view unlockFocus];
|
||||
macDraw->flags &= ~TK_FOCUSED_VIEW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -805,7 +805,7 @@ ContainerEventProc(
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ignore any X protocol errors that happen in this procedure (almost any
|
||||
* operation could fail, for example, if the embedded application has
|
||||
|
||||
@@ -112,14 +112,23 @@ enum {
|
||||
*
|
||||
* TkMacOSXFlushWindows --
|
||||
*
|
||||
* This routine flushes all the visible windows of the application. It is
|
||||
* called by XSync().
|
||||
* This routine is a stub called by XSync, which is called during the Tk
|
||||
* update command. The language specification does not require that the
|
||||
* update command be synchronous but many of the tests assume that is the
|
||||
* case. It is not naturally the case on macOS since many idle tasks are
|
||||
* run inside of the drawRect method of a window's contentView, and that
|
||||
* method will not be called until after this function returns. To make
|
||||
* the tests work, we attempt to force this to be synchronous by waiting
|
||||
* until drawRect has been called for each window. The mechanism we use
|
||||
* for this is to have drawRect post an ApplicationDefined NSEvent on the
|
||||
* AppKit event queue when it finishes drawing, and wait for it here.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Flushes all visible Cocoa windows
|
||||
* Calls the drawRect method of the contentView of each visible
|
||||
* window.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -128,11 +137,14 @@ MODULE_SCOPE void
|
||||
TkMacOSXFlushWindows(void)
|
||||
{
|
||||
NSArray *macWindows = [NSApp orderedWindows];
|
||||
|
||||
if ([NSApp simulateDrawing]) {
|
||||
[NSApp setSimulateDrawing:NO];
|
||||
return;
|
||||
}
|
||||
for (NSWindow *w in macWindows) {
|
||||
if (TkMacOSXGetXWindow(w)) {
|
||||
[w flushWindow];
|
||||
}
|
||||
if (TkMacOSXGetXWindow(w)) {
|
||||
[w displayIfNeeded];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,19 +14,11 @@
|
||||
|
||||
#include "tkMacOSXPrivate.h"
|
||||
#include "tkMacOSXFont.h"
|
||||
#include "tkMacOSXConstants.h"
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
|
||||
#define defaultOrientation kCTFontDefaultOrientation
|
||||
#define verticalOrientation kCTFontVerticalOrientation
|
||||
#else
|
||||
#define defaultOrientation kCTFontOrientationDefault
|
||||
#define verticalOrientation kCTFontOrientationVertical
|
||||
#endif
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101100
|
||||
#define fixedPitch kCTFontUserFixedPitchFontType
|
||||
#else
|
||||
#define fixedPitch kCTFontUIFontUserFixedPitch
|
||||
#endif
|
||||
|
||||
/*
|
||||
#ifdef TK_MAC_DEBUG
|
||||
@@ -259,7 +251,7 @@ InitFont(
|
||||
}
|
||||
fontPtr->nsFont = nsFont;
|
||||
// some don't like antialiasing on fixed-width even if bigger than limit
|
||||
// dontAA = [nsFont isFixedPitch] && fontPtr->font.fa.size <= 10;
|
||||
// dontAA = [nsFont isFixedPitch] && fontPtr->font.fa.size <= 10;
|
||||
if (antialiasedTextEnabled >= 0/* || dontAA*/) {
|
||||
renderingMode = (antialiasedTextEnabled == 0/* || dontAA*/) ?
|
||||
NSFontIntegerAdvancementsRenderingMode :
|
||||
@@ -819,15 +811,6 @@ TkpMeasureCharsInContext(
|
||||
*lengthPtr = 0;
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
/* Back-compatibility with ATSUI renderer, appears not to be needed */
|
||||
if (rangeStart == 0 && maxLength == 1 && (flags & TK_ISOLATE_END) &&
|
||||
!(flags & TK_AT_LEAST_ONE)) {
|
||||
length = 0;
|
||||
fit = 0;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
if (maxLength > 32767) {
|
||||
maxLength = 32767;
|
||||
}
|
||||
@@ -860,6 +843,10 @@ TkpMeasureCharsInContext(
|
||||
double maxWidth = maxLength + offset;
|
||||
NSCharacterSet *cs;
|
||||
|
||||
/*
|
||||
* Get a line breakpoint in the source string.
|
||||
*/
|
||||
|
||||
index = start;
|
||||
if (flags & TK_WHOLE_WORDS) {
|
||||
index = CTTypesetterSuggestLineBreak(typesetter, start, maxWidth);
|
||||
@@ -870,15 +857,43 @@ TkpMeasureCharsInContext(
|
||||
if (index <= start && !(flags & TK_WHOLE_WORDS)) {
|
||||
index = CTTypesetterSuggestClusterBreak(typesetter, start, maxWidth);
|
||||
}
|
||||
|
||||
/*
|
||||
* Trim right whitespace/lineending characters.
|
||||
*/
|
||||
|
||||
cs = (index <= len && (flags & TK_WHOLE_WORDS)) ?
|
||||
whitespaceCharacterSet : lineendingCharacterSet;
|
||||
while (index > start &&
|
||||
[cs characterIsMember:[string characterAtIndex:(index - 1)]]) {
|
||||
index--;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no line breakpoint in the source string between
|
||||
* its start and the index position that fits in maxWidth, then
|
||||
* CTTypesetterSuggestLineBreak() returns that very last index.
|
||||
* However if the TK_WHOLE_WORDS flag is set, we want to break
|
||||
* at a word boundary. In this situation, unless TK_AT_LEAST_ONE
|
||||
* is set, we must report that zero chars actually fit (in other
|
||||
* words the smallest word of the source string is still larger
|
||||
* than maxWidth).
|
||||
*/
|
||||
|
||||
if ((index >= start) && (index < len) &&
|
||||
(flags & TK_WHOLE_WORDS) && !(flags & TK_AT_LEAST_ONE) &&
|
||||
![cs characterIsMember:[string characterAtIndex:index]]) {
|
||||
index = start;
|
||||
}
|
||||
|
||||
if (index <= start && (flags & TK_AT_LEAST_ONE)) {
|
||||
index = start + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now measure the string width in pixels.
|
||||
*/
|
||||
|
||||
if (index > 0) {
|
||||
range.length = index;
|
||||
line = CTTypesetterCreateLine(typesetter, range);
|
||||
@@ -921,7 +936,6 @@ done:
|
||||
flags & TK_AT_LEAST_ONE ? "atLeastOne " : "",
|
||||
flags & TK_ISOLATE_END ? "isolateEnd " : "",
|
||||
length, fit);
|
||||
//if (!(rangeLength==1 && rangeStart == 0)) fprintf(stderr, " measure len=%d (max=%d, w=%.0f) from %d (nb=%d): source=\"%s\": index=%d return %d\n",rangeLength,maxLength,width,rangeStart,numBytes, source+rangeStart, index, fit);
|
||||
#endif
|
||||
*lengthPtr = length;
|
||||
return fit;
|
||||
|
||||
@@ -279,7 +279,7 @@ tkMacOSXProcessFiles(
|
||||
Tcl_Interp *interp,
|
||||
const char* procedure)
|
||||
{
|
||||
Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, "utf-8");
|
||||
Tcl_Encoding utf8;
|
||||
const AEDesc *fileSpecDesc = nil;
|
||||
AEDesc contents;
|
||||
char URLString[1 + URL_MAX_LENGTH];
|
||||
@@ -331,6 +331,7 @@ tkMacOSXProcessFiles(
|
||||
|
||||
Tcl_DStringInit(&command);
|
||||
Tcl_DStringAppend(&command, procedure, -1);
|
||||
utf8 = Tcl_GetEncoding(NULL, "utf-8");
|
||||
|
||||
for (index = 1; index <= count; index++) {
|
||||
if (noErr != AEGetNthPtr(fileSpecDesc, index, typeFileURL, &keyword,
|
||||
@@ -349,6 +350,8 @@ tkMacOSXProcessFiles(
|
||||
Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
|
||||
Tcl_DStringFree(&pathName);
|
||||
}
|
||||
|
||||
Tcl_FreeEncoding(utf8);
|
||||
AEDisposeDesc(&contents);
|
||||
|
||||
/*
|
||||
@@ -361,7 +364,6 @@ tkMacOSXProcessFiles(
|
||||
Tcl_BackgroundException(interp, code);
|
||||
}
|
||||
Tcl_DStringFree(&command);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
584
macosx/tkMacOSXImage.c
Normal file
584
macosx/tkMacOSXImage.c
Normal file
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
* tkMacOSXImage.c --
|
||||
*
|
||||
* The code in this file provides an interface for XImages,
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#include "tkMacOSXPrivate.h"
|
||||
#include "xbytes.h"
|
||||
|
||||
#pragma mark XImage handling
|
||||
|
||||
int
|
||||
_XInitImageFuncPtrs(
|
||||
XImage *image)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkMacOSXCreateCGImageWithXImage --
|
||||
*
|
||||
* Create CGImage from XImage, copying the image data. Called
|
||||
* in Tk_PutImage and (currently) nowhere else.
|
||||
*
|
||||
* Results:
|
||||
* CGImage, release after use.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void ReleaseData(void *info, const void *data, size_t size) {
|
||||
ckfree(info);
|
||||
}
|
||||
|
||||
CGImageRef
|
||||
TkMacOSXCreateCGImageWithXImage(
|
||||
XImage *image)
|
||||
{
|
||||
CGImageRef img = NULL;
|
||||
size_t bitsPerComponent, bitsPerPixel;
|
||||
size_t len = image->bytes_per_line * image->height;
|
||||
const CGFloat *decode = NULL;
|
||||
CGBitmapInfo bitmapInfo;
|
||||
CGDataProviderRef provider = NULL;
|
||||
char *data = NULL;
|
||||
CGDataProviderReleaseDataCallback releaseData = ReleaseData;
|
||||
|
||||
if (image->bits_per_pixel == 1) {
|
||||
/*
|
||||
* BW image
|
||||
*/
|
||||
|
||||
/* Reverses the sense of the bits */
|
||||
static const CGFloat decodeWB[2] = {1, 0};
|
||||
decode = decodeWB;
|
||||
|
||||
bitsPerComponent = 1;
|
||||
bitsPerPixel = 1;
|
||||
if (image->bitmap_bit_order != MSBFirst) {
|
||||
char *srcPtr = image->data + image->xoffset;
|
||||
char *endPtr = srcPtr + len;
|
||||
char *destPtr = (data = ckalloc(len));
|
||||
|
||||
while (srcPtr < endPtr) {
|
||||
*destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))];
|
||||
}
|
||||
} else {
|
||||
data = memcpy(ckalloc(len), image->data + image->xoffset, len);
|
||||
}
|
||||
if (data) {
|
||||
provider = CGDataProviderCreateWithData(data, data, len, releaseData);
|
||||
}
|
||||
if (provider) {
|
||||
img = CGImageMaskCreate(image->width, image->height, bitsPerComponent,
|
||||
bitsPerPixel, image->bytes_per_line, provider, decode, 0);
|
||||
}
|
||||
} else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
|
||||
|
||||
/*
|
||||
* Color image
|
||||
*/
|
||||
|
||||
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
|
||||
bitsPerComponent = 8;
|
||||
bitsPerPixel = 32;
|
||||
bitmapInfo = (image->byte_order == MSBFirst ?
|
||||
kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big);
|
||||
bitmapInfo |= kCGImageAlphaLast;
|
||||
data = memcpy(ckalloc(len), image->data + image->xoffset, len);
|
||||
if (data) {
|
||||
provider = CGDataProviderCreateWithData(data, data, len, releaseData);
|
||||
}
|
||||
if (provider) {
|
||||
img = CGImageCreate(image->width, image->height, bitsPerComponent,
|
||||
bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo,
|
||||
provider, decode, 0, kCGRenderingIntentDefault);
|
||||
CFRelease(provider);
|
||||
}
|
||||
if (colorspace) {
|
||||
CFRelease(colorspace);
|
||||
}
|
||||
} else {
|
||||
TkMacOSXDbgMsg("Unsupported image type");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* DestroyImage --
|
||||
*
|
||||
* Destroys storage associated with an image.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Deallocates the image.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
DestroyImage(
|
||||
XImage *image)
|
||||
{
|
||||
if (image) {
|
||||
if (image->data) {
|
||||
ckfree(image->data);
|
||||
}
|
||||
ckfree(image);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* ImageGetPixel --
|
||||
*
|
||||
* Get a single pixel from an image.
|
||||
*
|
||||
* Results:
|
||||
* Returns the 32 bit pixel value.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static unsigned long
|
||||
ImageGetPixel(
|
||||
XImage *image,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
unsigned char r = 0, g = 0, b = 0;
|
||||
|
||||
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: {
|
||||
r = (*((unsigned int*) srcPtr) >> 16) & 0xff;
|
||||
g = (*((unsigned int*) srcPtr) >> 8) & 0xff;
|
||||
b = (*((unsigned int*) srcPtr) ) & 0xff;
|
||||
/*if (image->byte_order == LSBFirst) {
|
||||
r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0];
|
||||
} else {
|
||||
r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3];
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
r = (*((unsigned short*) srcPtr) >> 7) & 0xf8;
|
||||
g = (*((unsigned short*) srcPtr) >> 2) & 0xf8;
|
||||
b = (*((unsigned short*) srcPtr) << 3) & 0xf8;
|
||||
break;
|
||||
case 8:
|
||||
r = (*srcPtr << 2) & 0xc0;
|
||||
g = (*srcPtr << 4) & 0xc0;
|
||||
b = (*srcPtr << 6) & 0xc0;
|
||||
r |= r >> 2 | r >> 4 | r >> 6;
|
||||
g |= g >> 2 | g >> 4 | g >> 6;
|
||||
b |= b >> 2 | b >> 4 | b >> 6;
|
||||
break;
|
||||
case 4: {
|
||||
unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4);
|
||||
r = (c & 0x04) ? 0xff : 0;
|
||||
g = (c & 0x02) ? 0xff : 0;
|
||||
b = (c & 0x01) ? 0xff : 0;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* ImagePutPixel --
|
||||
*
|
||||
* Set a single pixel in an image.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
ImagePutPixel(
|
||||
XImage *image,
|
||||
int x,
|
||||
int y,
|
||||
unsigned long pixel)
|
||||
{
|
||||
if (image && image->data) {
|
||||
unsigned char *dstPtr = ((unsigned char*) image->data)
|
||||
+ (y * image->bytes_per_line)
|
||||
+ (((image->xoffset + x) * image->bits_per_pixel) / NBBY);
|
||||
if (image->bits_per_pixel == 32) {
|
||||
*((unsigned int*) dstPtr) = pixel;
|
||||
} else {
|
||||
unsigned char r = ((pixel & image->red_mask) >> 16) & 0xff;
|
||||
unsigned char g = ((pixel & image->green_mask) >> 8) & 0xff;
|
||||
unsigned char b = ((pixel & image->blue_mask) ) & 0xff;
|
||||
switch (image->bits_per_pixel) {
|
||||
case 16:
|
||||
*((unsigned short*) dstPtr) = ((r & 0xf8) << 7) |
|
||||
((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
|
||||
break;
|
||||
case 8:
|
||||
*dstPtr = ((r & 0xc0) >> 2) | ((g & 0xc0) >> 4) |
|
||||
((b & 0xc0) >> 6);
|
||||
break;
|
||||
case 4: {
|
||||
unsigned char c = ((r & 0x80) >> 5) | ((g & 0x80) >> 6) |
|
||||
((b & 0x80) >> 7);
|
||||
*dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (c & 0x0f)) :
|
||||
((*dstPtr & 0x0f) | ((c << 4) & 0xf0));
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
*dstPtr = ((r|g|b) & 0x80) ? (*dstPtr | (0x80 >> (x % 8))) :
|
||||
(*dstPtr & ~(0x80 >> (x % 8)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* XCreateImage --
|
||||
*
|
||||
* Allocates storage for a new XImage.
|
||||
*
|
||||
* Results:
|
||||
* Returns a newly allocated XImage.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
XImage *
|
||||
XCreateImage(
|
||||
Display* display,
|
||||
Visual* visual,
|
||||
unsigned int depth,
|
||||
int format,
|
||||
int offset,
|
||||
char* data,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
int bitmap_pad,
|
||||
int bytes_per_line)
|
||||
{
|
||||
XImage *ximage;
|
||||
display->request++;
|
||||
ximage = ckalloc(sizeof(XImage));
|
||||
|
||||
ximage->height = height;
|
||||
ximage->width = width;
|
||||
ximage->depth = depth;
|
||||
ximage->xoffset = offset;
|
||||
ximage->format = format;
|
||||
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;
|
||||
} else {
|
||||
ximage->bits_per_pixel = 1;
|
||||
ximage->bitmap_unit = 8;
|
||||
}
|
||||
if (bitmap_pad) {
|
||||
ximage->bitmap_pad = bitmap_pad;
|
||||
} else {
|
||||
/* Use 16 byte alignment for best Quartz perfomance */
|
||||
ximage->bitmap_pad = 128;
|
||||
}
|
||||
if (bytes_per_line) {
|
||||
ximage->bytes_per_line = bytes_per_line;
|
||||
} else {
|
||||
ximage->bytes_per_line = ((width * ximage->bits_per_pixel +
|
||||
(ximage->bitmap_pad - 1)) >> 3) &
|
||||
~((ximage->bitmap_pad >> 3) - 1);
|
||||
}
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
ximage->byte_order = MSBFirst;
|
||||
ximage->bitmap_bit_order = MSBFirst;
|
||||
#else
|
||||
ximage->byte_order = LSBFirst;
|
||||
ximage->bitmap_bit_order = LSBFirst;
|
||||
#endif
|
||||
ximage->red_mask = 0x00FF0000;
|
||||
ximage->green_mask = 0x0000FF00;
|
||||
ximage->blue_mask = 0x000000FF;
|
||||
ximage->f.create_image = NULL;
|
||||
ximage->f.destroy_image = DestroyImage;
|
||||
ximage->f.get_pixel = ImageGetPixel;
|
||||
ximage->f.put_pixel = ImagePutPixel;
|
||||
ximage->f.sub_image = NULL;
|
||||
ximage->f.add_pixel = NULL;
|
||||
|
||||
return ximage;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkPutImage --
|
||||
*
|
||||
* Copies a rectangular subimage of an XImage into a drawable.
|
||||
* Currently this is only called by TkImgPhotoDisplay, using
|
||||
* a Window as the drawable.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Draws the image on the specified drawable.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TkPutImage(
|
||||
unsigned long *colors, /* Unused on Macintosh. */
|
||||
int ncolors, /* Unused on Macintosh. */
|
||||
Display* display, /* Display. */
|
||||
Drawable drawable, /* Drawable to place image on. */
|
||||
GC gc, /* GC to use. */
|
||||
XImage* image, /* Image to place. */
|
||||
int src_x, /* Source X & Y. */
|
||||
int src_y,
|
||||
int dest_x, /* Destination X & Y. */
|
||||
int dest_y,
|
||||
unsigned int width, /* Same width & height for both */
|
||||
unsigned int height) /* distination and source. */
|
||||
{
|
||||
TkMacOSXDrawingContext dc;
|
||||
MacDrawable *macDraw = (MacDrawable *) drawable;
|
||||
|
||||
display->request++;
|
||||
if (!TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc)) {
|
||||
return BadDrawable;
|
||||
}
|
||||
if (dc.context) {
|
||||
CGRect bounds, srcRect, dstRect;
|
||||
CGImageRef img = TkMacOSXCreateCGImageWithXImage(image);
|
||||
|
||||
/*
|
||||
* The CGContext for a pixmap is RGB only, with A = 0.
|
||||
*/
|
||||
|
||||
if (!(macDraw->flags & TK_IS_PIXMAP)) {
|
||||
CGContextSetBlendMode(dc.context, kCGBlendModeSourceAtop);
|
||||
}
|
||||
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);
|
||||
dstRect = CGRectMake(dest_x, dest_y, width, height);
|
||||
TkMacOSXDrawCGImage(drawable, gc, dc.context,
|
||||
img, gc->foreground, gc->background,
|
||||
bounds, srcRect, dstRect);
|
||||
CFRelease(img);
|
||||
} else {
|
||||
TkMacOSXDbgMsg("Invalid source drawable");
|
||||
}
|
||||
} else {
|
||||
TkMacOSXDbgMsg("Invalid destination drawable");
|
||||
}
|
||||
TkMacOSXRestoreDrawingContext(&dc);
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 79
|
||||
* coding: utf-8
|
||||
* End:
|
||||
*/
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "tkMacOSXPrivate.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <dlfcn.h>
|
||||
#include <objc/objc-auto.h>
|
||||
|
||||
@@ -29,8 +28,6 @@ static char tkLibPath[PATH_MAX + 1] = "";
|
||||
|
||||
static char scriptPath[PATH_MAX + 1] = "";
|
||||
|
||||
long tkMacOSXMacOSXVersion = 0;
|
||||
|
||||
#pragma mark TKApplication(TKInit)
|
||||
|
||||
@interface TKApplication(TKKeyboard)
|
||||
@@ -48,6 +45,9 @@ long tkMacOSXMacOSXVersion = 0;
|
||||
|
||||
@implementation TKApplication
|
||||
@synthesize poolLock = _poolLock;
|
||||
@synthesize macMinorVersion = _macMinorVersion;
|
||||
@synthesize isDrawing = _isDrawing;
|
||||
@synthesize simulateDrawing = _simulateDrawing;
|
||||
@end
|
||||
|
||||
/*
|
||||
@@ -152,6 +152,26 @@ long tkMacOSXMacOSXVersion = 0;
|
||||
_mainPool = [NSAutoreleasePool new];
|
||||
[NSApp setPoolLock:0];
|
||||
|
||||
/*
|
||||
* Record the OS version we are running on.
|
||||
*/
|
||||
int minorVersion;
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
|
||||
Gestalt(gestaltSystemVersionMinor, (SInt32*)&minorVersion);
|
||||
#else
|
||||
NSOperatingSystemVersion systemVersion;
|
||||
systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
|
||||
minorVersion = systemVersion.minorVersion;
|
||||
#endif
|
||||
[NSApp setMacMinorVersion: minorVersion];
|
||||
|
||||
/*
|
||||
* We are not drawing yet.
|
||||
*/
|
||||
|
||||
[NSApp setIsDrawing:NO];
|
||||
[NSApp setSimulateDrawing:NO];
|
||||
|
||||
/*
|
||||
* Be our own delegate.
|
||||
*/
|
||||
@@ -160,6 +180,7 @@ long tkMacOSXMacOSXVersion = 0;
|
||||
/*
|
||||
* Make sure we are allowed to open windows.
|
||||
*/
|
||||
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
||||
/*
|
||||
@@ -255,7 +276,6 @@ TkpInit(
|
||||
*/
|
||||
|
||||
if (!initialized) {
|
||||
struct utsname name;
|
||||
struct stat st;
|
||||
|
||||
initialized = 1;
|
||||
@@ -268,20 +288,6 @@ TkpInit(
|
||||
# error Mac OS X 10.6 required
|
||||
#endif
|
||||
|
||||
if (!uname(&name)) {
|
||||
tkMacOSXMacOSXVersion = (strtod(name.release, NULL) + 96) * 10;
|
||||
}
|
||||
/*Check for new versioning scheme on Yosemite (10.10) and later.*/
|
||||
if (MAC_OS_X_VERSION_MIN_REQUIRED > 100000) {
|
||||
tkMacOSXMacOSXVersion = MAC_OS_X_VERSION_MIN_REQUIRED/100;
|
||||
}
|
||||
if (tkMacOSXMacOSXVersion && MAC_OS_X_VERSION_MIN_REQUIRED < 100000 &&
|
||||
tkMacOSXMacOSXVersion/10 < MAC_OS_X_VERSION_MIN_REQUIRED/10) {
|
||||
Tcl_Panic("Mac OS X 10.%d or later required !",
|
||||
(MAC_OS_X_VERSION_MIN_REQUIRED/10)-100);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TK_FRAMEWORK
|
||||
/*
|
||||
* When Tk is in a framework, force tcl_findLibrary to look in the
|
||||
|
||||
@@ -83,11 +83,10 @@ typedef struct TkWindowPrivate MacDrawable;
|
||||
#define TK_CLIP_INVALID 0x02
|
||||
#define TK_HOST_EXISTS 0x04
|
||||
#define TK_DRAWN_UNDER_MENU 0x08
|
||||
#define TK_FOCUSED_VIEW 0x10
|
||||
#define TK_IS_PIXMAP 0x20
|
||||
#define TK_IS_BW_PIXMAP 0x40
|
||||
#define TK_DO_NOT_DRAW 0x80
|
||||
#define TK_USE_XIMAGE_ALPHA 0x100
|
||||
#define TK_IS_PIXMAP 0x10
|
||||
#define TK_IS_BW_PIXMAP 0x20
|
||||
#define TK_DO_NOT_DRAW 0x40
|
||||
|
||||
/*
|
||||
* I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags
|
||||
* This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the
|
||||
@@ -199,6 +198,10 @@ MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x,
|
||||
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 void TkTestSimulateDrawing(Bool);
|
||||
|
||||
/*
|
||||
* Include the stubbed internal platform-specific API.
|
||||
*/
|
||||
|
||||
@@ -41,6 +41,8 @@ static int caret_x = 0, caret_y = 0, caret_height = 0;
|
||||
static void setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state);
|
||||
static unsigned isFunctionKey(unsigned int code);
|
||||
|
||||
unsigned short releaseCode;
|
||||
|
||||
|
||||
#pragma mark TKApplication(TKKeyEvent)
|
||||
|
||||
@@ -66,14 +68,22 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
processingCompose = NO;
|
||||
}
|
||||
|
||||
w = [theEvent window];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
XEvent xEvent;
|
||||
|
||||
if (!winPtr) {
|
||||
return theEvent;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NSKeyUp:
|
||||
if (finishedCompose)
|
||||
{
|
||||
// if we were composing, swallow the last release since we already sent
|
||||
finishedCompose = NO;
|
||||
return theEvent;
|
||||
}
|
||||
/*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];
|
||||
@@ -82,10 +92,9 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
case NSFlagsChanged:
|
||||
modifiers = [theEvent modifierFlags];
|
||||
keyCode = [theEvent keyCode];
|
||||
// w = [self windowWithWindowNumber:[theEvent windowNumber]];
|
||||
w = [theEvent window];
|
||||
|
||||
#if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1
|
||||
NSLog(@"-[%@(%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);
|
||||
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;
|
||||
|
||||
@@ -171,7 +180,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
xEvent.xkey.keycode = (modifiers ^ savedModifiers);
|
||||
} else {
|
||||
if (type == NSKeyUp || repeat) {
|
||||
xEvent.xany.type = KeyRelease;
|
||||
xEvent.xany.type = KeyRelease;
|
||||
} else {
|
||||
xEvent.xany.type = KeyPress;
|
||||
}
|
||||
@@ -238,11 +247,9 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
{
|
||||
int i, len = [(NSString *)aString length];
|
||||
XEvent xEvent;
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
|
||||
if (NS_KEYLOG)
|
||||
NSLog (@"insertText '%@'\tlen = %d", aString, len);
|
||||
TKLog (@"insertText '%@'\tlen = %d", aString, len);
|
||||
processingCompose = NO;
|
||||
finishedCompose = YES;
|
||||
|
||||
@@ -255,20 +262,17 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
xEvent.xany.type = KeyPress;
|
||||
|
||||
for (i =0; i<len; i++)
|
||||
{
|
||||
xEvent.xkey.keycode = (UInt16) [aString characterAtIndex: i];
|
||||
[[aString substringWithRange: NSMakeRange(i,1)]
|
||||
getCString: xEvent.xkey.trans_chars
|
||||
maxLength: XMaxTransChars encoding: NSUTF8StringEncoding];
|
||||
xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
|
||||
xEvent.xany.type = KeyPress;
|
||||
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
|
||||
|
||||
xEvent.xany.type = KeyRelease;
|
||||
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
|
||||
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
|
||||
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
|
||||
}
|
||||
{
|
||||
xEvent.xkey.keycode = (UInt16) [aString characterAtIndex: i];
|
||||
[[aString substringWithRange: NSMakeRange(i,1)]
|
||||
getCString: xEvent.xkey.trans_chars
|
||||
maxLength: XMaxTransChars encoding: NSUTF8StringEncoding];
|
||||
xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
|
||||
xEvent.xany.type = KeyPress;
|
||||
releaseCode = (UInt16) [aString characterAtIndex: 0];
|
||||
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
|
||||
}
|
||||
releaseCode = (UInt16) [aString characterAtIndex: 0];
|
||||
}
|
||||
|
||||
|
||||
@@ -278,7 +282,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
NSString *str = [aString respondsToSelector: @selector (string)] ?
|
||||
[aString string] : aString;
|
||||
if (NS_KEYLOG)
|
||||
NSLog (@"setMarkedText '%@' len =%lu range %lu from %lu", str,
|
||||
TKLog (@"setMarkedText '%@' len =%lu range %lu from %lu", str,
|
||||
(unsigned long) [str length], (unsigned long) selRange.length,
|
||||
(unsigned long) selRange.location);
|
||||
|
||||
@@ -305,7 +309,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
NSRange rng = privateWorkingText != nil
|
||||
? NSMakeRange (0, [privateWorkingText length]) : NSMakeRange (NSNotFound, 0);
|
||||
if (NS_KEYLOG)
|
||||
NSLog (@"markedRange request");
|
||||
TKLog (@"markedRange request");
|
||||
return rng;
|
||||
}
|
||||
|
||||
@@ -313,7 +317,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
- (void)unmarkText
|
||||
{
|
||||
if (NS_KEYLOG)
|
||||
NSLog (@"unmark (accept) text");
|
||||
TKLog (@"unmark (accept) text");
|
||||
[self deleteWorkingText];
|
||||
processingCompose = NO;
|
||||
}
|
||||
@@ -329,7 +333,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
pt.y = caret_y;
|
||||
|
||||
pt = [self convertPoint: pt toView: nil];
|
||||
pt = [[self window] convertPointToScreen: pt];
|
||||
pt = [[self window] tkConvertPointToScreen: pt];
|
||||
pt.y -= caret_height;
|
||||
|
||||
rect.origin = pt;
|
||||
@@ -348,7 +352,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
- (void)doCommandBySelector: (SEL)aSelector
|
||||
{
|
||||
if (NS_KEYLOG)
|
||||
NSLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector));
|
||||
TKLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector));
|
||||
processingCompose = NO;
|
||||
if (aSelector == @selector (deleteBackward:))
|
||||
{
|
||||
@@ -378,7 +382,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
- (NSRange)selectedRange
|
||||
{
|
||||
if (NS_KEYLOG)
|
||||
NSLog (@"selectedRange request");
|
||||
TKLog (@"selectedRange request");
|
||||
return NSMakeRange (NSNotFound, 0);
|
||||
}
|
||||
|
||||
@@ -386,7 +390,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
- (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
|
||||
{
|
||||
if (NS_KEYLOG)
|
||||
NSLog (@"characterIndexForPoint request");
|
||||
TKLog (@"characterIndexForPoint request");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -396,7 +400,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
static NSAttributedString *str = nil;
|
||||
if (str == nil) str = [NSAttributedString new];
|
||||
if (NS_KEYLOG)
|
||||
NSLog (@"attributedSubstringFromRange request");
|
||||
TKLog (@"attributedSubstringFromRange request");
|
||||
return str;
|
||||
}
|
||||
/* End <NSTextInput> impl. */
|
||||
@@ -410,7 +414,7 @@ static unsigned isFunctionKey(unsigned int code);
|
||||
if (privateWorkingText == nil)
|
||||
return;
|
||||
if (NS_KEYLOG)
|
||||
NSLog(@"deleteWorkingText len = %lu\n",
|
||||
TKLog(@"deleteWorkingText len = %lu\n",
|
||||
(unsigned long)[privateWorkingText length]);
|
||||
[privateWorkingText release];
|
||||
privateWorkingText = nil;
|
||||
@@ -430,6 +434,9 @@ setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
|
||||
{
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
if (!winPtr) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(xEvent, 0, sizeof(XEvent));
|
||||
xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
|
||||
|
||||
@@ -690,7 +690,7 @@ TkpSetKeycodeAndState(
|
||||
eventPtr->xkey.keycode = 0;
|
||||
} else if ( modKeyArray[0] <= keysym &&
|
||||
keysym <= modKeyArray[NUM_MOD_KEYCODES - 1]) {
|
||||
/*
|
||||
/*
|
||||
* Keysyms for pure modifiers only arise in generated events.
|
||||
* We should just copy them to the keycode.
|
||||
*/
|
||||
|
||||
@@ -773,7 +773,7 @@ TkpPostMenu(
|
||||
int result;
|
||||
|
||||
inPostMenu = 1;
|
||||
|
||||
|
||||
result = TkPreprocessMenu(menuPtr);
|
||||
if (result != TCL_OK) {
|
||||
inPostMenu = 0;
|
||||
@@ -785,7 +785,7 @@ TkpPostMenu(
|
||||
NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1);
|
||||
|
||||
frame.origin = [view convertPoint:
|
||||
[win convertPointFromScreen:frame.origin] fromView:nil];
|
||||
[win tkConvertPointFromScreen:frame.origin] fromView:nil];
|
||||
|
||||
NSMenu *menu = (NSMenu *) menuPtr->platformData;
|
||||
NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc]
|
||||
@@ -1139,7 +1139,7 @@ TkpComputeStandardMenuGeometry(
|
||||
columnEntryPtr->x = x;
|
||||
columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
|
||||
}
|
||||
x += maxIndicatorSpace + maxWidth + 2 * borderWidth;
|
||||
x += maxIndicatorSpace + maxWidth + 2 * activeBorderWidth;
|
||||
maxWidth = maxIndicatorSpace = 0;
|
||||
lastColumnBreak = i;
|
||||
y = borderWidth;
|
||||
@@ -1625,8 +1625,7 @@ TkpDrawMenuEntry(
|
||||
int height, /* Height of the current rectangle */
|
||||
int strictMotif, /* Boolean flag */
|
||||
int drawArrow) /* Whether or not to draw the cascade arrow
|
||||
* for cascade items. Only applies to
|
||||
* Windows. */
|
||||
* for cascade items. */
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -843,3 +843,11 @@ TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 79
|
||||
* coding: utf-8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -379,13 +379,13 @@ GenerateEditEvent(
|
||||
XVirtualEvent event;
|
||||
int x, y;
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow([NSApp keyWindow]);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
Tk_Window tkwin;
|
||||
|
||||
if (tkwin == NULL) {
|
||||
if (!winPtr) {
|
||||
return;
|
||||
}
|
||||
tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
|
||||
if (tkwin == NULL) {
|
||||
if (!tkwin) {
|
||||
return;
|
||||
}
|
||||
bzero(&event, sizeof(XVirtualEvent));
|
||||
|
||||
@@ -90,14 +90,14 @@ enum {
|
||||
/* Create an Xevent to add to the Tk queue. */
|
||||
NSPoint global, local = [theEvent locationInWindow];
|
||||
if (eventWindow) { /* local will be in window coordinates. */
|
||||
global = [eventWindow convertPointToScreen: local];
|
||||
global = [eventWindow tkConvertPointToScreen: local];
|
||||
local.y = [eventWindow frame].size.height - local.y;
|
||||
global.y = tkMacOSXZeroScreenHeight - global.y;
|
||||
} else { /* local will be in screen coordinates. */
|
||||
if (_windowWithMouse ) {
|
||||
eventWindow = _windowWithMouse;
|
||||
global = local;
|
||||
local = [eventWindow convertPointFromScreen: local];
|
||||
local = [eventWindow tkConvertPointFromScreen: local];
|
||||
local.y = [eventWindow frame].size.height - local.y;
|
||||
global.y = tkMacOSXZeroScreenHeight - global.y;
|
||||
} else { /* We have no window. Use the screen???*/
|
||||
@@ -373,7 +373,7 @@ XQueryPointer(
|
||||
if (win) {
|
||||
NSPoint local;
|
||||
|
||||
local = [win convertPointFromScreen:global];
|
||||
local = [win tkConvertPointFromScreen:global];
|
||||
local.y = [win frame].size.height - local.y;
|
||||
if (macWin->winPtr && macWin->winPtr->wmInfoPtr) {
|
||||
local.x -= macWin->winPtr->wmInfoPtr->xInParent;
|
||||
@@ -471,7 +471,7 @@ TkGenerateButtonEvent(
|
||||
if (win) {
|
||||
NSPoint local = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
|
||||
|
||||
local = [win convertPointFromScreen:local];
|
||||
local = [win tkConvertPointFromScreen:local];
|
||||
local.y = [win frame].size.height - local.y;
|
||||
if (macWin->winPtr && macWin->winPtr->wmInfoPtr) {
|
||||
local.x -= macWin->winPtr->wmInfoPtr->xInParent;
|
||||
|
||||
@@ -32,6 +32,85 @@ static void TkMacOSXNotifyExitHandler(ClientData clientData);
|
||||
static void TkMacOSXEventsSetupProc(ClientData clientData, int flags);
|
||||
static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
|
||||
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
static char* Tk_EventName[39] = {
|
||||
"",
|
||||
"",
|
||||
"KeyPress", /*2*/
|
||||
"KeyRelease", /*3*/
|
||||
"ButtonPress", /*4*/
|
||||
"ButtonRelease", /*5*/
|
||||
"MotionNotify", /*6*/
|
||||
"EnterNotify", /*7*/
|
||||
"LeaveNotify", /*8*/
|
||||
"FocusIn", /*9*/
|
||||
"FocusOut", /*10*/
|
||||
"KeymapNotify", /*11*/
|
||||
"Expose", /*12*/
|
||||
"GraphicsExpose", /*13*/
|
||||
"NoExpose", /*14*/
|
||||
"VisibilityNotify", /*15*/
|
||||
"CreateNotify", /*16*/
|
||||
"DestroyNotify", /*17*/
|
||||
"UnmapNotify", /*18*/
|
||||
"MapNotify", /*19*/
|
||||
"MapRequest", /*20*/
|
||||
"ReparentNotify", /*21*/
|
||||
"ConfigureNotify", /*22*/
|
||||
"ConfigureRequest", /*23*/
|
||||
"GravityNotify", /*24*/
|
||||
"ResizeRequest", /*25*/
|
||||
"CirculateNotify", /*26*/
|
||||
"CirculateRequest", /*27*/
|
||||
"PropertyNotify", /*28*/
|
||||
"SelectionClear", /*29*/
|
||||
"SelectionRequest", /*30*/
|
||||
"SelectionNotify", /*31*/
|
||||
"ColormapNotify", /*32*/
|
||||
"ClientMessage", /*33*/
|
||||
"MappingNotify", /*34*/
|
||||
"VirtualEvent", /*35*/
|
||||
"ActivateNotify", /*36*/
|
||||
"DeactivateNotify", /*37*/
|
||||
"MouseWheelEvent" /*38*/
|
||||
};
|
||||
|
||||
static Tk_RestrictAction
|
||||
InspectQueueRestrictProc(
|
||||
ClientData arg,
|
||||
XEvent *eventPtr)
|
||||
{
|
||||
XVirtualEvent* ve = (XVirtualEvent*) eventPtr;
|
||||
const char *name;
|
||||
long serial = ve->serial;
|
||||
long time = eventPtr->xkey.time;
|
||||
|
||||
if (eventPtr->type == VirtualEvent) {
|
||||
name = ve->name;
|
||||
} else {
|
||||
name = Tk_EventName[eventPtr->type];
|
||||
}
|
||||
fprintf(stderr, " > %s;serial = %lu; time=%lu)\n",
|
||||
name, serial, time);
|
||||
return TK_DEFER_EVENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging tool which prints the current Tcl queue.
|
||||
*/
|
||||
|
||||
void DebugPrintQueue(void)
|
||||
{
|
||||
ClientData oldArg;
|
||||
Tk_RestrictProc *oldProc;
|
||||
|
||||
oldProc = Tk_RestrictEvents(InspectQueueRestrictProc, NULL, &oldArg);
|
||||
fprintf(stderr, "Current queue:\n");
|
||||
while (Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT)) {};
|
||||
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
|
||||
}
|
||||
# endif
|
||||
|
||||
#pragma mark TKApplication(TKNotify)
|
||||
|
||||
@interface NSApplication(TKNotify)
|
||||
@@ -39,31 +118,26 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
|
||||
- (void) _modalSession: (NSModalSession) session sendEvent: (NSEvent *) event;
|
||||
@end
|
||||
|
||||
@implementation NSWindow(TKNotify)
|
||||
- (id) tkDisplayIfNeeded
|
||||
{
|
||||
if (![self isAutodisplay]) {
|
||||
[self displayIfNeeded];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation TKApplication(TKNotify)
|
||||
/* Display all windows each time an event is removed from the queue.*/
|
||||
- (NSEvent *) nextEventMatchingMask: (NSUInteger) mask
|
||||
untilDate: (NSDate *) expiration inMode: (NSString *) mode
|
||||
dequeue: (BOOL) deqFlag
|
||||
{
|
||||
NSEvent *event = [super nextEventMatchingMask:mask
|
||||
untilDate:expiration
|
||||
inMode:mode
|
||||
dequeue:deqFlag];
|
||||
/* Retain this event for later use. Must be released.*/
|
||||
[event retain];
|
||||
[NSApp makeWindowsPerform:@selector(tkDisplayIfNeeded) inOrder:NO];
|
||||
return event;
|
||||
}
|
||||
/*
|
||||
* Earlier versions of Tk would override nextEventMatchingMask here, adding a
|
||||
* call to displayIfNeeded on all windows after calling super. This would cause
|
||||
* windows to be redisplayed (if necessary) each time that an event was
|
||||
* received. This was intended to replace Apple's default autoDisplay
|
||||
* mechanism, which the earlier versions of Tk would disable. When autoDisplay
|
||||
* is set to the default value of YES, the Apple event loop will call
|
||||
* displayIfNeeded on all windows at the beginning of each iteration of their
|
||||
* event loop. Since Tk does not call the Apple event loop, it was thought
|
||||
* that the autoDisplay behavior needed to be replicated.
|
||||
*
|
||||
* However, as of OSX 10.14 (Mojave) the autoDisplay property became
|
||||
* deprecated. Luckily it turns out that, even though we don't ever start the
|
||||
* Apple event loop, the Apple window manager still calls displayIfNeeded on
|
||||
* all windows on a regular basis, perhaps each time the queue is empty. So we
|
||||
* no longer, and perhaps never did need to set autoDisplay to NO, nor call
|
||||
* displayIfNeeded on our windows. We can just leave all of that to the window
|
||||
* manager.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Call super then check the pasteboard.
|
||||
@@ -72,6 +146,10 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
|
||||
{
|
||||
[super sendEvent:theEvent];
|
||||
[NSApp tkCheckPasteboard];
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
fprintf(stderr, "Sending event of type %d\n", (int)[theEvent type]);
|
||||
DebugPrintQueue();
|
||||
#endif
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -91,7 +169,7 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static NSString *
|
||||
NSString *
|
||||
GetRunLoopMode(NSModalSession modalSession)
|
||||
{
|
||||
NSString *runLoopMode = nil;
|
||||
@@ -229,7 +307,6 @@ TkMacOSXEventsSetupProc(
|
||||
if (currentEvent.type > 0) {
|
||||
Tcl_SetMaxBlockTime(&zeroBlockTime);
|
||||
}
|
||||
[currentEvent release];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,7 +375,6 @@ TkMacOSXEventsCheckProc(
|
||||
[NSApp sendEvent:currentEvent];
|
||||
}
|
||||
}
|
||||
[currentEvent release];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,6 @@ typedef struct TkMacOSXDrawingContext {
|
||||
NSView *view;
|
||||
HIShapeRef clipRgn;
|
||||
CGRect portBounds;
|
||||
int focusLocked;
|
||||
} TkMacOSXDrawingContext;
|
||||
|
||||
/*
|
||||
@@ -190,8 +189,7 @@ 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,
|
||||
int use_ximage_alpha);
|
||||
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,
|
||||
@@ -265,9 +263,15 @@ VISIBILITY_HIDDEN
|
||||
#ifdef __i386__
|
||||
/* The Objective C runtime used on i386 requires this. */
|
||||
int _poolLock;
|
||||
int _macMinorVersion;
|
||||
Bool _isDrawing;
|
||||
Bool _simulateDrawing;
|
||||
#endif
|
||||
}
|
||||
@property int poolLock;
|
||||
@property int macMinorVersion;
|
||||
@property Bool isDrawing;
|
||||
@property Bool simulateDrawing;
|
||||
|
||||
@end
|
||||
@interface TKApplication(TKInit)
|
||||
@@ -329,8 +333,7 @@ VISIBILITY_HIDDEN
|
||||
|
||||
@interface TKContentView(TKWindowEvent)
|
||||
- (void) drawRect: (NSRect) rect;
|
||||
- (void) generateExposeEvents: (HIShapeRef) shape;
|
||||
- (void) viewDidEndLiveResize;
|
||||
- (void) generateExposeEvents: (HIShapeRef) shape;
|
||||
- (void) tkToolbarButton: (id) sender;
|
||||
- (BOOL) isOpaque;
|
||||
- (BOOL) wantsDefaultClipping;
|
||||
@@ -343,8 +346,8 @@ VISIBILITY_HIDDEN
|
||||
@end
|
||||
|
||||
@interface NSWindow(TKWm)
|
||||
- (NSPoint) convertPointToScreen:(NSPoint)point;
|
||||
- (NSPoint) convertPointFromScreen:(NSPoint)point;
|
||||
- (NSPoint) tkConvertPointToScreen:(NSPoint)point;
|
||||
- (NSPoint) tkConvertPointFromScreen:(NSPoint)point;
|
||||
@end
|
||||
|
||||
#pragma mark NSMenu & NSMenuItem Utilities
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* Copyright 2001-2009, Apple Inc.
|
||||
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
|
||||
* Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC.
|
||||
* Copyright (c) 2018 Marc Culler
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
@@ -26,25 +27,40 @@
|
||||
|
||||
#define MIN_SLIDER_LENGTH 5
|
||||
|
||||
/*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling of scrollbar values.*/
|
||||
/*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling.*/
|
||||
#ifdef __LP64__
|
||||
#define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum))
|
||||
#else
|
||||
#define RangeToFactor(maximum) (((double) (LONG_MAX >> 1)) / (maximum))
|
||||
#endif /* __LP64__ */
|
||||
|
||||
#define MOUNTAIN_LION_STYLE (NSAppKitVersionNumber < 1138)
|
||||
/*
|
||||
* Apple reversed the scroll direction with the release of OSX 10.7 Lion.
|
||||
*/
|
||||
|
||||
#define SNOW_LEOPARD_STYLE (NSAppKitVersionNumber < 1138)
|
||||
|
||||
/*
|
||||
* Declaration of Mac specific scrollbar structure.
|
||||
* Declaration of an extended scrollbar structure with Mac specific additions.
|
||||
*/
|
||||
|
||||
typedef struct MacScrollbar {
|
||||
TkScrollbar information; /* Generic scrollbar info. */
|
||||
TkScrollbar information; /* Generic scrollbar info. */
|
||||
GC troughGC; /* For drawing trough. */
|
||||
GC copyGC; /* Used for copying from pixmap onto screen. */
|
||||
Bool buttonDown; /* Is the mouse button down? */
|
||||
Bool mouseOver; /* Is the pointer over the scrollbar. */
|
||||
HIThemeTrackDrawInfo info; /* Controls how the scrollbar is drawn. */
|
||||
} MacScrollbar;
|
||||
|
||||
/* Used to initialize a MacScrollbar's info field. */
|
||||
HIThemeTrackDrawInfo defaultInfo = {
|
||||
.version = 0,
|
||||
.min = 0.0,
|
||||
.max = 100.0,
|
||||
.attributes = kThemeTrackShowThumb,
|
||||
};
|
||||
|
||||
/*
|
||||
* The class procedure table for the scrollbar widget. All fields except size
|
||||
* are left initialized to NULL, which should happen automatically since the
|
||||
@@ -59,31 +75,25 @@ const Tk_ClassProcs tkpScrollbarProcs = {
|
||||
};
|
||||
|
||||
|
||||
/*Information on scrollbar layout, metrics, and draw info.*/
|
||||
/* Information on scrollbar layout, metrics, and draw info.*/
|
||||
typedef struct ScrollbarMetrics {
|
||||
SInt32 width, minThumbHeight;
|
||||
int minHeight, topArrowHeight, bottomArrowHeight;
|
||||
NSControlSize controlSize;
|
||||
} ScrollbarMetrics;
|
||||
|
||||
static ScrollbarMetrics metrics[2] = {
|
||||
{15, 54, 26, 14, 14, kControlSizeNormal}, /* kThemeScrollBarMedium */
|
||||
{11, 40, 20, 10, 10, kControlSizeSmall}, /* kThemeScrollBarSmall */
|
||||
};
|
||||
HIThemeTrackDrawInfo info = {
|
||||
.version = 0,
|
||||
.min = 0.0,
|
||||
.max = 100.0,
|
||||
.attributes = kThemeTrackShowThumb,
|
||||
|
||||
static ScrollbarMetrics metrics = {
|
||||
15, 54, 26, 14, 14, kControlSizeNormal /* kThemeScrollBarMedium */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Forward declarations for procedures defined later in this file:
|
||||
* Declarations of static functions defined later in this file:
|
||||
*/
|
||||
|
||||
static void ScrollbarEventProc(ClientData clientData, XEvent *eventPtr);
|
||||
static int ScrollbarPress(TkScrollbar *scrollPtr, XEvent *eventPtr);
|
||||
static int ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr);
|
||||
static void UpdateControlValues(TkScrollbar *scrollPtr);
|
||||
|
||||
/*
|
||||
@@ -111,8 +121,19 @@ TkpCreateScrollbar(
|
||||
|
||||
scrollPtr->troughGC = None;
|
||||
scrollPtr->copyGC = None;
|
||||
|
||||
Tk_CreateEventHandler(tkwin,ExposureMask|StructureNotifyMask|FocusChangeMask|ButtonPressMask|ButtonReleaseMask|EnterWindowMask|LeaveWindowMask|VisibilityChangeMask, ScrollbarEventProc, scrollPtr);
|
||||
scrollPtr->info = defaultInfo;
|
||||
scrollPtr->buttonDown = false;
|
||||
|
||||
Tk_CreateEventHandler(tkwin,
|
||||
ExposureMask |
|
||||
StructureNotifyMask |
|
||||
FocusChangeMask |
|
||||
ButtonPressMask |
|
||||
ButtonReleaseMask |
|
||||
EnterWindowMask |
|
||||
LeaveWindowMask |
|
||||
VisibilityChangeMask,
|
||||
ScrollbarEventProc, scrollPtr);
|
||||
|
||||
return (TkScrollbar *) scrollPtr;
|
||||
}
|
||||
@@ -130,7 +151,7 @@ TkpCreateScrollbar(
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Information appears on the screen.
|
||||
* Draws a scrollbar on the screen.
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
@@ -140,6 +161,7 @@ TkpDisplayScrollbar(
|
||||
ClientData clientData) /* Information about window. */
|
||||
{
|
||||
register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
|
||||
MacScrollbar *msPtr = (MacScrollbar *) scrollPtr;
|
||||
register Tk_Window tkwin = scrollPtr->tkwin;
|
||||
TkWindow *winPtr = (TkWindow *) tkwin;
|
||||
TkMacOSXDrawingContext dc;
|
||||
@@ -163,7 +185,7 @@ TkpDisplayScrollbar(
|
||||
.ty = viewHeight};
|
||||
CGContextConcatCTM(dc.context, t);
|
||||
|
||||
/*Draw Unix-style scroll trough to provide rect for native scrollbar.*/
|
||||
/*Draw a 3D rectangle to provide a base for the native scrollbar.*/
|
||||
if (scrollPtr->highlightWidth != 0) {
|
||||
GC fgGC, bgGC;
|
||||
|
||||
@@ -187,12 +209,13 @@ TkpDisplayScrollbar(
|
||||
Tk_Width(tkwin) - 2*scrollPtr->inset,
|
||||
Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT);
|
||||
|
||||
/*Update values and draw in native rect.*/
|
||||
/* Update values and then draw the native scrollbar over the rectangle.*/
|
||||
UpdateControlValues(scrollPtr);
|
||||
if (MOUNTAIN_LION_STYLE) {
|
||||
HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationInverted);
|
||||
|
||||
if (SNOW_LEOPARD_STYLE) {
|
||||
HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationInverted);
|
||||
} else {
|
||||
HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal);
|
||||
HIThemeDrawTrack (&(msPtr->info), 0, dc.context, kHIThemeOrientationNormal);
|
||||
}
|
||||
TkMacOSXRestoreDrawingContext(&dc);
|
||||
|
||||
@@ -218,76 +241,89 @@ TkpDisplayScrollbar(
|
||||
*/
|
||||
|
||||
|
||||
extern void
|
||||
|
||||
extern void
|
||||
TkpComputeScrollbarGeometry(
|
||||
register TkScrollbar *scrollPtr)
|
||||
/* Scrollbar whose geometry may have
|
||||
* changed. */
|
||||
register TkScrollbar *scrollPtr)
|
||||
/* Scrollbar whose geometry may have
|
||||
* changed. */
|
||||
{
|
||||
|
||||
int variant, fieldLength;
|
||||
/*
|
||||
* The code below is borrowed from tkUnixScrlbr.c but has been adjusted to
|
||||
* account for some differences between macOS and X11. The Unix scrollbar
|
||||
* has an arrow button on each end. On macOS 10.6 (Snow Leopard) the
|
||||
* scrollbars by default have both arrow buttons at the bottom or right.
|
||||
* (There is a preferences setting to use the Unix layout, but we are not
|
||||
* supporting that!) On more recent versions of macOS there are no arrow
|
||||
* buttons at all. The case of no arrow buttons can be handled as a special
|
||||
* case of having both buttons at the end, but where scrollPtr->arrowLength
|
||||
* happens to be zero. To adjust for having both arrows at the same end we
|
||||
* shift the scrollbar up by the arrowLength.
|
||||
*/
|
||||
|
||||
int fieldLength;
|
||||
|
||||
if (scrollPtr->highlightWidth < 0) {
|
||||
scrollPtr->highlightWidth = 0;
|
||||
scrollPtr->highlightWidth = 0;
|
||||
}
|
||||
scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
|
||||
variant = ((scrollPtr->vertical ? Tk_Width(scrollPtr->tkwin) :
|
||||
Tk_Height(scrollPtr->tkwin)) - 2 * scrollPtr->inset
|
||||
< metrics[0].width) ? 1 : 0;
|
||||
scrollPtr->arrowLength = (metrics[variant].topArrowHeight +
|
||||
metrics[variant].bottomArrowHeight) / 2;
|
||||
fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)
|
||||
: Tk_Width(scrollPtr->tkwin))
|
||||
- 2 * (scrollPtr->arrowLength + scrollPtr->inset);
|
||||
if (fieldLength < 0) {
|
||||
fieldLength = 0;
|
||||
if ([NSApp macMinorVersion] == 6) {
|
||||
scrollPtr->arrowLength = scrollPtr->width;
|
||||
} else {
|
||||
scrollPtr->arrowLength = 0;
|
||||
}
|
||||
scrollPtr->sliderFirst = fieldLength * scrollPtr->firstFraction;
|
||||
scrollPtr->sliderLast = fieldLength * scrollPtr->lastFraction;
|
||||
fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)
|
||||
: Tk_Width(scrollPtr->tkwin))
|
||||
- 2*(scrollPtr->arrowLength + scrollPtr->inset);
|
||||
if (fieldLength < 0) {
|
||||
fieldLength = 0;
|
||||
}
|
||||
scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction;
|
||||
scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction;
|
||||
|
||||
/*
|
||||
* Adjust the slider so that some piece of it is always
|
||||
* displayed in the scrollbar and so that it has at least
|
||||
* a minimal width (so it can be grabbed with the mouse).
|
||||
* Adjust the slider so that some piece of it is always displayed in the
|
||||
* scrollbar and so that it has at least a minimal width (so it can be
|
||||
* grabbed with the mouse).
|
||||
*/
|
||||
|
||||
if (scrollPtr->sliderFirst > (fieldLength - 2*scrollPtr->borderWidth)) {
|
||||
scrollPtr->sliderFirst = fieldLength - 2*scrollPtr->borderWidth;
|
||||
if (scrollPtr->sliderFirst > fieldLength - MIN_SLIDER_LENGTH) {
|
||||
scrollPtr->sliderFirst = fieldLength - MIN_SLIDER_LENGTH;
|
||||
}
|
||||
if (scrollPtr->sliderFirst < 0) {
|
||||
scrollPtr->sliderFirst = 0;
|
||||
scrollPtr->sliderFirst = 0;
|
||||
}
|
||||
if (scrollPtr->sliderLast < (scrollPtr->sliderFirst +
|
||||
metrics[variant].minThumbHeight)) {
|
||||
scrollPtr->sliderLast = scrollPtr->sliderFirst +
|
||||
metrics[variant].minThumbHeight;
|
||||
if (scrollPtr->sliderLast < scrollPtr->sliderFirst + MIN_SLIDER_LENGTH) {
|
||||
scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;
|
||||
}
|
||||
if (scrollPtr->sliderLast > fieldLength) {
|
||||
scrollPtr->sliderLast = fieldLength;
|
||||
scrollPtr->sliderLast = fieldLength;
|
||||
}
|
||||
scrollPtr->sliderFirst += -scrollPtr->arrowLength + scrollPtr->inset;
|
||||
scrollPtr->sliderLast += scrollPtr->inset;
|
||||
|
||||
scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset;
|
||||
scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset;
|
||||
|
||||
|
||||
/* Register the desired geometry for the window (leave enough space
|
||||
* for the two arrows plus a minimum-size slider, plus border around
|
||||
* the whole window, if any). Then arrange for the window to be
|
||||
* redisplayed.
|
||||
/*
|
||||
* Register the desired geometry for the window. Leave enough space for the
|
||||
* two arrows, if there are any arrows, plus a minimum-size slider, plus
|
||||
* border around the whole window, if any. Then arrange for the window to
|
||||
* be redisplayed.
|
||||
*/
|
||||
|
||||
if (scrollPtr->vertical) {
|
||||
Tk_GeometryRequest(scrollPtr->tkwin, scrollPtr->width + 2 * scrollPtr->inset, 2 * (scrollPtr->arrowLength + scrollPtr->borderWidth + scrollPtr->inset) + metrics[variant].minThumbHeight);
|
||||
if (scrollPtr->vertical) {
|
||||
Tk_GeometryRequest(scrollPtr->tkwin,
|
||||
scrollPtr->width + 2*scrollPtr->inset,
|
||||
2*(scrollPtr->arrowLength + scrollPtr->borderWidth
|
||||
+ scrollPtr->inset) + metrics.minThumbHeight);
|
||||
} else {
|
||||
Tk_GeometryRequest(scrollPtr->tkwin, 2 * (scrollPtr->arrowLength + scrollPtr->borderWidth + scrollPtr->inset) + metrics[variant].minThumbHeight, scrollPtr->width + 2 * scrollPtr->inset);
|
||||
Tk_GeometryRequest(scrollPtr->tkwin,
|
||||
2*(scrollPtr->arrowLength + scrollPtr->borderWidth
|
||||
+ scrollPtr->inset) + metrics.minThumbHeight,
|
||||
scrollPtr->width + 2*scrollPtr->inset);
|
||||
}
|
||||
Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -316,8 +352,6 @@ TkpDestroyScrollbar(
|
||||
if (macScrollPtr->copyGC != None) {
|
||||
Tk_FreeGC(scrollPtr->display, macScrollPtr->copyGC);
|
||||
}
|
||||
|
||||
macScrollPtr=NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -327,13 +361,13 @@ TkpDestroyScrollbar(
|
||||
*
|
||||
* This procedure is called after the generic code has finished
|
||||
* processing configuration options, in order to configure platform
|
||||
* specific options.
|
||||
* specific options. There are no such option on the Mac, however.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Configuration info may get changed.
|
||||
* Currently, none.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -341,8 +375,6 @@ TkpDestroyScrollbar(
|
||||
void
|
||||
TkpConfigureScrollbar(
|
||||
register TkScrollbar *scrollPtr)
|
||||
/* Information about widget; may or may not
|
||||
* already have values for some fields. */
|
||||
{
|
||||
|
||||
}
|
||||
@@ -372,54 +404,51 @@ TkpScrollbarPosition(
|
||||
int x, int y) /* Coordinates within scrollPtr's window. */
|
||||
{
|
||||
|
||||
/*
|
||||
* Using code from tkUnixScrlbr.c because Unix scroll bindings are
|
||||
* driving the display at the script level. All the Mac scrollbar
|
||||
* has to do is re-draw itself.
|
||||
/*
|
||||
* The code below is borrowed from tkUnixScrlbr.c and needs no adjustment
|
||||
* since it does not involve the arrow buttons.
|
||||
*/
|
||||
|
||||
int length, fieldlength, width, tmp;
|
||||
int length, width, tmp;
|
||||
register const int inset = scrollPtr->inset;
|
||||
register const int arrowSize = scrollPtr->arrowLength + inset;
|
||||
|
||||
if (scrollPtr->vertical) {
|
||||
length = Tk_Height(scrollPtr->tkwin);
|
||||
fieldlength = length - 2 * arrowSize;
|
||||
width = Tk_Width(scrollPtr->tkwin);
|
||||
} else {
|
||||
tmp = x;
|
||||
x = y;
|
||||
y = tmp;
|
||||
length = Tk_Width(scrollPtr->tkwin);
|
||||
fieldlength = length - 2 * arrowSize;
|
||||
width = Tk_Height(scrollPtr->tkwin);
|
||||
}
|
||||
|
||||
fieldlength = fieldlength < 0 ? 0 : fieldlength;
|
||||
|
||||
if (x<inset || x>=width-inset || y<inset || y>=length-inset) {
|
||||
if (x < inset || x >= width - inset ||
|
||||
y < inset || y >= length - inset) {
|
||||
return OUTSIDE;
|
||||
}
|
||||
|
||||
/*
|
||||
* All of the calculations in this procedure mirror those in
|
||||
* TkpDisplayScrollbar. Be sure to keep the two consistent.
|
||||
* Here we assume that the scrollbar is layed out with both arrow buttons
|
||||
* at the bottom (or right). Except on 10.6, however, the arrows do not
|
||||
* actually exist, i.e. the arrowLength is 0. These are the same
|
||||
* assumptions which are being made in TkpComputeScrollbarGeometry.
|
||||
*/
|
||||
|
||||
if (y < scrollPtr->sliderFirst) {
|
||||
if (y < scrollPtr->sliderFirst + scrollPtr->arrowLength) {
|
||||
return TOP_GAP;
|
||||
}
|
||||
if (y < scrollPtr->sliderLast) {
|
||||
}
|
||||
if (y < scrollPtr->sliderLast) {
|
||||
return SLIDER;
|
||||
}
|
||||
if (y < fieldlength){
|
||||
}
|
||||
if (y < length - (2*scrollPtr->arrowLength + inset)) {
|
||||
return BOTTOM_GAP;
|
||||
}
|
||||
if (y < fieldlength + arrowSize) {
|
||||
}
|
||||
/* On systems newer than 10.6 we have already returned. */
|
||||
if (y < length - (scrollPtr->arrowLength + inset)) {
|
||||
return TOP_ARROW;
|
||||
}
|
||||
return BOTTOM_ARROW;
|
||||
|
||||
}
|
||||
return BOTTOM_ARROW;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -429,7 +458,7 @@ TkpScrollbarPosition(
|
||||
*
|
||||
* This procedure updates the Macintosh scrollbar control to
|
||||
* display the values defined by the Tk scrollbar. This is the
|
||||
* key interface to the Mac-native * scrollbar; the Unix bindings
|
||||
* key interface to the Mac-native scrollbar; the Unix bindings
|
||||
* drive scrolling in the Tk window and all the Mac scrollbar has
|
||||
* to do is redraw itself.
|
||||
*
|
||||
@@ -446,11 +475,11 @@ static void
|
||||
UpdateControlValues(
|
||||
TkScrollbar *scrollPtr) /* Scrollbar data struct. */
|
||||
{
|
||||
MacScrollbar *msPtr = (MacScrollbar *)scrollPtr;
|
||||
Tk_Window tkwin = scrollPtr->tkwin;
|
||||
MacDrawable *macWin = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
|
||||
double dViewSize;
|
||||
HIRect contrlRect;
|
||||
int variant;
|
||||
short width, height;
|
||||
|
||||
NSView *view = TkMacOSXDrawableView(macWin);
|
||||
@@ -462,23 +491,21 @@ UpdateControlValues(
|
||||
frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
|
||||
|
||||
contrlRect = NSRectToCGRect(frame);
|
||||
info.bounds = contrlRect;
|
||||
msPtr->info.bounds = contrlRect;
|
||||
|
||||
width = contrlRect.size.width;
|
||||
height = contrlRect.size.height;
|
||||
|
||||
variant = contrlRect.size.width < metrics[0].width ? 1 : 0;
|
||||
|
||||
/*
|
||||
* Ensure we set scrollbar control bounds only once all size adjustments
|
||||
* have been computed.
|
||||
*/
|
||||
|
||||
info.bounds = contrlRect;
|
||||
msPtr->info.bounds = contrlRect;
|
||||
if (scrollPtr->vertical) {
|
||||
info.attributes &= ~kThemeTrackHorizontal;
|
||||
msPtr->info.attributes &= ~kThemeTrackHorizontal;
|
||||
} else {
|
||||
info.attributes |= kThemeTrackHorizontal;
|
||||
msPtr->info.attributes |= kThemeTrackHorizontal;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -495,25 +522,25 @@ UpdateControlValues(
|
||||
factor = RangeToFactor(maximum);
|
||||
dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction)
|
||||
* factor;
|
||||
info.max = MIN_SCROLLBAR_VALUE +
|
||||
msPtr->info.max = MIN_SCROLLBAR_VALUE +
|
||||
factor - dViewSize;
|
||||
info.trackInfo.scrollbar.viewsize = dViewSize;
|
||||
msPtr->info.trackInfo.scrollbar.viewsize = dViewSize;
|
||||
if (scrollPtr->vertical) {
|
||||
if (MOUNTAIN_LION_STYLE) {
|
||||
info.value = factor * scrollPtr->firstFraction;
|
||||
if (SNOW_LEOPARD_STYLE) {
|
||||
msPtr->info.value = factor * scrollPtr->firstFraction;
|
||||
} else {
|
||||
info.value = info.max - factor * scrollPtr->firstFraction;
|
||||
msPtr->info.value = msPtr->info.max - factor * scrollPtr->firstFraction;
|
||||
}
|
||||
} else {
|
||||
info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction;
|
||||
msPtr->info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction;
|
||||
}
|
||||
|
||||
if((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0)
|
||||
|| height <= metrics[variant].minHeight) {
|
||||
info.enableState = kThemeTrackHideTrack;
|
||||
|| height <= metrics.minHeight) {
|
||||
msPtr->info.enableState = kThemeTrackHideTrack;
|
||||
} else {
|
||||
info.enableState = kThemeTrackActive;
|
||||
info.attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost;
|
||||
msPtr->info.enableState = kThemeTrackActive;
|
||||
msPtr->info.attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -521,29 +548,79 @@ UpdateControlValues(
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
*
|
||||
* ScrollbarPress --
|
||||
* ScrollbarEvent --
|
||||
*
|
||||
* This procedure is invoked in response to <ButtonPress>, <ButtonRelease>,
|
||||
* <EnterNotify>, and <LeaveNotify> events. Scrollbar appearance is modified.
|
||||
* <EnterNotify>, and <LeaveNotify> events. The Scrollbar appearance is
|
||||
* modified for each event.
|
||||
*
|
||||
*--------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
ScrollbarPress(TkScrollbar *scrollPtr, XEvent *eventPtr)
|
||||
ScrollbarEvent(TkScrollbar *scrollPtr, XEvent *eventPtr)
|
||||
{
|
||||
MacScrollbar *msPtr = (MacScrollbar *)scrollPtr;
|
||||
|
||||
/* The pressState does not indicate whether the moused button was
|
||||
* pressed at some location in the Scrollbar. Rather, it indicates
|
||||
* that the scrollbar should appear as if it were pressed in that
|
||||
* location. The standard Mac behavior is that once the button is
|
||||
* pressed inside the Scrollbar the appearance should not change until
|
||||
* the button is released, even if the mouse moves outside of the
|
||||
* scrollbar. However, if the mouse lies over the scrollbar but the
|
||||
* button is not pressed then the appearance should be the same as if
|
||||
* the button had been pressed on the slider, i.e. kThemeThumbPressed.
|
||||
* See the file Appearance.r, or HIToolbox.bridgesupport on 10.14.
|
||||
*/
|
||||
|
||||
if (eventPtr->type == ButtonPress) {
|
||||
UpdateControlValues(scrollPtr);
|
||||
info.trackInfo.scrollbar.pressState = 1;
|
||||
}
|
||||
if (eventPtr->type == EnterNotify) {
|
||||
info.trackInfo.scrollbar.pressState = 1;
|
||||
}
|
||||
if (eventPtr->type == ButtonRelease || eventPtr->type == LeaveNotify) {
|
||||
info.trackInfo.scrollbar.pressState = 0;
|
||||
}
|
||||
return TCL_OK;
|
||||
if (eventPtr->type == ButtonPress) {
|
||||
msPtr->buttonDown = true;
|
||||
UpdateControlValues(scrollPtr);
|
||||
int where = TkpScrollbarPosition(scrollPtr,
|
||||
eventPtr->xbutton.x,
|
||||
eventPtr->xbutton.y);
|
||||
switch(where) {
|
||||
case OUTSIDE:
|
||||
msPtr->info.trackInfo.scrollbar.pressState = 0;
|
||||
break;
|
||||
case TOP_GAP:
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeTopTrackPressed;
|
||||
break;
|
||||
case SLIDER:
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed;
|
||||
break;
|
||||
case BOTTOM_GAP:
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomTrackPressed;
|
||||
break;
|
||||
case TOP_ARROW:
|
||||
/* This looks wrong and the docs say it is wrong but it works. */
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeTopInsideArrowPressed;
|
||||
break;
|
||||
case BOTTOM_ARROW:
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeBottomOutsideArrowPressed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (eventPtr->type == ButtonRelease) {
|
||||
msPtr->buttonDown = false;
|
||||
if (!msPtr->mouseOver) {
|
||||
msPtr->info.trackInfo.scrollbar.pressState = 0;
|
||||
}
|
||||
}
|
||||
if (eventPtr->type == EnterNotify) {
|
||||
msPtr->mouseOver = true;
|
||||
if (!msPtr->buttonDown) {
|
||||
msPtr->info.trackInfo.scrollbar.pressState = kThemeThumbPressed;
|
||||
}
|
||||
}
|
||||
if (eventPtr->type == LeaveNotify) {
|
||||
msPtr->mouseOver = false;
|
||||
if (!msPtr->buttonDown) {
|
||||
msPtr->info.trackInfo.scrollbar.pressState = 0;
|
||||
}
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -585,9 +662,18 @@ ScrollbarEventProc(
|
||||
case ButtonRelease:
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
ScrollbarPress(clientData, eventPtr);
|
||||
ScrollbarEvent(clientData, eventPtr);
|
||||
break;
|
||||
default:
|
||||
TkScrollbarEventProc(clientData, eventPtr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 79
|
||||
* coding: utf-8
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -205,6 +205,13 @@ XMapWindow(
|
||||
event.xvisibility.type = VisibilityNotify;
|
||||
event.xvisibility.state = VisibilityUnobscured;
|
||||
NotifyVisibility(macWin->winPtr, &event);
|
||||
|
||||
/*
|
||||
* Make sure that subwindows get displayed.
|
||||
*/
|
||||
|
||||
GenerateConfigureNotify(macWin->winPtr, 1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -295,10 +302,12 @@ XUnmapWindow(
|
||||
event.xunmap.from_configure = false;
|
||||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Rebuild the visRgn clip region for the parent so it will be allowed
|
||||
* to draw in the space from which this subwindow was removed.
|
||||
*/
|
||||
|
||||
if (parentPtr && parentPtr->privatePtr->visRgn) {
|
||||
TkMacOSXInvalidateViewRegion(TkMacOSXDrawableView(parentPtr->privatePtr),
|
||||
parentPtr->privatePtr->visRgn);
|
||||
@@ -380,10 +389,12 @@ XMoveResizeWindow(
|
||||
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
|
||||
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
|
||||
if (w) {
|
||||
|
||||
/* We explicitly convert everything to doubles so we don't get
|
||||
* surprised (again) by what happens when you do arithmetic with
|
||||
* unsigned ints.
|
||||
*/
|
||||
|
||||
CGFloat X = (CGFloat)x;
|
||||
CGFloat Y = (CGFloat)y;
|
||||
CGFloat Width = (CGFloat)width;
|
||||
@@ -470,6 +481,7 @@ MoveResizeWindow(
|
||||
if (contWinPtr) {
|
||||
macParent = contWinPtr->privatePtr;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Here we should handle out of process embedding. At this point,
|
||||
* we are assuming that the changes.x,y is not maintained, if you
|
||||
@@ -478,6 +490,7 @@ MoveResizeWindow(
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
* TODO: update all xOff & yOffs
|
||||
*/
|
||||
@@ -569,6 +582,7 @@ XRaiseWindow(
|
||||
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
|
||||
TkWmRestackToplevel(macWin->winPtr, Above, NULL);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* TODO: this should generate damage
|
||||
*/
|
||||
@@ -603,7 +617,8 @@ XLowerWindow(
|
||||
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
|
||||
TkWmRestackToplevel(macWin->winPtr, Below, NULL);
|
||||
} else {
|
||||
/*
|
||||
|
||||
/*
|
||||
* TODO: this should generate damage
|
||||
*/
|
||||
}
|
||||
@@ -874,6 +889,7 @@ TkMacOSXUpdateClipRgn(
|
||||
}
|
||||
CFRelease(rgn);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* An unmapped window has empty clip regions to prevent any
|
||||
* (erroneous) drawing into it or its children from becoming
|
||||
@@ -1134,6 +1150,7 @@ void *
|
||||
TkMacOSXGetRootControl(
|
||||
Drawable drawable)
|
||||
{
|
||||
|
||||
/*
|
||||
* will probably need to fix this up for embedding
|
||||
*/
|
||||
@@ -1314,6 +1331,7 @@ UpdateOffsets(
|
||||
TkWindow *childPtr;
|
||||
|
||||
if (winPtr->privatePtr == NULL) {
|
||||
|
||||
/*
|
||||
* We haven't called Tk_MakeWindowExist for this window yet. The offset
|
||||
* information will be postponed and calulated at that time. (This will
|
||||
|
||||
@@ -79,6 +79,35 @@ DebuggerObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkTestSimulateDrawing --
|
||||
*
|
||||
* A test widget display procedure which records calls can use this to
|
||||
* avoid duplicate calls which would occur due to fact that no valid
|
||||
* graphics context is available to the idle task which is running the
|
||||
* display proc. Note that no actual drawing to the screen will take
|
||||
* place when this flag is set. This is just a wrapper for the NSApp
|
||||
* property.
|
||||
*
|
||||
*
|
||||
* Results:
|
||||
* Calls to low level drawing routines will return without actually
|
||||
* drawing anything to the screen.
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
MODULE_SCOPE void
|
||||
TkTestSimulateDrawing(Bool yesno) {
|
||||
[NSApp setSimulateDrawing:yesno];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: objc
|
||||
|
||||
@@ -68,11 +68,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
#endif
|
||||
BOOL movedOnly = [[notification name]
|
||||
isEqualToString:NSWindowDidMoveNotification];
|
||||
|
||||
if (movedOnly) {
|
||||
/* constraining to screen after move not needed with AppKit */
|
||||
}
|
||||
isEqualToString:NSWindowDidMoveNotification];
|
||||
|
||||
NSWindow *w = [notification object];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
@@ -96,6 +92,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
flags |= TK_SIZE_CHANGED;
|
||||
}
|
||||
if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
|
||||
|
||||
/*
|
||||
* Propagate geometry changes immediately.
|
||||
*/
|
||||
@@ -119,6 +116,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
TkMacOSXIsWindowZoomed(winPtr) ? ZoomState : NormalState;
|
||||
Tk_MapWindow((Tk_Window) winPtr);
|
||||
if (Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
|
||||
|
||||
/*
|
||||
* Process all Tk events generated by Tk_MapWindow().
|
||||
*/
|
||||
@@ -174,6 +172,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
return (winPtr ? NO : YES);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
|
||||
- (void) windowDragStart: (NSNotification *) notification
|
||||
@@ -213,6 +212,8 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
//Tk_UnmapWindow((Tk_Window) winPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* TK_MAC_DEBUG_NOTIFICATIONS */
|
||||
|
||||
- (void) _setupWindowNotifications
|
||||
@@ -236,6 +237,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
observe(NSWindowDidOrderOffScreenNotification, windowUnmapped:);
|
||||
#endif
|
||||
#undef observe
|
||||
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -256,7 +258,6 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
|
||||
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
|
||||
#endif
|
||||
TkSuspendClipboard();
|
||||
}
|
||||
|
||||
- (void) applicationShowHide: (NSNotification *) notification
|
||||
@@ -292,6 +293,31 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkpAppIsDrawing --
|
||||
*
|
||||
* A widget display procedure can call this to determine whether it
|
||||
* is being run inside of the drawRect method. This is needed for
|
||||
* some tests, especially of the Text widget, which record data in
|
||||
* a global Tcl variable and assume that display procedures will be
|
||||
* run in a predictable sequence as Tcl idle tasks.
|
||||
*
|
||||
* Results:
|
||||
* True only while running the drawRect method of a TKContentView;
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
MODULE_SCOPE Bool
|
||||
TkpAppIsDrawing(void) {
|
||||
return [NSApp isDrawing];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -299,7 +325,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
|
||||
* GenerateUpdates --
|
||||
*
|
||||
* Given a Macintosh update region and a Tk window this function geneates
|
||||
* a X Expose event for the window if it is within the update region. The
|
||||
* an X Expose event for the window if it meets the update region. The
|
||||
* function will then recursivly have each damaged window generate Expose
|
||||
* events for its child windows.
|
||||
*
|
||||
@@ -360,7 +386,7 @@ GenerateUpdates(
|
||||
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
|
||||
|
||||
#ifdef TK_MAC_DEBUG_DRAWING
|
||||
NSLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
|
||||
TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
|
||||
event.xexpose.y, event.xexpose.width, event.xexpose.height);
|
||||
#endif
|
||||
|
||||
@@ -579,10 +605,12 @@ TkGenWMConfigureEvent(
|
||||
if ((flags & TK_SIZE_CHANGED) && !(wmPtr->flags & WM_SYNC_PENDING) &&
|
||||
((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) {
|
||||
if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) {
|
||||
|
||||
/*
|
||||
* Don't set external width, since the user didn't change it
|
||||
* from what the widgets asked for.
|
||||
*/
|
||||
|
||||
} else if (wmPtr->gridWin != NULL) {
|
||||
wmPtr->width = wmPtr->reqGridWidth
|
||||
+ (width - winPtr->reqWidth)/wmPtr->widthInc;
|
||||
@@ -594,10 +622,12 @@ TkGenWMConfigureEvent(
|
||||
}
|
||||
|
||||
if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) {
|
||||
|
||||
/*
|
||||
* Don't set external height, since the user didn't change it
|
||||
* from what the widgets asked for.
|
||||
*/
|
||||
|
||||
} else if (wmPtr->gridWin != NULL) {
|
||||
wmPtr->height = wmPtr->reqGridHeight
|
||||
+ (height - winPtr->reqHeight)/wmPtr->heightInc;
|
||||
@@ -796,131 +826,216 @@ ConfigureRestrictProc(
|
||||
const NSRect *rectsBeingDrawn;
|
||||
NSInteger rectsBeingDrawnCount;
|
||||
|
||||
[self getRectsBeingDrawn:&rectsBeingDrawn count:&rectsBeingDrawnCount];
|
||||
|
||||
#ifdef TK_MAC_DEBUG_DRAWING
|
||||
TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd, NSStringFromRect(rect));
|
||||
[[NSColor colorWithDeviceRed:0.0 green:1.0 blue:0.0 alpha:.1] setFill];
|
||||
NSRectFillListUsingOperation(rectsBeingDrawn, rectsBeingDrawnCount,
|
||||
NSCompositeSourceOver);
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
|
||||
if (winPtr) fprintf(stderr, "drawRect: drawing %s\n",
|
||||
Tk_PathName(winPtr));
|
||||
#endif
|
||||
|
||||
if ([NSApp simulateDrawing]) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do not allow recursive calls to drawRect, but we only log
|
||||
* them on OSX > 10.13, where they should never happen.
|
||||
*/
|
||||
|
||||
if ([NSApp isDrawing] && [NSApp macMinorVersion] > 13) {
|
||||
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);
|
||||
}
|
||||
if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
|
||||
[self generateExposeEvents:(HIShapeRef)drawShape];
|
||||
} else {
|
||||
[self performSelectorOnMainThread:@selector(generateExposeEvents:)
|
||||
withObject:(id)drawShape waitUntilDone:NO
|
||||
modes:[NSArray arrayWithObjects:NSRunLoopCommonModes,
|
||||
|
||||
NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode,
|
||||
nil]];
|
||||
}
|
||||
|
||||
[self generateExposeEvents:(HIShapeRef)drawShape];
|
||||
CFRelease(drawShape);
|
||||
[NSApp setIsDrawing: NO];
|
||||
|
||||
#ifdef TK_MAC_DEBUG_DRAWING
|
||||
fprintf(stderr, "drawRect: done.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
-(void) setFrameSize: (NSSize)newsize
|
||||
{
|
||||
[super setFrameSize: newsize];
|
||||
if ([self inLiveResize]) {
|
||||
NSWindow *w = [self window];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
NSWindow *w = [self window];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
if (winPtr) {
|
||||
/* On OSX versions below 10.14 setFrame calls drawRect.
|
||||
* On 10.14 it does its own drawing.
|
||||
*/
|
||||
if ([NSApp macMinorVersion] > 13) {
|
||||
[NSApp setIsDrawing:YES];
|
||||
}
|
||||
unsigned int width = (unsigned int)newsize.width;
|
||||
unsigned int height=(unsigned int)newsize.height;
|
||||
ClientData oldArg;
|
||||
Tk_RestrictProc *oldProc;
|
||||
|
||||
/* This can be called from outside the Tk event loop.
|
||||
/*
|
||||
* This can be called from outside the Tk event loop.
|
||||
* Since it calls Tcl_DoOneEvent, we need to make sure we
|
||||
* don't clobber the AutoreleasePool set up by the caller.
|
||||
*/
|
||||
|
||||
[NSApp _lockAutoreleasePool];
|
||||
|
||||
/*
|
||||
* Try to prevent flickers and flashes.
|
||||
* Disable Tk drawing until the window has been completely configured.
|
||||
*/
|
||||
[w disableFlushWindow];
|
||||
NSDisableScreenUpdates();
|
||||
|
||||
/* Disable Tk drawing until the window has been completely configured.*/
|
||||
TkMacOSXSetDrawingEnabled(winPtr, 0);
|
||||
|
||||
/* Generate and handle a ConfigureNotify event for the new size.*/
|
||||
/*
|
||||
* Generate and handle a ConfigureNotify event for the new size.
|
||||
*/
|
||||
|
||||
TkGenWMConfigureEvent(tkwin, Tk_X(tkwin), Tk_Y(tkwin), width, height,
|
||||
TK_SIZE_CHANGED | TK_MACOSX_HANDLE_EVENT_IMMEDIATELY);
|
||||
oldProc = Tk_RestrictEvents(ConfigureRestrictProc, NULL, &oldArg);
|
||||
while (Tk_DoOneEvent(TK_X_EVENTS|TK_DONT_WAIT)) {}
|
||||
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
|
||||
|
||||
/* Now that Tk has configured all subwindows we can create the clip regions. */
|
||||
/*
|
||||
* Now that Tk has configured all subwindows, create the clip regions.
|
||||
*/
|
||||
|
||||
TkMacOSXSetDrawingEnabled(winPtr, 1);
|
||||
TkMacOSXInvalClipRgns(tkwin);
|
||||
TkMacOSXUpdateClipRgn(winPtr);
|
||||
|
||||
/* Finally, generate and process expose events to redraw the window. */
|
||||
/*
|
||||
* Generate and process expose events to redraw the window.
|
||||
*/
|
||||
|
||||
HIRect bounds = NSRectToCGRect([self bounds]);
|
||||
HIShapeRef shape = HIShapeCreateWithRect(&bounds);
|
||||
[self generateExposeEvents: shape];
|
||||
while (Tk_DoOneEvent(TK_ALL_EVENTS|TK_DONT_WAIT)) {}
|
||||
[w enableFlushWindow];
|
||||
[w flushWindowIfNeeded];
|
||||
NSEnableScreenUpdates();
|
||||
[w displayIfNeeded];
|
||||
|
||||
/*
|
||||
* Finally, unlock the main autoreleasePool.
|
||||
*/
|
||||
|
||||
[NSApp _unlockAutoreleasePool];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* As insurance against bugs that might cause layout glitches during a live
|
||||
* resize, we redraw the window one more time at the end of the resize
|
||||
* operation.
|
||||
* Core method of this class: generates expose events for redrawing. The
|
||||
* expose events are immediately removed from the Tcl event loop and processed.
|
||||
* This causes drawing procedures to be scheduled as idle events. Then all
|
||||
* pending idle events are processed so the drawing will actually take place.
|
||||
*/
|
||||
|
||||
- (void)viewDidEndLiveResize
|
||||
{
|
||||
HIRect bounds = NSRectToCGRect([self bounds]);
|
||||
HIShapeRef shape = HIShapeCreateWithRect(&bounds);
|
||||
[super viewDidEndLiveResize];
|
||||
[self generateExposeEvents: shape];
|
||||
}
|
||||
|
||||
/* Core method of this class: generates expose events for redrawing. If the
|
||||
* Tcl_ServiceMode is set to TCL_SERVICE_ALL then the expose events will be
|
||||
* immediately removed from the Tcl event loop and processed. Typically, they
|
||||
* should be queued, however.
|
||||
*/
|
||||
- (void) generateExposeEvents: (HIShapeRef) shape
|
||||
{
|
||||
unsigned long serial;
|
||||
CGRect updateBounds;
|
||||
int updatesNeeded;
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
|
||||
|
||||
ClientData oldArg;
|
||||
Tk_RestrictProc *oldProc;
|
||||
if (!winPtr) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate Tk Expose events. */
|
||||
/*
|
||||
* Generate Tk Expose events.
|
||||
*/
|
||||
|
||||
HIShapeGetBounds(shape, &updateBounds);
|
||||
/* All of these events will share the same serial number. */
|
||||
|
||||
/*
|
||||
* All of these events will share the same serial number.
|
||||
*/
|
||||
|
||||
serial = LastKnownRequestProcessed(Tk_Display(winPtr));
|
||||
updatesNeeded = GenerateUpdates(shape, &updateBounds, winPtr);
|
||||
|
||||
/* Process the Expose events if the service mode is TCL_SERVICE_ALL */
|
||||
if (updatesNeeded && Tcl_GetServiceMode() == TCL_SERVICE_ALL) {
|
||||
ClientData oldArg;
|
||||
Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc,
|
||||
UINT2PTR(serial), &oldArg);
|
||||
while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
|
||||
if (updatesNeeded) {
|
||||
|
||||
/*
|
||||
* First process all of the Expose events.
|
||||
*/
|
||||
|
||||
oldProc = Tk_RestrictEvents(ExposeRestrictProc, UINT2PTR(serial), &oldArg);
|
||||
while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {};
|
||||
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
|
||||
|
||||
/*
|
||||
* Starting with OSX 10.14, which uses Core Animation to draw windows,
|
||||
* all drawing must be done within the drawRect method. (The CGContext
|
||||
* which draws to the backing CALayer is created by the NSView before
|
||||
* calling drawRect, and destroyed when drawRect returns. Drawing done
|
||||
* with the current CGContext outside of the drawRect method has no
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
||||
- (void) viewDidChangeEffectiveAppearance
|
||||
{
|
||||
XVirtualEvent event;
|
||||
int x, y;
|
||||
NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
||||
NSWindow *w = [self window];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
|
||||
if (!winPtr) {
|
||||
return;
|
||||
}
|
||||
bzero(&event, sizeof(XVirtualEvent));
|
||||
event.type = VirtualEvent;
|
||||
event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
|
||||
event.send_event = false;
|
||||
event.display = Tk_Display(tkwin);
|
||||
event.event = Tk_WindowId(tkwin);
|
||||
event.root = XRootWindow(Tk_Display(tkwin), 0);
|
||||
event.subwindow = None;
|
||||
event.time = TkpGetMS();
|
||||
XQueryPointer(NULL, winPtr->window, NULL, NULL,
|
||||
&event.x_root, &event.y_root, &x, &y, &event.state);
|
||||
Tk_TopCoordsToWindow(tkwin, x, y, &event.x, &event.y);
|
||||
event.same_screen = true;
|
||||
if (osxMode == nil) {
|
||||
event.name = Tk_GetUid("LightAqua");
|
||||
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
|
||||
return;
|
||||
}
|
||||
if ([osxMode isEqual:@"Dark"]) {
|
||||
event.name = Tk_GetUid("DarkAqua");
|
||||
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -928,6 +1043,7 @@ ConfigureRestrictProc(
|
||||
* This is no-op on 10.7 and up because Apple has removed this widget,
|
||||
* but we are leaving it here for backwards compatibility.
|
||||
*/
|
||||
|
||||
- (void) tkToolbarButton: (id) sender
|
||||
{
|
||||
#ifdef TK_MAC_DEBUG_EVENTS
|
||||
@@ -937,6 +1053,9 @@ ConfigureRestrictProc(
|
||||
int x, y;
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
|
||||
Tk_Window tkwin = (Tk_Window) winPtr;
|
||||
if (!winPtr){
|
||||
return;
|
||||
}
|
||||
bzero(&event, sizeof(XVirtualEvent));
|
||||
event.type = VirtualEvent;
|
||||
event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
|
||||
@@ -957,7 +1076,6 @@ ConfigureRestrictProc(
|
||||
- (BOOL) isOpaque
|
||||
{
|
||||
NSWindow *w = [self window];
|
||||
|
||||
return (w && (([w styleMask] & NSTexturedBackgroundWindowMask) ||
|
||||
![w isOpaque]) ? NO : YES);
|
||||
}
|
||||
|
||||
@@ -204,16 +204,16 @@ static int windowHashInit = false;
|
||||
|
||||
@implementation NSWindow(TKWm)
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
|
||||
- (NSPoint) convertPointToScreen: (NSPoint) point
|
||||
- (NSPoint) tkConvertPointToScreen: (NSPoint) point
|
||||
{
|
||||
return [self convertBaseToScreen:point];
|
||||
}
|
||||
- (NSPoint) convertPointFromScreen: (NSPoint)point
|
||||
- (NSPoint) tkConvertPointFromScreen: (NSPoint)point
|
||||
{
|
||||
return [self convertScreenToBase:point];
|
||||
}
|
||||
#else
|
||||
- (NSPoint) convertPointToScreen: (NSPoint) point
|
||||
- (NSPoint) tkConvertPointToScreen: (NSPoint) point
|
||||
{
|
||||
NSRect pointrect;
|
||||
pointrect.origin = point;
|
||||
@@ -221,7 +221,7 @@ static int windowHashInit = false;
|
||||
pointrect.size.height = 0;
|
||||
return [self convertRectToScreen:pointrect].origin;
|
||||
}
|
||||
- (NSPoint) convertPointFromScreen: (NSPoint)point
|
||||
- (NSPoint) tkConvertPointFromScreen: (NSPoint)point
|
||||
{
|
||||
NSRect pointrect;
|
||||
pointrect.origin = point;
|
||||
@@ -231,6 +231,21 @@ static int windowHashInit = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (NSSize)windowWillResize:(NSWindow *)sender
|
||||
toSize:(NSSize)frameSize
|
||||
{
|
||||
NSRect currentFrame = [sender frame];
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(sender);
|
||||
if (winPtr) {
|
||||
if (winPtr->wmInfoPtr->flags & WM_WIDTH_NOT_RESIZABLE) {
|
||||
frameSize.width = currentFrame.size.width;
|
||||
}
|
||||
if (winPtr->wmInfoPtr->flags & WM_HEIGHT_NOT_RESIZABLE) {
|
||||
frameSize.height = currentFrame.size.height;
|
||||
}
|
||||
}
|
||||
return frameSize;
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@@ -372,20 +387,48 @@ static void RemapWindows(TkWindow *winPtr,
|
||||
|
||||
|
||||
@implementation TKWindow: NSWindow
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_12
|
||||
/*
|
||||
* Override automatic fullscreen button on >10.12 because system fullscreen API
|
||||
* confuses Tk window geometry.
|
||||
*/
|
||||
|
||||
/* Custom fullscreen implementation on 10.13 and above. On older versions of
|
||||
* macOS dating back to 10.7, the NSWindow fullscreen API was opt-in, requiring
|
||||
* explicit calls to toggleFullScreen. On 10.13, the API became implicit,
|
||||
* applying to all NSWindows unless they were marked non-resizable; this caused
|
||||
* issues with Tk, which was not aware of changes in screen geometry. Here we
|
||||
* override the toggleFullScreen call to hook directly into Tk's own fullscreen
|
||||
* API, allowing Tk to function smoothly with the Mac's fullscreen button.
|
||||
*/
|
||||
|
||||
NSStatusItem *exitFullScreen;
|
||||
|
||||
|
||||
- (void)toggleFullScreen:(id)sender
|
||||
{
|
||||
if ([self isZoomed]) {
|
||||
TkMacOSXZoomToplevel(self, inZoomIn);
|
||||
} else {
|
||||
TkMacOSXZoomToplevel(self, inZoomOut);
|
||||
}
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(self);
|
||||
if (!winPtr) {
|
||||
return;
|
||||
}
|
||||
Tcl_Interp *interp = Tk_Interp((Tk_Window)winPtr);
|
||||
if ([NSApp macMinorVersion] > 12) {
|
||||
if (([self styleMask] & NSFullScreenWindowMask) == NSFullScreenWindowMask) {
|
||||
TkMacOSXMakeFullscreen(winPtr, self, 0, interp);
|
||||
} else {
|
||||
TkMacOSXMakeFullscreen(winPtr, self, 1, interp);
|
||||
}
|
||||
} else {
|
||||
TKLog (@"toggleFullScreen is ignored by Tk on OSX versions < 10.13");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
-(void)restoreOldScreen:(id)sender
|
||||
{
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(self);
|
||||
if (!winPtr) {
|
||||
return;
|
||||
}
|
||||
Tcl_Interp *interp = Tk_Interp((Tk_Window)winPtr);
|
||||
TkMacOSXMakeFullscreen(winPtr, self, 0, interp);
|
||||
[[NSStatusBar systemStatusBar] removeStatusItem: exitFullScreen];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TKWindow(TKWm)
|
||||
@@ -393,14 +436,15 @@ static void RemapWindows(TkWindow *winPtr,
|
||||
- (BOOL) canBecomeKeyWindow
|
||||
{
|
||||
TkWindow *winPtr = TkMacOSXGetTkWindow(self);
|
||||
|
||||
return (winPtr && winPtr->wmInfoPtr && (winPtr->wmInfoPtr->macClass ==
|
||||
kHelpWindowClass || winPtr->wmInfoPtr->attributes &
|
||||
kWindowNoActivatesAttribute)) ? NO : YES;
|
||||
if (!winPtr) {
|
||||
return NO;
|
||||
}
|
||||
return (winPtr->wmInfoPtr &&
|
||||
(winPtr->wmInfoPtr->macClass == kHelpWindowClass ||
|
||||
winPtr->wmInfoPtr->attributes & kWindowNoActivatesAttribute)
|
||||
) ? NO : YES;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if DEBUG_ZOMBIES
|
||||
- (id) retain
|
||||
{
|
||||
@@ -410,7 +454,8 @@ static void RemapWindows(TkWindow *winPtr,
|
||||
title = "unnamed window";
|
||||
}
|
||||
if (DEBUG_ZOMBIES > 1){
|
||||
printf("Retained <%s>. Count is: %lu\n", title, [self retainCount]);
|
||||
fprintf(stderr, "Retained <%s>. Count is: %lu\n",
|
||||
title, [self retainCount]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -423,7 +468,8 @@ static void RemapWindows(TkWindow *winPtr,
|
||||
title = "unnamed window";
|
||||
}
|
||||
if (DEBUG_ZOMBIES > 1){
|
||||
printf("Autoreleased <%s>. Count is %lu\n", title, [self retainCount]);
|
||||
fprintf(stderr, "Autoreleased <%s>. Count is %lu\n",
|
||||
title, [self retainCount]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -434,7 +480,8 @@ static void RemapWindows(TkWindow *winPtr,
|
||||
title = "unnamed window";
|
||||
}
|
||||
if (DEBUG_ZOMBIES > 1){
|
||||
printf("Releasing <%s>. Count is %lu\n", title, [self retainCount]);
|
||||
fprintf(stderr, "Releasing <%s>. Count is %lu\n",
|
||||
title, [self retainCount]);
|
||||
}
|
||||
[super release];
|
||||
}
|
||||
@@ -445,7 +492,8 @@ static void RemapWindows(TkWindow *winPtr,
|
||||
title = "unnamed window";
|
||||
}
|
||||
if (DEBUG_ZOMBIES > 0){
|
||||
printf(">>>> Freeing <%s>. Count is %lu\n", title, [self retainCount]);
|
||||
fprintf(stderr, ">>>> Freeing <%s>. Count is %lu\n",
|
||||
title, [self retainCount]);
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
@@ -566,15 +614,15 @@ FrontWindowAtPoint(
|
||||
{
|
||||
NSPoint p = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
|
||||
NSArray *windows = [NSApp orderedWindows];
|
||||
TkWindow *front = NULL;
|
||||
TkWindow *winPtr = NULL;
|
||||
|
||||
for (NSWindow *w in windows) {
|
||||
if (w && NSMouseInRect(p, [w frame], NO)) {
|
||||
front = TkMacOSXGetTkWindow(w);
|
||||
break;
|
||||
}
|
||||
winPtr = TkMacOSXGetTkWindow(w);
|
||||
if (winPtr && NSMouseInRect(p, [w frame], NO)) {
|
||||
break;
|
||||
}
|
||||
return front;
|
||||
}
|
||||
return winPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -702,7 +750,6 @@ TkWmMapWindow(
|
||||
* mapped. */
|
||||
{
|
||||
WmInfo *wmPtr = winPtr->wmInfoPtr;
|
||||
|
||||
if (wmPtr->flags & WM_NEVER_MAPPED) {
|
||||
/*
|
||||
* Create the underlying Mac window for this Tk window.
|
||||
@@ -774,7 +821,6 @@ TkWmMapWindow(
|
||||
/*Add window to Window menu.*/
|
||||
NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
|
||||
[win setExcludedFromWindowsMenu:NO];
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3430,7 +3476,15 @@ WmTransientCmd(
|
||||
if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tk_MakeWindowExist(master);
|
||||
TkWindow* masterPtr = (TkWindow*) master;
|
||||
while (!Tk_TopWinHierarchy(masterPtr)) {
|
||||
/*
|
||||
* Ensure that the master window is actually a Tk toplevel.
|
||||
*/
|
||||
|
||||
masterPtr = masterPtr->parentPtr;
|
||||
}
|
||||
Tk_MakeWindowExist((Tk_Window)masterPtr);
|
||||
|
||||
if (wmPtr->iconFor != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
@@ -3440,8 +3494,7 @@ WmTransientCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
wmPtr2 = ((TkWindow *) master)->wmInfoPtr;
|
||||
|
||||
wmPtr2 = masterPtr->wmInfoPtr;
|
||||
/* Under some circumstances, wmPtr2 is NULL here */
|
||||
if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
@@ -3451,15 +3504,16 @@ WmTransientCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if ((TkWindow *) master == winPtr) {
|
||||
if (masterPtr == winPtr) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"can't make \"%s\" its own master", Tk_PathName(winPtr)));
|
||||
Tcl_SetErrorCode(interp, "TK", "WM", "TRANSIENT", "SELF", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
wmPtr->master = Tk_WindowId(master);
|
||||
masterWindowName = Tcl_GetStringFromObj(objv[3], &length);
|
||||
wmPtr->master = Tk_WindowId(masterPtr);
|
||||
masterWindowName = masterPtr->pathName;
|
||||
length = strlen(masterWindowName);
|
||||
if (wmPtr->masterWindowName != NULL) {
|
||||
ckfree(wmPtr->masterWindowName);
|
||||
}
|
||||
@@ -4251,15 +4305,7 @@ Tk_GetRootCoords(
|
||||
*/
|
||||
|
||||
winPtr = otherPtr;
|
||||
|
||||
/*
|
||||
* Remember to offset by the container window here, since at the
|
||||
* end of this if branch, we will pop out to the container's
|
||||
* parent...
|
||||
*/
|
||||
|
||||
x += winPtr->changes.x + winPtr->changes.border_width;
|
||||
y += winPtr->changes.y + winPtr->changes.border_width;
|
||||
continue;
|
||||
}
|
||||
winPtr = winPtr->parentPtr;
|
||||
}
|
||||
@@ -5612,20 +5658,18 @@ TkMacOSXMakeRealWindowExist(
|
||||
}
|
||||
TKContentView *contentView = [[TKContentView alloc]
|
||||
initWithFrame:NSZeroRect];
|
||||
[window setColorSpace:[NSColorSpace deviceRGBColorSpace]];
|
||||
[window setContentView:contentView];
|
||||
[contentView release];
|
||||
[window setDelegate:NSApp];
|
||||
[window setAcceptsMouseMovedEvents:YES];
|
||||
[window setReleasedWhenClosed:NO];
|
||||
[window setAutodisplay:NO];
|
||||
if (styleMask & NSUtilityWindowMask) {
|
||||
[(NSPanel*)window setFloatingPanel:YES];
|
||||
}
|
||||
if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) &&
|
||||
!(styleMask & NSDocModalWindowMask)) {
|
||||
/*
|
||||
* Workaround for [Bug 2824538]: Texured windows are draggable
|
||||
* Workaround for [Bug 2824538]: Textured windows are draggable
|
||||
* from opaque content.
|
||||
*/
|
||||
[window setMovableByWindowBackground:NO];
|
||||
@@ -5641,11 +5685,38 @@ TkMacOSXMakeRealWindowExist(
|
||||
geometry.size.height += structureRect.size.height;
|
||||
geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y +
|
||||
geometry.size.height);
|
||||
[window setFrame:geometry display:NO];
|
||||
[window setFrame:geometry display:YES];
|
||||
TkMacOSXRegisterOffScreenWindow((Window) macWin, window);
|
||||
macWin->flags |= TK_HOST_EXISTS;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TkpDisplayWindow --
|
||||
*
|
||||
* Mark the contentView of this window as needing display so the
|
||||
* window will be drawn by the window manager. If this is called
|
||||
* within the drawRect method, do nothing.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The window's contentView is marked as needing display.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
MODULE_SCOPE void
|
||||
TkpDisplayWindow(Tk_Window tkwin) {
|
||||
if (![NSApp isDrawing]) {
|
||||
TkWindow *winPtr = (TkWindow*)tkwin;
|
||||
NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);
|
||||
[[w contentView] setNeedsDisplay: YES];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -6268,12 +6339,15 @@ ApplyWindowAttributeFlagChanges(
|
||||
[[macWindow standardWindowButton:NSWindowZoomButton]
|
||||
setEnabled:(newAttributes & kWindowResizableAttribute) &&
|
||||
(newAttributes & kWindowFullZoomAttribute)];
|
||||
if (newAttributes & kWindowResizableAttribute) {
|
||||
wmPtr->flags &= ~(WM_WIDTH_NOT_RESIZABLE |
|
||||
WM_HEIGHT_NOT_RESIZABLE);
|
||||
if (newAttributes & kWindowHorizontalZoomAttribute) {
|
||||
wmPtr->flags &= ~(WM_WIDTH_NOT_RESIZABLE);
|
||||
} else {
|
||||
wmPtr->flags |= (WM_WIDTH_NOT_RESIZABLE |
|
||||
WM_HEIGHT_NOT_RESIZABLE);
|
||||
wmPtr->flags |= (WM_WIDTH_NOT_RESIZABLE);
|
||||
}
|
||||
if (newAttributes & kWindowVerticalZoomAttribute) {
|
||||
wmPtr->flags &= ~(WM_HEIGHT_NOT_RESIZABLE);
|
||||
} else {
|
||||
wmPtr->flags |= (WM_HEIGHT_NOT_RESIZABLE);
|
||||
}
|
||||
WmUpdateGeom(wmPtr, winPtr);
|
||||
}
|
||||
@@ -6457,12 +6531,10 @@ TkMacOSXMakeFullscreen(
|
||||
Tcl_Interp *interp)
|
||||
{
|
||||
WmInfo *wmPtr = winPtr->wmInfoPtr;
|
||||
int result = TCL_OK, wasFullscreen = (wmPtr->flags & WM_FULLSCREEN);
|
||||
static unsigned long prevMask = 0, prevPres = 0;
|
||||
int screenWidth = WidthOfScreen(Tk_Screen(winPtr));
|
||||
int screenHeight = HeightOfScreen(Tk_Screen(winPtr));
|
||||
|
||||
if (fullscreen) {
|
||||
int screenWidth = WidthOfScreen(Tk_Screen(winPtr));
|
||||
int screenHeight = HeightOfScreen(Tk_Screen(winPtr));
|
||||
|
||||
/*
|
||||
* Check max width and height if set by the user.
|
||||
@@ -6477,58 +6549,73 @@ TkMacOSXMakeFullscreen(
|
||||
Tcl_SetErrorCode(interp, "TK", "FULLSCREEN",
|
||||
"CONSTRAINT_FAILURE", NULL);
|
||||
}
|
||||
result = TCL_ERROR;
|
||||
wmPtr->flags &= ~WM_FULLSCREEN;
|
||||
} else {
|
||||
Tk_UnmapWindow((Tk_Window) winPtr);
|
||||
NSRect bounds = [window contentRectForFrameRect:[window frame]];
|
||||
NSRect screenBounds = NSMakeRect(0, 0, screenWidth, screenHeight);
|
||||
|
||||
if (!NSEqualRects(bounds, screenBounds) && !wasFullscreen) {
|
||||
wmPtr->configX = wmPtr->x;
|
||||
wmPtr->configY = wmPtr->y;
|
||||
wmPtr->configAttributes = wmPtr->attributes;
|
||||
wmPtr->attributes &= ~kWindowResizableAttribute;
|
||||
ApplyWindowAttributeFlagChanges(winPtr, window,
|
||||
wmPtr->configAttributes, wmPtr->flags, 1, 0);
|
||||
wmPtr->flags |= WM_SYNC_PENDING;
|
||||
[window setFrame:[window frameRectForContentRect:
|
||||
screenBounds] display:YES];
|
||||
wmPtr->flags &= ~WM_SYNC_PENDING;
|
||||
}
|
||||
wmPtr->flags |= WM_FULLSCREEN;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
prevMask = [window styleMask];
|
||||
prevPres = [NSApp presentationOptions];
|
||||
[window setStyleMask: NSBorderlessWindowMask];
|
||||
[NSApp setPresentationOptions: NSApplicationPresentationAutoHideDock
|
||||
| NSApplicationPresentationAutoHideMenuBar];
|
||||
Tk_MapWindow((Tk_Window) winPtr);
|
||||
/*
|
||||
* Save the current window state.
|
||||
*/
|
||||
|
||||
wmPtr->cachedBounds = [window frame];
|
||||
wmPtr->cachedStyle = [window styleMask];
|
||||
wmPtr->cachedPresentation = [NSApp presentationOptions];
|
||||
|
||||
/*
|
||||
* Adjust the window style so it looks like a Fullscreen window.
|
||||
*/
|
||||
|
||||
[window setStyleMask: NSFullScreenWindowMask];
|
||||
[NSApp setPresentationOptions: (NSApplicationPresentationAutoHideDock |
|
||||
NSApplicationPresentationAutoHideMenuBar)];
|
||||
|
||||
/*For 10.13 and later add a button for exiting Fullscreen.*/
|
||||
if ([NSApp macMinorVersion] > 12) {
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > 101200
|
||||
exitFullScreen = [[[NSStatusBar systemStatusBar]
|
||||
statusItemWithLength:NSVariableStatusItemLength] retain];
|
||||
NSImage *exitIcon = [NSImage imageNamed:@"NSExitFullScreenTemplate"];
|
||||
exitFullScreen.button.image = exitIcon;
|
||||
exitFullScreen.button.cell.highlighted = NO;
|
||||
exitFullScreen.button.toolTip = @"Exit Full Screen";
|
||||
exitFullScreen.button.target = window;
|
||||
exitFullScreen.button.action = @selector(restoreOldScreen:);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize the window to fill the screen. (After setting the style!)
|
||||
*/
|
||||
|
||||
wmPtr->flags |= WM_SYNC_PENDING;
|
||||
NSRect screenBounds = NSMakeRect(0, 0, screenWidth, screenHeight);
|
||||
[window setFrame:screenBounds display:YES];
|
||||
wmPtr->flags &= ~WM_SYNC_PENDING;
|
||||
wmPtr->flags |= WM_FULLSCREEN;
|
||||
} else {
|
||||
wmPtr->flags &= ~WM_FULLSCREEN;
|
||||
[NSApp setPresentationOptions: prevPres];
|
||||
[window setStyleMask: prevMask];
|
||||
}
|
||||
|
||||
if (wasFullscreen && !(wmPtr->flags & WM_FULLSCREEN)) {
|
||||
Tk_UnmapWindow((Tk_Window) winPtr);
|
||||
/*
|
||||
* Restore the previous styles and attributes.
|
||||
*/
|
||||
|
||||
[NSApp setPresentationOptions: wmPtr->cachedPresentation];
|
||||
[window setStyleMask: wmPtr->cachedStyle];
|
||||
UInt64 oldAttributes = wmPtr->attributes;
|
||||
NSRect bounds = NSMakeRect(wmPtr->configX, tkMacOSXZeroScreenHeight -
|
||||
(wmPtr->configY + wmPtr->yInParent + wmPtr->configHeight),
|
||||
wmPtr->xInParent + wmPtr->configWidth,
|
||||
wmPtr->yInParent + wmPtr->configHeight);
|
||||
|
||||
wmPtr->flags &= ~WM_FULLSCREEN;
|
||||
wmPtr->attributes |= wmPtr->configAttributes &
|
||||
kWindowResizableAttribute;
|
||||
ApplyWindowAttributeFlagChanges(winPtr, window, oldAttributes,
|
||||
wmPtr->flags, 1, 0);
|
||||
|
||||
/*
|
||||
* Resize the window to its previous size.
|
||||
*/
|
||||
|
||||
wmPtr->flags |= WM_SYNC_PENDING;
|
||||
[window setFrame:[window frameRectForContentRect:bounds] display:YES];
|
||||
[window setFrame:wmPtr->cachedBounds display:YES];
|
||||
wmPtr->flags &= ~WM_SYNC_PENDING;
|
||||
Tk_MapWindow((Tk_Window) winPtr);
|
||||
}
|
||||
return result;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -185,6 +185,15 @@ typedef struct TkWmInfo {
|
||||
TkWindow *scrollWinPtr; /* Ptr to scrollbar handling grow widget. */
|
||||
TkMenu *menuPtr;
|
||||
NSWindow *window;
|
||||
|
||||
/*
|
||||
* Space to cache current window state when window becomes Fullscreen.
|
||||
*/
|
||||
|
||||
unsigned long cachedStyle;
|
||||
unsigned long cachedPresentation;
|
||||
NSRect cachedBounds;
|
||||
|
||||
} WmInfo;
|
||||
|
||||
/*
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file contains most of the X calls called by Tk. Many of these
|
||||
* calls are just stubs and either don't make sense on the Macintosh or
|
||||
* their implamentation just doesn't do anything. Other calls will
|
||||
* their implementation just doesn't do anything. Other calls will
|
||||
* eventually be moved into other files.
|
||||
*
|
||||
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
||||
@@ -40,10 +40,13 @@ CGFloat tkMacOSXZeroScreenTop = 0;
|
||||
* Declarations of static variables used in this file.
|
||||
*/
|
||||
|
||||
/* The unique Macintosh display. */
|
||||
static TkDisplay *gMacDisplay = NULL;
|
||||
/* Macintosh display. */
|
||||
/* The default name of the Macintosh display. */
|
||||
static const char *macScreenName = ":0";
|
||||
/* Default name of macintosh display. */
|
||||
/* Timestamp showing the last reset of the inactivity timer. */
|
||||
static Time lastInactivityReset = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Forward declarations of procedures used in this file.
|
||||
@@ -175,7 +178,7 @@ TkpOpenDisplay(
|
||||
{
|
||||
int major, minor, patch;
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
|
||||
Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
|
||||
Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
|
||||
Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
|
||||
@@ -200,7 +203,6 @@ TkpOpenDisplay(
|
||||
screen->root_visual = ckalloc(sizeof(Visual));
|
||||
screen->root_visual->visualid = 0;
|
||||
screen->root_visual->class = TrueColor;
|
||||
screen->root_visual->alpha_mask = 0xFF000000;
|
||||
screen->root_visual->red_mask = 0x00FF0000;
|
||||
screen->root_visual->green_mask = 0x0000FF00;
|
||||
screen->root_visual->blue_mask = 0x000000FF;
|
||||
@@ -874,13 +876,10 @@ TkGetDefaultScreenName(
|
||||
Tcl_Interp *interp, /* Not used. */
|
||||
const char *screenName) /* If NULL, use default string. */
|
||||
{
|
||||
#if 0
|
||||
if ((screenName == NULL) || (screenName[0] == '\0')) {
|
||||
screenName = macScreenName;
|
||||
}
|
||||
return screenName;
|
||||
#endif
|
||||
return macScreenName;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -928,27 +927,23 @@ Tk_GetUserInactiveTime(
|
||||
timeObj = CFDictionaryGetValue(props, CFSTR("HIDIdleTime"));
|
||||
|
||||
if (timeObj) {
|
||||
CFTypeID type = CFGetTypeID(timeObj);
|
||||
|
||||
if (type == CFDataGetTypeID()) { /* Jaguar */
|
||||
CFDataGetBytes((CFDataRef) timeObj,
|
||||
CFRangeMake(0, sizeof(time)), (UInt8 *) &time);
|
||||
/* Convert nanoseconds to milliseconds. */
|
||||
/* ret /= kMillisecondScale; */
|
||||
ret = (long) (time/kMillisecondScale);
|
||||
} else if (type == CFNumberGetTypeID()) { /* Panther+ */
|
||||
CFNumberGetValue((CFNumberRef)timeObj,
|
||||
kCFNumberSInt64Type, &time);
|
||||
/* Convert nanoseconds to milliseconds. */
|
||||
/* ret /= kMillisecondScale; */
|
||||
ret = (long) (time/kMillisecondScale);
|
||||
} else {
|
||||
ret = -1l;
|
||||
}
|
||||
}
|
||||
/* Cleanup */
|
||||
CFRelease(props);
|
||||
|
||||
/*
|
||||
* If the idle time reported by the system is larger than the elapsed
|
||||
* time since the last reset, return the elapsed time.
|
||||
*/
|
||||
long elapsed = (long)(TkpGetMS() - lastInactivityReset);
|
||||
if (ret > elapsed) {
|
||||
ret = elapsed;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -973,28 +968,7 @@ void
|
||||
Tk_ResetUserInactiveTime(
|
||||
Display *dpy)
|
||||
{
|
||||
IOGPoint loc = {0, 0};
|
||||
kern_return_t kr;
|
||||
NXEvent nullEvent = {NX_NULLEVENT, {0, 0}, 0, -1, 0};
|
||||
enum { kNULLEventPostThrottle = 10 };
|
||||
static io_connect_t io_connection = MACH_PORT_NULL;
|
||||
|
||||
if (io_connection == MACH_PORT_NULL) {
|
||||
io_service_t service = IOServiceGetMatchingService(
|
||||
kIOMasterPortDefault, IOServiceMatching(kIOHIDSystemClass));
|
||||
|
||||
if (service == MACH_PORT_NULL) {
|
||||
return;
|
||||
}
|
||||
kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType,
|
||||
&io_connection);
|
||||
IOObjectRelease(service);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
kr = IOHIDPostEvent(io_connection, NX_NULLEVENT, loc, &nullEvent.data,
|
||||
FALSE, 0, FALSE);
|
||||
lastInactivityReset = TkpGetMS();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user