Update to tk 8.5.19
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 & Ian Reid</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
|
||||
@@ -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 & Ian Reid</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
@@ -72,5 +75,7 @@ Copyright © 2001-2002 Jim Ingham & Ian Reid</string>
|
||||
<true/>
|
||||
<key>OSAScriptingDefinition</key>
|
||||
<string>Wish.sdef</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -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 */,
|
||||
|
||||
@@ -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
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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
/*
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user