Update to tk 8.5.19

This commit is contained in:
Zachary Ware
2017-11-24 17:53:51 -06:00
parent 27e7dfc7da
commit c67b328f06
325 changed files with 12511 additions and 12047 deletions

View File

@@ -35,7 +35,7 @@ MANDIR ?= ${PREFIX}/man
TCL_BUILD_DIR ?= ${BUILD_DIR}/tcl/${BUILD_STYLE}
# location of installed tcl, only used if tcl in TCL_BUILD_DIR can't be found
TCL_FRAMEWORK_DIR ?= /Library/Frameworks
TCLSH_DIR ?= ${PREFIX}
TCLSH_DIR ?= ${PREFIX}/bin
# set to non-empty value to install manpages in addition to html help:
INSTALL_MANPAGES ?=
@@ -132,7 +132,7 @@ wish := ${wish}-X11
override EMBEDDED_BUILD :=
endif
INSTALL_TARGETS = install-binaries install-libraries
INSTALL_TARGETS = install-binaries install-headers install-libraries
ifeq (${EMBEDDED_BUILD},)
INSTALL_TARGETS += install-private-headers install-demos
endif

View File

@@ -386,3 +386,64 @@ make overrides to the tk/macosx GNUmakefile, e.g.
sudo make -C tk${ver}/macosx install \
TCL_FRAMEWORK_DIR=$HOME/Library/Frameworks TCLSH_DIR=$HOME/usr/bin
The Makefile variables TCL_FRAMEWORK_DIR and TCLSH_DIR were added with Tk 8.4.3.
4. About the event loop in Tk for Mac OSX
-----------------------------------------
The main program in a typical OSX application looks like this (see *)
void NSApplicationMain(int argc, char *argv[]) {
[NSApplication sharedApplication];
[NSBundle loadNibNamed:@"myMain" owner:NSApp];
[NSApp run];
}
The run method implements the event loop for the application. There
are three key steps in the run method. First it calls
[NSApp finishLaunching], which creates the bouncing application icon
and does other mysterious things. Second it creates an
NSAutoreleasePool. Third, it starts an event loop which drains the
NSAutoreleasePool every time the queue is empty, and replaces the
drained pool with a new one. This third step is essential to
preventing memory leaks, since the internal methods of Appkit objects
all assume that an autorelease pool is in scope and will be drained
when the event processing cycle ends.
Mac OSX Tk does not call the [NSApp run] method at all. Instead it
uses the event loop built in to Tk. So we must take care to replicate
the important features of the method ourselves. Here is how this
works in outline.
We add a private NSAUtoreleasePool* property to our subclass of
NSApplication. (The subclass is called TKApplication but can be
referenced with the global variable NSApp). The TkpInit
function calls [NSApp _setup] which initializes this property by
creating an NSAutoreleasePool. A bit later on, TkpInit calls
[NSAPP _setupEventLoop] which in turn calls the
[NSApp finishLaunching] method.
Each time that Tcl processes an event in its queue, it calls a
platform specific function which, in the case of Mac OSX, is named
TkMacOSXEventsCheckProc. In the unix implementations of Tk, including
the Mac OSX version, this function collects events from an "event
source", and transfers them to the Tcl event queue. In Mac OSX the
event source is the NSApplication event queue. Each NSEvent is
converted to a Tcl event which is added to the Tcl event queue. The
NSEvent is also passed to [NSApp sendevent], which sends the event on
to the application's NSWindows, which send it to their NSViews, etc.
Since the CheckProc function gets called for every Tk event, it is an
appropriate place to drain the main NSAutoreleasePool and replace it
with a new pool. This is done by calling the method
[NSApp _resetAutoreleasePool], where _resetAutoreleasePool is a method
which we define for the subclass TKApplication.
One minor caveat is that there are several steps of the Tk
initialization which precede the call to TkpInit. Notably, the font
package is initialized first. Since there is no NSAUtoreleasePool in
scope prior to calling TkpInit, the functions called in these
preliminary stages need to create and drain their own
NSAutoreleasePools whenever they call methods of Appkit objects
(e.g. NSFont).
* https://developer.apple.com/library/mac/documentation/Cocoa/\
Reference/ApplicationKit/Classes/NSApplication_Class

View File

@@ -17,6 +17,9 @@
<string>Tk @TK_WINDOWINGSYSTEM@ @TK_VERSION@@TK_PATCH_LEVEL@,
Copyright © 1989-@TK_YEAR@ Tcl Core Team,
Copyright © 2002-@TK_YEAR@ Daniel A. Steffen,
Copyright © 1989-@TK_YEAR@ Contributors,
Copyright © 2011-@TK_YEAR@ Kevin Walzer/WordTech
Communications LLC,
Copyright © 2001-2009 Apple Inc.,
Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
<key>CFBundleIdentifier</key>

View File

@@ -42,6 +42,9 @@
<string>Wish Shell @TK_VERSION@@TK_PATCH_LEVEL@,
Copyright © 1989-@TK_YEAR@ Tcl Core Team,
Copyright © 2002-@TK_YEAR@ Daniel A. Steffen,
Copyright © 1989-@TK_YEAR@ Contributors,
Copyright © 2011-@TK_YEAR@ Kevin Walzer/WordTech
Communications LLC,
Copyright © 2001-2009 Apple Inc.,
Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
<key>CFBundleIconFile</key>
@@ -72,5 +75,7 @@ Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
<true/>
<key>OSAScriptingDefinition</key>
<string>Wish.sdef</string>
<key>NSHighResolutionCapable</key>
<string>True</string>
</dict>
</plist>

View File

@@ -1920,7 +1920,6 @@
F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = "<group>"; };
F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = "<group>"; };
F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
@@ -3715,7 +3714,6 @@
F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
F96D43D208F272B8004A47F5 /* configure */,
F96D43D308F272B8004A47F5 /* configure.in */,
F96D442208F272B8004A47F5 /* eolFix.tcl */,
F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */,
F96D442508F272B8004A47F5 /* genStubs.tcl */,
F96D442708F272B8004A47F5 /* index.tcl */,

View File

@@ -1920,7 +1920,6 @@
F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = checkLibraryDoc.tcl; sourceTree = "<group>"; };
F96D43D208F272B8004A47F5 /* configure */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = configure; sourceTree = "<group>"; };
F96D43D308F272B8004A47F5 /* configure.in */ = {isa = PBXFileReference; explicitFileType = text.script.sh; fileEncoding = 4; path = configure.in; sourceTree = "<group>"; };
F96D442208F272B8004A47F5 /* eolFix.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = eolFix.tcl; sourceTree = "<group>"; };
F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = fix_tommath_h.tcl; sourceTree = "<group>"; };
F96D442508F272B8004A47F5 /* genStubs.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = genStubs.tcl; sourceTree = "<group>"; };
F96D442708F272B8004A47F5 /* index.tcl */ = {isa = PBXFileReference; explicitFileType = text.script; fileEncoding = 4; path = index.tcl; sourceTree = "<group>"; };
@@ -3715,7 +3714,6 @@
F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,
F96D43D208F272B8004A47F5 /* configure */,
F96D43D308F272B8004A47F5 /* configure.in */,
F96D442208F272B8004A47F5 /* eolFix.tcl */,
F96D442408F272B8004A47F5 /* fix_tommath_h.tcl */,
F96D442508F272B8004A47F5 /* genStubs.tcl */,
F96D442708F272B8004A47F5 /* index.tcl */,

