diff options
Diffstat (limited to 'macosx')
-rw-r--r-- | macosx/tkMacOSXDraw.c | 54 | ||||
-rw-r--r-- | macosx/tkMacOSXEvent.c | 4 | ||||
-rw-r--r-- | macosx/tkMacOSXInit.c | 408 | ||||
-rw-r--r-- | macosx/tkMacOSXInt.h | 4 | ||||
-rw-r--r-- | macosx/tkMacOSXKeyEvent.c | 75 | ||||
-rw-r--r-- | macosx/tkMacOSXMenus.c | 19 | ||||
-rw-r--r-- | macosx/tkMacOSXSubwindows.c | 349 |
7 files changed, 491 insertions, 422 deletions
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index edf3817..5d254f1 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -7,16 +7,23 @@ * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006 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. * - * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.14 2006/04/11 10:20:33 das Exp $ + * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.15 2006/05/12 18:17:48 das Exp $ */ #include "tkMacOSXInt.h" #include "tkMacOSXDebug.h" +/* +#ifdef TK_MAC_DEBUG +#define TK_MAC_DEBUG_DRAWING +#endif +*/ + #ifndef PI # define PI 3.14159265358979323846 #endif @@ -272,16 +279,12 @@ XCopyPlane( srcPort = TkMacOSXGetDrawablePort(src); dstPort = TkMacOSXGetDrawablePort(dst); - if (tmpRgn == NULL) { - tmpRgn = NewRgn(); - } display->request++; GetGWorld(&saveWorld, &saveDevice); SetGWorld(dstPort, NULL); TkMacOSXSetUpClippingRgn(dst); - srcBit = GetPortBitMapForCopyBits(srcPort); dstBit = GetPortBitMapForCopyBits(dstPort); SetRect(&srcRect, (short) (srcDraw->xOff + src_x), @@ -395,12 +398,9 @@ TkPutImage( int i, j; BitMap bitmap; char *newData = NULL; - Rect destRect, srcRect; + Rect destRect, srcRect, *destPtr, *srcPtr; destPort = TkMacOSXGetDrawablePort(d); - SetRect(&destRect, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, - dstDraw->xOff + dest_x + width, dstDraw->yOff + dest_y + height); - SetRect(&srcRect, src_x, src_y, src_x + width, src_y + height); display->request++; GetGWorld(&saveWorld, &saveDevice); @@ -408,12 +408,32 @@ TkPutImage( TkMacOSXSetUpClippingRgn(d); + srcPtr = &srcRect; + SetRect(srcPtr, src_x, src_y, src_x + width, src_y + height); + if (tkPictureIsOpen) { + /* + * When rendering into a picture, after a call to "OpenCPicture" + * the clipping is seriously WRONG and also INCONSISTENT with the + * clipping for single plane bitmaps. + * To circumvent this problem, we clip to the whole window + */ + + Rect clpRect; + GetPortBounds(destPort,&clpRect); + ClipRect(&clpRect); + destPtr = srcPtr; + } else { + destPtr = &destRect; + SetRect(destPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, + dstDraw->xOff + dest_x + width, dstDraw->yOff + dest_y + height); + } + if (image->obdata) { /* Image from XGetImage, copy from containing GWorld directly */ GWorldPtr srcPort = TkMacOSXGetDrawablePort((Drawable)image->obdata); CopyBits(GetPortBitMapForCopyBits(srcPort), GetPortBitMapForCopyBits(destPort), - &srcRect, &destRect, srcCopy, NULL); + srcPtr, destPtr, srcCopy, NULL); } else if (image->depth == 1) { /* * This code assumes a pixel depth of 1 @@ -448,7 +468,7 @@ TkPutImage( bitmap.rowBytes = image->bytes_per_line; } destBits = GetPortBitMapForCopyBits(destPort); - CopyBits(&bitmap, destBits, &srcRect, &destRect, srcCopy, NULL); + CopyBits(&bitmap, destBits, srcPtr, destPtr, srcCopy, NULL); } else { /* * Color image @@ -479,7 +499,7 @@ TkPutImage( pixmap.rowBytes = image->bytes_per_line | 0x8000; CopyBits((BitMap *) &pixmap, GetPortBitMapForCopyBits(destPort), - &srcRect, &destRect, srcCopy, NULL); + srcPtr, destPtr, srcCopy, NULL); } if (newData != NULL) { @@ -1895,6 +1915,16 @@ TkMacOSXSetUpClippingRgn( TkMacOSXUpdateClipRgn(macDraw->winPtr); } +#if defined(TK_MAC_DEBUG) && defined(TK_MAC_DEBUG_DRAWING) + TkMacOSXInitNamedDebugSymbol(HIToolbox, int, QDDebugFlashRegion, + CGrafPtr port, RgnHandle region); + if (QDDebugFlashRegion) { + CGrafPtr grafPtr = TkMacOSXGetDrawablePort(drawable); + /* Carbon-internal region flashing SPI (c.f. Technote 2124) */ + QDDebugFlashRegion(grafPtr, macDraw->clipRgn); + } +#endif /* TK_MAC_DEBUG_DRAWING */ + /* * When a menu is up, the Mac does not expect drawing to occur and * does not clip out the menu. We have to do it ourselves. This diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c index 5f479b0..40abc96 100644 --- a/macosx/tkMacOSXEvent.c +++ b/macosx/tkMacOSXEvent.c @@ -5,11 +5,12 @@ * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2005-2006 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. * - * RCS: @(#) $Id: tkMacOSXEvent.c,v 1.10 2006/04/11 10:22:34 das Exp $ + * RCS: @(#) $Id: tkMacOSXEvent.c,v 1.11 2006/05/12 18:17:48 das Exp $ */ #include "tkMacOSXInt.h" @@ -228,6 +229,7 @@ TkMacOSXProcessCommandEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) command.menu.menuItemIndex); } } + statusPtr->stopProcessing = 1; return 1; } } diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index 269dce0..e12a56e 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -6,11 +6,12 @@ * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2005-2006 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. * - * RCS: @(#) $Id: tkMacOSXInit.c,v 1.20 2006/04/11 10:19:51 das Exp $ + * RCS: @(#) $Id: tkMacOSXInit.c,v 1.21 2006/05/12 18:17:48 das Exp $ */ #include "tkMacOSXInt.h" @@ -88,7 +89,7 @@ Tcl_Encoding TkMacOSXCarbonEncoding = NULL; /* * If the App is in an App package, then we want to add the Scripts - * directory to the auto_path. + * directory to the auto_path. */ static char scriptPath[PATH_MAX + 1] = ""; @@ -98,7 +99,7 @@ static char scriptPath[PATH_MAX + 1] = ""; * TkpInit -- * * Performs Mac-specific interpreter initialization related to the - * tk_library variable. + * tk_library variable. * * Results: * Returns a standard Tcl result. Leaves an error message or result @@ -130,16 +131,17 @@ TkpInit(interp) char *encodingStr = NULL; int i; - tkMacOSXInitialized = true; + tkMacOSXInitialized = true; + + TkMacOSXInitAppleEvents(interp); + TkMacOSXInitCarbonEvents(interp); + TkMacOSXInitMenus(interp); + TkMacOSXUseAntialiasedText(interp, -1); + TkMacOSXInitCGDrawing(interp, TRUE, 3); + TkMacOSXInitKeyboard(interp); - TkMacOSXInitAppleEvents(interp); - TkMacOSXInitCarbonEvents(interp); - TkMacOSXInitMenus(interp); - TkMacOSXUseAntialiasedText(interp, -1); - TkMacOSXInitCGDrawing(interp, TRUE, 3); - encoding = CFStringGetSystemEncoding(); - + for (i = 0; scriptMap[i].strKey != NULL; i++) { if (scriptMap[i].numKey == encoding) { encodingStr = scriptMap[i].strKey; @@ -149,178 +151,178 @@ TkpInit(interp) if (encodingStr == NULL) { encodingStr = "macRoman"; } - + TkMacOSXCarbonEncoding = Tcl_GetEncoding (NULL, encodingStr); if (TkMacOSXCarbonEncoding == NULL) { TkMacOSXCarbonEncoding = Tcl_GetEncoding (NULL, NULL); } - - /* - * When Tk is in a framework, force tcl_findLibrary to look in the - * framework scripts directory. - * FIXME: Should we come up with a more generic way of doing this? - */ - + + /* + * When Tk is in a framework, force tcl_findLibrary to look in the + * framework scripts directory. + * FIXME: Should we come up with a more generic way of doing this? + */ + #ifdef TK_FRAMEWORK - if (Tcl_MacOSXOpenVersionedBundleResources(interp, - "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 1, PATH_MAX, tkLibPath) != TCL_OK) + if (Tcl_MacOSXOpenVersionedBundleResources(interp, + "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 1, PATH_MAX, tkLibPath) != TCL_OK) #endif - { - /* Tk.framework not found, check if resource file is open */ - Handle rsrc = Get1NamedResource('CURS', "\phand"); - if (rsrc) { - ReleaseResource(rsrc); - } else { + { + /* Tk.framework not found, check if resource file is open */ + Handle rsrc = Get1NamedResource('CURS', "\phand"); + if (rsrc) { + ReleaseResource(rsrc); + } else { #ifndef __LP64__ - const struct mach_header *image; - char *data = NULL; - uint32_t size; - int fd = -1; - char fileName[L_tmpnam + 15]; - uint32_t i, n; - - /* Get resource data from __tk_rsrc section of tk library file */ - n = _dyld_image_count(); - for (i = 0; i < n; i++) { - image = _dyld_get_image_header(i); - if (image) { - data = getsectdatafromheader(image, SEG_TEXT, "__tk_rsrc", &size); - if (data) { - data += _dyld_get_image_vmaddr_slide(i); - break; - } - } - } - while (data) { - OSStatus err; - FSRef ref; - SInt16 refNum; - - /* Write resource data to temporary file and open it */ - strcpy(fileName, P_tmpdir); - if (fileName[strlen(fileName) - 1] != '/') { - strcat(fileName, "/"); - } - strcat(fileName, "tkMacOSX_XXXXXX"); - fd = mkstemp(fileName); - if (fd == -1) break; - fcntl(fd, F_SETFD, FD_CLOEXEC); - if (write(fd, data, size) == -1) break; - err = FSPathMakeRef((unsigned char*)fileName, &ref, NULL); - if (err != noErr) break; - err = FSOpenResourceFile(&ref, 0, NULL, fsRdPerm, &refNum); + const struct mach_header *image; + char *data = NULL; + uint32_t size; + int fd = -1; + char fileName[L_tmpnam + 15]; + uint32_t i, n; + + /* Get resource data from __tk_rsrc section of tk library file */ + n = _dyld_image_count(); + for (i = 0; i < n; i++) { + image = _dyld_get_image_header(i); + if (image) { + data = getsectdatafromheader(image, SEG_TEXT, "__tk_rsrc", &size); + if (data) { + data += _dyld_get_image_vmaddr_slide(i); + break; + } + } + } + while (data) { + OSStatus err; + FSRef ref; + SInt16 refNum; + + /* Write resource data to temporary file and open it */ + strcpy(fileName, P_tmpdir); + if (fileName[strlen(fileName) - 1] != '/') { + strcat(fileName, "/"); + } + strcat(fileName, "tkMacOSX_XXXXXX"); + fd = mkstemp(fileName); + if (fd == -1) break; + fcntl(fd, F_SETFD, FD_CLOEXEC); + if (write(fd, data, size) == -1) break; + err = FSPathMakeRef((unsigned char*)fileName, &ref, NULL); + if (err != noErr) break; + err = FSOpenResourceFile(&ref, 0, NULL, fsRdPerm, &refNum); #ifdef TK_MAC_DEBUG - if (err != noErr) fprintf(stderr,"FSOpenResourceFile error %ld\n",err); + if (err != noErr) fprintf(stderr,"FSOpenResourceFile error %ld\n",err); #endif - break; - } - if (fd != -1) { - unlink(fileName); - close(fd); - } + break; + } + if (fd != -1) { + unlink(fileName); + close(fd); + } #endif /* __LP64__ */ - } - } - - /* - * If we don't have a TTY and stdin is a special character file of length 0, - * (e.g. /dev/null, which is what Finder sets when double clicking Wish) - * then use the Tk based console interpreter. - */ - - /* REMOVE ME: Close stdin & stdout for remote debugging otherwise we - * will fight with gdb for stdin & stdout - */ - - if (getenv ("XCNOSTDIN") != NULL) { - close (0); - close (1); - } - - if (!isatty(0)) { - struct stat st; - if (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0)) { - Tk_InitConsoleChannels(interp); - Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN)); - Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT)); - Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR)); - /* Only show the console if we don't have a startup script */ - if (Tcl_GetStartupScript(NULL) == NULL) { - Tcl_SetVar(interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY); - } - if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) { - return TCL_ERROR; - } - } - } + } + } + + /* + * If we don't have a TTY and stdin is a special character file of length 0, + * (e.g. /dev/null, which is what Finder sets when double clicking Wish) + * then use the Tk based console interpreter. + */ + + /* REMOVE ME: Close stdin & stdout for remote debugging otherwise we + * will fight with gdb for stdin & stdout + */ + + if (getenv ("XCNOSTDIN") != NULL) { + close (0); + close (1); + } + + if (!isatty(0)) { + struct stat st; + if (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0)) { + Tk_InitConsoleChannels(interp); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN)); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT)); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR)); + /* Only show the console if we don't have a startup script */ + if (Tcl_GetStartupScript(NULL) == NULL) { + Tcl_SetVar(interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY); + } + if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) { + return TCL_ERROR; + } + } + } #if MAC_OSX_TK_USE_CPS_SPI - /* - * If we are loaded into an executable that is not a bundled application, - * the window server does not let us come to the foreground. - * For such an executable, we attempt to use an undocumented SPI to - * notify the window server that we are now a full GUI application. - */ - { - /* Check whether we are a bundled executable: */ - int bundledExecutable = 0; - CFBundleRef bundleRef = CFBundleGetMainBundle(); - CFURLRef bundleUrl = NULL; - if (bundleRef) { - bundleUrl = CFBundleCopyBundleURL(bundleRef); - } - if (bundleUrl) { - /* - * A bundled executable is two levels down from its main bundle - * directory (e.g. Wish.app/Contents/MacOS/Wish), whereas - * an unbundled executable's main bundle directory is just - * the directory containing the executable. - * So to check whether we are bundled, we delete the last three - * path components of the executable's url and compare the - * resulting url with the main bundle url. - */ - int j = 3; - CFURLRef url = CFBundleCopyExecutableURL(bundleRef); - while (url && j--) { - CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(NULL, url); - CFRelease(url); - url = parent; - } - if (url) { - bundledExecutable = CFEqual(bundleUrl, url); - CFRelease(url); - } - CFRelease(bundleUrl); - } - - /* If we are not a bundled executable, attempt to use the CPS SPI: */ - if (!bundledExecutable) { - /* - * Load the CPS SPI symbol dynamically, so that we don't break - * if it every disappears or changes its name. - */ - TkMacOSXInitNamedSymbol(CoreGraphics, OSErr, \ - CPSEnableForegroundOperation, ProcessSerialNumberPtr); - if (CPSEnableForegroundOperation) { - ProcessSerialNumber psn = { 0, kCurrentProcess }; - /* - * Let the window server know that we are a foregroundable app - */ - CPSEnableForegroundOperation(&psn); - } - } - } + /* + * If we are loaded into an executable that is not a bundled application, + * the window server does not let us come to the foreground. + * For such an executable, we attempt to use an undocumented SPI to + * notify the window server that we are now a full GUI application. + */ + { + /* Check whether we are a bundled executable: */ + int bundledExecutable = 0; + CFBundleRef bundleRef = CFBundleGetMainBundle(); + CFURLRef bundleUrl = NULL; + if (bundleRef) { + bundleUrl = CFBundleCopyBundleURL(bundleRef); + } + if (bundleUrl) { + /* + * A bundled executable is two levels down from its main bundle + * directory (e.g. Wish.app/Contents/MacOS/Wish), whereas + * an unbundled executable's main bundle directory is just + * the directory containing the executable. + * So to check whether we are bundled, we delete the last three + * path components of the executable's url and compare the + * resulting url with the main bundle url. + */ + int j = 3; + CFURLRef url = CFBundleCopyExecutableURL(bundleRef); + while (url && j--) { + CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(NULL, url); + CFRelease(url); + url = parent; + } + if (url) { + bundledExecutable = CFEqual(bundleUrl, url); + CFRelease(url); + } + CFRelease(bundleUrl); + } + + /* If we are not a bundled executable, attempt to use the CPS SPI: */ + if (!bundledExecutable) { + /* + * Load the CPS SPI symbol dynamically, so that we don't break + * if it every disappears or changes its name. + */ + TkMacOSXInitNamedSymbol(CoreGraphics, OSErr, \ + CPSEnableForegroundOperation, ProcessSerialNumberPtr); + if (CPSEnableForegroundOperation) { + ProcessSerialNumber psn = { 0, kCurrentProcess }; + /* + * Let the window server know that we are a foregroundable app + */ + CPSEnableForegroundOperation(&psn); + } + } + } #endif /* MAC_OSX_TK_USE_CPS_SPI */ } if (tkLibPath[0] != '\0') { - Tcl_SetVar(interp, "tk_library", tkLibPath, TCL_GLOBAL_ONLY); + Tcl_SetVar(interp, "tk_library", tkLibPath, TCL_GLOBAL_ONLY); } if (scriptPath[0] != '\0') { - Tcl_SetVar(interp, "auto_path", scriptPath, - TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE); + Tcl_SetVar(interp, "auto_path", scriptPath, + TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE); } - + return Tcl_Eval(interp, initScript); } @@ -351,12 +353,12 @@ TkpGetAppName(interp, namePtr) name = Tcl_GetVar(interp, "argv0", TCL_GLOBAL_ONLY); if ((name == NULL) || (*name == 0)) { - name = "tk"; + name = "tk"; } else { - p = strrchr(name, '/'); - if (p != NULL) { - name = p+1; - } + p = strrchr(name, '/'); + if (p != NULL) { + name = p+1; + } } Tcl_DStringAppend(namePtr, name, -1); } @@ -385,10 +387,10 @@ TkpDisplayWarning(msg, title) { Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel) { - Tcl_WriteChars(errChannel, title, -1); - Tcl_WriteChars(errChannel, ": ", 2); - Tcl_WriteChars(errChannel, msg, -1); - Tcl_WriteChars(errChannel, "\n", 1); + Tcl_WriteChars(errChannel, title, -1); + Tcl_WriteChars(errChannel, ": ", 2); + Tcl_WriteChars(errChannel, msg, -1); + Tcl_WriteChars(errChannel, "\n", 1); } } @@ -404,7 +406,7 @@ TkpDisplayWarning(msg, title) * Scripts folder to the auto_path. If we don't find the startup * script, we just bag it, assuming the user is starting up some * other way. - * + * * Results: * None. * @@ -418,33 +420,33 @@ MODULE_SCOPE void TkMacOSXDefaultStartupScript(void) { CFBundleRef bundleRef; - + bundleRef = CFBundleGetMainBundle(); - + if (bundleRef != NULL) { - CFURLRef appMainURL; - appMainURL = CFBundleCopyResourceURL(bundleRef, - CFSTR("AppMain"), - CFSTR("tcl"), - CFSTR("Scripts")); - - if (appMainURL != NULL) { - CFURLRef scriptFldrURL; - char startupScript[PATH_MAX + 1]; - - if (CFURLGetFileSystemRepresentation (appMainURL, true, - (unsigned char*) startupScript, PATH_MAX)) { - Tcl_SetStartupScript(Tcl_NewStringObj(startupScript, -1), NULL); - scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent( - NULL, appMainURL); - if (scriptFldrURL != NULL) { - CFURLGetFileSystemRepresentation(scriptFldrURL, - true, (unsigned char*) scriptPath, PATH_MAX); - CFRelease(scriptFldrURL); - } - } - CFRelease(appMainURL); - } + CFURLRef appMainURL; + appMainURL = CFBundleCopyResourceURL(bundleRef, + CFSTR("AppMain"), + CFSTR("tcl"), + CFSTR("Scripts")); + + if (appMainURL != NULL) { + CFURLRef scriptFldrURL; + char startupScript[PATH_MAX + 1]; + + if (CFURLGetFileSystemRepresentation (appMainURL, true, + (unsigned char*) startupScript, PATH_MAX)) { + Tcl_SetStartupScript(Tcl_NewStringObj(startupScript, -1), NULL); + scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent( + NULL, appMainURL); + if (scriptFldrURL != NULL) { + CFURLGetFileSystemRepresentation(scriptFldrURL, + true, (unsigned char*) scriptPath, PATH_MAX); + CFRelease(scriptFldrURL); + } + } + CFRelease(appMainURL); + } } } @@ -478,13 +480,13 @@ TkMacOSXGetNamedSymbol(const char* module, const char* symbol) nsSymbol = NSLookupAndBindSymbolWithHint(symbol, module); } } else { - if(NSIsSymbolNameDefined(symbol)) { - nsSymbol = NSLookupAndBindSymbol(symbol); - } + if(NSIsSymbolNameDefined(symbol)) { + nsSymbol = NSLookupAndBindSymbol(symbol); + } } if(nsSymbol) { return NSAddressOfSymbol(nsSymbol); } else { - return NULL; + return NULL; } } diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index 2bc85e4..f57a5e9 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -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. * - * RCS: @(#) $Id: tkMacOSXInt.h,v 1.16 2006/04/28 06:02:48 das Exp $ + * RCS: @(#) $Id: tkMacOSXInt.h,v 1.17 2006/05/12 18:17:48 das Exp $ */ #ifndef _TKMACINT @@ -66,7 +66,6 @@ typedef struct TkMacOSXWindowList { #define TK_CLIP_INVALID 2 #define TK_HOST_EXISTS 4 #define TK_DRAWN_UNDER_MENU 8 -#define TK_MAPPED_IN_PARENT 16 /* * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags @@ -163,6 +162,7 @@ MODULE_SCOPE void TkMacOSXDisplayChanged(Display *display); MODULE_SCOPE int TkMacOSXUseAntialiasedText(Tcl_Interp *interp, int enable); MODULE_SCOPE void TkMacOSXInitCarbonEvents(Tcl_Interp *interp); MODULE_SCOPE int TkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable, int antiAlias); +MODULE_SCOPE void TkMacOSXInitKeyboard(Tcl_Interp *interp); MODULE_SCOPE void TkMacOSXDefaultStartupScript(void); MODULE_SCOPE int TkMacOSXGenerateFocusEvent( Window window, int activeFlag); MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr); diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 17923e8..0201054 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -4,7 +4,11 @@ * This file implements functions that decode & handle keyboard events * on MacOS X. * - * Copyright 2001, Apple Computer, Inc. + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006 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. * * The following terms apply to all files originating from Apple * Computer, Inc. ("Apple") and associated with the software @@ -50,7 +54,7 @@ * software in accordance with the terms specified in this * license. * - * RCS: @(#) $Id: tkMacOSXKeyEvent.c,v 1.14 2006/04/28 06:02:49 das Exp $ + * RCS: @(#) $Id: tkMacOSXKeyEvent.c,v 1.15 2006/05/12 18:17:48 das Exp $ */ #include "tkMacOSXInt.h" @@ -173,24 +177,23 @@ TkMacOSXProcessKeyboardEvent( */ if ((eventPtr->eKind == kEventRawKeyDown - || eventPtr->eKind == kEventRawKeyRepeat) - && IsMenuKeyEvent(NULL, eventPtr->eventRef, - kMenuEventQueryOnly, &menuRef, &menuItemIndex)) { - MenuCommand menuCmd; - - GetMenuItemCommandID (menuRef, menuItemIndex, &menuCmd); - - switch (menuCmd) { - case kHICommandHide: - case kHICommandHideOthers: - case kHICommandShowAll: - case kHICommandPreferences: - statusPtr->stopProcessing = 0; - return 0; /* TODO: may not be on event on queue. */ - break; - default: - break; - } + || eventPtr->eKind == kEventRawKeyRepeat) + && IsMenuKeyEvent(tkAppleMenu, eventPtr->eventRef, + kMenuEventQueryOnly, &menuRef, &menuItemIndex)) { + MenuCommand menuCmd; + + GetMenuItemCommandID (menuRef, menuItemIndex, &menuCmd); + switch (menuCmd) { + case kHICommandHide: + case kHICommandHideOthers: + case kHICommandShowAll: + case kHICommandPreferences: + statusPtr->stopProcessing = 0; + return 0; /* TODO: may not be on event on queue. */ + break; + default: + break; + } } status = GetEventParameter(eventPtr->eventRef, @@ -1187,7 +1190,7 @@ XUngrabKeyboard( { gKeyboardWinPtr = NULL; } - + /* *---------------------------------------------------------------------- * @@ -1204,7 +1207,7 @@ TkMacOSXGetCapture() { return gGrabWinPtr; } - + /* *---------------------------------------------------------------------- * @@ -1233,7 +1236,7 @@ TkpSetCapture( } gGrabWinPtr = (Tk_Window) winPtr; } - + /* *---------------------------------------------------------------------- * @@ -1260,3 +1263,29 @@ Tk_SetCaretPos(tkwin, x, y, height) int height; { } + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInitKeyboard -- + * + * This procedure initializes the keyboard layout. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE void +TkMacOSXInitKeyboard ( + Tcl_Interp *interp) +{ + Ptr resource; + TextEncoding encoding; + + GetKeyboardLayout(&resource,&encoding); +} diff --git a/macosx/tkMacOSXMenus.c b/macosx/tkMacOSXMenus.c index ab1926e..b5c319c 100644 --- a/macosx/tkMacOSXMenus.c +++ b/macosx/tkMacOSXMenus.c @@ -6,11 +6,12 @@ * * Copyright (c) 1995-1996 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2005-2006 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. * - * RCS: @(#) $Id: tkMacOSXMenus.c,v 1.11 2006/04/28 06:02:49 das Exp $ + * RCS: @(#) $Id: tkMacOSXMenus.c,v 1.12 2006/05/12 18:17:48 das Exp $ */ #include "tkMacOSXInt.h" @@ -192,7 +193,16 @@ TkMacOSXInitMenus( if (TkMacOSXUseMenuID(kHMHelpMenuID) != TCL_OK) { Tcl_Panic("Help menu ID %s is already in use!", kHMHelpMenuID); } - + + /* + * Workarund a Carbon bug with kHICommandPreferences: the first call to + * IsMenuKeyEvent returns false for the preferences menu item key shorcut + * event (even if the corresponding menu item is dynamically enabled by a + * kEventCommandUpdateStatus handler), unless the kHICommandPreferences + * menu item has previously been enabled manually. [Bug 1481503] + */ + EnableMenuCommand(NULL, kHICommandPreferences); + DrawMenuBar(); return; } @@ -304,3 +314,8 @@ SourceDialog() Tcl_BackgroundError(gInterp); } } +/* + * Local Variables: + * coding: macintosh; + * End: + */ diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 82ca23c..1ac6579 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -5,11 +5,12 @@ * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006 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. * - * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.12 2006/03/24 14:58:01 das Exp $ + * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.13 2006/05/12 18:17:48 das Exp $ */ #include "tkMacOSXInt.h" @@ -17,6 +18,12 @@ #include "tkMacOSXWm.h" /* +#ifdef TK_MAC_DEBUG +#define TK_MAC_DEBUG_CLIP_REGIONS +#endif +*/ + +/* * Temporary region that can be reused. */ static RgnHandle tmpRgn = NULL; @@ -149,57 +156,6 @@ XDestroyWindow( ckfree((char *) macWin); } } - -/* - *---------------------------------------------------------------------- - * - * FixMappingFlags -- - * - * If on is 0, mark the child windows of the window passed in in winPtr - * as unmapped, but remember whether they were originally mapped in their - * parent. - * If on is 1, set all the child windows of winPtr that WERE mapped in - * their parent before the parent was unmapped back to mapped. - * - * Results: - * None. - * - * Side effects: - * The TkWindow and MacDrawable flags may be adjusted. - * - *---------------------------------------------------------------------- - */ - -static void -FixMappingFlags (TkWindow *winPtr, int on) -{ - TkWindow *childPtr; - childPtr = winPtr->childList; - - while (childPtr != NULL) { - /* - * We might get called before the Mac OS X side of the widget - * is created yet. If so, wait till later... - */ - - if (childPtr->privatePtr != NULL) { - - if (((MacDrawable *)childPtr->privatePtr)->flags - & TK_MAPPED_IN_PARENT) { - if (on) { - childPtr->flags |= TK_MAPPED; - } else { - childPtr->flags &= ~TK_MAPPED; - } - } - if (!Tk_TopWinHierarchy(childPtr)) { - FixMappingFlags (childPtr, on); - } - } - childPtr = childPtr->nextPtr; - } - -} /* *---------------------------------------------------------------------- @@ -237,12 +193,10 @@ XMapWindow( if (!TkMacOSXHostToplevelExists(macWin->toplevel->winPtr)) { TkMacOSXMakeRealWindowExist(macWin->toplevel->winPtr); } - destPort = TkMacOSXGetDrawablePort (window); display->request++; macWin->winPtr->flags |= TK_MAPPED; - macWin->flags |= TK_MAPPED_IN_PARENT; - FixMappingFlags(macWin->winPtr, 1); + destPort = TkMacOSXGetDrawablePort (window); if (Tk_IsTopLevel(macWin->winPtr)) { if (!Tk_IsEmbedded(macWin->winPtr)) { /* @@ -273,15 +227,13 @@ XMapWindow( event.xmap.override_redirect = macWin->winPtr->atts.override_redirect; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); } else { + /* + * Generate damage for that area of the window + */ + SetGWorld(destPort, NULL); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr); } - - /* - * Generate damage for that area of the window - */ - SetGWorld (destPort, NULL); - TkMacOSXUpdateClipRgn(macWin->winPtr); - TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); } /* @@ -310,15 +262,12 @@ XUnmapWindow( XEvent event; CGrafPtr destPort; - destPort = TkMacOSXGetDrawablePort(window); - display->request++; macWin->winPtr->flags &= ~TK_MAPPED; - macWin->flags &= ~TK_MAPPED_IN_PARENT; - FixMappingFlags(macWin->winPtr, 0); + destPort = TkMacOSXGetDrawablePort(window); if (Tk_IsTopLevel(macWin->winPtr)) { if (!Tk_IsEmbedded(macWin->winPtr) - && macWin->winPtr->wmInfoPtr->hints.initial_state != IconicState) { + && macWin->winPtr->wmInfoPtr->hints.initial_state != IconicState) { /* * XXX This should be HideSheetWindow for kSheetWindowClass * XXX windows that have a wmPtr->master parent set. @@ -350,7 +299,7 @@ XUnmapWindow( * Generate damage for that area of the window. */ SetGWorld(destPort, NULL); - TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); /* TODO: may not be valid */ + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); TkMacOSXInvalClipRgns((Tk_Window) macWin->winPtr->parentPtr); } } @@ -892,41 +841,85 @@ TkMacOSXUpdateClipRgn( return; } - if (winPtr->privatePtr->flags & TK_CLIP_INVALID) { - rgn = winPtr->privatePtr->aboveClipRgn; - if (tmpRgn == NULL) { - tmpRgn = NewRgn(); - } - - /* - * Start with a region defined by the window bounds. - */ + if (winPtr->privatePtr && winPtr->privatePtr->flags & TK_CLIP_INVALID) { + if (Tk_IsMapped(winPtr)) { + rgn = winPtr->privatePtr->aboveClipRgn; + if (tmpRgn == NULL) { + tmpRgn = NewRgn(); + } - x = winPtr->privatePtr->xOff; - y = winPtr->privatePtr->yOff; - SetRectRgn(rgn, (short) x, (short) y, - (short) (winPtr->changes.width + x), - (short) (winPtr->changes.height + y)); - - /* - * Clip away the area of any windows that may obscure this - * window. - * For a non-toplevel window, first, clip to the parents visable - * clip region. - * Second, clip away any siblings that are higher in the - * stacking order. - * For an embedded toplevel, just clip to the container's visible - * clip region. Remember, we only allow one contained window - * in a frame, and don't support any other widgets in the frame either. - * This is not currently enforced, however. - */ - - if (!Tk_IsTopLevel(winPtr)) { - TkMacOSXUpdateClipRgn(winPtr->parentPtr); - SectRgn(rgn, - winPtr->parentPtr->privatePtr->aboveClipRgn, rgn); - - win2Ptr = winPtr->nextPtr; + /* + * Start with a region defined by the window bounds. + */ + + x = winPtr->privatePtr->xOff; + y = winPtr->privatePtr->yOff; + SetRectRgn(rgn, (short) x, (short) y, + (short) (winPtr->changes.width + x), + (short) (winPtr->changes.height + y)); + + /* + * Clip away the area of any windows that may obscure this + * window. + * For a non-toplevel window, first, clip to the parents visible + * clip region. + * Second, clip away any siblings that are higher in the + * stacking order. + * For an embedded toplevel, just clip to the container's visible + * clip region. Remember, we only allow one contained window + * in a frame, and don't support any other widgets in the frame + * either. This is not currently enforced, however. + */ + + if (!Tk_IsTopLevel(winPtr)) { + TkMacOSXUpdateClipRgn(winPtr->parentPtr); + SectRgn(rgn, + winPtr->parentPtr->privatePtr->aboveClipRgn, rgn); + + win2Ptr = winPtr->nextPtr; + while (win2Ptr != NULL) { + if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) { + win2Ptr = win2Ptr->nextPtr; + continue; + } + x = win2Ptr->privatePtr->xOff; + y = win2Ptr->privatePtr->yOff; + SetRectRgn(tmpRgn, (short) x, (short) y, + (short) (win2Ptr->changes.width + x), + (short) (win2Ptr->changes.height + y)); + DiffRgn(rgn, tmpRgn, rgn); + + win2Ptr = win2Ptr->nextPtr; + } + } else if (Tk_IsEmbedded(winPtr)) { + TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); + + if (contWinPtr != NULL) { + TkMacOSXUpdateClipRgn(contWinPtr); + SectRgn(rgn, + contWinPtr->privatePtr->aboveClipRgn, rgn); + } else if (gMacEmbedHandler != NULL) { + gMacEmbedHandler->getClipProc((Tk_Window) winPtr, tmpRgn); + SectRgn(rgn, tmpRgn, rgn); + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } + + /* + * The final clip region is the aboveClip region (or visible + * region) minus all the children of this window. + * Alternatively, if the window is a container, we must also + * subtract the region of the embedded window. + */ + + rgn = winPtr->privatePtr->clipRgn; + CopyRgn(winPtr->privatePtr->aboveClipRgn, rgn); + + win2Ptr = winPtr->childList; while (win2Ptr != NULL) { if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) { win2Ptr = win2Ptr->nextPtr; @@ -938,75 +931,61 @@ TkMacOSXUpdateClipRgn( (short) (win2Ptr->changes.width + x), (short) (win2Ptr->changes.height + y)); DiffRgn(rgn, tmpRgn, rgn); - + win2Ptr = win2Ptr->nextPtr; } - } else if (Tk_IsEmbedded(winPtr)) { - TkWindow *contWinPtr; - - contWinPtr = TkpGetOtherWindow(winPtr); - - if (contWinPtr != NULL) { - TkMacOSXUpdateClipRgn(contWinPtr); - SectRgn(rgn, - contWinPtr->privatePtr->aboveClipRgn, rgn); - } else if (gMacEmbedHandler != NULL) { - gMacEmbedHandler->getClipProc((Tk_Window) winPtr, tmpRgn); - SectRgn(rgn, tmpRgn, rgn); - } - - /* - * NOTE: Here we should handle out of process embedding. - */ - - } - - /* - * The final clip region is the aboveClip region (or visable - * region) minus all the children of this window. - * Alternatively, if the window is a container, we must also - * subtract the region of the embedded window. - */ - - rgn = winPtr->privatePtr->clipRgn; - CopyRgn(winPtr->privatePtr->aboveClipRgn, rgn); - - win2Ptr = winPtr->childList; - while (win2Ptr != NULL) { - if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) { - win2Ptr = win2Ptr->nextPtr; - continue; + + if (Tk_IsContainer(winPtr)) { + win2Ptr = TkpGetOtherWindow(winPtr); + if (win2Ptr != NULL) { + if (Tk_IsMapped(win2Ptr)) { + x = win2Ptr->privatePtr->xOff; + y = win2Ptr->privatePtr->yOff; + SetRectRgn(tmpRgn, (short) x, (short) y, + (short) (win2Ptr->changes.width + x), + (short) (win2Ptr->changes.height + y)); + DiffRgn(rgn, tmpRgn, rgn); + } + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + } - x = win2Ptr->privatePtr->xOff; - y = win2Ptr->privatePtr->yOff; - SetRectRgn(tmpRgn, (short) x, (short) y, - (short) (win2Ptr->changes.width + x), - (short) (win2Ptr->changes.height + y)); - DiffRgn(rgn, tmpRgn, rgn); - - win2Ptr = win2Ptr->nextPtr; - } - - if (Tk_IsContainer(winPtr)) { - win2Ptr = TkpGetOtherWindow(winPtr); - if (win2Ptr != NULL) { - if (Tk_IsMapped(win2Ptr)) { - x = win2Ptr->privatePtr->xOff; - y = win2Ptr->privatePtr->yOff; - SetRectRgn(tmpRgn, (short) x, (short) y, - (short) (win2Ptr->changes.width + x), - (short) (win2Ptr->changes.height + y)); - DiffRgn(rgn, tmpRgn, rgn); - } - } - + } else { /* - * NOTE: Here we should handle out of process embedding. + * An unmapped window has empty clip regions to prevent any + * (erroneous) drawing into it or its children from becoming + * visible. [Bug 940117] */ - + + if (!Tk_IsTopLevel(winPtr)) { + TkMacOSXUpdateClipRgn(winPtr->parentPtr); + } else if (Tk_IsEmbedded(winPtr)) { + TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); + + if (contWinPtr != NULL) { + TkMacOSXUpdateClipRgn(contWinPtr); + } + } + SetEmptyRgn(winPtr->privatePtr->aboveClipRgn); + SetEmptyRgn(winPtr->privatePtr->clipRgn); } - + winPtr->privatePtr->flags &= ~TK_CLIP_INVALID; + +#if defined(TK_MAC_DEBUG) && defined(TK_MAC_DEBUG_CLIP_REGIONS) + TkMacOSXInitNamedDebugSymbol(HIToolbox, int, QDDebugFlashRegion, + CGrafPtr port, RgnHandle region); + if (QDDebugFlashRegion) { + MacDrawable *macDraw = (MacDrawable *) winPtr->privatePtr; + CGrafPtr grafPtr = TkMacOSXGetDrawablePort((Drawable) macDraw); + /* Carbon-internal region flashing SPI (c.f. Technote 2124) */ + QDDebugFlashRegion(grafPtr, macDraw->clipRgn); + } +#endif /* TK_MAC_DEBUG_CLIP_REGIONS */ + } } @@ -1066,13 +1045,23 @@ TkMacOSXInvalidateWindow( grafPtr = TkMacOSXGetDrawablePort((Drawable)macWin); windowRef = GetWindowFromPort(grafPtr); - + if (flag == TK_WINDOW_ONLY) { InvalWindowRgn(windowRef,macWin->clipRgn); } else { if (!EmptyRgn(macWin->aboveClipRgn)) { - InvalWindowRgn(windowRef,macWin->aboveClipRgn); + InvalWindowRgn(windowRef, macWin->aboveClipRgn); + } + +#if defined(TK_MAC_DEBUG) && defined(TK_MAC_DEBUG_CLIP_REGIONS) + TkMacOSXInitNamedDebugSymbol(HIToolbox, int, QDDebugFlashRegion, + CGrafPtr port, RgnHandle region); + if (QDDebugFlashRegion) { + /* Carbon-internal region flashing SPI (c.f. Technote 2124) */ + QDDebugFlashRegion(grafPtr, macWin->aboveClipRgn); } +#endif /* TK_MAC_DEBUG_CLIP_REGIONS */ + } } @@ -1217,7 +1206,7 @@ TkMacOSXGetRootControl( * This function invalidates the clipping regions for a given * window and all of its children. This function should be * called whenever changes are made to subwindows that would - * effect the size or position of windows. + * affect the size or position of windows. * * Results: * None. @@ -1235,45 +1224,47 @@ TkMacOSXInvalClipRgns( { TkWindow *winPtr = (TkWindow *) tkwin; TkWindow *childPtr; - + /* * If already marked we can stop because all * decendants will also already be marked. */ - if (winPtr->privatePtr->flags & TK_CLIP_INVALID) { + if (!winPtr->privatePtr || winPtr->privatePtr->flags & TK_CLIP_INVALID) { return; } - + winPtr->privatePtr->flags |= TK_CLIP_INVALID; - + SetEmptyRgn(winPtr->privatePtr->aboveClipRgn); + SetEmptyRgn(winPtr->privatePtr->clipRgn); + /* * Invalidate clip regions for all children & * their decendants - unless the child is a toplevel. */ childPtr = winPtr->childList; - while (childPtr != NULL) { - if (!Tk_IsTopLevel(childPtr) && Tk_IsMapped(childPtr)) { + while (childPtr) { + if (!Tk_IsTopLevel(childPtr)) { TkMacOSXInvalClipRgns((Tk_Window) childPtr); } childPtr = childPtr->nextPtr; } - + /* * Also, if the window is a container, mark its embedded window */ - + if (Tk_IsContainer(winPtr)) { childPtr = TkpGetOtherWindow(winPtr); - if (childPtr != NULL && Tk_IsMapped(childPtr)) { + if (childPtr) { TkMacOSXInvalClipRgns((Tk_Window) childPtr); } - + /* * NOTE: Here we should handle out of process embedding. */ - - } + + } } /* |