11879
macosx/configure vendored Normal file → Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -344,7 +344,7 @@ FindCursorByName(
macCursor = [[NSCursor alloc] initWithImage:image hotSpot:hotSpot];
[image release];
}
macCursorPtr->macCursor = TkMacOSXMakeUncollectable(macCursor);
macCursorPtr->macCursor = macCursor;
}
/*
@@ -452,7 +452,8 @@ TkpFreeCursor(
{
TkMacOSXCursor *macCursorPtr = (TkMacOSXCursor *) cursorPtr;
TkMacOSXMakeCollectableAndRelease(macCursorPtr->macCursor);
[macCursorPtr->macCursor release];
macCursorPtr->macCursor = NULL;
if (macCursorPtr == gCurrentCursor) {
gCurrentCursor = NULL;
}

View File

@@ -16,9 +16,9 @@
#ifndef _TKMACDEFAULT
#define _TKMACDEFAULT
#ifndef TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
#define TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS 1
#endif
//#ifndef TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
//#define TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS 1
//#endif
/*
* The definitions below provide symbolic names for the default colors.
@@ -72,12 +72,12 @@
#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO
#define DEF_BUTTON_HIGHLIGHT "systemButtonFrame"
#define DEF_LABEL_HIGHLIGHT_WIDTH "0"
#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
#define DEF_BUTTON_HIGHLIGHT_WIDTH "4"
#define DEF_BUTTON_HIGHLIGHT_WIDTH_NOCM "1"
#else
//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
//#define DEF_BUTTON_HIGHLIGHT_WIDTH "4"
//#define DEF_BUTTON_HIGHLIGHT_WIDTH_NOCM "1"
//#else
#define DEF_BUTTON_HIGHLIGHT_WIDTH "1"
#endif
//#endif
#define DEF_BUTTON_IMAGE ((char *) NULL)
#define DEF_BUTTON_INDICATOR "1"
#define DEF_BUTTON_JUSTIFY "center"
@@ -85,19 +85,19 @@
#define DEF_BUTTON_ON_VALUE "1"
#define DEF_BUTTON_TRISTATE_VALUE ""
#define DEF_BUTTON_OVER_RELIEF ""
#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
#define DEF_BUTTON_PADX "12"
#define DEF_BUTTON_PADX_NOCM "1"
#else
//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
//#define DEF_BUTTON_PADX "12"
//#define DEF_BUTTON_PADX_NOCM "1"
//#else
#define DEF_BUTTON_PADX "1"
#endif
//#endif
#define DEF_LABCHKRAD_PADX "1"
#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
#define DEF_BUTTON_PADY "3"
#define DEF_BUTTON_PADY_NOCM "1"
#else
//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
//#define DEF_BUTTON_PADY "3"
//#define DEF_BUTTON_PADY_NOCM "1"
//#else
#define DEF_BUTTON_PADY "1"
#endif
//#endif
#define DEF_LABCHKRAD_PADY "1"
#define DEF_BUTTON_RELIEF "flat"
#define DEF_LABCHKRAD_RELIEF "flat"
@@ -409,6 +409,7 @@
#define DEF_PANEDWINDOW_HEIGHT ""
#define DEF_PANEDWINDOW_OPAQUERESIZE "1"
#define DEF_PANEDWINDOW_ORIENT "horizontal"
#define DEF_PANEDWINDOW_PROXYBORDER "2"
#define DEF_PANEDWINDOW_RELIEF "flat"
#define DEF_PANEDWINDOW_SASHCURSOR ""
#define DEF_PANEDWINDOW_SASHPAD "0"

View File

@@ -7,24 +7,34 @@
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
* 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 "tkFileFilter.h"
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
#define modalOK NSOKButton
#define modalCancel NSCancelButton
#else
#define modalOK NSModalResponseOK
#define modalCancel NSModalResponseCancel
#endif
#define modalOther -1
#define modalError -2
static int TkBackgroundEvalObjv(Tcl_Interp *interp, int objc,
Tcl_Obj *const *objv, int flags);
static const char *colorOptionStrings[] = {
static const char *const colorOptionStrings[] = {
"-initialcolor", "-parent", "-title", NULL
};
enum colorOptions {
COLOR_INITIAL, COLOR_PARENT, COLOR_TITLE
};
static const char *openOptionStrings[] = {
static const char *const openOptionStrings[] = {
"-defaultextension", "-filetypes", "-initialdir", "-initialfile",
"-message", "-multiple", "-parent", "-title", "-typevariable",
"-command", NULL
@@ -34,7 +44,7 @@ enum openOptions {
OPEN_MESSAGE, OPEN_MULTIPLE, OPEN_PARENT, OPEN_TITLE,
OPEN_TYPEVARIABLE, OPEN_COMMAND,
};
static const char *saveOptionStrings[] = {
static const char *const saveOptionStrings[] = {
"-defaultextension", "-filetypes", "-initialdir", "-initialfile",
"-message", "-parent", "-title", "-typevariable", "-command",
"-confirmoverwrite", NULL
@@ -44,7 +54,7 @@ enum saveOptions {
SAVE_MESSAGE, SAVE_PARENT, SAVE_TITLE, SAVE_TYPEVARIABLE, SAVE_COMMAND,
SAVE_CONFIRMOW
};
static const char *chooseOptionStrings[] = {
static const char *const chooseOptionStrings[] = {
"-initialdir", "-message", "-mustexist", "-parent", "-title", "-command",
NULL
};
@@ -58,7 +68,7 @@ typedef struct {
int multiple;
} FilePanelCallbackInfo;
static const char *alertOptionStrings[] = {
static const char *const alertOptionStrings[] = {
"-default", "-detail", "-icon", "-message", "-parent", "-title",
"-type", "-command", NULL
};
@@ -71,7 +81,7 @@ typedef struct {
Tcl_Obj *cmdObj;
int typeIndex;
} AlertCallbackInfo;
static const char *alertTypeStrings[] = {
static const char *const alertTypeStrings[] = {
"abortretryignore", "ok", "okcancel", "retrycancel", "yesno",
"yesnocancel", NULL
};
@@ -79,13 +89,13 @@ enum alertTypeOptions {
TYPE_ABORTRETRYIGNORE, TYPE_OK, TYPE_OKCANCEL, TYPE_RETRYCANCEL,
TYPE_YESNO, TYPE_YESNOCANCEL
};
static const char *alertIconStrings[] = {
static const char *const alertIconStrings[] = {
"error", "info", "question", "warning", NULL
};
enum alertIconOptions {
ICON_ERROR, ICON_INFO, ICON_QUESTION, ICON_WARNING
};
static const char *alertButtonStrings[] = {
static const char *const alertButtonStrings[] = {
"abort", "retry", "ignore", "ok", "cancel", "yes", "no", NULL
};
@@ -105,9 +115,9 @@ static const NSAlertStyle alertStyles[] = {
};
/*
* Need to map from 'alertButtonStrings' and its corresponding integer,
* index to the native button index, which is 1, 2, 3, from right to left.
* This is necessary to do for each separate '-type' of button sets.
* Need to map from 'alertButtonStrings' and its corresponding integer, index
* to the native button index, which is 1, 2, 3, from right to left. This is
* necessary to do for each separate '-type' of button sets.
*/
static const short alertButtonIndexAndTypeToNativeButtonIndex[][7] = {
@@ -134,32 +144,53 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {
[TYPE_YESNOCANCEL] = {5, 6, 4},
};
/*
* Construct a file URL from directory and filename. Either may
* be nil. If both are nil, returns nil.
*/
#if MAC_OS_X_VERSION_MIN_REQUIRED > 1050
static NSURL *getFileURL(NSString *directory, NSString *filename) {
NSURL *url = nil;
if (directory) {
url = [NSURL fileURLWithPath:directory];
}
if (filename) {
url = [NSURL URLWithString:filename relativeToURL:url];
}
return url;
}
#endif
#pragma mark TKApplication(TKDialog)
@interface NSColorPanel(TKDialog)
- (void)_setUseModalAppearance:(BOOL)flag;
- (void) _setUseModalAppearance: (BOOL) flag;
@end
@implementation TKApplication(TKDialog)
- (void)tkFilePanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)returnCode
contextInfo:(void *)contextInfo {
- (void) tkFilePanelDidEnd: (NSSavePanel *) panel
returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
{
FilePanelCallbackInfo *callbackInfo = contextInfo;
if (returnCode == NSFileHandlingPanelOKButton) {
Tcl_Obj *resultObj;
if (callbackInfo->multiple) {
resultObj = Tcl_NewListObj(0, NULL);
for (NSString *name in [(NSOpenPanel*)panel filenames]) {
for (NSURL *url in [(NSOpenPanel*)panel URLs]) {
Tcl_ListObjAppendElement(callbackInfo->interp, resultObj,
Tcl_NewStringObj([name UTF8String], -1));
Tcl_NewStringObj([[url path] UTF8String], -1));
}
} else {
resultObj = Tcl_NewStringObj([[panel filename] UTF8String], -1);
resultObj = Tcl_NewStringObj([[[panel URL]path] UTF8String], -1);
}
if (callbackInfo->cmdObj) {
Tcl_Obj **objv, **tmpv;
int objc, result = Tcl_ListObjGetElements(callbackInfo->interp,
callbackInfo->cmdObj, &objc, &objv);
if (result == TCL_OK && objc) {
tmpv = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
@@ -179,21 +210,25 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {
}
if (callbackInfo->cmdObj) {
Tcl_DecrRefCount(callbackInfo->cmdObj);
ckfree((char*) callbackInfo);
ckfree((char *)callbackInfo);
}
}
- (void)tkAlertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode
contextInfo:(void *)contextInfo {
- (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode
contextInfo: (void *) contextInfo
{
AlertCallbackInfo *callbackInfo = contextInfo;
if (returnCode != NSAlertErrorReturn) {
if (returnCode >= NSAlertFirstButtonReturn) {
Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[
alertNativeButtonIndexAndTypeToButtonIndex[callbackInfo->
typeIndex][returnCode - NSAlertFirstButtonReturn]], -1);
if (callbackInfo->cmdObj) {
Tcl_Obj **objv, **tmpv;
int objc, result = Tcl_ListObjGetElements(callbackInfo->interp,
callbackInfo->cmdObj, &objc, &objv);
if (result == TCL_OK && objc) {
tmpv = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc);
@@ -211,7 +246,7 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = {
}
if (callbackInfo->cmdObj) {
Tcl_DecrRefCount(callbackInfo->cmdObj);
ckfree((char*) callbackInfo);
ckfree((char *) callbackInfo);
}
}
@end
@@ -252,43 +287,41 @@ Tk_ChooseColorObjCmd(
for (i = 1; i < objc; i += 2) {
int index;
const char *option, *value;
const char *value;
if (Tcl_GetIndexFromObj(interp, objv[i], colorOptionStrings, "option",
TCL_EXACT, &index) != TCL_OK) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i], colorOptionStrings,
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
option = Tcl_GetString(objv[i]);
Tcl_AppendResult(interp, "value for \"", option, "\" missing",
NULL);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"value for \"%s\" missing", Tcl_GetString(objv[i])));
Tcl_SetErrorCode(interp, "TK", "COLORDIALOG", "VALUE", NULL);
goto end;
}
value = Tcl_GetString(objv[i + 1]);
switch (index) {
case COLOR_INITIAL: {
XColor *colorPtr;
case COLOR_INITIAL: {
XColor *colorPtr;
colorPtr = Tk_GetColor(interp, tkwin, value);
if (colorPtr == NULL) {
goto end;
}
initialColor = TkMacOSXGetNSColor(NULL, colorPtr->pixel);
Tk_FreeColor(colorPtr);
break;
colorPtr = Tk_GetColor(interp, tkwin, value);
if (colorPtr == NULL) {
goto end;
}
case COLOR_PARENT: {
parent = Tk_NameToWindow(interp, value, tkwin);
if (parent == NULL) {
goto end;
}
break;
}
case COLOR_TITLE: {
title = value;
break;
initialColor = TkMacOSXGetNSColor(NULL, colorPtr->pixel);
Tk_FreeColor(colorPtr);
break;
}
case COLOR_PARENT:
parent = Tk_NameToWindow(interp, value, tkwin);
if (parent == NULL) {
goto end;
}
break;
case COLOR_TITLE:
title = value;
break;
}
}
colorPanel = [NSColorPanel sharedColorPanel];
@@ -306,7 +339,7 @@ Tk_ChooseColorObjCmd(
[colorPanel setColor:initialColor];
}
returnCode = [NSApp runModalForWindow:colorPanel];
if (returnCode == NSOKButton) {
if (returnCode == modalOK) {
color = [[colorPanel color] colorUsingColorSpace:
[NSColorSpace genericRGBColorSpace]];
numberOfComponents = [color numberOfComponents];
@@ -325,6 +358,7 @@ Tk_ChooseColorObjCmd(
Tcl_ResetResult(interp);
}
result = TCL_OK;
end:
return result;
}
@@ -365,17 +399,19 @@ Tk_GetOpenFileObjCmd(
NSWindow *parent;
NSMutableArray *fileTypes = nil;
NSOpenPanel *panel = [NSOpenPanel openPanel];
NSInteger returnCode = NSAlertErrorReturn;
NSInteger modalReturnCode = modalError;
BOOL parentIsKey = NO;
TkInitFileFilters(&fl);
for (i = 1; i < objc; i += 2) {
if (Tcl_GetIndexFromObj(interp, objv[i], openOptionStrings, "option",
TCL_EXACT, &index) != TCL_OK) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings,
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
str = Tcl_GetString(objv[i]);
Tcl_AppendResult(interp, "value for \"", str, "\" missing", NULL);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"value for \"%s\" missing", Tcl_GetString(objv[i])));
Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
goto end;
}
switch (index) {
@@ -434,6 +470,7 @@ Tk_GetOpenFileObjCmd(
break;
}
}
[panel setAllowsMultipleSelection:multiple];
if (fl.filters) {
fileTypes = [NSMutableArray array];
for (FileFilter *filterPtr = fl.filters; filterPtr;
@@ -466,10 +503,9 @@ Tk_GetOpenFileObjCmd(
}
}
}
[panel setAllowsMultipleSelection:multiple];
[panel setAllowedFileTypes:fileTypes];
if (cmdObj) {
callbackInfo = (FilePanelCallbackInfo *)
ckalloc(sizeof(FilePanelCallbackInfo));
callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
if (Tcl_IsShared(cmdObj)) {
cmdObj = Tcl_DuplicateObj(cmdObj);
}
@@ -480,28 +516,51 @@ Tk_GetOpenFileObjCmd(
callbackInfo->multiple = multiple;
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
if (haveParentOption && parent && ![parent attachedSheet]) {
[panel beginSheetForDirectory:directory file:filename types:fileTypes
modalForWindow:parent modalDelegate:NSApp didEndSelector:
@selector(tkFilePanelDidEnd:returnCode:contextInfo:)
contextInfo:callbackInfo];
returnCode = cmdObj ? NSAlertOtherReturn :
[NSApp runModalForWindow:panel];
parentIsKey = [parent isKeyWindow];
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
[panel beginSheetForDirectory:directory
file:filename
types:fileTypes
modalForWindow:parent
modalDelegate:NSApp
didEndSelector:
@selector(tkFilePanelDidEnd:returnCode:contextInfo:)
contextInfo:callbackInfo];
#else
[panel setAllowedFileTypes:fileTypes];
[panel setDirectoryURL:getFileURL(directory, filename)];
[panel beginSheetModalForWindow:parent
completionHandler:^(NSInteger returnCode)
{ [NSApp tkFilePanelDidEnd:panel
returnCode:returnCode
contextInfo:callbackInfo ]; } ];
#endif
modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel];
} else {
returnCode = [panel runModalForDirectory:directory file:filename
types:fileTypes];
[NSApp tkFilePanelDidEnd:panel returnCode:returnCode
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
modalReturnCode = [panel runModalForDirectory:directory
file:filename];
#else
[panel setDirectoryURL:getFileURL(directory, filename)];
modalReturnCode = [panel runModal];
#endif
[NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
contextInfo:callbackInfo];
}
result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR;
result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
if (parentIsKey) {
[parent makeKeyWindow];
}
if (typeVariablePtr && result == TCL_OK) {
/*
* The -typevariable option is not really supported.
*/
Tcl_SetVar(interp, Tcl_GetString(typeVariablePtr), "",
TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, Tcl_GetString(typeVariablePtr), NULL,
"", TCL_GLOBAL_ONLY);
}
end:
end:
TkFreeFileFilters(&fl);
return result;
}
@@ -543,18 +602,19 @@ Tk_GetSaveFileObjCmd(
NSWindow *parent;
NSMutableArray *fileTypes = nil;
NSSavePanel *panel = [NSSavePanel savePanel];
NSInteger returnCode = NSAlertErrorReturn;
NSInteger modalReturnCode = modalError;
BOOL parentIsKey = NO;
TkInitFileFilters(&fl);
for (i = 1; i < objc; i += 2) {
if (Tcl_GetIndexFromObj(interp, objv[i], saveOptionStrings, "option",
TCL_EXACT, &index) != TCL_OK) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings,
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
str = Tcl_GetString(objv[i]);
Tcl_AppendResult(interp, "value for \"", str, "\" missing",
NULL);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"value for \"%s\" missing", Tcl_GetString(objv[i])));
Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
goto end;
}
switch (index) {
@@ -614,7 +674,7 @@ Tk_GetSaveFileObjCmd(
break;
case SAVE_CONFIRMOW:
if (Tcl_GetBooleanFromObj(interp, objv[i + 1],
&confirmOverwrite) != TCL_OK) {
&confirmOverwrite) != TCL_OK) {
goto end;
}
break;
@@ -649,8 +709,7 @@ Tk_GetSaveFileObjCmd(
[panel setCanSelectHiddenExtension:YES];
[panel setExtensionHidden:NO];
if (cmdObj) {
callbackInfo = (FilePanelCallbackInfo *)
ckalloc(sizeof(FilePanelCallbackInfo));
callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
if (Tcl_IsShared(cmdObj)) {
cmdObj = Tcl_DuplicateObj(cmdObj);
}
@@ -661,19 +720,39 @@ Tk_GetSaveFileObjCmd(
callbackInfo->multiple = 0;
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
if (haveParentOption && parent && ![parent attachedSheet]) {
[panel beginSheetForDirectory:directory file:filename
modalForWindow:parent modalDelegate:NSApp didEndSelector:
@selector(tkFilePanelDidEnd:returnCode:contextInfo:)
contextInfo:callbackInfo];
returnCode = cmdObj ? NSAlertOtherReturn :
[NSApp runModalForWindow:panel];
parentIsKey = [parent isKeyWindow];
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
[panel beginSheetForDirectory:directory
file:filename
modalForWindow:parent
modalDelegate:NSApp
didEndSelector:
@selector(tkFilePanelDidEnd:returnCode:contextInfo:)
contextInfo:callbackInfo];
#else
[panel setDirectoryURL:getFileURL(directory, filename)];
[panel beginSheetModalForWindow:parent
completionHandler:^(NSInteger returnCode)
{ [NSApp tkFilePanelDidEnd:panel
returnCode:returnCode
contextInfo:callbackInfo ]; } ];
#endif
modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel];
} else {
returnCode = [panel runModalForDirectory:directory file:filename];
[NSApp tkFilePanelDidEnd:panel returnCode:returnCode
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
modalReturnCode = [panel runModalForDirectory:directory file:filename];
#else
[panel setDirectoryURL:getFileURL(directory, filename)];
modalReturnCode = [panel runModal];
#endif
[NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
contextInfo:callbackInfo];
}
result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR;
end:
result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
if (parentIsKey) {
[parent makeKeyWindow];
}
end:
TkFreeFileFilters(&fl);
return result;
}
@@ -714,16 +793,18 @@ Tk_ChooseDirectoryObjCmd(
NSString *message, *title;
NSWindow *parent;
NSOpenPanel *panel = [NSOpenPanel openPanel];
NSInteger returnCode = NSAlertErrorReturn;
NSInteger modalReturnCode = modalError;
BOOL parentIsKey = NO;
for (i = 1; i < objc; i += 2) {
if (Tcl_GetIndexFromObj(interp, objv[i], chooseOptionStrings, "option",
TCL_EXACT, &index) != TCL_OK) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i], chooseOptionStrings,
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
str = Tcl_GetString(objv[i]);
Tcl_AppendResult(interp, "value for \"", str, "\" missing", NULL);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"value for \"%s\" missing", Tcl_GetString(objv[i])));
Tcl_SetErrorCode(interp, "TK", "DIRDIALOG", "VALUE", NULL);
goto end;
}
switch (index) {
@@ -770,8 +851,7 @@ Tk_ChooseDirectoryObjCmd(
[panel setCanChooseDirectories:YES];
[panel setCanCreateDirectories:!mustexist];
if (cmdObj) {
callbackInfo = (FilePanelCallbackInfo *)
ckalloc(sizeof(FilePanelCallbackInfo));
callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo));
if (Tcl_IsShared(cmdObj)) {
cmdObj = Tcl_DuplicateObj(cmdObj);
}
@@ -782,19 +862,38 @@ Tk_ChooseDirectoryObjCmd(
callbackInfo->multiple = 0;
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
if (haveParentOption && parent && ![parent attachedSheet]) {
[panel beginSheetForDirectory:directory file:filename
modalForWindow:parent modalDelegate:NSApp didEndSelector:
@selector(tkFilePanelDidEnd:returnCode:contextInfo:)
parentIsKey = [parent isKeyWindow];
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
[panel beginSheetForDirectory:directory
file:filename
modalForWindow:parent
modalDelegate:NSApp
didEndSelector: @selector(tkFilePanelDidEnd:returnCode:contextInfo:)
contextInfo:callbackInfo];
returnCode = cmdObj ? NSAlertOtherReturn :
[NSApp runModalForWindow:panel];
#else
[panel setDirectoryURL:getFileURL(directory, filename)];
[panel beginSheetModalForWindow:parent
completionHandler:^(NSInteger returnCode)
{ [NSApp tkFilePanelDidEnd:panel
returnCode:returnCode
contextInfo:callbackInfo ]; } ];
#endif
modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel];
} else {
returnCode = [panel runModalForDirectory:directory file:filename];
[NSApp tkFilePanelDidEnd:panel returnCode:returnCode
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
modalReturnCode = [panel runModalForDirectory:directory file:nil];
#else
[panel setDirectoryURL:getFileURL(directory, filename)];
modalReturnCode = [panel runModal];
#endif
[NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode
contextInfo:callbackInfo];
}
result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR;
end:
result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR;
if (parentIsKey) {
[parent makeKeyWindow];
}
end:
return result;
}
@@ -818,20 +917,29 @@ void
TkAboutDlg(void)
{
NSImage *image;
NSString *path = [NSApp tkFrameworkImagePath:@"Tk.tiff"];
NSString *path = [NSApp tkFrameworkImagePath: @"Tk.tiff"];
if (path) {
image = [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
} else {
image = [NSApp applicationIconImage];
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setDateFormat:@"Y"];
NSString *year = [dateFormatter stringFromDate:[NSDate date]];
[dateFormatter release];
NSMutableParagraphStyle *style = [[[NSParagraphStyle defaultParagraphStyle]
mutableCopy] autorelease];
NSMutableParagraphStyle *style =
[[[NSParagraphStyle defaultParagraphStyle] mutableCopy]
autorelease];
[style setAlignment:NSCenterTextAlignment];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
@"Tcl & Tk", @"ApplicationName",
@"Tcl " TCL_VERSION " & Tk " TK_VERSION, @"ApplicationVersion",
@@ -842,12 +950,15 @@ TkAboutDlg(void)
[[[NSAttributedString alloc] initWithString:
[NSString stringWithFormat:
@"%1$C 1987-%2$@ Tcl Core Team." "\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:
"%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];
@@ -881,7 +992,7 @@ TkMacOSXStandardAboutPanelObjCmd(
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
[NSApp orderFrontStandardAboutPanelWithOptions:nil];
[NSApp orderFrontStandardAboutPanelWithOptions:[NSDictionary dictionary]];
return TCL_OK;
}
@@ -919,18 +1030,20 @@ Tk_MessageBoxObjCmd(
NSWindow *parent;
NSArray *buttons;
NSAlert *alert = [NSAlert new];
NSInteger returnCode = NSAlertErrorReturn;
NSInteger modalReturnCode = 1;
BOOL parentIsKey = NO;
iconIndex = ICON_INFO;
typeIndex = TYPE_OK;
for (i = 1; i < objc; i += 2) {
if (Tcl_GetIndexFromObj(interp, objv[i], alertOptionStrings, "option",
TCL_EXACT, &index) != TCL_OK) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i], alertOptionStrings,
sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
if (i + 1 == objc) {
str = Tcl_GetString(objv[i]);
Tcl_AppendResult(interp, "value for \"", str, "\" missing", NULL);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"value for \"%s\" missing", Tcl_GetString(objv[i])));
Tcl_SetErrorCode(interp, "TK", "MSGBOX", "VALUE", NULL);
goto end;
}
switch (index) {
@@ -951,8 +1064,8 @@ Tk_MessageBoxObjCmd(
break;
case ALERT_ICON:
if (Tcl_GetIndexFromObj(interp, objv[i + 1], alertIconStrings,
"value", TCL_EXACT, &iconIndex) != TCL_OK) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertIconStrings,
sizeof(char *), "value", TCL_EXACT, &iconIndex) != TCL_OK) {
goto end;
}
break;
@@ -981,8 +1094,8 @@ Tk_MessageBoxObjCmd(
break;
case ALERT_TYPE:
if (Tcl_GetIndexFromObj(interp, objv[i + 1], alertTypeStrings,
"value", TCL_EXACT, &typeIndex) != TCL_OK) {
if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertTypeStrings,
sizeof(char *), "value", TCL_EXACT, &typeIndex) != TCL_OK) {
goto end;
}
break;
@@ -993,13 +1106,12 @@ Tk_MessageBoxObjCmd(
}
if (indexDefaultOption) {
/*
* Any '-default' option needs to know the '-type' option, which is why
* we do this here.
* Any '-default' option needs to know the '-type' option, which is
* why we do this here.
*/
if (Tcl_GetIndexFromObj(interp, objv[indexDefaultOption + 1],
alertButtonStrings, "value", TCL_EXACT, &index)
!= TCL_OK) {
if (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1],
alertButtonStrings, sizeof(char *), "value", TCL_EXACT, &index) != TCL_OK) {
goto end;
}
@@ -1012,6 +1124,7 @@ Tk_MessageBoxObjCmd(
if (!defaultNativeButtonIndex) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("Illegal default option", -1));
Tcl_SetErrorCode(interp, "TK", "MSGBOX", "DEFAULT", NULL);
goto end;
}
}
@@ -1024,15 +1137,17 @@ Tk_MessageBoxObjCmd(
buttons = [alert buttons];
for (NSButton *b in buttons) {
NSString *ke = [b keyEquivalent];
if (([ke isEqualToString:@"\r"] || [ke isEqualToString:@"\033"]) &&
![b keyEquivalentModifierMask]) {
[b setKeyEquivalent:@""];
}
}
[[buttons objectAtIndex:[buttons count]-1] setKeyEquivalent:@"\033"];
[[buttons objectAtIndex:defaultNativeButtonIndex-1] setKeyEquivalent:@"\r"];
[[buttons objectAtIndex: [buttons count]-1] setKeyEquivalent: @"\033"];
[[buttons objectAtIndex: defaultNativeButtonIndex-1]
setKeyEquivalent: @"\r"];
if (cmdObj) {
callbackInfo = (AlertCallbackInfo *) ckalloc(sizeof(AlertCallbackInfo));
callbackInfo = (AlertCallbackInfo *)ckalloc(sizeof(AlertCallbackInfo));
if (Tcl_IsShared(cmdObj)) {
cmdObj = Tcl_DuplicateObj(cmdObj);
}
@@ -1043,19 +1158,32 @@ Tk_MessageBoxObjCmd(
callbackInfo->typeIndex = typeIndex;
parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window);
if (haveParentOption && parent && ![parent attachedSheet]) {
[alert beginSheetModalForWindow:parent modalDelegate:NSApp
didEndSelector:@selector(tkAlertDidEnd:returnCode:contextInfo:)
contextInfo:callbackInfo];
returnCode = cmdObj ? NSAlertOtherReturn :
[NSApp runModalForWindow:[alert window]];
parentIsKey = [parent isKeyWindow];
#if MAC_OS_X_VERSION_MIN_REQUIRED > 1090
[alert beginSheetModalForWindow:parent
completionHandler:^(NSModalResponse returnCode)
{ [NSApp tkAlertDidEnd:alert
returnCode:returnCode
contextInfo:callbackInfo ]; } ];
#else
[alert beginSheetModalForWindow:parent
modalDelegate:NSApp
didEndSelector:@selector(tkAlertDidEnd:returnCode:contextInfo:)
contextInfo:callbackInfo];
#endif
modalReturnCode = cmdObj ? 0 :
[NSApp runModalForWindow:[alert window]];
} else {
returnCode = [alert runModal];
[NSApp tkAlertDidEnd:alert returnCode:returnCode
modalReturnCode = [alert runModal];
[NSApp tkAlertDidEnd:alert returnCode:modalReturnCode
contextInfo:callbackInfo];
}
result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR;
end:
result = (modalReturnCode >= NSAlertFirstButtonReturn) ? TCL_OK : TCL_ERROR;
end:
[alert release];
if (parentIsKey) {
[parent makeKeyWindow];
}
return result;
}

View File

@@ -8,6 +8,7 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright 2014 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -16,6 +17,7 @@
#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"
#include "xbytes.h"
#include "tkButton.h"
/*
#ifdef TK_MAC_DEBUG
@@ -99,24 +101,88 @@ TkMacOSXInitCGDrawing(
(char *) &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) {
Tcl_ResetResult(interp);
}
#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
if (Tcl_LinkVar(interp, "::tk::mac::useCompatibilityMetrics",
(char *) &tkMacOSXUseCompatibilityMetrics, TCL_LINK_BOOLEAN)
!= TCL_OK) {
Tcl_ResetResult(interp);
}
#endif
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* BitmapRepFromDrawableRect
*
* Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep.
*
* Results:
* Returns an autoreleased NSBitmapRep representing the image of the given
* rectangle of the given drawable.
*
* NOTE: The x,y coordinates should be relative to a coordinate system with
* origin at the top left, as used by XImage and CGImage, not bottom
* left as used by NSView.
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
NSBitmapImageRep*
BitmapRepFromDrawableRect(
Drawable drawable,
int x,
int y,
unsigned int width,
unsigned int height)
{
MacDrawable *mac_drawable = (MacDrawable *) drawable;
CGContextRef cg_context=NULL;
CGImageRef cg_image=NULL, sub_cg_image=NULL;
NSBitmapImageRep *bitmap_rep=NULL;
NSView *view=NULL;
if ( mac_drawable->flags & TK_IS_PIXMAP ) {
/*
This means that the MacDrawable is functioning as a Tk Pixmap, so its view
field is NULL.
*/
cg_context = GetCGContextForDrawable(drawable);
CGRect image_rect = CGRectMake(x, y, width, height);
cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context);
sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect);
if ( sub_cg_image ) {
/*This can be dealloc'ed prematurely if set for autorelease, causing crashes.*/
bitmap_rep = [NSBitmapImageRep alloc];
[bitmap_rep initWithCGImage:sub_cg_image];
}
if ( cg_image ) {
CGImageRelease(cg_image);
}
} else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) {
/* convert top-left coordinates to NSView 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] ) {
/*This can be dealloc'ed prematurely if set for autorelease, causing crashes.*/
bitmap_rep = [NSBitmapImageRep alloc];
bitmap_rep = [bitmap_rep initWithFocusedViewRect:view_rect];
[view unlockFocus];
} else {
TkMacOSXDbgMsg("Could not lock focus on view.");
}
} else {
TkMacOSXDbgMsg("Invalid source drawable");
}
return bitmap_rep;
}
/*
*----------------------------------------------------------------------
*
* XCopyArea --
*
* Copies data from one drawable to another using block transfer
* routines.
* Copies data from one drawable to another.
*
* Results:
* None.
@@ -133,86 +199,63 @@ XCopyArea(
Display *display, /* Display. */
Drawable src, /* Source drawable. */
Drawable dst, /* Destination drawable. */
GC gc, /* GC to use. */
GC gc, /* GC to use. */
int src_x, /* X & Y, width & height */
int src_y, /* define the source rectangle */
unsigned int width, /* that will be copied. */
unsigned int width, /* that will be copied. */
unsigned int height,
int dest_x, /* Dest X & Y on dest rect. */
int dest_y)
{
TkMacOSXDrawingContext dc;
MacDrawable *srcDraw = (MacDrawable *) src;
NSBitmapImageRep *bitmap_rep = NULL;
CGImageRef img = NULL;
display->request++;
if (!width || !height) {
/* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */
/* This happens all the time.
TkMacOSXDbgMsg("Drawing of empty area requested");
*/
return;
}
if (srcDraw->flags & TK_IS_PIXMAP) {
if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
return;
}
if (dc.context) {
CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);
if (img) {
DrawCGImage(dst, gc, dc.context, img, gc->foreground,
gc->background, CGRectMake(0, 0,
srcDraw->size.width, srcDraw->size.height),
if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
return;
/*TkMacOSXDbgMsg("Failed to setup drawing context.");*/
}
if ( dc.context ) {
if (srcDraw->flags & TK_IS_PIXMAP) {
img = TkMacOSXCreateCGImageWithDrawable(src);
}else if (TkMacOSXDrawableWindow(src)) {
bitmap_rep = BitmapRepFromDrawableRect(src, src_x, src_y, width, height);
if ( bitmap_rep ) {
img = [bitmap_rep CGImage];
}
} else {
TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
}
if (img) {
DrawCGImage(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));
CFRelease(img);
} else {
TkMacOSXDbgMsg("Invalid source drawable");
}
} else {
TkMacOSXDbgMsg("Invalid destination drawable");
}
TkMacOSXRestoreDrawingContext(&dc);
} else if (TkMacOSXDrawableWindow(src)) {
NSView *view = TkMacOSXDrawableView(srcDraw);
NSWindow *w = [view window];
NSInteger gs = [w windowNumber] > 0 ? [w gState] : 0;
/* // alternative using per-view gState:
NSInteger gs = [view gState];
if (!gs) {
[view allocateGState];
if ([view lockFocusIfCanDraw]) {
[view unlockFocus];
}
gs = [view gState];
}
*/
if (!gs || !TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
return;
}
if (dc.context) {
NSGraphicsContext *gc = nil;
CGFloat boundsH = [view bounds].size.height;
NSRect srcRect = NSMakeRect(srcDraw->xOff + src_x, boundsH -
height - (srcDraw->yOff + src_y), width, height);
CFRelease(img);
if (((MacDrawable *) dst)->flags & TK_IS_PIXMAP) {
gc = [NSGraphicsContext graphicsContextWithGraphicsPort:
dc.context flipped:NO];
if (gc) {
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:gc];
}
}
NSCopyBits(gs, srcRect, NSMakePoint(dest_x,
dc.portBounds.size.height - dest_y));
if (gc) {
[NSGraphicsContext restoreGraphicsState];
}
} else {
TkMacOSXDbgMsg("Invalid destination drawable");
TkMacOSXDbgMsg("Failed to construct CGImage.");
}
TkMacOSXRestoreDrawingContext(&dc);
} else {
TkMacOSXDbgMsg("Invalid source drawable");
TkMacOSXDbgMsg("Invalid destination drawable - no context.");
return;
}
TkMacOSXRestoreDrawingContext(&dc);
}
/*
@@ -239,10 +282,10 @@ XCopyPlane(
Display *display, /* Display. */
Drawable src, /* Source drawable. */
Drawable dst, /* Destination drawable. */
GC gc, /* GC to use. */
GC gc, /* GC to use. */
int src_x, /* X & Y, width & height */
int src_y, /* define the source rectangle */
unsigned int width, /* that will be copied. */
unsigned int width, /* that will be copied. */
unsigned int height,
int dest_x, /* Dest X & Y on dest rect. */
int dest_y,
@@ -250,10 +293,11 @@ XCopyPlane(
{
TkMacOSXDrawingContext dc;
MacDrawable *srcDraw = (MacDrawable *) src;
MacDrawable *dstDraw = (MacDrawable *) dst;
display->request++;
if (!width || !height) {
/* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */
/* TkMacOSXDbgMsg("Drawing of empty area requested"); */
return;
}
if (plane != 1) {
@@ -263,33 +307,47 @@ XCopyPlane(
if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
return;
}
if (dc.context) {
CGContextRef context = dc.context;
if (context) {
CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);
if (img) {
TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
unsigned long imageBackground = gc->background;
if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP &&
clipPtr->value.pixmap == src) {
imageBackground = TRANSPARENT_PIXEL << 24;
if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP){
CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(clipPtr->value.pixmap);
CGRect rect = CGRectMake(dest_x, dest_y, width, height);
rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);
CGContextSaveGState(context);
/* Move the origin of the destination to top left. */
CGContextTranslateCTM(context, 0, rect.origin.y + CGRectGetMaxY(rect));
CGContextScaleCTM(context, 1, -1);
/* Fill with the background color, clipping to the mask. */
CGContextClipToMask(context, rect, mask);
TkMacOSXSetColorInContext(gc, gc->background, dc.context);
CGContextFillRect(dc.context, rect);
/* Fill with the foreground color, clipping to the intersection of img and mask. */
CGContextClipToMask(context, rect, img);
TkMacOSXSetColorInContext(gc, gc->foreground, context);
CGContextFillRect(context, rect);
CGContextRestoreGState(context);
CGImageRelease(mask);
CGImageRelease(img);
} else {
DrawCGImage(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));
CGImageRelease(img);
}
DrawCGImage(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));
CFRelease(img);
} else {
} else { /* no image */
TkMacOSXDbgMsg("Invalid source drawable");
}
} else {
TkMacOSXDbgMsg("Invalid destination drawable");
TkMacOSXDbgMsg("Invalid destination drawable - could not get a bitmap context.");
}
TkMacOSXRestoreDrawingContext(&dc);
} else {
XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x,
dest_y);
} else { /* source drawable is a window, not a Pixmap */
XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x, dest_y);
}
}
@@ -313,16 +371,16 @@ XCopyPlane(
int
TkPutImage(
unsigned long *colors, /* Unused on Macintosh. */
int ncolors, /* Unused on Macintosh. */
int ncolors, /* Unused on Macintosh. */
Display* display, /* Display. */
Drawable d, /* Drawable to place image on. */
GC gc, /* GC to use. */
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 width, /* Same width & height for both */
unsigned int height) /* distination and source. */
{
TkMacOSXDrawingContext dc;
@@ -383,22 +441,17 @@ CreateCGImageWithXImage(
char *data = NULL;
CGDataProviderReleaseDataCallback releaseData = ReleaseData;
if (image->obdata) {
/*
* Image from XGetImage
*/
img = TkMacOSXCreateCGImageWithDrawable((Pixmap) image->obdata);
} else if (image->bits_per_pixel == 1) {
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;
decode = decodeWB;
if (image->bitmap_bit_order != MSBFirst) {
char *srcPtr = image->data + image->xoffset;
char *endPtr = srcPtr + len;
@@ -408,29 +461,27 @@ CreateCGImageWithXImage(
*destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))];
}
} else {
data = memcpy(ckalloc(len), image->data + image->xoffset,
len);
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);
bitsPerPixel, image->bytes_per_line, provider, decode, 0);
}
} else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
/*
* Color image
*/
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
bitsPerComponent = 8;
bitsPerPixel = 32;
bitmapInfo = (image->byte_order == MSBFirst ?
kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little) |
kCGImageAlphaNoneSkipFirst;
kCGImageAlphaNoneSkipFirst;
data = memcpy(ckalloc(len), image->data + image->xoffset, len);
if (data) {
provider = CGDataProviderCreateWithData(data, data, len, releaseData);
@@ -439,6 +490,7 @@ CreateCGImageWithXImage(
img = CGImageCreate(image->width, image->height, bitsPerComponent,
bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo,
provider, decode, 0, kCGRenderingIntentDefault);
CFRelease(provider);
}
if (colorspace) {
CFRelease(colorspace);
@@ -446,10 +498,6 @@ CreateCGImageWithXImage(
} else {
TkMacOSXDbgMsg("Unsupported image type");
}
if (provider) {
CFRelease(provider);
}
return img;
}
@@ -618,17 +666,16 @@ GetCGContextForDrawable(
CGColorSpaceRef colorspace = NULL;
CGBitmapInfo bitmapInfo =
#ifdef __LITTLE_ENDIAN__
kCGBitmapByteOrder32Host;
kCGBitmapByteOrder32Host;
#else
kCGBitmapByteOrderDefault;
kCGBitmapByteOrderDefault;
#endif
char *data;
CGRect bounds = CGRectMake(0, 0, macDraw->size.width,
macDraw->size.height);
CGRect bounds = CGRectMake(0, 0, macDraw->size.width, macDraw->size.height);
if (macDraw->flags & TK_IS_BW_PIXMAP) {
bitsPerPixel = 8;
bitmapInfo = kCGImageAlphaOnly;
bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly;
} else {
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
bitsPerPixel = 32;
@@ -697,9 +744,11 @@ DrawCGImage(
}
}
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. */
if (imageBackground != TRANSPARENT_PIXEL << 24) {
CGContextClearRect(context, dstBounds);
}
@@ -712,6 +761,7 @@ DrawCGImage(
TkMacOSXSetColorInContext(gc, imageForeground, context);
}
}
#ifdef TK_MAC_DEBUG_IMAGE_DRAWING
CGContextSaveGState(context);
CGContextSetLineWidth(context, 1.0);
@@ -1439,43 +1489,94 @@ TkScrollWindow(
int dx, int dy, /* Distance rectangle should be moved. */
TkRegion damageRgn) /* Region to accumulate damage in. */
{
MacDrawable *macDraw = (MacDrawable *) Tk_WindowId(tkwin);
NSView *view = TkMacOSXDrawableView(macDraw);
CGRect visRect, srcRect, dstRect;
CGFloat boundsH;
HIShapeRef dmgRgn, dstRgn;
int result;
Drawable drawable = Tk_WindowId(tkwin);
MacDrawable *macDraw = (MacDrawable *) drawable;
TKContentView *view = (TKContentView *)TkMacOSXDrawableView(macDraw);
CGRect srcRect, dstRect;
HIShapeRef dmgRgn = NULL, extraRgn = NULL;
NSRect bounds, visRect, scrollSrc, scrollDst;
int result = 0;
if (view && !CGRectIsEmpty(visRect = NSRectToCGRect([view visibleRect]))) {
boundsH = [view bounds].size.height;
srcRect = CGRectMake(macDraw->xOff + x, boundsH - height -
(macDraw->yOff + y), width, height);
dstRect = CGRectIntersection(CGRectOffset(srcRect, dx, -dy), visRect);
srcRect = CGRectIntersection(srcRect, visRect);
if (!CGRectIsEmpty(srcRect) && !CGRectIsEmpty(dstRect)) {
/*
CGRect sRect = CGRectIntersection(CGRectOffset(dstRect, -dx, dy),
srcRect);
NSCopyBits(0, NSRectFromCGRect(sRect),
NSPointFromCGPoint(CGRectOffset(sRect, dx, -dy).origin));
*/
[view scrollRect:NSRectFromCGRect(srcRect) by:NSMakeSize(dx, -dy)];
}
srcRect.origin.y = boundsH - srcRect.size.height - srcRect.origin.y;
dstRect.origin.y = boundsH - dstRect.size.height - dstRect.origin.y;
srcRect = CGRectUnion(srcRect, dstRect);
dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
dstRgn = HIShapeCreateWithRect(&dstRect);
ChkErr(HIShapeDifference, dmgRgn, dstRgn, (HIMutableShapeRef) dmgRgn);
CFRelease(dstRgn);
TkMacOSXInvalidateViewRegion(view, dmgRgn);
if ( view ) {
/* Get the scroll area in NSView coordinates (origin at bottom left). */
bounds = [view bounds];
scrollSrc = NSMakeRect(
macDraw->xOff + x,
bounds.size.height - height - (macDraw->yOff + y),
width, height);
scrollDst = NSOffsetRect(scrollSrc, dx, -dy);
/* Limit scrolling to the window content area. */
visRect = [view visibleRect];
scrollSrc = NSIntersectionRect(scrollSrc, visRect);
scrollDst = NSIntersectionRect(scrollDst, visRect);
if ( !NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst) ) {
/*
* Mark the difference between source and destination as damaged.
* This region is described in NSView coordinates (y=0 at the bottom)
* and converted to Tk coordinates later.
*/
srcRect = CGRectMake(x, y, width, height);
dstRect = CGRectOffset(srcRect, dx, dy);
/* Expand the rectangles slightly to avoid degeneracies. */
srcRect.origin.y -= 1;
srcRect.size.height += 2;
dstRect.origin.y += 1;
dstRect.size.height -= 2;
/* Compute the damage. */
dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
extraRgn = HIShapeCreateWithRect(&dstRect);
ChkErr(HIShapeDifference, dmgRgn, extraRgn, (HIMutableShapeRef) dmgRgn);
result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
/* Convert to Tk coordinates. */
TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
if (extraRgn) {
CFRelease(extraRgn);
}
/* Scroll the rectangle. */
[view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)];
/* Shift the Tk children which meet the source rectangle. */
TkWindow *winPtr = (TkWindow *)tkwin;
TkWindow *childPtr;
CGRect childBounds;
for (childPtr = winPtr->childList; childPtr != NULL; childPtr = childPtr->nextPtr) {
if (Tk_IsMapped(childPtr) && !Tk_IsTopLevel(childPtr)) {
TkMacOSXWinCGBounds(childPtr, &childBounds);
if (CGRectIntersectsRect(srcRect, childBounds)) {
MacDrawable *macChild = childPtr->privatePtr;
if (macChild) {
macChild->yOff += dy;
macChild->xOff += dx;
childPtr->changes.y = macChild->yOff;
childPtr->changes.x = macChild->xOff;
}
}
}
}
/* Queue up Expose events for the damage region. */
int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
[view generateExposeEvents:dmgRgn childrenOnly:1];
Tcl_SetServiceMode(oldMode);
/* Belt and suspenders: make the AppKit request a redraw
when it gets control again. */
}
} else {
dmgRgn = HIShapeCreateEmpty();
TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
}
TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
CFRelease(dmgRgn);
if (dmgRgn) {
CFRelease(dmgRgn);
}
return result;
}
@@ -1688,6 +1789,7 @@ TkMacOSXRestoreDrawingContext(
{
if (dcPtr->context) {
CGContextSynchronize(dcPtr->context);
[[dcPtr->view window] setViewsNeedDisplay:YES];
[[dcPtr->view window] enableFlushWindow];
if (dcPtr->focusLocked) {
[dcPtr->view unlockFocus];
@@ -1726,7 +1828,7 @@ TkMacOSXGetClipRgn(
{
MacDrawable *macDraw = (MacDrawable *) drawable;
HIShapeRef clipRgn = NULL;
if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) {
TkMacOSXUpdateClipRgn(macDraw->winPtr);
#ifdef TK_MAC_DEBUG_DRAWING
@@ -1751,7 +1853,6 @@ TkMacOSXGetClipRgn(
} else if (macDraw->visRgn) {
clipRgn = HIShapeCreateCopy(macDraw->visRgn);
}
return clipRgn;
}
@@ -1804,15 +1905,16 @@ TkpClipDrawableToRect(
{
MacDrawable *macDraw = (MacDrawable *) d;
NSView *view = TkMacOSXDrawableView(macDraw);
if (macDraw->drawRgn) {
CFRelease(macDraw->drawRgn);
macDraw->drawRgn = NULL;
}
if (width >= 0 && height >= 0) {
CGRect drawRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff,
CGRect clipRect = CGRectMake(x + macDraw->xOff, y + macDraw->yOff,
width, height);
HIShapeRef drawRgn = HIShapeCreateWithRect(&drawRect);
HIShapeRef drawRgn = HIShapeCreateWithRect(&clipRect);
if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) {
TkMacOSXUpdateClipRgn(macDraw->winPtr);
@@ -1825,9 +1927,9 @@ TkpClipDrawableToRect(
macDraw->drawRgn = drawRgn;
}
if (view && view != [NSView focusView] && [view lockFocusIfCanDraw]) {
drawRect.origin.y = [view bounds].size.height -
(drawRect.origin.y + drawRect.size.height);
NSRectClip(NSRectFromCGRect(drawRect));
clipRect.origin.y = [view bounds].size.height -
(clipRect.origin.y + clipRect.size.height);
NSRectClip(NSRectFromCGRect(clipRect));
macDraw->flags |= TK_FOCUSED_VIEW;
}
} else {
@@ -1956,7 +2058,7 @@ TkpDrawHighlightBorder (
* TkpDrawFrame --
*
* This procedure draws the rectangular frame area. If the user
* has request themeing, it draws with a the background theme.
* has requested themeing, it draws with the background theme.
*
* Results:
* None.
@@ -1986,6 +2088,7 @@ TkpDrawFrame(
border = themedBorder;
}
}
Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
border, highlightWidth, highlightWidth,
Tk_Width(tkwin) - 2 * highlightWidth,

View File

@@ -13,7 +13,7 @@
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
*/
#include "tkMacOSXPrivate.h"
@@ -171,6 +171,50 @@ TkpMakeWindow(
return (Window) macWin;
}
/*
*----------------------------------------------------------------------
*
* TkpScanWindowId --
*
* Given a string, produce the corresponding Window Id.
*
* Results:
* The return value is normally TCL_OK; in this case *idPtr will be set
* to the Window value equivalent to string. If string is improperly
* formed then TCL_ERROR is returned and an error message will be left in
* the interp's result.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TkpScanWindowId(
Tcl_Interp *interp,
CONST char * string,
Window *idPtr)
{
int code;
Tcl_Obj obj;
obj.refCount = 1;
obj.bytes = (char *) string; /* DANGER?! */
obj.length = strlen(string);
obj.typePtr = NULL;
code = Tcl_GetLongFromObj(interp, &obj, (long *)idPtr);
if (obj.refCount > 1) {
Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
}
if (obj.typePtr && obj.typePtr->freeIntRepProc) {
obj.typePtr->freeIntRepProc(&obj);
}
return code;
}
/*
*----------------------------------------------------------------------
*
@@ -214,7 +258,7 @@ TkpUseWindow(
}
/*
* Decode the container pointer, and look for it among the list of
* Decode the container window ID, and look for it among the list of
* available containers.
*
* N.B. For now, we are limiting the containers to be in the same Tk
@@ -222,7 +266,7 @@ TkpUseWindow(
* containers.
*/
if (Tcl_GetInt(interp, string, (int*) &parent) != TCL_OK) {
if (TkpScanWindowId(interp, string, (Window *)&parent) != TCL_OK) {
return TCL_ERROR;
}

View File

@@ -30,18 +30,19 @@ enum {
NSEvent *processedEvent = theEvent;
NSEventType type = [theEvent type];
NSInteger subtype;
NSUInteger flags;
switch ((NSInteger)type) {
case NSAppKitDefined:
subtype = [theEvent subtype];
switch (subtype) {
/* Ignored at the moment. */
case NSApplicationActivatedEventType:
break;
case NSApplicationDeactivatedEventType:
break;
case NSWindowExposedEventType:
break;
case NSScreenChangedEventType:
break;
case NSWindowMovedEventType:
@@ -52,13 +53,12 @@ enum {
default:
break;
}
break;
break; /* AppkitEvent. Return theEvent */
case NSKeyUp:
case NSKeyDown:
case NSFlagsChanged:
flags = [theEvent modifierFlags];
processedEvent = [self tkProcessKeyEvent:theEvent];
break;
break; /* Key event. Return the processed event. */
case NSLeftMouseDown:
case NSLeftMouseUp:
case NSRightMouseDown:
@@ -75,7 +75,7 @@ enum {
case NSTabletPoint:
case NSTabletProximity:
processedEvent = [self tkProcessMouseEvent:theEvent];
break;
break; /* Mouse event. Return the processed event. */
#if 0
case NSSystemDefined:
subtype = [theEvent subtype];
@@ -99,7 +99,7 @@ enum {
#endif
default:
break;
break; /* return theEvent */
}
return processedEvent;
}
@@ -112,35 +112,26 @@ enum {
*
* TkMacOSXFlushWindows --
*
* This routine flushes all the windows of the application. It is
* This routine flushes all the visible windows of the application. It is
* called by XSync().
*
* Results:
* None.
*
* Side effects:
* Flushes all Carbon windows
* Flushes all visible Cocoa windows
*
*----------------------------------------------------------------------
*/
MODULE_SCOPE void
TkMacOSXFlushWindows(void)
{
NSInteger windowCount;
NSInteger *windowNumbers;
NSArray *macWindows = [NSApp orderedWindows];
NSCountWindows(&windowCount);
if(windowCount) {
windowNumbers = (NSInteger *) ckalloc(windowCount * sizeof(NSInteger));
NSWindowList(windowCount, windowNumbers);
for (NSInteger index = 0; index < windowCount; index++) {
NSWindow *w = [NSApp windowWithWindowNumber:windowNumbers[index]];
if (TkMacOSXGetXWindow(w)) {
[w flushWindow];
}
for (NSWindow *w in macWindows) {
if (TkMacOSXGetXWindow(w)) {
[w flushWindow];
}
ckfree((char*) windowNumbers);
}
}

View File

@@ -15,6 +15,19 @@
#include "tkMacOSXPrivate.h"
#include "tkMacOSXFont.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
#define TK_MAC_DEBUG_FONTS
@@ -197,6 +210,7 @@ FindNSFont(
nsFont = [fm convertFont:nsFont toSize:size];
nsFont = [fm convertFont:nsFont toHaveTrait:traits];
}
[nsFont retain];
#undef defaultFont
return nsFont;
}
@@ -270,7 +284,7 @@ InitFont(
fmPtr->fixed = [nsFont advancementForGlyph:glyphs[0]].width ==
[nsFont advancementForGlyph:glyphs[1]].width;
bounds = NSRectFromCGRect(CTFontGetBoundingRectsForGlyphs((CTFontRef)
nsFont, kCTFontDefaultOrientation, ch, boundingRects, nCh));
nsFont, defaultOrientation, ch, boundingRects, nCh));
kern = [nsFont advancementForGlyph:glyphs[2]].width -
[fontPtr->nsFont advancementForGlyph:glyphs[2]].width;
}
@@ -293,7 +307,7 @@ InitFont(
[NSNumber numberWithInt:fmPtr->fixed ? 0 : 1],
NSLigatureAttributeName,
[NSNumber numberWithDouble:kern], NSKernAttributeName, nil];
fontPtr->nsAttributes = TkMacOSXMakeUncollectableAndRetain(nsAttributes);
fontPtr->nsAttributes = [nsAttributes retain];
#undef nCh
}
@@ -358,6 +372,7 @@ TkpFontPkgInit(
NSFont *nsFont;
TkFontAttributes fa;
NSMutableCharacterSet *cs;
/* Since we called before TkpInit, we need our own autorelease pool. */
NSAutoreleasePool *pool = [NSAutoreleasePool new];
/* force this for now */
@@ -382,8 +397,7 @@ TkpFontPkgInit(
systemFont++;
}
TkInitFontAttributes(&fa);
nsFont = (NSFont*) CTFontCreateUIFontForLanguage(
kCTFontUserFixedPitchFontType, 11, NULL);
nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL);
if (nsFont) {
GetTkFontAttributesForNSFont(nsFont, &fa);
CFRelease(nsFont);
@@ -518,7 +532,7 @@ TkpGetFontFromAttributes(
nsFont = FindNSFont(faPtr->family, traits, weight, points, 1);
}
if (!nsFont) {
Tcl_Panic("Could not deternmine NSFont from TkFontAttributes");
Tcl_Panic("Could not determine NSFont from TkFontAttributes");
}
if (tkFontPtr == NULL) {
fontPtr = (MacFont *) ckalloc(sizeof(MacFont));
@@ -557,7 +571,8 @@ TkpDeleteFont(
{
MacFont *fontPtr = (MacFont *) tkFontPtr;
TkMacOSXMakeCollectableAndRelease(fontPtr->nsAttributes);
[fontPtr->nsAttributes release];
fontPtr->nsAttributes = NULL;
CFRelease(fontPtr->nsFont); /* Either a CTFontRef or a CFRetained NSFont */
}
@@ -662,7 +677,6 @@ TkpGetFontAttrsForChar(
{
MacFont *fontPtr = (MacFont *) tkfont;
NSFont *nsFont = fontPtr->nsFont;
*faPtr = fontPtr->font.fa;
if (nsFont && ![[nsFont coveredCharacterSet] characterIsMember:c]) {
UTF16Char ch = c;

View File

@@ -7,12 +7,15 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright (c) 2015 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 <sys/param.h>
#define URL_MAX_LENGTH (17 + MAXPATHLEN)
/*
* This is a Tcl_Event structure that the Quit AppleEvent handler uses to
@@ -30,47 +33,344 @@ typedef struct KillEvent {
* Static functions used only in this file.
*/
static OSErr QuitHandler(const AppleEvent *event,
AppleEvent *reply, SRefCon handlerRefcon);
static OSErr OappHandler(const AppleEvent *event,
AppleEvent *reply, SRefCon handlerRefcon);
static OSErr RappHandler(const AppleEvent *event,
AppleEvent *reply, SRefCon handlerRefcon);
static OSErr OdocHandler(const AppleEvent *event,
AppleEvent *reply, SRefCon handlerRefcon);
static OSErr PrintHandler(const AppleEvent *event,
AppleEvent *reply, SRefCon handlerRefcon);
static OSErr ScriptHandler(const AppleEvent *event,
AppleEvent *reply, SRefCon handlerRefcon);
static OSErr PrefsHandler(const AppleEvent *event,
AppleEvent *reply, SRefCon handlerRefcon);
static int MissedAnyParameters(const AppleEvent *theEvent);
static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
static OSStatus FSRefToDString(const FSRef *fsref, Tcl_DString *ds);
static void tkMacOSXProcessFiles(NSAppleEventDescriptor* event,
NSAppleEventDescriptor* replyEvent,
Tcl_Interp *interp,
char* procedure);
static int MissedAnyParameters(const AppleEvent *theEvent);
static int ReallyKillMe(Tcl_Event *eventPtr, int flags);
#pragma mark TKApplication(TKHLEvents)
@implementation TKApplication(TKHLEvents)
- (void)terminate:(id)sender {
QuitHandler(NULL, NULL, (SRefCon) _eventInterp);
- (void) terminate: (id) sender
{
[self handleQuitApplicationEvent:Nil withReplyEvent:Nil];
}
- (void)preferences:(id)sender {
PrefsHandler(NULL, NULL, (SRefCon) _eventInterp);
- (void) preferences: (id) sender
{
[self handleShowPreferencesEvent:Nil withReplyEvent:Nil];
}
- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
KillEvent *eventPtr;
if (_eventInterp) {
/*
* Call the exit command from the event loop, since you are not
* supposed to call ExitToShell in an Apple Event Handler. We put this
* at the head of Tcl's event queue because this message usually comes
* when the Mac is shutting down, and we want to kill the shell as
* quickly as possible.
*/
eventPtr = (KillEvent*)ckalloc(sizeof(KillEvent));
eventPtr->header.proc = ReallyKillMe;
eventPtr->interp = _eventInterp;
Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD);
}
}
- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
Tcl_Interp *interp = _eventInterp;
if (interp &&
Tcl_FindCommand(_eventInterp, "::tk::mac::OpenApplication", NULL, 0)){
int code = Tcl_EvalEx(_eventInterp, "::tk::mac::OpenApplication",
-1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(_eventInterp);
}
}
}
- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
ProcessSerialNumber thePSN = {0, kCurrentProcess};
SetFrontProcess(&thePSN);
#else
[[NSApplication sharedApplication] activateIgnoringOtherApps: YES];
#endif
if (_eventInterp && Tcl_FindCommand(_eventInterp,
"::tk::mac::ReopenApplication", NULL, 0)) {
int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ReopenApplication",
-1, TCL_EVAL_GLOBAL);
if (code != TCL_OK){
Tcl_BackgroundError(_eventInterp);
}
}
}
- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
if (_eventInterp &&
Tcl_FindCommand(_eventInterp, "::tk::mac::ShowPreferences", NULL, 0)){
int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ShowPreferences",
-1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(_eventInterp);
}
}
}
- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::OpenDocument");
}
- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::PrintDocument");
}
- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent
{
OSStatus err;
const AEDesc *theDesc = nil;
DescType type = 0, initialType = 0;
Size actual;
int tclErr = -1;
char URLBuffer[1 + URL_MAX_LENGTH];
char errString[128];
char typeString[5];
/*
* The DoScript event receives one parameter that should be text data or a
* fileURL.
*/
theDesc = [event aeDesc];
if (theDesc == nil) {
return;
}
err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType,
NULL, 0, NULL);
if (err != noErr) {
sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", (int)err);
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
errString, strlen(errString));
return;
}
if (MissedAnyParameters((AppleEvent*)theDesc)) {
sprintf(errString, "AEDoScriptHandler: extra parameters");
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
errString, strlen(errString));
return;
}
if (initialType == typeFileURL || initialType == typeAlias) {
/*
* The descriptor can be coerced to a file url. Source the file, or
* pass the path as a string argument to ::tk::mac::DoScriptFile if
* that procedure exists.
*/
err = AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type,
(Ptr) URLBuffer, URL_MAX_LENGTH, &actual);
if (err == noErr && actual > 0){
URLBuffer[actual] = '\0';
NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer];
NSURL *fileURL = [NSURL URLWithString:urlString];
Tcl_DString command;
Tcl_DStringInit(&command);
if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptFile", NULL, 0)){
Tcl_DStringAppend(&command, "::tk::mac::DoScriptFile", -1);
} else {
Tcl_DStringAppend(&command, "source", -1);
}
Tcl_DStringAppendElement(&command, [[fileURL path] UTF8String]);
tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
}
} else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
NULL, 0, &actual)) {
if (actual > 0) {
/*
* The descriptor can be coerced to UTF8 text. Evaluate as Tcl, or
* or pass the text as a string argument to ::tk::mac::DoScriptText
* if that procedure exists.
*/
char *data = ckalloc(actual + 1);
if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type,
data, actual, NULL)) {
if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptText", NULL, 0)){
Tcl_DString command;
Tcl_DStringInit(&command);
Tcl_DStringAppend(&command, "::tk::mac::DoScriptText", -1);
Tcl_DStringAppendElement(&command, data);
tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command),
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
} else {
tclErr = Tcl_EvalEx(_eventInterp, data, actual, TCL_EVAL_GLOBAL);
}
}
ckfree(data);
}
} else {
/*
* The descriptor can not be coerced to a fileURL or UTF8 text.
*/
for (int i = 0; i < 4; i++) {
typeString[i] = ((char*)&initialType)[3-i];
}
typeString[4] = '\0';
sprintf(errString, "AEDoScriptHandler: invalid script type '%s', "
"must be coercable to 'furl' or 'utf8'", typeString);
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, errString,
strlen(errString));
}
/*
* If we ran some Tcl code, put the result in the reply.
*/
if (tclErr >= 0) {
int reslen;
const char *result =
Tcl_GetStringFromObj(Tcl_GetObjResult(_eventInterp), &reslen);
if (tclErr == TCL_OK) {
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyDirectObject, typeChar,
result, reslen);
} else {
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar,
result, reslen);
AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorNumber, typeSInt32,
(Ptr) &tclErr,sizeof(int));
}
}
return;
}
@end
#pragma mark -
/*
*----------------------------------------------------------------------
*
* TkMacOSXProcessFiles --
*
* Extract a list of fileURLs from an AppleEvent and call the specified
* procedure with the file paths as arguments.
*
* Results:
* None.
*
* Side effects:
* The event is handled by running the procedure.
*
*----------------------------------------------------------------------
*/
static void
tkMacOSXProcessFiles(
NSAppleEventDescriptor* event,
NSAppleEventDescriptor* replyEvent,
Tcl_Interp *interp,
char* procedure)
{
Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, "utf-8");
const AEDesc *fileSpecDesc = nil;
AEDesc contents;
char URLString[1 + URL_MAX_LENGTH];
NSURL *fileURL;
DescType type;
Size actual;
long count, index;
AEKeyword keyword;
Tcl_DString command, pathName;
int code;
/*
* Do nothing if we don't have an interpreter or the procedure doesn't exist.
*/
if (!interp || !Tcl_FindCommand(interp, procedure, NULL, 0)) {
return;
}
fileSpecDesc = [event aeDesc];
if (fileSpecDesc == nil ) {
return;
}
/*
* The AppleEvent's descriptor should either contain a value of
* typeObjectSpecifier or typeAEList. In the first case, the descriptor
* can be treated as a list of size 1 containing a value which can be
* coerced into a fileURL. In the second case we want to work with the list
* itself. Values in the list will be coerced into fileURL's if possible;
* otherwise they will be ignored.
*/
/* Get a copy of the AppleEvent's descriptor. */
AEGetParamDesc(fileSpecDesc, keyDirectObject, typeWildCard, &contents);
if (contents.descriptorType == typeAEList) {
fileSpecDesc = &contents;
}
if (AECountItems(fileSpecDesc, &count) != noErr) {
AEDisposeDesc(&contents);
return;
}
/*
* Construct a Tcl command which calls the procedure, passing the
* paths contained in the AppleEvent as arguments.
*/
Tcl_DStringInit(&command);
Tcl_DStringAppend(&command, procedure, -1);
for (index = 1; index <= count; index++) {
if (noErr != AEGetNthPtr(fileSpecDesc, index, typeFileURL, &keyword,
&type, (Ptr) URLString, URL_MAX_LENGTH, &actual)) {
continue;
}
if (type != typeFileURL) {
continue;
}
URLString[actual] = '\0';
fileURL = [NSURL URLWithString:[NSString stringWithUTF8String:(char*)URLString]];
if (fileURL == nil) {
continue;
}
Tcl_ExternalToUtfDString(utf8, [[fileURL path] UTF8String], -1, &pathName);
Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
Tcl_DStringFree(&pathName);
}
AEDisposeDesc(&contents);
/*
* Handle the event by evaluating the Tcl expression we constructed.
*/
code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(interp);
}
Tcl_DStringFree(&command);
return;
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXInitAppleEvents --
*
* Initilize the Apple Events on the Macintosh. This registers the core
* event handlers.
* Register AppleEvent handlers with the NSAppleEventManager for
* this NSApplication.
*
* Results:
* None.
@@ -83,49 +383,41 @@ static OSStatus FSRefToDString(const FSRef *fsref, Tcl_DString *ds);
void
TkMacOSXInitAppleEvents(
Tcl_Interp *interp) /* Interp to handle basic events. */
Tcl_Interp *interp) /* not used */
{
AEEventHandlerUPP OappHandlerUPP, RappHandlerUPP, OdocHandlerUPP;
AEEventHandlerUPP PrintHandlerUPP, QuitHandlerUPP, ScriptHandlerUPP;
AEEventHandlerUPP PrefsHandlerUPP;
NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];
static Boolean initialized = FALSE;
if (!initialized) {
initialized = TRUE;
/*
* Install event handlers for the core apple events.
*/
[aeManager setEventHandler:NSApp
andSelector:@selector(handleQuitApplicationEvent:withReplyEvent:)
forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
QuitHandlerUPP = NewAEEventHandlerUPP(QuitHandler);
ChkErr(AEInstallEventHandler, kCoreEventClass, kAEQuitApplication,
QuitHandlerUPP, (SRefCon) interp, false);
[aeManager setEventHandler:NSApp
andSelector:@selector(handleOpenApplicationEvent:withReplyEvent:)
forEventClass:kCoreEventClass andEventID:kAEOpenApplication];
OappHandlerUPP = NewAEEventHandlerUPP(OappHandler);
ChkErr(AEInstallEventHandler, kCoreEventClass, kAEOpenApplication,
OappHandlerUPP, (SRefCon) interp, false);
[aeManager setEventHandler:NSApp
andSelector:@selector(handleReopenApplicationEvent:withReplyEvent:)
forEventClass:kCoreEventClass andEventID:kAEReopenApplication];
RappHandlerUPP = NewAEEventHandlerUPP(RappHandler);
ChkErr(AEInstallEventHandler, kCoreEventClass, kAEReopenApplication,
RappHandlerUPP, (SRefCon) interp, false);
[aeManager setEventHandler:NSApp
andSelector:@selector(handleShowPreferencesEvent:withReplyEvent:)
forEventClass:kCoreEventClass andEventID:kAEShowPreferences];
OdocHandlerUPP = NewAEEventHandlerUPP(OdocHandler);
ChkErr(AEInstallEventHandler, kCoreEventClass, kAEOpenDocuments,
OdocHandlerUPP, (SRefCon) interp, false);
[aeManager setEventHandler:NSApp
andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:)
forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
PrintHandlerUPP = NewAEEventHandlerUPP(PrintHandler);
ChkErr(AEInstallEventHandler, kCoreEventClass, kAEPrintDocuments,
PrintHandlerUPP, (SRefCon) interp, false);
[aeManager setEventHandler:NSApp
andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:)
forEventClass:kCoreEventClass andEventID:kAEPrintDocuments];
PrefsHandlerUPP = NewAEEventHandlerUPP(PrefsHandler);
ChkErr(AEInstallEventHandler, kCoreEventClass, kAEShowPreferences,
PrefsHandlerUPP, (SRefCon) interp, false);
if (interp) {
ScriptHandlerUPP = NewAEEventHandlerUPP(ScriptHandler);
ChkErr(AEInstallEventHandler, kAEMiscStandards, kAEDoScript,
ScriptHandlerUPP, (SRefCon) interp, false);
}
[aeManager setEventHandler:NSApp
andSelector:@selector(handleDoScriptEvent:withReplyEvent:)
forEventClass:kAEMiscStandards andEventID:kAEDoScript];
}
}
@@ -134,13 +426,13 @@ TkMacOSXInitAppleEvents(
*
* TkMacOSXDoHLEvent --
*
* Dispatch incomming highlevel events.
* Dispatch an AppleEvent.
*
* Results:
* None.
*
* Side effects:
* Depends on the incoming event.
* Depend on the AppleEvent.
*
*----------------------------------------------------------------------
*/
@@ -149,455 +441,31 @@ int
TkMacOSXDoHLEvent(
void *theEvent)
{
return AEProcessAppleEvent((EventRecord *)theEvent);
}
/*
*----------------------------------------------------------------------
*
* QuitHandler --
*
* This is the 'quit' core Apple event handler.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static OSErr
QuitHandler(
const AppleEvent *event,
AppleEvent *reply,
SRefCon handlerRefcon)
{
Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
KillEvent *eventPtr;
if (interp) {
/*
* Call the exit command from the event loop, since you are not
* supposed to call ExitToShell in an Apple Event Handler. We put this
* at the head of Tcl's event queue because this message usually comes
* when the Mac is shutting down, and we want to kill the shell as
* quickly as possible.
*/
eventPtr = (KillEvent *) ckalloc(sizeof(KillEvent));
eventPtr->header.proc = ReallyKillMe;
eventPtr->interp = interp;
Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD);
}
return noErr;
}
/*
*----------------------------------------------------------------------
*
* OappHandler --
*
* This is the 'oapp' core Apple event handler.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static OSErr
OappHandler(
const AppleEvent *event,
AppleEvent *reply,
SRefCon handlerRefcon)
{
Tcl_CmdInfo dummy;
Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
if (interp &&
Tcl_GetCommandInfo(interp, "::tk::mac::OpenApplication", &dummy)){
int code = Tcl_EvalEx(interp, "::tk::mac::OpenApplication", -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(interp);
}
}
return noErr;
}
/*
*----------------------------------------------------------------------
*
* RappHandler --
*
* This is the 'rapp' core Apple event handler.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static OSErr
RappHandler(
const AppleEvent *event,
AppleEvent *reply,
SRefCon handlerRefcon)
{
Tcl_CmdInfo dummy;
Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
ProcessSerialNumber thePSN = {0, kCurrentProcess};
OSStatus err = ChkErr(SetFrontProcess, &thePSN);
if (interp && Tcl_GetCommandInfo(interp,
"::tk::mac::ReopenApplication", &dummy)) {
int code = Tcl_EvalEx(interp, "::tk::mac::ReopenApplication", -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK){
Tcl_BackgroundError(interp);
}
}
return err;
}
/*
*----------------------------------------------------------------------
*
* PrefsHandler --
*
* This is the 'pref' core Apple event handler. Called when the user
* selects 'Preferences...' in MacOS X
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static OSErr
PrefsHandler(
const AppleEvent *event,
AppleEvent *reply,
SRefCon handlerRefcon)
{
Tcl_CmdInfo dummy;
Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
if (interp &&
Tcl_GetCommandInfo(interp, "::tk::mac::ShowPreferences", &dummy)){
int code = Tcl_EvalEx(interp, "::tk::mac::ShowPreferences", -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(interp);
}
}
return noErr;
}
/*
*----------------------------------------------------------------------
*
* OdocHandler --
*
* This is the 'odoc' core Apple event handler.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static OSErr
OdocHandler(
const AppleEvent *event,
AppleEvent *reply,
SRefCon handlerRefcon)
{
Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
AEDescList fileSpecList;
FSRef file;
DescType type;
Size actual;
long count, index;
AEKeyword keyword;
Tcl_DString command, pathName;
Tcl_CmdInfo dummy;
int code;
/*
* Don't bother if we don't have an interp or the open document procedure
* doesn't exist.
/* According to the NSAppleEventManager reference:
* "The theReply parameter always specifies a reply Apple event, never
* nil. However, the handler should not fill out the reply if the
* descriptor type for the reply event is typeNull, indicating the sender
* does not want a reply."
* The specified way to build such a non-nil descriptor is used here. But
* on OSX 10.11, the compiler nonetheless generates a warning. I am
* supressing the warning here -- maybe the warnings will stop in a future
* compiler release.
*/
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnonnull"
#endif
if (!interp ||
!Tcl_GetCommandInfo(interp, "::tk::mac::OpenDocument", &dummy)) {
return noErr;
}
NSAppleEventDescriptor* theReply = [NSAppleEventDescriptor nullDescriptor];
NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager];
/*
* If we get any errors while retrieving our parameters we just return with
* no error.
*/
return [aeManager dispatchRawAppleEvent:(const AppleEvent*)theEvent
withRawReply: (AppleEvent *)theReply
handlerRefCon: (SRefCon)0];
if (ChkErr(AEGetParamDesc, event, keyDirectObject, typeAEList,
&fileSpecList) != noErr) {
return noErr;
}
if (MissedAnyParameters(event) != noErr) {
return noErr;
}
if (ChkErr(AECountItems, &fileSpecList, &count) != noErr) {
return noErr;
}
/*
* Convert our parameters into a script to evaluate, skipping things that
* we can't handle right.
*/
Tcl_DStringInit(&command);
Tcl_DStringAppend(&command, "::tk::mac::OpenDocument", -1);
for (index = 1; index <= count; index++) {
if (ChkErr(AEGetNthPtr, &fileSpecList, index, typeFSRef, &keyword,
&type, (Ptr) &file, sizeof(FSRef), &actual) != noErr) {
continue;
}
if (ChkErr(FSRefToDString, &file, &pathName) == noErr) {
Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
Tcl_DStringFree(&pathName);
}
}
/*
* Now handle the event by evaluating a script.
*/
code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(interp);
}
Tcl_DStringFree(&command);
return noErr;
}
/*
*----------------------------------------------------------------------
*
* PrintHandler --
*
* This is the 'pdoc' core Apple event handler.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static OSErr
PrintHandler(
const AppleEvent * event,
AppleEvent * reply,
SRefCon handlerRefcon)
{
Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
AEDescList fileSpecList;
FSRef file;
DescType type;
Size actual;
long count, index;
AEKeyword keyword;
Tcl_DString command, pathName;
Tcl_CmdInfo dummy;
int code;
/*
* Don't bother if we don't have an interp or the print document procedure
* doesn't exist.
*/
if (!interp ||
!Tcl_GetCommandInfo(interp, "::tk::mac::PrintDocument", &dummy)) {
return noErr;
}
/*
* If we get any errors while retrieving our parameters we just return with
* no error.
*/
if (ChkErr(AEGetParamDesc, event, keyDirectObject, typeAEList,
&fileSpecList) != noErr) {
return noErr;
}
if (ChkErr(MissedAnyParameters, event) != noErr) {
return noErr;
}
if (ChkErr(AECountItems, &fileSpecList, &count) != noErr) {
return noErr;
}
Tcl_DStringInit(&command);
Tcl_DStringAppend(&command, "::tk::mac::PrintDocument", -1);
for (index = 1; index <= count; index++) {
if (ChkErr(AEGetNthPtr, &fileSpecList, index, typeFSRef, &keyword,
&type, (Ptr) &file, sizeof(FSRef), &actual) != noErr) {
continue;
}
if (ChkErr(FSRefToDString, &file, &pathName) == noErr) {
Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName));
Tcl_DStringFree(&pathName);
}
}
/*
* Now handle the event by evaluating a script.
*/
code = Tcl_EvalEx(interp, Tcl_DStringValue(&command),
Tcl_DStringLength(&command), TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(interp);
}
Tcl_DStringFree(&command);
return noErr;
}
/*
*----------------------------------------------------------------------
*
* ScriptHandler --
*
* This handler process the script event.
*
* Results:
* Schedules the given event to be processed.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static OSErr
ScriptHandler(
const AppleEvent *event,
AppleEvent *reply,
SRefCon handlerRefcon)
{
OSStatus theErr;
AEDescList theDesc;
Size size;
int tclErr = -1;
Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon;
char errString[128];
/*
* The do script event receives one parameter that should be data or a
* file.
*/
theErr = AEGetParamDesc(event, keyDirectObject, typeWildCard,
&theDesc);
if (theErr != noErr) {
sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d",
(int)theErr);
theErr = AEPutParamPtr(reply, keyErrorString, typeChar, errString,
strlen(errString));
} else if (MissedAnyParameters(event)) {
/*
* Return error if parameter is missing.
*/
sprintf(errString, "AEDoScriptHandler: extra parameters");
AEPutParamPtr(reply, keyErrorString, typeChar, errString,
strlen(errString));
theErr = -1771;
} else if (theDesc.descriptorType == (DescType) typeAlias &&
AEGetParamPtr(event, keyDirectObject, typeFSRef, NULL, NULL,
0, &size) == noErr && size == sizeof(FSRef)) {
/*
* We've had a file sent to us. Source it.
*/
FSRef file;
theErr = AEGetParamPtr(event, keyDirectObject, typeFSRef, NULL, &file,
size, NULL);
if (theErr == noErr) {
Tcl_DString scriptName;
theErr = FSRefToDString(&file, &scriptName);
if (theErr == noErr) {
tclErr = Tcl_EvalFile(interp, Tcl_DStringValue(&scriptName));
Tcl_DStringFree(&scriptName);
} else {
sprintf(errString, "AEDoScriptHandler: file not found");
AEPutParamPtr(reply, keyErrorString, typeChar, errString,
strlen(errString));
}
}
} else if (AEGetParamPtr(event, keyDirectObject, typeUTF8Text, NULL, NULL,
0, &size) == noErr && size) {
/*
* We've had some data sent to us. Evaluate it.
*/
char *data = ckalloc(size + 1);
theErr = AEGetParamPtr(event, keyDirectObject, typeUTF8Text, NULL, data,
size, NULL);
if (theErr == noErr) {
tclErr = Tcl_EvalEx(interp, data, size, TCL_EVAL_GLOBAL);
}
} else {
/*
* Umm, don't recognize what we've got...
*/
sprintf(errString, "AEDoScriptHandler: invalid script type '%-4.4s', "
"must be 'alis' or coercable to 'utf8'",
(char*) &theDesc.descriptorType);
AEPutParamPtr(reply, keyErrorString, typeChar, errString,
strlen(errString));
theErr = -1770;
}
/*
* If we actually go to run Tcl code - put the result in the reply.
*/
if (tclErr >= 0) {
int reslen;
const char *result =
Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &reslen);
if (tclErr == TCL_OK) {
AEPutParamPtr(reply, keyDirectObject, typeChar, result, reslen);
} else {
AEPutParamPtr(reply, keyErrorString, typeChar, result, reslen);
AEPutParamPtr(reply, keyErrorNumber, typeSInt32, (Ptr) &tclErr,
sizeof(int));
}
}
AEDisposeDesc(&theDesc);
return theErr;
#ifdef __clang__
#pragma clang diagnostic pop
#endif
}
/*
@@ -616,7 +484,6 @@ ScriptHandler(
*
*----------------------------------------------------------------------
*/
static int
ReallyKillMe(
Tcl_Event *eventPtr,
@@ -666,38 +533,7 @@ MissedAnyParameters(
return (err != errAEDescNotFound);
}
/*
*----------------------------------------------------------------------
*
* FSRefToDString --
*
* Get a POSIX path from an FSRef.
*
* Results:
* In the parameter ds.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static OSStatus
FSRefToDString(
const FSRef *fsref,
Tcl_DString *ds)
{
UInt8 fileName[PATH_MAX+1];
OSStatus err;
err = ChkErr(FSRefMakePath, fsref, fileName, sizeof(fileName));
if (err == noErr) {
Tcl_ExternalToUtfDString(NULL, (char*) fileName, -1, ds);
}
return err;
}
/*
* Local Variables:
* mode: objc

View File

@@ -30,10 +30,9 @@ static char tkLibPath[PATH_MAX + 1] = "";
static char scriptPath[PATH_MAX + 1] = "";
int tkMacOSXGCEnabled = 0;
long tkMacOSXMacOSXVersion = 0;
#pragma mark TKApplication(TKInit)
#pragma mark TKApplication(TKInit)
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
#define NSTextInputContextKeyboardSelectionDidChangeNotification @"NSTextInputContextKeyboardSelectionDidChangeNotification"
@@ -55,23 +54,29 @@ static void keyboardChanged(CFNotificationCenterRef center, void *observer, CFSt
- (void)_setupWindowNotifications;
@end
@interface TKApplication(TKScrlbr)
- (void)_setupScrollBarNotifications;
@end
@interface TKApplication(TKMenus)
- (void)_setupMenus;
@end
@implementation TKApplication
@synthesize poolProtected = _poolProtected;
@end
@implementation TKApplication(TKInit)
- (void) _resetAutoreleasePool
{
if(![self poolProtected]) {
[_mainPool drain];
_mainPool = [NSAutoreleasePool new];
}
}
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
- (void)_postedNotification:(NSNotification *)notification {
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
}
#endif
- (void)_setupApplicationNotifications {
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
#define observe(n, s) [nc addObserver:self selector:@selector(s) name:(n) object:nil]
@@ -86,16 +91,18 @@ static void keyboardChanged(CFNotificationCenterRef center, void *observer, CFSt
CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), NULL, &keyboardChanged, kTISNotifySelectedKeyboardInputSourceChanged, NULL, CFNotificationSuspensionBehaviorCoalesce);
#endif
}
- (void)_setupEventLoop {
_running = 1;
if (!_appFlags._hasBeenRun) {
_appFlags._hasBeenRun = YES;
[self finishLaunching];
}
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[self finishLaunching];
[self setWindowsNeedUpdate:YES];
[pool drain];
}
- (void)_setup:(Tcl_Interp *)interp {
_eventInterp = interp;
_mainPool = [NSAutoreleasePool new];
[NSApp setPoolProtected:NO];
_defaultMainMenu = nil;
[self _setupMenus];
[self setDelegate:self];
@@ -104,11 +111,12 @@ static void keyboardChanged(CFNotificationCenterRef center, void *observer, CFSt
selector:@selector(_postedNotification:) name:nil object:nil];
#endif
[self _setupWindowNotifications];
[self _setupScrollBarNotifications];
[self _setupApplicationNotifications];
}
- (NSString *)tkFrameworkImagePath:(NSString*)image {
NSString *path = nil;
NSAutoreleasePool *pool = [NSAutoreleasePool new];
if (tkLibPath[0] != '\0') {
path = [[NSBundle bundleWithPath:[[NSString stringWithUTF8String:
tkLibPath] stringByAppendingString:@"/../.."]]
@@ -139,6 +147,8 @@ static void keyboardChanged(CFNotificationCenterRef center, void *observer, CFSt
}
}
#endif
[path retain];
[pool drain];
return path;
}
@end
@@ -165,6 +175,7 @@ static void
SetApplicationIcon(
ClientData clientData)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSString *path = [NSApp tkFrameworkImagePath:@"Tk.icns"];
if (path) {
NSImage *image = [[NSImage alloc] initWithContentsOfFile:path];
@@ -173,6 +184,7 @@ SetApplicationIcon(
[image release];
}
}
[pool drain];
}
/*
@@ -225,11 +237,16 @@ TkpInit(
if (!uname(&name)) {
tkMacOSXMacOSXVersion = (strtod(name.release, NULL) + 96) * 10;
}
if (tkMacOSXMacOSXVersion &&
/*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
/*
@@ -245,20 +262,19 @@ TkpInit(
}
#endif
static NSAutoreleasePool *pool = nil;
if (!pool) {
pool = [NSAutoreleasePool new];
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[[NSUserDefaults standardUserDefaults] registerDefaults:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
@"_NSCanWrapButtonTitles",
[NSNumber numberWithInt:-1],
@"NSStringDrawingTypesetterBehavior",
nil]];
[TKApplication sharedApplication];
[pool drain];
[NSApp _setup:interp];
}
tkMacOSXGCEnabled = ([NSGarbageCollector defaultCollector] != nil);
[[NSUserDefaults standardUserDefaults] registerDefaults:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
@"_NSCanWrapButtonTitles",
[NSNumber numberWithInt:-1],
@"NSStringDrawingTypesetterBehavior",
nil]];
[TKApplication sharedApplication];
[NSApp _setup:interp];
/* Check whether we are a bundled executable: */
bundleRef = CFBundleGetMainBundle();
@@ -315,13 +331,15 @@ TkpInit(
Tcl_DoWhenIdle(SetApplicationIcon, NULL);
}
[NSApp _setupEventLoop];
TkMacOSXInitAppleEvents(interp);
TkMacOSXUseAntialiasedText(interp, -1);
TkMacOSXInitCGDrawing(interp, TRUE, 0);
[pool drain];
pool = [NSAutoreleasePool new];
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[NSApp _setupEventLoop];
TkMacOSXInitAppleEvents(interp);
TkMacOSXUseAntialiasedText(interp, -1);
TkMacOSXInitCGDrawing(interp, TRUE, 0);
[pool drain];
}
/*
* FIXME: Close stdin & stdout for remote debugging otherwise we will
* fight with gdb for stdin & stdout
@@ -477,9 +495,8 @@ TkpDisplayWarning(
MODULE_SCOPE void
TkMacOSXDefaultStartupScript(void)
{
CFBundleRef bundleRef;
bundleRef = CFBundleGetMainBundle();
NSAutoreleasePool *pool = [NSAutoreleasePool new];
CFBundleRef bundleRef = CFBundleGetMainBundle();
if (bundleRef != NULL) {
CFURLRef appMainURL = CFBundleCopyResourceURL(bundleRef,
@@ -503,6 +520,7 @@ TkMacOSXDefaultStartupScript(void)
CFRelease(appMainURL);
}
}
[pool drain];
}
/*

View File

@@ -24,6 +24,7 @@
#ifndef _TKMAC
#include "tkMacOSX.h"
#import <Cocoa/Cocoa.h>
#endif
/*
@@ -85,7 +86,7 @@ typedef struct TkWindowPrivate MacDrawable;
#define TK_FOCUSED_VIEW 0x10
#define TK_IS_PIXMAP 0x20
#define TK_IS_BW_PIXMAP 0x40
#define TK_DO_NOT_DRAW 0x80
/*
* 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
@@ -196,7 +197,7 @@ MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x,
int y, int width, int height);
MODULE_SCOPE void TkpRetainRegion(TkRegion r);
MODULE_SCOPE void TkpReleaseRegion(TkRegion r);
MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
/*
* Include the stubbed internal platform-specific API.
*/

View File

@@ -7,6 +7,7 @@
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright (c) 2012 Adrian Robert.
* Copyright 2015 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -27,7 +28,9 @@ static Tk_Window grabWinPtr = NULL;
/* Current grab window, NULL if no grab. */
static Tk_Window keyboardGrabWinPtr = NULL;
/* Current keyboard grab window. */
static NSModalSession modalSession = NULL;
static NSWindow *keyboardGrabNSWindow = nil;
/* NSWindow for the current keyboard grab window. */
static NSModalSession modalSession = nil;
static BOOL processingCompose = NO;
static BOOL finishedCompose = NO;
@@ -78,16 +81,18 @@ static unsigned isFunctionKey(unsigned int code);
case NSFlagsChanged:
modifiers = [theEvent modifierFlags];
keyCode = [theEvent keyCode];
w = [self windowWithWindowNumber:[theEvent windowNumber]];
// 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);
#endif
break;
default:
return theEvent;
return theEvent; /* Unrecognized key event. */
}
/* Create an Xevent to add to the Tk queue. */
if (!processingCompose) {
unsigned int state = 0;
@@ -128,7 +133,7 @@ static unsigned isFunctionKey(unsigned int code);
tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
if (!tkwin) {
TkMacOSXDbgMsg("tkwin == NULL");
return theEvent;
return theEvent; /* Give up. No window for this event. */
}
/*
@@ -222,7 +227,7 @@ static unsigned isFunctionKey(unsigned int code);
@implementation TKContentView(TKKeyEvent)
@implementation TKContentView
/* <NSTextInput> implementation (called through interpretKeyEvents:]). */
/* <NSTextInput>: called when done composing;
@@ -241,7 +246,7 @@ static unsigned isFunctionKey(unsigned int code);
finishedCompose = YES;
/* first, clear any working text */
if (_workingText != nil)
if (privateWorkingText != nil)
[self deleteWorkingText];
/* now insert the string as keystrokes */
@@ -272,46 +277,32 @@ static unsigned isFunctionKey(unsigned int code);
NSString *str = [aString respondsToSelector: @selector (string)] ?
[aString string] : aString;
if (NS_KEYLOG)
NSLog (@"setMarkedText '%@' len =%d range %d from %d", str, [str length],
selRange.length, selRange.location);
NSLog (@"setMarkedText '%@' len =%lu range %lu from %lu", str,
(unsigned long) [str length], (unsigned long) selRange.length,
(unsigned long) selRange.location);
if (_workingText != nil)
if (privateWorkingText != nil)
[self deleteWorkingText];
if ([str length] == 0)
return;
processingCompose = YES;
_workingText = [str copy];
privateWorkingText = [str copy];
//PENDING: insert workingText underlined
}
/* delete display of composing characters [not in <NSTextInput>] */
- (void)deleteWorkingText
{
if (_workingText == nil)
return;
if (NS_KEYLOG)
NSLog(@"deleteWorkingText len = %d\n", [_workingText length]);
[_workingText release];
_workingText = nil;
processingCompose = NO;
//PENDING: delete working text
}
- (BOOL)hasMarkedText
{
return _workingText != nil;
return privateWorkingText != nil;
}
- (NSRange)markedRange
{
NSRange rng = _workingText != nil
? NSMakeRange (0, [_workingText length]) : NSMakeRange (NSNotFound, 0);
NSRange rng = privateWorkingText != nil
? NSMakeRange (0, [privateWorkingText length]) : NSMakeRange (NSNotFound, 0);
if (NS_KEYLOG)
NSLog (@"markedRange request");
return rng;
@@ -337,7 +328,7 @@ static unsigned isFunctionKey(unsigned int code);
pt.y = caret_y;
pt = [self convertPoint: pt toView: nil];
pt = [[self window] convertBaseToScreen: pt];
pt = [[self window] convertPointToScreen: pt];
pt.y -= caret_height;
rect.origin = pt;
@@ -411,6 +402,24 @@ static unsigned isFunctionKey(unsigned int code);
@end
@implementation TKContentView(TKKeyEvent)
/* delete display of composing characters [not in <NSTextInput>] */
- (void)deleteWorkingText
{
if (privateWorkingText == nil)
return;
if (NS_KEYLOG)
NSLog(@"deleteWorkingText len = %lu\n",
(unsigned long)[privateWorkingText length]);
[privateWorkingText release];
privateWorkingText = nil;
processingCompose = NO;
//PENDING: delete working text
}
@end
/*
* Set up basic fields in xevent for keyboard input.
@@ -472,7 +481,9 @@ XGrabKeyboard(
if (modalSession) {
Tcl_Panic("XGrabKeyboard: already grabbed");
}
modalSession = [NSApp beginModalSessionForWindow:[w retain]];
keyboardGrabNSWindow = w;
[w retain];
modalSession = [NSApp beginModalSessionForWindow:w];
}
}
return GrabSuccess;
@@ -500,11 +511,12 @@ XUngrabKeyboard(
Time time)
{
if (modalSession) {
NSWindow *w = keyboardGrabWinPtr ? TkMacOSXDrawableWindow(
((TkWindow *) keyboardGrabWinPtr)->window) : nil;
[NSApp endModalSession:modalSession];
[w release];
modalSession = NULL;
modalSession = nil;
}
if (keyboardGrabNSWindow) {
[keyboardGrabNSWindow release];
keyboardGrabNSWindow = nil;
}
keyboardGrabWinPtr = NULL;
}

View File

@@ -734,7 +734,7 @@ TkpGetKeySym(
*/
if (eventPtr->xany.send_event == -1) {
int modifier = eventPtr->xkey.keycode;
int modifier = eventPtr->xkey.keycode & NSDeviceIndependentModifierFlagsMask;
if (modifier == NSCommandKeyMask) {
return XK_Meta_L;

View File

@@ -258,9 +258,10 @@ static int ModifierCharWidth(Tk_Font tkfont);
if (menuPtr && mePtr) {
Tcl_Interp *interp = menuPtr->interp;
/*Add time for errors to fire if necessary. This is sub-optimal but avoids issues with Tcl/Cocoa event loop integration.*/
/*Add time for errors to fire if necessary. This is sub-optimal
*but avoids issues with Tcl/Cocoa event loop integration.
*/
Tcl_Sleep(100);
Tcl_Preserve(interp);
Tcl_Preserve(menuPtr);
@@ -411,7 +412,7 @@ static int ModifierCharWidth(Tk_Font tkfont);
if (!mePtr || !(mePtr->entryFlags & ENTRY_APPLE_MENU)) {
applicationMenuItem = [NSMenuItem itemWithSubmenu:
[[_defaultApplicationMenu copy] autorelease]];
[_defaultApplicationMenu copy]];
[menu insertItem:applicationMenuItem atIndex:0];
}
[menu setSpecial:tkMainMenu];
@@ -419,7 +420,7 @@ static int ModifierCharWidth(Tk_Font tkfont);
applicationMenu = (TKMenu *)[applicationMenuItem submenu];
if (![applicationMenu isSpecial:tkApplicationMenu]) {
for (NSMenuItem *item in _defaultApplicationMenuItems) {
[applicationMenu addItem:[[item copy] autorelease]];
[applicationMenu addItem:[item copy]];
}
[applicationMenu setSpecial:tkApplicationMenu];
}
@@ -429,15 +430,13 @@ static int ModifierCharWidth(Tk_Font tkfont);
for (NSMenuItem *item in itemArray) {
TkMenuEntry *mePtr = (TkMenuEntry *)[item tag];
TKMenu *submenu = (TKMenu *)[item submenu];
if (mePtr && submenu) {
if ((mePtr->entryFlags & ENTRY_WINDOWS_MENU) &&
![submenu isSpecial:tkWindowsMenu]) {
NSInteger index = 0;
for (NSMenuItem *i in _defaultWindowsMenuItems) {
[submenu insertItem:[[i copy] autorelease] atIndex:
index++];
[submenu insertItem:[i copy] atIndex:index++];
}
[self setWindowsMenu:submenu];
[submenu setSpecial:tkWindowsMenu];
@@ -446,8 +445,7 @@ static int ModifierCharWidth(Tk_Font tkfont);
NSInteger index = 0;
for (NSMenuItem *i in _defaultHelpMenuItems) {
[submenu insertItem:[[i copy] autorelease] atIndex:
index++];
[submenu insertItem:[i copy] atIndex:index++];
}
[submenu setSpecial:tkHelpMenu];
}
@@ -496,8 +494,7 @@ TkpNewMenu(
* platform structure for. */
{
TKMenu *menu = [[TKMenu alloc] initWithTkMenu:menuPtr];
menuPtr->platformData = (TkMenuPlatformData)
TkMacOSXMakeUncollectable(menu);
menuPtr->platformData = (TkMenuPlatformData) menu;
CheckForSpecialMenu(menuPtr);
return TCL_OK;
}
@@ -522,7 +519,10 @@ void
TkpDestroyMenu(
TkMenu *menuPtr) /* The common menu structure */
{
TkMacOSXMakeCollectableAndRelease(menuPtr->platformData);
NSMenu* nsmenu = (NSMenu*)(menuPtr->platformData);
[nsmenu release];
menuPtr->platformData = NULL;
}
/*
@@ -555,8 +555,7 @@ TkpMenuNewEntry(
} else {
menuItem = [menu newTkMenuItem:mePtr];
}
mePtr->platformEntryData = (TkMenuPlatformEntryData)
TkMacOSXMakeUncollectable(menuItem);
mePtr->platformEntryData = (TkMenuPlatformEntryData) menuItem;
/*
* Caller TkMenuEntry() already did this same insertion into the generic
@@ -683,15 +682,18 @@ TkpConfigureMenuEntry(
int i = 0;
NSArray *itemArray = [submenu itemArray];
for (NSMenuItem *item in itemArray) {
TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
[item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
i++;
TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
/* Work around an apparent bug where itemArray can have
more items than the menu's entries[] array. */
if (i >= menuRefPtr->menuPtr->numEntries) break;
[item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
i++;
}
}
}
}
}
[menuItem setSubmenu:submenu];
return TCL_OK;
@@ -717,16 +719,21 @@ void
TkpDestroyMenuEntry(
TkMenuEntry *mePtr)
{
NSMenuItem *menuItem;
TKMenu *menu;
NSInteger index;
if (mePtr->platformEntryData && mePtr->menuPtr->platformData) {
TKMenu *menu = (TKMenu *) mePtr->menuPtr->platformData;
NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
NSInteger index = [menu indexOfItem:menuItem];
menu = (TKMenu *) mePtr->menuPtr->platformData;
menuItem = (NSMenuItem *) mePtr->platformEntryData;
index = [menu indexOfItem:menuItem];
if (index > -1) {
[menu removeItemAtIndex:index];
}
[menuItem release];
mePtr->platformEntryData = NULL;
}
TkMacOSXMakeCollectableAndRelease(mePtr->platformEntryData);
}
/*
@@ -754,11 +761,19 @@ TkpPostMenu(
* to be posted. */
int y) /* The global y-coordinate */
{
NSWindow *win = [NSApp keyWindow];
if (!win) {
/* Get the object that holds this Tk Window.*/
Tk_Window root;
root = Tk_MainWindow(interp);
if (root == NULL) {
return TCL_ERROR;
}
Drawable d = Tk_WindowId(root);
NSView *rootview = TkMacOSXGetRootControl(d);
NSWindow *win = [rootview window];
inPostMenu = 1;
int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
@@ -766,7 +781,7 @@ TkpPostMenu(
NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1);
frame.origin = [view convertPoint:
[win convertScreenToBase:frame.origin] fromView:nil];
[win convertPointFromScreen:frame.origin] fromView:nil];
NSMenu *menu = (NSMenu *) menuPtr->platformData;
NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc]
@@ -819,11 +834,16 @@ TkpSetWindowMenuBar(
* Puts the menu associated with a window into the menubar. Should only
* be called when the window is in front.
*
* This is a no-op on all other platforms. On OS X it is a no-op when
* passed a NULL menuName or a nonexistent menuName, with an exception
* for the first call in a new interpreter. In that special case, passing a
* NULL menuName installs the default menu.
*
* Results:
* None.
*
* Side effects:
* The menubar is changed.
* The menubar may be changed.
*
*----------------------------------------------------------------------
*/
@@ -832,8 +852,7 @@ void
TkpSetMainMenubar(
Tcl_Interp *interp, /* The interpreter of the application */
Tk_Window tkwin, /* The frame we are setting up */
char *menuName) /* The name of the menu to put in front. If
* NULL, use the default menu bar. */
char *menuName) /* The name of the menu to put in front.*/
{
static Tcl_Interp *currentInterp = NULL;
TKMenu *menu = nil;

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,7 @@ typedef struct {
static int GenerateButtonEvent(MouseEventData *medPtr);
static unsigned int ButtonModifiers2State(UInt32 buttonState,
UInt32 keyModifiers);
UInt32 keyModifiers);
#pragma mark TKApplication(TKMouseEvent)
@@ -34,37 +34,50 @@ enum {
NSWindowWillMoveEventType = 20
};
/*
* In OS X 10.6 an NSEvent of type NSMouseMoved would always have a non-Nil
* window attribute pointing to the active window. As of 10.8 this behavior
* had changed. The new behavior was that if the mouse were ever moved outside
* of a window, all subsequent NSMouseMoved NSEvents would have a Nil window
* attribute. To work around this the TKApplication remembers the last non-Nil
* window that it received in a mouse event. If it receives an NSEvent with a
* Nil window attribute then the saved window is used.
*/
@implementation TKApplication(TKMouseEvent)
- (NSEvent *)tkProcessMouseEvent:(NSEvent *)theEvent {
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent);
#endif
id win;
NSEventType type = [theEvent type];
NSWindow* eventWindow = [theEvent window];
NSEventType eventType = [theEvent type];
#if 0
NSTrackingArea *trackingArea = nil;
NSInteger eventNumber, clickCount, buttonNumber;
#endif
switch (type) {
switch (eventType) {
case NSMouseEntered:
/* Remember which window has the mouse. */
if (_windowWithMouse) {
[_windowWithMouse release];
}
_windowWithMouse = [theEvent window];
if (_windowWithMouse) {
[_windowWithMouse retain];
}
break;
case NSMouseExited:
case NSCursorUpdate:
#if 0
trackingArea = [theEvent trackingArea];
#endif
/* fall through */
case NSLeftMouseDown:
case NSLeftMouseUp:
case NSRightMouseDown:
case NSRightMouseUp:
case NSOtherMouseDown:
case NSOtherMouseUp:
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
case NSMouseMoved:
#if 0
eventNumber = [theEvent eventNumber];
@@ -73,45 +86,52 @@ enum {
buttonNumber = [theEvent buttonNumber];
}
#endif
case NSTabletPoint:
case NSTabletProximity:
case NSScrollWheel:
win = [self windowWithWindowNumber:[theEvent windowNumber]];
break;
default:
default: /* Unrecognized mouse event. */
return theEvent;
break;
}
/* Remember the window in case we need it next time. */
if (eventWindow && eventWindow != _windowWithMouse) {
if (_windowWithMouse) {
[_windowWithMouse release];
}
_windowWithMouse = eventWindow;
[_windowWithMouse retain];
}
/* Create an Xevent to add to the Tk queue. */
NSPoint global, local = [theEvent locationInWindow];
if (win) {
global = [win convertBaseToScreen:local];
local.y = [win frame].size.height - local.y;
if (eventWindow) { /* local will be in window coordinates. */
global = [eventWindow convertPointToScreen: local];
local.y = [eventWindow frame].size.height - local.y;
global.y = tkMacOSXZeroScreenHeight - global.y;
} else {
local.y = tkMacOSXZeroScreenHeight - local.y;
global = local;
} else { /* local will be in screen coordinates. */
if (_windowWithMouse ) {
eventWindow = _windowWithMouse;
global = local;
local = [eventWindow convertPointFromScreen: local];
local.y = [eventWindow frame].size.height - local.y;
global.y = tkMacOSXZeroScreenHeight - global.y;
} else { /* We have no window. Use the screen???*/
local.y = tkMacOSXZeroScreenHeight - local.y;
global = local;
}
}
Window window = TkMacOSXGetXWindow(win);
Window window = TkMacOSXGetXWindow(eventWindow);
Tk_Window tkwin = window ? Tk_IdToWindow(TkGetDisplayList()->display,
window) : NULL;
if (!tkwin) {
tkwin = TkMacOSXGetCapture();
}
if (!tkwin) {
return theEvent;
return theEvent; /* Give up. No window for this event. */
}
/*
MacDrawable *macWin = (MacDrawable *) window;
NSView *view = TkMacOSXDrawableView(macWin);
local = [view convertPoint:local fromView:nil];
local.y = NSHeight([view bounds]) - local.y;
*/
TkWindow *winPtr = (TkWindow *) tkwin;
local.x -= winPtr->wmInfoPtr->xInParent;
local.y -= winPtr->wmInfoPtr->yInParent;
@@ -130,7 +150,7 @@ enum {
state |= (buttons & ((1<<5) - 1)) << 8;
} else {
if (button < 5) {
switch (type) {
switch (eventType) {
case NSLeftMouseDown:
case NSRightMouseDown:
case NSLeftMouseDragged:
@@ -167,12 +187,12 @@ enum {
state |= Mod4Mask;
}
if (type != NSScrollWheel) {
if (eventType != NSScrollWheel) {
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state);
#endif
Tk_UpdatePointer(tkwin, global.x, global.y, state);
} else {
} else { /* handle scroll wheel event */
CGFloat delta;
int coarseDelta;
XEvent xEvent;
@@ -188,7 +208,8 @@ enum {
delta = [theEvent deltaY];
if (delta != 0.0) {
coarseDelta = (delta > -1.0 && delta < 1.0) ? (signbit(delta) ? -1 : 1) : lround(delta);
coarseDelta = (delta > -1.0 && delta < 1.0) ?
(signbit(delta) ? -1 : 1) : lround(delta);
xEvent.xbutton.state = state;
xEvent.xkey.keycode = coarseDelta;
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
@@ -196,14 +217,14 @@ enum {
}
delta = [theEvent deltaX];
if (delta != 0.0) {
coarseDelta = (delta > -1.0 && delta < 1.0) ? (signbit(delta) ? -1 : 1) : lround(delta);
coarseDelta = (delta > -1.0 && delta < 1.0) ?
(signbit(delta) ? -1 : 1) : lround(delta);
xEvent.xbutton.state = state | ShiftMask;
xEvent.xkey.keycode = coarseDelta;
xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
}
}
return theEvent;
}
@end
@@ -368,7 +389,7 @@ XQueryPointer(
if (win) {
NSPoint local;
local = [win convertScreenToBase:global];
local = [win convertPointFromScreen:global];
local.y = [win frame].size.height - local.y;
if (macWin->winPtr && macWin->winPtr->wmInfoPtr) {
local.x -= macWin->winPtr->wmInfoPtr->xInParent;
@@ -466,7 +487,7 @@ TkGenerateButtonEvent(
if (win) {
NSPoint local = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
local = [win convertScreenToBase:local];
local = [win convertPointFromScreen:local];
local.y = [win frame].size.height - local.y;
if (macWin->winPtr && macWin->winPtr->wmInfoPtr) {
local.x -= macWin->winPtr->wmInfoPtr->xInParent;

View File

@@ -7,6 +7,7 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright 2015 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -18,9 +19,9 @@
#include <pthread.h>
#import <objc/objc-auto.h>
/* This is not used for anything at the moment. */
typedef struct ThreadSpecificData {
int initialized, sendEventNestingLevel;
NSEvent *currentEvent;
int initialized;
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
@@ -34,6 +35,7 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
#pragma mark TKApplication(TKNotify)
@interface NSApplication(TKNotify)
/* We need to declare this hidden method. */
- (void)_modalSession:(NSModalSession)session sendEvent:(NSEvent *)event;
@end
@@ -47,34 +49,25 @@ static void TkMacOSXEventsCheckProc(ClientData clientData, int flags);
@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 {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
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];
int oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
NSEvent *event = [[super nextEventMatchingMask:mask untilDate:expiration
inMode:mode dequeue:deqFlag] retain];
Tcl_SetServiceMode(oldMode);
if (event) {
TSD_INIT();
if (tsdPtr->sendEventNestingLevel) {
if (![NSApp tkProcessEvent:event]) {
[event release];
event = nil;
}
}
}
[pool drain];
return [event autorelease];
return event;
}
/*
* Call super then check the pasteboard.
*/
- (void)sendEvent:(NSEvent *)theEvent {
TSD_INIT();
int oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
tsdPtr->sendEventNestingLevel++;
[super sendEvent:theEvent];
tsdPtr->sendEventNestingLevel--;
Tcl_SetServiceMode(oldMode);
[NSApp tkCheckPasteboard];
}
@end
@@ -152,7 +145,8 @@ Tk_MacOSXSetupTkNotifier(void)
"first [load] of TkAqua has to occur in the main thread!");
}
Tcl_CreateEventSource(TkMacOSXEventsSetupProc,
TkMacOSXEventsCheckProc, GetMainEventQueue());
TkMacOSXEventsCheckProc,
GetMainEventQueue());
TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL);
Tcl_SetServiceMode(TCL_SERVICE_ALL);
TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode);
@@ -184,7 +178,8 @@ TkMacOSXNotifyExitHandler(
{
TSD_INIT();
Tcl_DeleteEventSource(TkMacOSXEventsSetupProc,
TkMacOSXEventsCheckProc, GetMainEventQueue());
TkMacOSXEventsCheckProc,
GetMainEventQueue());
tsdPtr->initialized = 0;
}
@@ -193,16 +188,19 @@ TkMacOSXNotifyExitHandler(
*
* TkMacOSXEventsSetupProc --
*
* This procedure implements the setup part of the TkAqua Events event
* source. It is invoked by Tcl_DoOneEvent before entering the notifier
* to check for events.
* This procedure implements the setup part of the MacOSX event
* source. It is invoked by Tcl_DoOneEvent before calling
* TkMacOSXEventsProc to process all queued NSEvents. In our
* case, all we need to do is to set the Tcl MaxBlockTime to
* 0 before starting the loop to process all queued NSEvents.
*
* Results:
* None.
*
* Side effects:
* If TkAqua events are queued, then the maximum block time will be set
* to 0 to ensure that the notifier returns control to Tcl.
*
* If NSEvents are queued, then the maximum block time will be set
* to 0 to ensure that control returns immediately to Tcl.
*
*----------------------------------------------------------------------
*/
@@ -212,23 +210,20 @@ TkMacOSXEventsSetupProc(
ClientData clientData,
int flags)
{
if (flags & TCL_WINDOW_EVENTS &&
![[NSRunLoop currentRunLoop] currentMode]) {
NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
/* runloopMode will be nil if we are in the Tcl event loop. */
if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
static Tcl_Time zeroBlockTime = { 0, 0 };
TSD_INIT();
if (!tsdPtr->currentEvent) {
NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:GetRunLoopMode(TkMacOSXGetModalSession())
dequeue:YES];
if (currentEvent) {
tsdPtr->currentEvent =
TkMacOSXMakeUncollectableAndRetain(currentEvent);
/* Call this with dequeue=NO -- just checking if the queue is empty. */
NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:GetRunLoopMode(TkMacOSXGetModalSession())
dequeue:NO];
if (currentEvent) {
if (currentEvent.type > 0) {
Tcl_SetMaxBlockTime(&zeroBlockTime);
}
}
if (tsdPtr->currentEvent) {
Tcl_SetMaxBlockTime(&zeroBlockTime);
[currentEvent release];
}
}
}
@@ -238,69 +233,69 @@ TkMacOSXEventsSetupProc(
*
* TkMacOSXEventsCheckProc --
*
* This procedure processes events sitting in the TkAqua event queue.
* This procedure loops through all NSEvents waiting in the
* TKApplication event queue, generating X events from them.
*
* Results:
* None.
*
* Side effects:
* Moves applicable queued TkAqua events onto the Tcl event queue.
* NSevents are used to generate X events, which are added to the
* Tcl event queue.
*
*----------------------------------------------------------------------
*/
static void
TkMacOSXEventsCheckProc(
ClientData clientData,
int flags)
{
if (flags & TCL_WINDOW_EVENTS &&
![[NSRunLoop currentRunLoop] currentMode]) {
NSString *runloopMode = [[NSRunLoop currentRunLoop] currentMode];
/* runloopMode will be nil if we are in the Tcl event loop. */
if (flags & TCL_WINDOW_EVENTS && !runloopMode) {
NSEvent *currentEvent = nil;
NSAutoreleasePool *pool = nil;
NSEvent *testEvent = nil;
NSModalSession modalSession;
TSD_INIT();
if (tsdPtr->currentEvent) {
currentEvent = TkMacOSXMakeCollectableAndAutorelease(
tsdPtr->currentEvent);
}
do {
[NSApp _resetAutoreleasePool];
modalSession = TkMacOSXGetModalSession();
if (!currentEvent) {
currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:GetRunLoopMode(modalSession) dequeue:YES];
}
if (!currentEvent) {
testEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:GetRunLoopMode(modalSession)
dequeue:NO];
/* We must not steal any events during LiveResize. */
if (testEvent && [[testEvent window] inLiveResize]) {
break;
}
[currentEvent retain];
pool = [NSAutoreleasePool new];
if (tkMacOSXGCEnabled) {
objc_clear_stack(0);
}
if (![NSApp tkProcessEvent:currentEvent]) {
[currentEvent release];
currentEvent = nil;
}
currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:GetRunLoopMode(modalSession)
dequeue:YES];
if (currentEvent) {
/* Generate Xevents. */
int oldServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
NSEvent *processedEvent = [NSApp tkProcessEvent:currentEvent];
Tcl_SetServiceMode(oldServiceMode);
if (processedEvent) { /* Should always be non-NULL. */
#ifdef TK_MAC_DEBUG_EVENTS
TKLog(@" event: %@", currentEvent);
TKLog(@" event: %@", currentEvent);
#endif
if (modalSession) {
[NSApp _modalSession:modalSession sendEvent:currentEvent];
} else {
[NSApp sendEvent:currentEvent];
if (modalSession) {
[NSApp _modalSession:modalSession sendEvent:currentEvent];
} else {
[NSApp sendEvent:currentEvent];
}
}
[currentEvent release];
currentEvent = nil;
} else {
break;
}
[pool drain];
pool = nil;
} while (1);
}
}
/*
* Local Variables:

View File

@@ -158,18 +158,10 @@
/*
* This macro stores a representation of the window handle in a string.
* This should perhaps use the real size of an XID.
*/
#define TkpPrintWindowId(buf,w) \
sprintf((buf), "0x%x", (unsigned int) (w))
/*
* TkpScanWindowId is just an alias for Tcl_GetInt on Unix.
*/
#define TkpScanWindowId(i,s,wp) \
Tcl_GetInt((i),(s),(int *) (wp))
sprintf((buf), "0x%lx", (unsigned long) (w))
/*
* Turn off Tk double-buffering as Aqua windows are already double-buffered.

View File

@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#ifndef _TKMACPRIV
#define _TKMACPRIV
@@ -141,23 +141,6 @@
STRINGIFY(symbol)); \
}
/*
* Macros for GC
*/
#define TkMacOSXMakeUncollectable(x) ({ id o = (id)(x); \
if (o) { if(tkMacOSXGCEnabled) CFRetain(o); } o; })
#define TkMacOSXMakeUncollectableAndRetain(x) ({ id o = (id)(x); \
if (o) { if(tkMacOSXGCEnabled) CFRetain(o); else [o retain]; } o; })
#define TkMacOSXMakeCollectable(x) ({ id o = (id)(x); \
if (o) { x = nil; if (tkMacOSXGCEnabled) CFRelease(o); } o; })
#define TkMacOSXMakeCollectableAndRelease(x) ({ id o = (id)(x); \
if (o) { x = nil; if (tkMacOSXGCEnabled) CFRelease(o); \
else [o release]; } o; })
#define TkMacOSXMakeCollectableAndAutorelease(x) ({ id o = (id)(x); \
if (o) { x = nil; if (tkMacOSXGCEnabled) CFRelease(o); \
else [o autorelease]; } o; })
/*
* Structure encapsulating current drawing environment.
*/
@@ -176,11 +159,7 @@ typedef struct TkMacOSXDrawingContext {
MODULE_SCOPE CGFloat tkMacOSXZeroScreenHeight;
MODULE_SCOPE CGFloat tkMacOSXZeroScreenTop;
MODULE_SCOPE int tkMacOSXGCEnabled;
MODULE_SCOPE long tkMacOSXMacOSXVersion;
#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
MODULE_SCOPE int tkMacOSXUseCompatibilityMetrics;
#endif
/*
* Prototypes for TkMacOSXRegion.c.
@@ -228,6 +207,8 @@ MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr);
MODULE_SCOPE int TkMacOSXIsWindowZoomed(TkWindow *winPtr);
MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window);
MODULE_SCOPE EventModifiers TkMacOSXModifierState(void);
MODULE_SCOPE NSBitmapImageRep* BitmapRepFromDrawableRect(Drawable drawable,
int x, int y, unsigned int width, unsigned int height);
MODULE_SCOPE int TkMacOSXSetupDrawingContext(Drawable d, GC gc,
int useCG, TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void TkMacOSXRestoreDrawingContext(
@@ -291,10 +272,17 @@ VISIBILITY_HIDDEN
TKMenu *_defaultMainMenu, *_defaultApplicationMenu;
NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
NSArray *_defaultHelpMenuItems;
NSWindow *_windowWithMouse;
NSAutoreleasePool *_mainPool;
#ifdef __i386__
BOOL _poolProtected;
#endif
}
@property BOOL poolProtected;
@end
@interface TKApplication(TKInit)
- (NSString *)tkFrameworkImagePath:(NSString*)image;
- (void)_resetAutoreleasePool;
@end
@interface TKApplication(TKEvent)
- (NSEvent *)tkProcessEvent:(NSEvent *)theEvent;
@@ -312,13 +300,34 @@ VISIBILITY_HIDDEN
- (void)tkProvidePasteboard:(TkDisplay *)dispPtr;
- (void)tkCheckPasteboard;
@end
@interface TKApplication(TKHLEvents)
- (void) terminate: (id) sender;
- (void) preferences: (id) sender;
- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event
withReplyEvent: (NSAppleEventDescriptor *)replyEvent;
@end
VISIBILITY_HIDDEN
@interface TKContentView : NSView <NSTextInput> {
@private
/*Remove private API calls.*/
#if 0
id _savedSubviews;
BOOL _subviewsSetAside;
NSString *_workingText;
#endif
NSString *privateWorkingText;
}
@end
@@ -326,10 +335,27 @@ VISIBILITY_HIDDEN
- (void) deleteWorkingText;
@end
@interface TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect;
- (void) generateExposeEvents: (HIShapeRef) shape;
- (void) generateExposeEvents: (HIShapeRef) shape childrenOnly: (int) childrenOnly;
- (void) viewDidEndLiveResize;
- (void) tkToolbarButton: (id) sender;
- (BOOL) isOpaque;
- (BOOL) wantsDefaultClipping;
- (BOOL) acceptsFirstResponder;
- (void) keyDown: (NSEvent *) theEvent;
@end
VISIBILITY_HIDDEN
@interface TKWindow : NSWindow
@end
@interface NSWindow(TKWm)
- (NSPoint) convertPointToScreen:(NSPoint)point;
- (NSPoint) convertPointFromScreen:(NSPoint)point;
@end
#pragma mark NSMenu & NSMenuItem Utilities
@interface NSMenu(TKUtils)
@@ -358,9 +384,4 @@ VISIBILITY_HIDDEN
keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask;
@end
/* From WebKit/WebKit/mac/WebCoreSupport/WebChromeClient.mm: */
@interface NSWindow(TKGrowBoxRect)
- (NSRect)_growBoxRect;
@end
#endif /* _TKMACPRIV */

View File

@@ -155,6 +155,29 @@ TkUnionRectWithRegion(
}
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXIsEmptyRegion --
*
* Return native region for given tk region.
*
* Results:
* 1 if empty, 0 otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TkMacOSXIsEmptyRegion(
TkRegion r)
{
return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0;
}
/*
*----------------------------------------------------------------------
*
@@ -181,12 +204,14 @@ TkRectInRegion(
unsigned int width,
unsigned int height)
{
int result;
const CGRect r = CGRectMake(x, y, width, height);
result = HIShapeIntersectsRect((HIShapeRef) region, &r) ?
if ( TkMacOSXIsEmptyRegion(region) ) {
return RectangleOut;
}
else {
const CGRect r = CGRectMake(x, y, width, height);
return HIShapeIntersectsRect((HIShapeRef) region, &r) ?
RectanglePart : RectangleOut;
return result;
}
}
/*
@@ -332,12 +357,11 @@ TkpReleaseRegion(
{
CFRelease(r);
}
#if 0
/*
*----------------------------------------------------------------------
*
* TkMacOSXEmtpyRegion --
* TkMacOSXSetEmptyRegion --
*
* Set region to emtpy.
*
@@ -351,36 +375,12 @@ TkpReleaseRegion(
*/
void
TkMacOSXEmtpyRegion(
TkMacOSXSetEmptyRegion(
TkRegion r)
{
ChkErr(HIShapeSetEmpty, (HIMutableShapeRef) r);
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXIsEmptyRegion --
*
* Return native region for given tk region.
*
* Results:
* 1 if empty, 0 otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TkMacOSXIsEmptyRegion(
TkRegion r)
{
return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0;
}
#endif
/*
*----------------------------------------------------------------------
*

View File

@@ -145,7 +145,7 @@ TkpDisplayScale(
Tk_Window tkwin = scalePtr->tkwin;
Tcl_Interp *interp = scalePtr->interp;
int result;
char string[PRINT_CHARS];
char string[TCL_DOUBLE_SPACE];
MacScale *macScalePtr = (MacScale *) clientData;
Rect r;
WindowRef windowRef;

View File

@@ -1,5 +1,5 @@
/*
* tkMacOSXScrollbar.c --
* tkMacOSXScrollbar.c --
*
* This file implements the Macintosh specific portion of the scrollbar
* widget.
@@ -7,30 +7,52 @@
* Copyright (c) 1996 by Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
*
* Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC.
* 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 "tkInt.h"
#include "tkScrollbar.h"
#include "tkMacOSXPrivate.h"
/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_SCROLLBAR
#endif
*/
#define MIN_SCROLLBAR_VALUE 0
/*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling of scrollbar values.*/
#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)
/*
* Declaration of Mac specific scrollbar structure.
*/
typedef struct MacScrollbar {
TkScrollbar info;
NSScroller *scroller;
int variant;
TkScrollbar information; /* Generic scrollbar info. */
GC troughGC; /* For drawing trough. */
GC copyGC; /* Used for copying from pixmap onto screen. */
} MacScrollbar;
/*
* The class procedure table for the scrollbar widget. All fields except size
* are left initialized to NULL, which should happen automatically since the
* variable is declared at this scope.
*/
Tk_ClassProcs tkpScrollbarProcs = {
sizeof(Tk_ClassProcs), /* size */
NULL, /* worldChangedProc */
NULL, /* createProc */
NULL /* modalProc */
};
/*Information on scrollbar layout, metrics, and draw info.*/
typedef struct ScrollbarMetrics {
SInt32 width, minThumbHeight;
int minHeight, topArrowHeight, bottomArrowHeight;
@@ -42,169 +64,23 @@ static ScrollbarMetrics metrics[2] = {
{11, 40, 20, 10, 10, NSSmallControlSize}, /* kThemeScrollBarSmall */
};
/*
* Declarations for functions defined in this file.
*/
static void UpdateScrollbarMetrics(void);
static void ScrollbarEventProc(ClientData clientData,
XEvent *eventPtr);
/*
* The class procedure table for the scrollbar widget.
*/
Tk_ClassProcs tkpScrollbarProcs = {
sizeof(Tk_ClassProcs), /* size */
NULL, /* worldChangedProc */
NULL, /* createProc */
NULL /* modalProc */
HIThemeTrackDrawInfo info = {
.version = 0,
.min = 0.0,
.max = 100.0,
.attributes = kThemeTrackShowThumb,
.kind = kThemeScrollBarMedium,
};
#pragma mark TKApplication(TKScrlbr)
#define NSAppleAquaScrollBarVariantChanged @"AppleAquaScrollBarVariantChanged"
@implementation TKApplication(TKScrlbr)
- (void) tkScroller: (NSScroller *) scroller
{
NSScrollerPart hitPart = [scroller hitPart];
TkScrollbar *scrollPtr = (TkScrollbar *)[scroller tag];
Tcl_DString cmdString;
Tcl_Interp *interp;
int result;
if (!scrollPtr || !scrollPtr->command || !scrollPtr->commandSize ||
hitPart == NSScrollerNoPart) {
return;
}
Tcl_DStringInit(&cmdString);
Tcl_DStringAppend(&cmdString, scrollPtr->command,
scrollPtr->commandSize);
switch (hitPart) {
case NSScrollerKnob:
case NSScrollerKnobSlot: {
char valueString[TCL_DOUBLE_SPACE];
Tcl_PrintDouble(NULL, [scroller doubleValue] *
(1.0 - [scroller knobProportion]), valueString);
Tcl_DStringAppendElement(&cmdString, "moveto");
Tcl_DStringAppendElement(&cmdString, valueString);
break;
}
case NSScrollerDecrementLine:
case NSScrollerIncrementLine:
Tcl_DStringAppendElement(&cmdString, "scroll");
Tcl_DStringAppendElement(&cmdString,
(hitPart == NSScrollerDecrementLine) ? "-1" : "1");
Tcl_DStringAppendElement(&cmdString, "unit");
break;
case NSScrollerDecrementPage:
case NSScrollerIncrementPage:
Tcl_DStringAppendElement(&cmdString, "scroll");
Tcl_DStringAppendElement(&cmdString,
(hitPart == NSScrollerDecrementPage) ? "-1" : "1");
Tcl_DStringAppendElement(&cmdString, "page");
break;
}
interp = scrollPtr->interp;
Tcl_Preserve(interp);
Tcl_Preserve(scrollPtr);
result = Tcl_EvalEx(interp, Tcl_DStringValue(&cmdString),
Tcl_DStringLength(&cmdString), TCL_EVAL_GLOBAL);
if (result != TCL_OK && result != TCL_CONTINUE && result != TCL_BREAK) {
Tcl_AddErrorInfo(interp, "\n (scrollbar command)");
Tcl_BackgroundError(interp);
}
Tcl_Release(scrollPtr);
Tcl_Release(interp);
Tcl_DStringFree(&cmdString);
#ifdef TK_MAC_DEBUG_SCROLLBAR
TKLog(@"scroller %s value %f knobProportion %f",
((TkWindow *)scrollPtr->tkwin)->pathName, [scroller doubleValue],
[scroller knobProportion]);
#endif
}
- (void) scrollBarVariantChanged: (NSNotification *) notification
{
#ifdef TK_MAC_DEBUG_NOTIFICATIONS
TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
#endif
UpdateScrollbarMetrics();
}
- (void) _setupScrollBarNotifications
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
#define observe(n, s) [nc addObserver:self selector:@selector(s) name:(n) object:nil]
observe(NSAppleAquaScrollBarVariantChanged, scrollBarVariantChanged:);
#undef observe
UpdateScrollbarMetrics();
}
@end
#pragma mark -
/*
*----------------------------------------------------------------------
*
* UpdateScrollbarMetrics --
*
* This function retrieves the current system metrics for a scrollbar.
*
* Results:
* None.
*
* Side effects:
* Updates the geometry cache info for all scrollbars.
*
*----------------------------------------------------------------------
* Forward declarations for procedures defined later in this file:
*/
static void
UpdateScrollbarMetrics(void)
{
const short height = 100, width = 50;
HIThemeTrackDrawInfo info = {
.version = 0,
.bounds = {{0, 0}, {width, height}},
.min = 0,
.max = 1,
.value = 0,
.attributes = kThemeTrackShowThumb,
.enableState = kThemeTrackActive,
.trackInfo.scrollbar = {.viewsize = 1, .pressState = 0},
};
CGRect bounds;
static void ScrollbarEventProc(ClientData clientData, XEvent *eventPtr);
static int ScrollbarPress(TkScrollbar *scrollPtr, XEvent *eventPtr);
static void UpdateControlValues(TkScrollbar *scrollPtr);
ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &metrics[0].width);
ChkErr(GetThemeMetric, kThemeMetricScrollBarMinThumbHeight,
&metrics[0].minThumbHeight);
info.kind = kThemeScrollBarMedium;
ChkErr(HIThemeGetTrackDragRect, &info, &bounds);
metrics[0].topArrowHeight = bounds.origin.y;
metrics[0].bottomArrowHeight = height - (bounds.origin.y +
bounds.size.height);
metrics[0].minHeight = metrics[0].minThumbHeight +
metrics[0].topArrowHeight + metrics[0].bottomArrowHeight;
ChkErr(GetThemeMetric, kThemeMetricSmallScrollBarWidth, &metrics[1].width);
ChkErr(GetThemeMetric, kThemeMetricSmallScrollBarMinThumbHeight,
&metrics[1].minThumbHeight);
info.kind = kThemeScrollBarSmall;
ChkErr(HIThemeGetTrackDragRect, &info, &bounds);
metrics[1].topArrowHeight = bounds.origin.y;
metrics[1].bottomArrowHeight = height - (bounds.origin.y +
bounds.size.height);
metrics[1].minHeight = metrics[1].minThumbHeight +
metrics[1].topArrowHeight + metrics[1].bottomArrowHeight;
sprintf(tkDefScrollbarWidth, "%d", (int)(metrics[0].width));
}
/*
*----------------------------------------------------------------------
*
@@ -223,51 +99,27 @@ UpdateScrollbarMetrics(void)
TkScrollbar *
TkpCreateScrollbar(
Tk_Window tkwin)
Tk_Window tkwin)
{
MacScrollbar *scrollPtr = (MacScrollbar *) ckalloc(sizeof(MacScrollbar));
scrollPtr->scroller = nil;
Tk_CreateEventHandler(tkwin, StructureNotifyMask|FocusChangeMask|
ActivateMask|ExposureMask, ScrollbarEventProc, (ClientData) scrollPtr);
MacScrollbar *scrollPtr = (MacScrollbar *)ckalloc(sizeof(MacScrollbar));
scrollPtr->troughGC = None;
scrollPtr->copyGC = None;
Tk_CreateEventHandler(tkwin,ExposureMask|StructureNotifyMask|FocusChangeMask|ButtonPressMask|VisibilityChangeMask, ScrollbarEventProc, scrollPtr);
return (TkScrollbar *) scrollPtr;
}
/*
*----------------------------------------------------------------------
*
* TkpDestroyScrollbar --
*
* Free data structures associated with the scrollbar control.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
TkpDestroyScrollbar(
TkScrollbar *scrollPtr)
{
MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
NSScroller *scroller = macScrollPtr->scroller;
[scroller setTag:(NSInteger)0];
TkMacOSXMakeCollectableAndRelease(macScrollPtr->scroller);
}
/*
*--------------------------------------------------------------
*
* TkpDisplayScrollbar --
*
* This procedure redraws the contents of a scrollbar window. It is
* invoked as a do-when-idle handler, so it only runs when there's nothing
* else for the application to do.
* invoked as a do-when-idle handler, so it only runs when there's
* nothing else for the application to do.
*
* Results:
* None.
@@ -280,91 +132,68 @@ TkpDestroyScrollbar(
void
TkpDisplayScrollbar(
ClientData clientData) /* Information about window. */
ClientData clientData) /* Information about window. */
{
TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
MacScrollbar *macScrollPtr = (MacScrollbar *) clientData;
NSScroller *scroller = macScrollPtr->scroller;
Tk_Window tkwin = scrollPtr->tkwin;
register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
register Tk_Window tkwin = scrollPtr->tkwin;
TkWindow *winPtr = (TkWindow *) tkwin;
MacDrawable *macWin = (MacDrawable *) winPtr->window;
TkMacOSXDrawingContext dc;
scrollPtr->flags &= ~REDRAW_PENDING;
if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
return;
}
MacDrawable *macWin = (MacDrawable *) winPtr->window;
NSView *view = TkMacOSXDrawableView(macWin);
if (!view ||
macWin->flags & TK_DO_NOT_DRAW ||
!TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
return;
}
CGFloat viewHeight = [view bounds].size.height;
CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
.ty = viewHeight};
NSRect frame;
double knobProportion = scrollPtr->lastFraction - scrollPtr->firstFraction;
scrollPtr->flags &= ~REDRAW_PENDING;
if (!scrollPtr->tkwin || !Tk_IsMapped(tkwin) || !view ||
!TkMacOSXSetupDrawingContext((Drawable) macWin, NULL, 1, &dc)) {
return;
}
.ty = viewHeight};
CGContextConcatCTM(dc.context, t);
/*Draw Unix-style scroll trough to provide rect for native scrollbar.*/
if (scrollPtr->highlightWidth != 0) {
GC fgGC, bgGC;
GC fgGC, bgGC;
bgGC = Tk_GCForColor(scrollPtr->highlightBgColorPtr, (Pixmap) macWin);
if (scrollPtr->flags & GOT_FOCUS) {
fgGC = Tk_GCForColor(scrollPtr->highlightColorPtr, (Pixmap) macWin);
} else {
fgGC = bgGC;
}
TkpDrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth,
(Pixmap) macWin);
bgGC = Tk_GCForColor(scrollPtr->highlightBgColorPtr, (Pixmap) macWin);
if (scrollPtr->flags & GOT_FOCUS) {
fgGC = Tk_GCForColor(scrollPtr->highlightColorPtr, (Pixmap) macWin);
} else {
fgGC = bgGC;
}
TkpDrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth,
(Pixmap) macWin);
}
Tk_Draw3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
scrollPtr->highlightWidth, scrollPtr->highlightWidth,
Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
scrollPtr->borderWidth, scrollPtr->relief);
scrollPtr->highlightWidth, scrollPtr->highlightWidth,
Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
scrollPtr->borderWidth, scrollPtr->relief);
Tk_Fill3DRectangle(tkwin, (Pixmap) macWin, scrollPtr->bgBorder,
scrollPtr->inset, scrollPtr->inset,
Tk_Width(tkwin) - 2*scrollPtr->inset,
Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT);
if ([scroller superview] != view) {
[view addSubview:scroller];
scrollPtr->inset, scrollPtr->inset,
Tk_Width(tkwin) - 2*scrollPtr->inset,
Tk_Height(tkwin) - 2*scrollPtr->inset, 0, TK_RELIEF_FLAT);
/*Update values and draw in native rect.*/
UpdateControlValues(scrollPtr);
if (MOUNTAIN_LION_STYLE) {
HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationInverted);
} else {
HIThemeDrawTrack (&info, 0, dc.context, kHIThemeOrientationNormal);
}
frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin),
Tk_Height(tkwin));
frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset);
frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
NSWindow *w = [view window];
if ([w showsResizeIndicator]) {
NSRect growBox = [view convertRect:[w _growBoxRect] fromView:nil];
if (NSIntersectsRect(growBox, frame)) {
if (scrollPtr->vertical) {
CGFloat y = frame.origin.y;
frame.origin.y = growBox.origin.y + growBox.size.height;
frame.size.height -= frame.origin.y - y;
} else {
frame.size.width = growBox.origin.x - frame.origin.x;
}
TkMacOSXSetScrollbarGrow(winPtr, true);
}
}
if (!NSEqualRects(frame, [scroller frame])) {
[scroller setFrame:frame];
}
[scroller setEnabled:(knobProportion < 1.0 &&
(scrollPtr->vertical ? frame.size.height : frame.size.width) >
metrics[macScrollPtr->variant].minHeight)];
[scroller setDoubleValue:scrollPtr->firstFraction / (1.0 - knobProportion)];
[scroller setKnobProportion:knobProportion];
[scroller displayRectIgnoringOpacity:[scroller bounds]];
TkMacOSXRestoreDrawingContext(&dc);
#ifdef TK_MAC_DEBUG_SCROLLBAR
TKLog(@"scroller %s frame %@ width %d height %d",
((TkWindow *)scrollPtr->tkwin)->pathName, NSStringFromRect(frame),
Tk_Width(tkwin), Tk_Height(tkwin));
#endif
scrollPtr->flags &= ~REDRAW_PENDING;
}
/*
*----------------------------------------------------------------------
*
@@ -383,123 +212,107 @@ TkpDisplayScrollbar(
*----------------------------------------------------------------------
*/
void
extern void
TkpComputeScrollbarGeometry(
register TkScrollbar *scrollPtr)
/* Scrollbar whose geometry may have
* changed. */
register TkScrollbar *scrollPtr)
/* Scrollbar whose geometry may have
* changed. */
{
MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
NSScroller *scroller = macScrollPtr->scroller;
int width, height, variant, fieldLength;
int variant, fieldLength;
if (scrollPtr->highlightWidth < 0) {
scrollPtr->highlightWidth = 0;
scrollPtr->highlightWidth = 0;
}
scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
width = Tk_Width(scrollPtr->tkwin) - 2 * scrollPtr->inset;
height = Tk_Height(scrollPtr->tkwin) - 2 * scrollPtr->inset;
variant = ((scrollPtr->vertical ? width : height) < metrics[0].width) ?
1 : 0;
macScrollPtr->variant = variant;
if (scroller) {
NSSize size = [scroller frame].size;
if ((size.width > size.height) ^ !scrollPtr->vertical) {
/*
* Orientation changed, need new scroller.
*/
if ([scroller superview]) {
[scroller removeFromSuperviewWithoutNeedingDisplay];
}
TkMacOSXMakeCollectableAndRelease(scroller);
}
}
if (!scroller) {
if ((width > height) ^ !scrollPtr->vertical) {
/* -[NSScroller initWithFrame:] determines horizonalness for the
* lifetime of the scroller via isHoriz = (width > height) */
if (scrollPtr->vertical) {
width = height;
} else if (width > 1) {
height = width - 1;
} else {
height = 1;
width = 2;
}
}
scroller = [[NSScroller alloc] initWithFrame:
NSMakeRect(0, 0, width, height)];
macScrollPtr->scroller = TkMacOSXMakeUncollectable(scroller);
[scroller setAction:@selector(tkScroller:)];
[scroller setTarget:NSApp];
[scroller setTag:(NSInteger)scrollPtr];
}
[[scroller cell] setControlSize:metrics[variant].controlSize];
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;
metrics[variant].bottomArrowHeight) / 2;
fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)
: Tk_Width(scrollPtr->tkwin))
- 2 * (scrollPtr->arrowLength + scrollPtr->inset);
: Tk_Width(scrollPtr->tkwin))
- 2 * (scrollPtr->arrowLength + scrollPtr->inset);
if (fieldLength < 0) {
fieldLength = 0;
fieldLength = 0;
}
scrollPtr->sliderFirst = fieldLength * scrollPtr->firstFraction;
scrollPtr->sliderLast = fieldLength * scrollPtr->lastFraction;
/*
* Adjust the slider so that some piece of it is always displayed in the
* scrollbar and so that it has at least a minimal width (so it can be
* grabbed with the mouse).
* Adjust the slider so that 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;
scrollPtr->sliderFirst = fieldLength - 2*scrollPtr->borderWidth;
}
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;
metrics[variant].minThumbHeight)) {
scrollPtr->sliderLast = scrollPtr->sliderFirst +
metrics[variant].minThumbHeight;
}
if (scrollPtr->sliderLast > fieldLength) {
scrollPtr->sliderLast = fieldLength;
scrollPtr->sliderLast = fieldLength;
}
if (!(MOUNTAIN_LION_STYLE)) {
scrollPtr->sliderFirst += scrollPtr->inset +
metrics[variant].topArrowHeight;
scrollPtr->sliderLast += scrollPtr->inset +
metrics[variant].bottomArrowHeight;
}
scrollPtr->sliderFirst += scrollPtr->inset +
metrics[variant].topArrowHeight;
scrollPtr->sliderLast += scrollPtr->inset +
metrics[variant].bottomArrowHeight;
/*
* 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 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);
Tk_GeometryRequest(scrollPtr->tkwin, scrollPtr->width + 2 * scrollPtr->inset, 2 * (scrollPtr->arrowLength + scrollPtr->borderWidth + scrollPtr->inset) + metrics[variant].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[variant].minThumbHeight, scrollPtr->width + 2 * scrollPtr->inset);
}
Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);
#ifdef TK_MAC_DEBUG_SCROLLBAR
TKLog(@"scroller %s bounds %@ width %d height %d inset %d borderWidth %d",
((TkWindow *)scrollPtr->tkwin)->pathName,
NSStringFromRect([scroller bounds]),
width, height, scrollPtr->inset, scrollPtr->borderWidth);
#endif
}
/*
*----------------------------------------------------------------------
*
* TkpDestroyScrollbar --
*
* Free data structures associated with the scrollbar control.
*
* Results:
* None.
*
* Side effects:
* Frees the GCs associated with the scrollbar.
*
*----------------------------------------------------------------------
*/
void
TkpDestroyScrollbar(
TkScrollbar *scrollPtr)
{
MacScrollbar *macScrollPtr = (MacScrollbar *)scrollPtr;
if (macScrollPtr->troughGC != None) {
Tk_FreeGC(scrollPtr->display, macScrollPtr->troughGC);
}
if (macScrollPtr->copyGC != None) {
Tk_FreeGC(scrollPtr->display, macScrollPtr->copyGC);
}
macScrollPtr=NULL;
}
/*
*----------------------------------------------------------------------
*
@@ -513,19 +326,20 @@ TkpComputeScrollbarGeometry(
* None.
*
* Side effects:
* None.
* Configuration info may get changed.
*
*----------------------------------------------------------------------
*/
void
TkpConfigureScrollbar(
register TkScrollbar *scrollPtr)
/* Information about widget; may or may not
* already have values for some fields. */
register TkScrollbar *scrollPtr)
/* Information about widget; may or may not
* already have values for some fields. */
{
}
/*
*--------------------------------------------------------------
*
@@ -550,30 +364,175 @@ TkpScrollbarPosition(
/* Scrollbar widget record. */
int x, int y) /* Coordinates within scrollPtr's window. */
{
NSScroller *scroller = ((MacScrollbar *) scrollPtr)->scroller;
MacDrawable *macWin = (MacDrawable *)
((TkWindow *) scrollPtr->tkwin)->window;
NSView *view = TkMacOSXDrawableView(macWin);
switch ([scroller testPart:NSMakePoint(macWin->xOff + x,
[view bounds].size.height - (macWin->yOff + y))]) {
case NSScrollerDecrementLine:
return TOP_ARROW;
case NSScrollerDecrementPage:
return TOP_GAP;
case NSScrollerKnob:
return SLIDER;
case NSScrollerIncrementPage:
return BOTTOM_GAP;
case NSScrollerIncrementLine:
return BOTTOM_ARROW;
case NSScrollerKnobSlot:
case NSScrollerNoPart:
default:
/*
* 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.
*/
int length, fieldlength, 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) {
return OUTSIDE;
}
/*
* All of the calculations in this procedure mirror those in
* TkpDisplayScrollbar. Be sure to keep the two consistent.
*/
if (y < scrollPtr->sliderFirst) {
return TOP_GAP;
}
if (y < scrollPtr->sliderLast) {
return SLIDER;
}
if (y < fieldlength){
return BOTTOM_GAP;
}
if (y < fieldlength + arrowSize) {
return TOP_ARROW;
}
return BOTTOM_ARROW;
}
/*
*--------------------------------------------------------------
*
* UpdateControlValues --
*
* This procedure updates the Macintosh scrollbar control to
* display the values defined by the Tk scrollbar. This is the
* key interface to the Mac-native * scrollbar; the Unix bindings
* drive scrolling in the Tk window and all the Mac scrollbar has
* to do is redraw itself.
*
* Results:
* None.
*
* Side effects:
* The Macintosh control is updated.
*
*--------------------------------------------------------------
*/
static void
UpdateControlValues(
TkScrollbar *scrollPtr) /* Scrollbar data struct. */
{
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);
CGFloat viewHeight = [view bounds].size.height;
NSRect frame;
frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin),
Tk_Height(tkwin));
frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset);
frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
contrlRect = NSRectToCGRect(frame);
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;
if (scrollPtr->vertical) {
info.attributes &= ~kThemeTrackHorizontal;
} else {
info.attributes |= kThemeTrackHorizontal;
}
/*
* Given the Tk parameters for the fractions of the start and end of the
* thumb, the following calculation determines the location for the
* Macintosh thumb. The Aqua scroll control works as follows. The
* scrollbar's value is the position of the left (or top) side of the view
* area in the content area being scrolled. The maximum value of the
* control is therefore the dimension of the content area less the size of
* the view area.
*/
double maximum = 100, factor;
factor = RangeToFactor(maximum);
dViewSize = (scrollPtr->lastFraction - scrollPtr->firstFraction)
* factor;
info.max = MIN_SCROLLBAR_VALUE +
factor - dViewSize;
info.trackInfo.scrollbar.viewsize = dViewSize;
if (scrollPtr->vertical) {
if (MOUNTAIN_LION_STYLE) {
info.value = factor * scrollPtr->firstFraction;
} else {
info.value = info.max - factor * scrollPtr->firstFraction;
}
} else {
info.value = MIN_SCROLLBAR_VALUE + factor * scrollPtr->firstFraction;
}
if((scrollPtr->firstFraction <= 0.0 && scrollPtr->lastFraction >= 1.0)
|| height <= metrics[variant].minHeight) {
info.enableState = kThemeTrackHideTrack;
} else {
info.enableState = kThemeTrackActive;
info.attributes = kThemeTrackShowThumb | kThemeTrackThumbRgnIsNotGhost;
}
}
/*
*--------------------------------------------------------------
*
* ScrollbarPress --
*
* This procedure is invoked in response to <ButtonPress> events.
* Enters a modal loop to handle scrollbar interactions.
*
*--------------------------------------------------------------
*/
static int
ScrollbarPress(TkScrollbar *scrollPtr, XEvent *eventPtr)
{
if (eventPtr->type == ButtonPress) {
UpdateControlValues(scrollPtr);
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
@@ -594,10 +553,10 @@ TkpScrollbarPosition(
static void
ScrollbarEventProc(
ClientData clientData, /* Information about window. */
XEvent *eventPtr) /* Information about event. */
ClientData clientData, /* Information about window. */
XEvent *eventPtr) /* Information about event. */
{
TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
TkScrollbar *scrollPtr = clientData;
switch (eventPtr->type) {
case UnmapNotify:
@@ -605,18 +564,13 @@ ScrollbarEventProc(
break;
case ActivateNotify:
case DeactivateNotify:
TkScrollbarEventuallyRedraw((ClientData) scrollPtr);
TkScrollbarEventuallyRedraw(scrollPtr);
break;
case ButtonPress:
ScrollbarPress(clientData, eventPtr);
break;
default:
TkScrollbarEventProc(clientData, eventPtr);
}
}
/*
* Local Variables:
* mode: objc
* c-basic-offset: 4
* fill-column: 79
* coding: utf-8
* End:
*/

View File

@@ -149,8 +149,11 @@ XMapWindow(
if (Tk_IsTopLevel(macWin->winPtr)) {
if (!Tk_IsEmbedded(macWin->winPtr)) {
NSWindow *win = TkMacOSXDrawableWindow(window);
[win makeKeyAndOrderFront:NSApp];
[NSApp activateIgnoringOtherApps:YES];
if ( [win canBecomeKeyWindow] ) {
[win makeKeyAndOrderFront:NSApp];
}
/* Why do we need this? (It is used by Carbon)*/
[win windowRef];
TkMacOSXApplyWindowAttributes(macWin->winPtr, win);
}
@@ -310,7 +313,6 @@ XResizeWindow(
unsigned int height)
{
MacDrawable *macWin = (MacDrawable *) window;
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
@@ -357,7 +359,6 @@ XMoveResizeWindow(
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
if (w) {
NSRect r = NSMakeRect(x + macWin->winPtr->wmInfoPtr->xInParent,
tkMacOSXZeroScreenHeight - (y +
@@ -398,7 +399,6 @@ XMoveWindow(
display->request++;
if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) {
NSWindow *w = macWin->winPtr->wmInfoPtr->window;
if (w) {
[w setFrameTopLeftPoint:NSMakePoint(x, tkMacOSXZeroScreenHeight - y)];
}
@@ -646,12 +646,71 @@ XConfigureWindow(
macWin->winPtr->changes.x, macWin->winPtr->changes.y); */
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXSetDrawingEnabled --
*
* This function sets the TK_DO_NOT_DRAW flag for a given window and
* all of its children.
*
* Results:
* None.
*
* Side effects:
* The clipping regions for the window and its children are cleared.
*
*----------------------------------------------------------------------
*/
void
TkMacOSXSetDrawingEnabled(
TkWindow *winPtr,
int flag)
{
TkWindow *childPtr;
MacDrawable *macWin = winPtr->privatePtr;
if (macWin) {
if (flag ) {
macWin->flags &= ~TK_DO_NOT_DRAW;
} else {
macWin->flags |= TK_DO_NOT_DRAW;
}
}
/*
* Set the flag for all children & their descendants, excluding
* Toplevels. (??? Do we need to exclude Toplevels?)
*/
childPtr = winPtr->childList;
while (childPtr) {
if (!Tk_IsTopLevel(childPtr)) {
TkMacOSXSetDrawingEnabled(childPtr, flag);
}
childPtr = childPtr->nextPtr;
}
/*
* If the window is a container, set the flag for its embedded window.
*/
if (Tk_IsContainer(winPtr)) {
childPtr = TkpGetOtherWindow(winPtr);
if (childPtr) {
TkMacOSXSetDrawingEnabled(childPtr, flag);
}
}
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXUpdateClipRgn --
*
* This function updates the cliping regions for a given window and all of
* This function updates the clipping regions for a given window and all of
* its children. Once updated the TK_CLIP_INVALID flag in the subwindow
* data structure is unset. The TK_CLIP_INVALID flag should always be
* unset before any drawing is attempted.
@@ -738,17 +797,6 @@ TkMacOSXUpdateClipRgn(
/*
* TODO: Here we should handle out of process embedding.
*/
} else if (winPtr->wmInfoPtr->attributes &
kWindowResizableAttribute) {
NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);
if (w) {
bounds = NSRectToCGRect([w _growBoxRect]);
bounds.origin.y = [w contentRectForFrameRect:
[w frame]].size.height - bounds.size.height -
bounds.origin.y;
ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);
}
}
macWin->aboveVisRgn = HIShapeCreateCopy(rgn);
@@ -825,7 +873,7 @@ TkMacOSXUpdateClipRgn(
*
* TkMacOSXVisableClipRgn --
*
* This function returns the Macintosh cliping region for the given
* This function returns the Macintosh clipping region for the given
* window. The caller is responsible for disposing of the returned
* region via TkDestroyRegion().
*
@@ -920,7 +968,7 @@ TkMacOSXInvalidateWindow(
* TK_PARENT_WINDOW */
{
#ifdef TK_MAC_DEBUG_CLIP_REGIONS
TkMacOSXDbgMsg("%s", winPtr->pathName);
TkMacOSXDbgMsg("%s", macWin->winPtr->pathName);
#endif
if (macWin->flags & TK_CLIP_INVALID) {
TkMacOSXUpdateClipRgn(macWin->winPtr);
@@ -1078,7 +1126,7 @@ TkMacOSXGetRootControl(
* None.
*
* Side effects:
* The cliping regions for the window and its children are mark invalid.
* The clipping regions for the window and its children are marked invalid.
* (Make sure they are valid before drawing.)
*
*----------------------------------------------------------------------
@@ -1097,6 +1145,10 @@ TkMacOSXInvalClipRgns(
* be marked.
*/
#ifdef TK_MAC_DEBUG_CLIP_REGIONS
TkMacOSXDbgMsg("%s", winPtr->pathName);
#endif
if (!macWin || macWin->flags & TK_CLIP_INVALID) {
return;
}
@@ -1277,7 +1329,7 @@ UpdateOffsets(
* Returns a handle to a new pixmap.
*
* Side effects:
* Allocates a new Macintosh GWorld.
* Allocates a new CGBitmapContext.
*
*----------------------------------------------------------------------
*/
@@ -1323,7 +1375,7 @@ Tk_GetPixmap(
* None.
*
* Side effects:
* Deletes the Macintosh GWorld created by Tk_GetPixmap.
* Deletes the CGBitmapContext created by Tk_GetPixmap.
*
*----------------------------------------------------------------------
*/

View File

@@ -6,6 +6,8 @@
*
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright (c) 2015 Kevin Walzer/WordTech Communications LLC.
* Copyright (c) 2015 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -15,7 +17,7 @@
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"
/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_EVENTS
@@ -27,7 +29,7 @@
* Declaration of functions used only in this file
*/
static int GenerateUpdates(HIMutableShapeRef updateRgn,
static int GenerateUpdates(HIShapeRef updateRgn,
CGRect *updateBounds, TkWindow *winPtr);
static int GenerateActivateEvents(TkWindow *winPtr,
int activeFlag);
@@ -46,7 +48,7 @@ extern NSString *NSWindowDidOrderOffScreenNotification;
#endif
#endif
extern NSString *opaqueTag;
extern BOOL opaqueTag;
@implementation TKApplication(TKWindowEvent)
@@ -163,6 +165,10 @@ extern NSString *opaqueTag;
if (winPtr) {
TkGenWMDestroyEvent((Tk_Window) winPtr);
if (_windowWithMouse == w) {
_windowWithMouse = nil;
[w release];
}
}
/*
@@ -314,7 +320,7 @@ extern NSString *opaqueTag;
static int
GenerateUpdates(
HIMutableShapeRef updateRgn,
HIShapeRef updateRgn,
CGRect *updateBounds,
TkWindow *winPtr)
{
@@ -357,11 +363,12 @@ GenerateUpdates(
event.xexpose.width = damageBounds.size.width;
event.xexpose.height = damageBounds.size.height;
event.xexpose.count = 0;
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
#ifdef TK_MAC_DEBUG_DRAWING
TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
Tk_HandleEvent(&event);
#ifdef TK_MAC_DEBUG_DRAWING
NSLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
event.xexpose.y, event.xexpose.width, event.xexpose.height);
#endif
#endif
/*
* Generate updates for the children of this window
@@ -388,7 +395,7 @@ GenerateUpdates(
/*
* TODO: Here we should handle out of process embedding.
*/
}
}
return 1;
}
@@ -744,15 +751,16 @@ TkWmProtocolEventProc(
int
Tk_MacOSXIsAppInFront(void)
{
OSStatus err;
ProcessSerialNumber frontPsn, ourPsn = {0, kCurrentProcess};
Boolean isFrontProcess = true;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
ProcessSerialNumber frontPsn, ourPsn = {0, kCurrentProcess};
err = ChkErr(GetFrontProcess, &frontPsn);
if (err == noErr) {
ChkErr(SameProcess, &frontPsn, &ourPsn, &isFrontProcess);
if (noErr == GetFrontProcess(&frontPsn)){
SameProcess(&frontPsn, &ourPsn, &isFrontProcess);
}
#else
isFrontProcess = [NSRunningApplication currentApplication].active;
#endif
return (isFrontProcess == true);
}
@@ -761,27 +769,25 @@ Tk_MacOSXIsAppInFront(void)
#import <ApplicationServices/ApplicationServices.h>
/*
* Custom content view for Tk NSWindows, containing standard NSView subviews.
* The goal is to emulate X11-style drawing in response to Expose events:
* during the normal AppKit drawing cycle, we supress drawing of all subviews
* (using a technique adapted from WebKit's WebHTMLView) and instead send
* Expose events about the subviews that would be redrawn. Tk Expose event
* handling and drawing handlers then draw the subviews manually via their
* -displayRectIgnoringOpacity:
* Custom content view for use in Tk NSWindows.
*
* Since Tk handles all drawing of widgets, we only use the AppKit event loop
* as a source of input events. To do this, we overload the NSView drawRect
* method with a method which generates Expose events for Tk but does no
* drawing. The redrawing operations are then done when Tk processes these
* events.
*
* Earlier versions of Mac Tk used subclasses of NSView, e.g. NSButton, as the
* basis for Tk widgets. These would then appear as subviews of the
* TKContentView. To prevent the AppKit from redrawing and corrupting the Tk
* Widgets it was necessary to use Apple private API calls. In order to avoid
* using private API calls, the NSView-based widgets have been replaced with
* normal Tk widgets which draw themselves as native widgets by using the
* HITheme API.
*
*/
@interface TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect;
- (void) generateExposeEvents: (HIMutableShapeRef) shape;
- (BOOL) isOpaque;
- (BOOL) wantsDefaultClipping;
- (BOOL) acceptsFirstResponder;
- (void) keyDown: (NSEvent *) theEvent;
@end
@implementation TKContentView
@end
/*Restrict event processing to Expose events.*/
static Tk_RestrictAction
ExposeRestrictProc(
ClientData arg,
@@ -791,14 +797,24 @@ ExposeRestrictProc(
? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}
/*Restrict event processing to ConfigureNotify events.*/
static Tk_RestrictAction
ConfigureRestrictProc(
ClientData arg,
XEvent *eventPtr)
{
return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}
@implementation TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect
{
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];
@@ -806,73 +822,140 @@ ExposeRestrictProc(
NSCompositeSourceOver);
#endif
NSWindow *w = [self window];
if ([self isOpaque] && [w showsResizeIndicator]) {
NSRect bounds = [self convertRect:[w _growBoxRect] fromView:nil];
if ([self needsToDrawRect:bounds]) {
NSEraseRect(bounds);
}
}
CGFloat height = [self bounds].size.height;
HIMutableShapeRef drawShape = HIShapeCreateMutable();
while (rectsBeingDrawnCount--) {
CGRect r = NSRectToCGRect(*rectsBeingDrawn++);
r.origin.y = height - (r.origin.y + r.size.height);
HIShapeUnionWithRect(drawShape, &r);
}
if (CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
[self generateExposeEvents:drawShape];
[self generateExposeEvents:(HIShapeRef)drawShape];
} else {
[self performSelectorOnMainThread:@selector(generateExposeEvents:)
withObject:(id)drawShape waitUntilDone:NO
modes:[NSArray arrayWithObjects:NSRunLoopCommonModes,
NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode,
nil]];
}
CFRelease(drawShape);
}
- (void) generateExposeEvents: (HIMutableShapeRef) shape
-(void) setFrameSize: (NSSize)newsize
{
[super setFrameSize: newsize];
if ([self inLiveResize]) {
NSWindow *w = [self window];
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
Tk_Window tkwin = (Tk_Window) winPtr;
unsigned int width = (unsigned int)newsize.width;
unsigned int height=(unsigned int)newsize.height;
ClientData oldArg;
Tk_RestrictProc *oldProc;
/* This can be called from outside the Tk event loop.
* Since it calls Tcl_DoOneEvent, we need to make sure we
* don't clobber the AutoreleasePool set up by the caller.
*/
[NSApp setPoolProtected:YES];
/*
* Try to prevent flickers and flashes.
*/
[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.*/
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. */
TkMacOSXSetDrawingEnabled(winPtr, 1);
TkMacOSXInvalClipRgns(tkwin);
TkMacOSXUpdateClipRgn(winPtr);
/* Finally, 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();
[NSApp setPoolProtected:NO];
}
}
/*
* 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.
*/
- (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.
* Whereas drawRect is intended to be called only from the Appkit event
* loop, this can be called from Tk. 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
{
[self generateExposeEvents:shape childrenOnly:0];
}
- (void) generateExposeEvents: (HIShapeRef) shape
childrenOnly: (int) childrenOnly
{
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
unsigned long serial;
CGRect updateBounds;
int updatesNeeded;
if (!winPtr) {
return;
return;
}
/* Generate Tk Expose events. */
HIShapeGetBounds(shape, &updateBounds);
/* All of these events will share the same serial number. */
serial = LastKnownRequestProcessed(Tk_Display(winPtr));
if (GenerateUpdates(shape, &updateBounds, winPtr) &&
![[NSRunLoop currentRunLoop] currentMode] &&
Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
/*
* Ensure there are no pending idle-time redraws that could prevent the
* just posted Expose events from generating new redraws.
*/
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
/*
* For smoother drawing, process Expose events and resulting redraws
* immediately instead of at idle time.
*/
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)) {}
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc,
UINT2PTR(serial), &oldArg);
while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
Tk_RestrictEvents(oldProc, oldArg, &oldArg);
}
}
/*
* 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
@@ -882,7 +965,6 @@ ExposeRestrictProc(
int x, y;
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
Tk_Window tkwin = (Tk_Window) winPtr;
bzero(&event, sizeof(XVirtualEvent));
event.type = VirtualEvent;
event.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
@@ -900,27 +982,11 @@ ExposeRestrictProc(
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}
#ifdef TK_MAC_DEBUG_DRAWING
- (void) setFrameSize: (NSSize) newSize
{
TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
NSStringFromSize(newSize));
[super setFrameSize:newSize];
}
- (void) setNeedsDisplayInRect: (NSRect) invalidRect
{
TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
NSStringFromRect(invalidRect));
[super setNeedsDisplayInRect:invalidRect];
}
#endif
- (BOOL) isOpaque
{
NSWindow *w = [self window];
if (opaqueTag != NULL) {
if (opaqueTag) {
return YES;
} else {
@@ -946,153 +1012,6 @@ ExposeRestrictProc(
#endif
}
@end
#pragma mark TKContentViewPrivate
/*
* Technique adapted from WebKit/WebKit/mac/WebView/WebHTMLView.mm to supress
* normal AppKit subview drawing and make all drawing go through us.
* Overrides NSView internals.
*/
@interface TKContentView(TKContentViewPrivate)
- (id) initWithFrame: (NSRect) frame;
- (void) _setAsideSubviews;
- (void) _restoreSubviews;
@end
@interface NSView(TKContentViewPrivate)
- (void) _recursiveDisplayRectIfNeededIgnoringOpacity: (NSRect) rect
isVisibleRect: (BOOL) isVisibleRect
rectIsVisibleRectForView: (NSView *) visibleView
topView: (BOOL) topView;
- (void) _recursiveDisplayAllDirtyWithLockFocus: (BOOL) needsLockFocus
visRect: (NSRect) visRect;
- (void) _recursive: (BOOL) recurse
displayRectIgnoringOpacity: (NSRect) displayRect
inContext: (NSGraphicsContext *) context topView: (BOOL) topView;
- (void) _lightWeightRecursiveDisplayInRect: (NSRect) visRect;
- (BOOL) _drawRectIfEmpty;
- (void) _drawRect: (NSRect) inRect clip: (BOOL) clip;
- (void) _setDrawsOwnDescendants: (BOOL) drawsOwnDescendants;
@end
@implementation TKContentView(TKContentViewPrivate)
- (id) initWithFrame: (NSRect) frame
{
self = [super initWithFrame:frame];
if (self) {
_savedSubviews = nil;
_subviewsSetAside = NO;
[self _setDrawsOwnDescendants:YES];
}
return self;
}
- (void) _setAsideSubviews
{
#ifdef TK_MAC_DEBUG
if (_subviewsSetAside || _savedSubviews) {
Tcl_Panic("TKContentView _setAsideSubviews called incorrectly");
}
#endif
_savedSubviews = _subviews;
_subviews = nil;
_subviewsSetAside = YES;
}
- (void) _restoreSubviews
{
#ifdef TK_MAC_DEBUG
if (!_subviewsSetAside || _subviews) {
Tcl_Panic("TKContentView _restoreSubviews called incorrectly");
}
#endif
_subviews = _savedSubviews;
_savedSubviews = nil;
_subviewsSetAside = NO;
}
- (void) _recursiveDisplayRectIfNeededIgnoringOpacity: (NSRect) rect
isVisibleRect: (BOOL) isVisibleRect
rectIsVisibleRectForView: (NSView *) visibleView
topView: (BOOL) topView
{
[self _setAsideSubviews];
[super _recursiveDisplayRectIfNeededIgnoringOpacity:rect
isVisibleRect:isVisibleRect rectIsVisibleRectForView:visibleView
topView:topView];
[self _restoreSubviews];
}
- (void) _recursiveDisplayAllDirtyWithLockFocus: (BOOL) needsLockFocus
visRect: (NSRect) visRect
{
BOOL needToSetAsideSubviews = !_subviewsSetAside;
if (needToSetAsideSubviews) {
[self _setAsideSubviews];
}
[super _recursiveDisplayAllDirtyWithLockFocus:needsLockFocus
visRect:visRect];
if (needToSetAsideSubviews) {
[self _restoreSubviews];
}
}
- (void) _recursive: (BOOL) recurse
displayRectIgnoringOpacity: (NSRect) displayRect
inContext: (NSGraphicsContext *) context topView: (BOOL) topView
{
[self _setAsideSubviews];
[super _recursive:recurse
displayRectIgnoringOpacity:displayRect inContext:context
topView:topView];
[self _restoreSubviews];
}
- (void) _lightWeightRecursiveDisplayInRect: (NSRect) visRect
{
BOOL needToSetAsideSubviews = !_subviewsSetAside;
if (needToSetAsideSubviews) {
[self _setAsideSubviews];
}
[super _lightWeightRecursiveDisplayInRect:visRect];
if (needToSetAsideSubviews) {
[self _restoreSubviews];
}
}
- (BOOL) _drawRectIfEmpty
{
/*
* Our -drawRect manages subview drawing directly, so it needs to be called
* even if the area to be redrawn is completely obscured by subviews.
*/
return YES;
}
- (void) _drawRect: (NSRect) inRect clip: (BOOL) clip
{
#ifdef TK_MAC_DEBUG_DRAWING
TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
NSStringFromRect(inRect));
#endif
BOOL subviewsWereSetAside = _subviewsSetAside;
if (subviewsWereSetAside) {
[self _restoreSubviews];
}
[super _drawRect:inRect clip:clip];
if (subviewsWereSetAside) {
[self _setAsideSubviews];
}
}
@end
/*

View File

@@ -22,6 +22,8 @@
#include "tkMacOSXDebug.h"
#include <Carbon/Carbon.h>
#define DEBUG_ZOMBIES 0
/*
#ifdef TK_MAC_DEBUG
#define TK_MAC_DEBUG_WINDOWS
@@ -55,7 +57,7 @@
/*Objects for use in setting background color and opacity of window.*/
NSColor *colorName = NULL;
NSString *opaqueTag = NULL;
BOOL opaqueTag = FALSE;
static const struct {
const UInt64 validAttrs, defaultAttrs, forceOnAttrs, forceOffAttrs;
@@ -196,6 +198,48 @@ static int tkMacOSXWmAttrNotifyVal = 0;
static Tcl_HashTable windowTable;
static int windowHashInit = false;
#pragma mark NSWindow(TKWm)
/*
* Conversion of coordinates between window and screen.
*/
@implementation NSWindow(TKWm)
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
- (NSPoint) convertPointToScreen: (NSPoint) point
{
return [self convertBaseToScreen:point];
}
- (NSPoint) convertPointFromScreen: (NSPoint)point
{
return [self convertScreenToBase:point];
}
@end
#else
- (NSPoint) convertPointToScreen: (NSPoint) point
{
NSRect pointrect;
pointrect.origin = point;
pointrect.size.width = 0;
pointrect.size.height = 0;
return [self convertRectToScreen:pointrect].origin;
}
- (NSPoint) convertPointFromScreen: (NSPoint)point
{
NSRect pointrect;
pointrect.origin = point;
pointrect.size.width = 0;
pointrect.size.height = 0;
return [self convertRectFromScreen:pointrect].origin;
}
@end
#endif
#pragma mark -
/*
* Forward declarations for procedures defined in this file:
*/
@@ -344,6 +388,7 @@ static void RemapWindows(TkWindow *winPtr,
@end
@implementation TKWindow(TKWm)
- (BOOL) canBecomeKeyWindow
{
TkWindow *winPtr = TkMacOSXGetTkWindow(self);
@@ -353,6 +398,58 @@ static void RemapWindows(TkWindow *winPtr,
kWindowNoActivatesAttribute)) ? NO : YES;
}
#if DEBUG_ZOMBIES
- (id) retain
{
id result = [super retain];
const char *title = [[self title] UTF8String];
if (title == nil) {
title = "unnamed window";
}
if (DEBUG_ZOMBIES > 1){
printf("Retained <%s>. Count is: %lu\n", title, [self retainCount]);
}
return result;
}
- (id) autorelease
{
static int xcount = 0;
id result = [super autorelease];
const char *title = [[self title] UTF8String];
if (title == nil) {
title = "unnamed window";
}
if (DEBUG_ZOMBIES > 1){
printf("Autoreleased <%s>. Count is %lu\n", title, [self retainCount]);
}
return result;
}
- (oneway void) release {
const char *title = [[self title] UTF8String];
if (title == nil) {
title = "unnamed window";
}
if (DEBUG_ZOMBIES > 1){
printf("Releasing <%s>. Count is %lu\n", title, [self retainCount]);
}
[super release];
}
- (void) dealloc {
const char *title = [[self title] UTF8String];
if (title == nil) {
title = "unnamed window";
}
if (DEBUG_ZOMBIES > 0){
printf(">>>> Freeing <%s>. Count is %lu\n", title, [self retainCount]);
}
[super dealloc];
}
#endif
@end
#pragma mark -
@@ -464,28 +561,18 @@ static TkWindow*
FrontWindowAtPoint(
int x, int y)
{
NSPoint p = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
NSWindow *win = nil;
NSInteger windowCount;
NSInteger *windowNumbers;
NSArray *windows = [NSApp orderedWindows];
TkWindow *front = NULL;
NSCountWindows(&windowCount);
if (windowCount) {
windowNumbers = (NSInteger *) ckalloc(windowCount * sizeof(NSInteger));
NSWindowList(windowCount, windowNumbers);
for (NSInteger index = 0; index < windowCount; index++) {
NSWindow *w = [NSApp windowWithWindowNumber:windowNumbers[index]];
for (NSWindow *w in windows) {
if (w && NSMouseInRect(p, [w frame], NO)) {
win = w;
front = TkMacOSXGetTkWindow(w);
break;
}
}
ckfree((char *) windowNumbers);
}
return (win ? TkMacOSXGetTkWindow(win) : NULL);
return front;
}
/*
*----------------------------------------------------------------------
@@ -681,6 +768,7 @@ TkWmMapWindow(
*/
XMapWindow(winPtr->display, winPtr->window);
}
/*
@@ -703,7 +791,7 @@ TkWmMapWindow(
void
TkWmUnmapWindow(
TkWindow *winPtr) /* Top-level window that's about to be
* mapped. */
* unmapped. */
{
XUnmapWindow(winPtr->display, winPtr->window);
}
@@ -786,17 +874,45 @@ TkWmDeadWindow(
*/
NSWindow *window = wmPtr->window;
if (window && !Tk_IsEmbedded(winPtr) ) {
[[window parentWindow] removeChildWindow:window];
NSWindow *parent = [window parentWindow];
if (parent) {
[parent removeChildWindow:window];
}
[window close];
TkMacOSXUnregisterMacWindow(window);
if (winPtr->window) {
((MacDrawable *)winPtr->window)->view = nil;
if (winPtr->window) {
((MacDrawable *) winPtr->window)->view = nil;
}
#if DEBUG_ZOMBIES > 0
{
const char *title = [[window title] UTF8String];
if (title == nil) {
title = "unnamed window";
}
printf(">>>> Closing <%s>. Count is: %lu\n", title, [window retainCount]);
}
TkMacOSXMakeCollectableAndRelease(wmPtr->window);
}
#endif
[window release];
wmPtr->window = NULL;
ckfree((char *) wmPtr);
/* Activate the highest window left on the screen. */
NSArray *windows = [NSApp orderedWindows];
if ( [windows count] > 0 ) {
NSWindow *front = [windows objectAtIndex:0];
if ( front && [front canBecomeKeyWindow] ) {
[front makeKeyAndOrderFront:NSApp];
}
}
[NSApp _resetAutoreleasePool];
#if DEBUG_ZOMBIES > 0
fprintf(stderr, "================= Pool dump ===================\n");
[NSAutoreleasePool showPools];
#endif
}
ckfree((char *)wmPtr);
winPtr->wmInfoPtr = NULL;
}
@@ -1652,8 +1768,8 @@ WmForgetCmd(
MacDrawable *macWin;
Tk_MakeWindowExist(winPtr);
Tk_MakeWindowExist(winPtr->parentPtr);
Tk_MakeWindowExist(frameWin);
Tk_MakeWindowExist((Tk_Window)winPtr->parentPtr);
macWin = (MacDrawable *) winPtr->window;
@@ -2403,7 +2519,6 @@ WmManageCmd(
register Tk_Window frameWin = (Tk_Window)winPtr;
register WmInfo *wmPtr = winPtr->wmInfoPtr;
char *oldClass = (char*)Tk_Class(frameWin);
if (!Tk_IsTopLevel(frameWin)) {
MacDrawable *macWin = (MacDrawable *) winPtr->window;
@@ -4997,7 +5112,7 @@ TkUnsupported1ObjCmd(
};
Tk_Window tkwin = clientData;
TkWindow *winPtr;
int index;
int index, i;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?");
@@ -5006,56 +5121,40 @@ TkUnsupported1ObjCmd(
/* Iterate through objc/objv to set correct background color and toggle opacity of window. */
int i;
for (i= 0; i < objc; i++) {
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*black*") == 1) {
colorName = [NSColor blackColor]; // use #000000 in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*dark*") == 1) {
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*black*")) {
colorName = [NSColor blackColor]; // use #000000 in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*dark*")) {
colorName = [NSColor darkGrayColor]; //use #545454 in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*light*") == 1) {
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*light*")) {
colorName = [NSColor lightGrayColor]; //use #ababab in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*white*")) {
colorName = [NSColor whiteColor]; //use #ffffff in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "gray*")) {
colorName = [NSColor grayColor]; //use #7f7f7f in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*red*")) {
colorName = [NSColor redColor]; //use #ff0000 in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*green*")) {
colorName = [NSColor greenColor]; //use #00ff00 in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*blue*")) {
colorName = [NSColor blueColor]; //use #0000ff in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*cyan*")) {
colorName = [NSColor cyanColor]; //use #00ffff in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*yellow*")) {
colorName = [NSColor yellowColor]; //use #ffff00 in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*magenta*")) {
colorName = [NSColor magentaColor]; //use #ff00ff in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*orange*")) {
colorName = [NSColor orangeColor]; //use #ff8000 in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*purple*")) {
colorName = [NSColor purpleColor]; //use #800080 in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*brown*")){
colorName = [NSColor brownColor]; //use #996633 in Tk scripts to match
} else if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*clear*")) {
colorName = [NSColor clearColor]; //use systemTransparent in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*white*") == 1) {
colorName = [NSColor whiteColor]; //use #ffffff in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "gray*") == 1) {
colorName = [NSColor grayColor]; //use #7f7f7f in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*red*") == 1) {
colorName = [NSColor redColor]; //use #ff0000 in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*green*") == 1) {
colorName = [NSColor greenColor]; //use #00ff00 in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*blue*") == 1) {
colorName = [NSColor blueColor]; //use #0000ff in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*cyan*") == 1) {
colorName = [NSColor cyanColor]; //use #00ffff in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*yellow*") == 1) {
colorName = [NSColor yellowColor]; //use #ffff00 in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*magenta*") == 1) {
colorName = [NSColor magentaColor]; //use #ff00ff in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*orange*") == 1) {
colorName = [NSColor orangeColor]; //use #ff8000 in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*purple*") == 1) {
colorName = [NSColor purpleColor]; //use #800080 in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*brown*") == 1){
colorName = [NSColor brownColor]; //use #996633 in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*clear*") == 1) {
colorName = [NSColor clearColor]; //use systemTransparent in Tk scripts to match
}
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*opacity*") == 1) {
opaqueTag=@"YES";
if (Tcl_StringMatch(Tcl_GetString(objv[i]), "*opacity*")) {
opaqueTag = YES;
}
}
@@ -5174,22 +5273,22 @@ WmWinStyle(
{ "moveToActiveSpace", tkMoveToActiveSpaceAttribute },
{ "nonActivating", tkNonactivatingPanelAttribute },
{ "hud", tkHUDWindowAttribute },
{ "black", NULL },
{ "dark", NULL },
{ "light", NULL },
{ "gray", NULL },
{ "red", NULL },
{ "green", NULL },
{ "blue", NULL },
{ "cyan", NULL },
{ "yellow", NULL },
{ "magenta", NULL },
{ "orange", NULL },
{ "purple", NULL },
{ "brown", NULL },
{ "clear", NULL },
{ "opacity", NULL },
{ "fullscreen", NULL },
{ "black", 0 },
{ "dark", 0 },
{ "light", 0 },
{ "gray", 0 },
{ "red", 0 },
{ "green", 0 },
{ "blue", 0 },
{ "cyan", 0 },
{ "yellow", 0 },
{ "magenta", 0 },
{ "orange", 0 },
{ "purple", 0 },
{ "brown", 0 },
{ "clear", 0 },
{ "opacity", 0 },
{ "fullscreen", 0 },
{ NULL }
};
@@ -5384,7 +5483,6 @@ TkMacOSXMakeRealWindowExist(
* TODO: Here we should handle out of process embedding.
*/
}
WindowClass macClass = wmPtr->macClass;
wmPtr->attributes &= (tkAlwaysValidAttributes |
macClassAttrs[macClass].validAttrs);
@@ -5418,11 +5516,10 @@ TkMacOSXMakeRealWindowExist(
NSWindow *window = [[winClass alloc] initWithContentRect:contentRect
styleMask:styleMask backing:NSBackingStoreBuffered defer:YES];
if (!window) {
Tcl_Panic("couldn't allocate new Mac window");
Tcl_Panic("couldn't allocate new Mac window");
}
TkMacOSXMakeUncollectable(window);
TKContentView *contentView = [[TKContentView alloc]
initWithFrame:NSZeroRect];
initWithFrame:NSZeroRect];
[window setContentView:contentView];
[contentView release];
[window setDelegate:NSApp];
@@ -5447,7 +5544,7 @@ TkMacOSXMakeRealWindowExist(
[window setBackgroundColor: colorName];
}
if (opaqueTag != NULL) {
if (opaqueTag) {
#ifdef TK_GOT_AT_LEAST_SNOW_LEOPARD
[window setOpaque: opaqueTag];
#else
@@ -5457,7 +5554,7 @@ TkMacOSXMakeRealWindowExist(
[window setDocumentEdited:NO];
wmPtr->window = window;
macWin->view = contentView;
macWin->view = window.contentView;
TkMacOSXApplyWindowAttributes(winPtr, window);
NSRect geometry = InitialWindowBounds(winPtr, window);
@@ -5466,7 +5563,6 @@ TkMacOSXMakeRealWindowExist(
geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y +
geometry.size.height);
[window setFrame:geometry display:NO];
TkMacOSXRegisterOffScreenWindow((Window) macWin, window);
macWin->flags |= TK_HOST_EXISTS;
}
@@ -5855,15 +5951,21 @@ TkpChangeFocus(
* didn't originally belong to topLevelPtr's
* application. */
{
/*
* We don't really need to do anything on the Mac. Tk will keep all this
* state for us.
*/
if (winPtr->atts.override_redirect) {
return 0;
}
if (Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr) ){
NSWindow *win = TkMacOSXDrawableWindow(winPtr->window);
TkWmRestackToplevel(winPtr, Above, NULL);
if (force ) {
[NSApp activateIgnoringOtherApps:YES];
}
if ( win && [win canBecomeKeyWindow] ) {
[win makeKeyAndOrderFront:NSApp];
}
}
/*
* Remember the current serial number for the X server and issue a dummy
* server request. This marks the position at which we changed the focus,
@@ -5880,7 +5982,7 @@ TkpChangeFocus(
* WmStackorderToplevelWrapperMap --
*
* This procedure will create a table that maps the reparent wrapper X id
* for a toplevel to the TkWindow structure that is wraps. Tk keeps track
* for a toplevel to the TkWindow structure that it wraps. Tk keeps track
* of a mapping from the window X id to the TkWindow structure but that
* does us no good here since we only get the X id of the wrapper window.
* Only those toplevel windows that are mapped have a position in the
@@ -5939,12 +6041,10 @@ TkWindow **
TkWmStackorderToplevel(
TkWindow *parentPtr) /* Parent toplevel window. */
{
TkWindow *childWinPtr, **windows, **window_ptr;
TkWindow *childWinPtr, **windows, **windowPtr;
Tcl_HashTable table;
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
NSInteger windowCount;
NSInteger *windowNumbers;
/*
* Map mac windows to a TkWindow of the wrapped toplevel.
@@ -5971,31 +6071,26 @@ TkWmStackorderToplevel(
goto done;
}
NSCountWindows(&windowCount);
NSArray *macWindows = [NSApp orderedWindows];
NSInteger windowCount = [macWindows count];
if (!windowCount) {
ckfree((char *) windows);
ckfree((char *)windows);
windows = NULL;
} else {
window_ptr = windows + table.numEntries;
*window_ptr-- = NULL;
windowNumbers = (NSInteger*)ckalloc(windowCount * sizeof(NSInteger));
NSWindowList(windowCount, windowNumbers);
for (NSInteger index = 0; index < windowCount; index++) {
NSWindow *w = [NSApp windowWithWindowNumber:windowNumbers[index]];
if (w) {
hPtr = Tcl_FindHashEntry(&table, (char*) w);
if (hPtr != NULL) {
childWinPtr = Tcl_GetHashValue(hPtr);
*window_ptr-- = childWinPtr;
}
windowPtr = windows + table.numEntries;
*windowPtr-- = NULL;
for (NSWindow *w in macWindows) {
hPtr = Tcl_FindHashEntry(&table, (char*) w);
if (hPtr != NULL) {
childWinPtr = Tcl_GetHashValue(hPtr);
*windowPtr-- = childWinPtr;
}
}
if (window_ptr != (windows-1)) {
if (windowPtr != windows-1) {
Tcl_Panic("num matched toplevel windows does not equal num "
"children");
"children");
}
ckfree((char *) windowNumbers);
}
done:
@@ -6557,7 +6652,6 @@ RemapWindows(
MacDrawable *parentWin)
{
TkWindow *childPtr;
/*
* Remove the OS specific window. It will get rebuilt when the window gets
* Mapped.

View File

@@ -9,6 +9,7 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright 2014 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -141,7 +142,7 @@ TkpOpenDisplay(
static NSRect maxBounds = {{0, 0}, {0, 0}};
static char vendor[25] = "";
NSArray *cgVers;
NSAutoreleasePool *pool;
NSAutoreleasePool *pool = [NSAutoreleasePool new];
if (gMacDisplay != NULL) {
if (strcmp(gMacDisplay->display->display_name, display_name) == 0) {
@@ -165,7 +166,6 @@ TkpOpenDisplay(
display->default_screen = 0;
display->display_name = (char *) macScreenName;
pool = [NSAutoreleasePool new];
cgVers = [[[NSBundle bundleWithIdentifier:@"com.apple.CoreGraphics"]
objectForInfoDictionaryKey:@"CFBundleShortVersionString"]
componentsSeparatedByString:@"."];
@@ -176,12 +176,25 @@ TkpOpenDisplay(
display->proto_minor_version = [[cgVers objectAtIndex:2] integerValue];
}
if (!vendor[0]) {
snprintf(vendor, sizeof(vendor), "Apple AppKit %s %g",
([NSGarbageCollector defaultCollector] ? "GC" : "RR"),
snprintf(vendor, sizeof(vendor), "Apple AppKit %g",
NSAppKitVersionNumber);
}
display->vendor = vendor;
Gestalt(gestaltSystemVersion, (SInt32 *) &display->release);
{
int major, minor, patch;
#if MAC_OS_X_VERSION_MIN_REQUIRED < 10100
Gestalt(gestaltSystemVersionMajor, (SInt32*)&major);
Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor);
Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch);
#else
NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
major = systemVersion.majorVersion;
minor = systemVersion.minorVersion;
patch = systemVersion.patchVersion;
#endif
display->release = major << 16 | minor << 8 | patch;
}
/*
* These screen bits never change
@@ -809,7 +822,6 @@ XCreateImage(
int bytes_per_line)
{
XImage *ximage;
display->request++;
ximage = (XImage *) ckalloc(sizeof(XImage));
@@ -819,6 +831,7 @@ XCreateImage(
ximage->xoffset = offset;
ximage->format = format;
ximage->data = data;
ximage->obdata = NULL;
if (format == ZPixmap) {
ximage->bits_per_pixel = 32;
@@ -850,7 +863,6 @@ XCreateImage(
ximage->red_mask = 0x00FF0000;
ximage->green_mask = 0x0000FF00;
ximage->blue_mask = 0x000000FF;
ximage->obdata = NULL;
ximage->f.create_image = NULL;
ximage->f.destroy_image = DestroyImage;
ximage->f.get_pixel = ImageGetPixel;
@@ -869,8 +881,9 @@ XCreateImage(
* This function copies data from a pixmap or window into an XImage.
*
* Results:
* Returns a newly allocated image containing the data from the given
* rectangle of the given drawable.
* Returns a newly allocated XImage containing the data from the given
* rectangle of the given drawable, or NULL if the XImage could not be
* constructed.
*
* Side effects:
* None.
@@ -889,60 +902,84 @@ XGetImage(
unsigned long plane_mask,
int format)
{
MacDrawable *macDraw = (MacDrawable *) d;
XImage * imagePtr = NULL;
Pixmap pixmap = (Pixmap) NULL;
Tk_Window win = (Tk_Window) macDraw->winPtr;
GC gc;
char * data = NULL;
int depth = 32;
int offset = 0;
int bitmap_pad = 0;
int bytes_per_line = 0;
NSBitmapImageRep *bitmap_rep;
NSUInteger bitmap_fmt;
XImage * imagePtr = NULL;
char * bitmap = NULL;
char * image_data=NULL;
int depth = 32;
int offset = 0;
int bitmap_pad = 0;
int bytes_per_row = 4*width;
int size;
TkMacOSXDbgMsg("XGetImage");
if (format == ZPixmap) {
if (width > 0 && height > 0) {
/*
* Tk_GetPixmap fails for zero width or height.
*/
pixmap = Tk_GetPixmap(display, d, width, height, depth);
if (width == 0 || height == 0) {
/* This happens all the time.
TkMacOSXDbgMsg("XGetImage: empty image requested");
*/
return NULL;
}
if (win) {
XGCValues values;
gc = Tk_GetGC(win, 0, &values);
} else {
gc = XCreateGC(display, pixmap, 0, NULL);
bitmap_rep = BitmapRepFromDrawableRect(d, x, y,width, height);
bitmap_fmt = [bitmap_rep bitmapFormat];
if ( bitmap_rep == Nil ||
(bitmap_fmt != 0 && bitmap_fmt != 1) ||
[bitmap_rep samplesPerPixel] != 4 ||
[bitmap_rep isPlanar] != 0 ) {
TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
return NULL;
}
if (pixmap) {
CGContextRef context;
XCopyArea(display, d, pixmap, gc, x, y, width, height, 0, 0);
context = ((MacDrawable *) pixmap)->context;
if (context) {
data = CGBitmapContextGetData(context);
bytes_per_line = CGBitmapContextGetBytesPerRow(context);
NSSize image_size = NSMakeSize(width, height);
NSImage* ns_image = [[NSImage alloc]initWithSize:image_size];
[ns_image addRepresentation:bitmap_rep];
/* Assume premultiplied nonplanar data with 4 bytes per pixel.*/
if ( [bitmap_rep isPlanar ] == 0 &&
[bitmap_rep samplesPerPixel] == 4 ) {
bytes_per_row = [bitmap_rep bytesPerRow];
size = bytes_per_row*height;
image_data = (char*)[bitmap_rep bitmapData];
if ( image_data ) {
int row, n, m;
bitmap = ckalloc(size);
/*
Oddly enough, the bitmap has the top row at the beginning,
and the pixels are in BGRA or ABGR format.
*/
if (bitmap_fmt == 0) {
/* BGRA */
for (row=0, n=0; row<height; row++, n+=bytes_per_row) {
for (m=n; m<n+bytes_per_row; m+=4) {
*(bitmap+m) = *(image_data+m+2);
*(bitmap+m+1) = *(image_data+m+1);
*(bitmap+m+2) = *(image_data+m);
*(bitmap+m+3) = *(image_data+m+3);
}
}
} else {
/* ABGR */
for (row=0, n=0; row<height; row++, n+=bytes_per_row) {
for (m=n; m<n+bytes_per_row; m+=4) {
*(bitmap+m) = *(image_data+m+3);
*(bitmap+m+1) = *(image_data+m+2);
*(bitmap+m+2) = *(image_data+m+1);
*(bitmap+m+3) = *(image_data+m);
}
}
}
}
}
if (data) {
if (bitmap) {
imagePtr = XCreateImage(display, NULL, depth, format, offset,
data, width, height, bitmap_pad, bytes_per_line);
/*
* Track Pixmap underlying the XImage in the unused obdata field
* so that we can treat XImages coming from XGetImage specially.
*/
imagePtr->obdata = (XPointer) pixmap;
} else if (pixmap) {
Tk_FreePixmap(display, pixmap);
}
if (!win) {
XFreeGC(display, gc);
(char*)bitmap, width, height, bitmap_pad, bytes_per_row);
[ns_image removeRepresentation:bitmap_rep]; /*releases the rep*/
[ns_image release];
}
} else {
TkMacOSXDbgMsg("Invalid image format");
TkMacOSXDbgMsg("Could not extract image from drawable.");
}
return imagePtr;
}
@@ -968,9 +1005,7 @@ DestroyImage(
XImage *image)
{
if (image) {
if (image->obdata) {
Tk_FreePixmap((Display*) gMacDisplay, (Pixmap) image->obdata);
} else if (image->data) {
if (image->data) {
ckfree(image->data);
}
ckfree((char*) image);

View File

@@ -294,14 +294,14 @@ static Ttk_StateTable TabPositionTable[] = {
* TP30000359-TPXREF116>
*/
static const int TAB_HEIGHT = 10;
static const int TAB_OVERLAP = 10;
static void TabElementSize(
void *clientData, void *elementRecord, Tk_Window tkwin,
int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
*heightPtr = TAB_HEIGHT + TAB_OVERLAP - 1;
GetThemeMetric(kThemeMetricLargeTabHeight, (SInt32 *)heightPtr);
*paddingPtr = Ttk_MakePadding(0, 0, 0, 2);
}
static void TabElementDraw(
@@ -319,7 +319,6 @@ static void TabElementDraw(
.position = Ttk_StateTableLookup(TabPositionTable, state),
};
bounds.size.height += TAB_OVERLAP;
BEGIN_DRAWING(d)
ChkErr(HIThemeDrawTab, &bounds, &info, dc.context, HIOrientation, NULL);
END_DRAWING
@@ -357,8 +356,8 @@ static void PaneElementDraw(
.adornment = kHIThemeTabPaneAdornmentNormal,
};
bounds.origin.y -= TAB_OVERLAP;
bounds.size.height += TAB_OVERLAP;
bounds.origin.y -= kThemeMetricTabFrameOverlap;
bounds.size.height += kThemeMetricTabFrameOverlap;
BEGIN_DRAWING(d)
ChkErr(HIThemeDrawTabPane, &bounds, &info, dc.context, HIOrientation);
END_DRAWING