diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | generic/tkWindow.c | 4 | ||||
-rw-r--r-- | macosx/tkMacOSXDialog.c | 394 | ||||
-rw-r--r-- | macosx/tkMacOSXMenu.c | 9 | ||||
-rw-r--r-- | macosx/tkMacOSXMouseEvent.c | 16 |
5 files changed, 429 insertions, 7 deletions
@@ -1,3 +1,16 @@ +2003-07-18 Vince Darley <vincentdarley@users.sourceforge.net> + + * generic/tkWindow.c: + * macosx/tkMacOSXDialog.c: added native tk_messageBox command, + (Tk_MessageBoxObjCmd) for MacOS X platform. + + * macosx/tkMacOSXMenu.c: corrected encoding conversion for + torn-off menu entries (but many other display problems still + exist with these) + + * macosx/tkMacOSXMouseEvent.c: improved handling of events in the + presence of grabs, particularly activation events. + 2003-07-18 Donal K. Fellows <fellowsd@cs.man.ac.uk> * tests/panedwindow.test (panedwindow-30.2): diff --git a/generic/tkWindow.c b/generic/tkWindow.c index e374c2f..db0c69a 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWindow.c,v 1.58 2003/07/16 22:54:08 hobbs Exp $ + * RCS: @(#) $Id: tkWindow.c,v 1.59 2003/07/18 11:04:58 vincentdarley Exp $ */ #include "tkPort.h" @@ -142,7 +142,7 @@ static TkCmd commands[] = { {"tk_getOpenFile", NULL, Tk_GetOpenFileObjCmd, 0, 1}, {"tk_getSaveFile", NULL, Tk_GetSaveFileObjCmd, 0, 1}, #endif -#ifdef __WIN32__ +#ifdef defined(__WIN32__) || defined(MAC_OSX_TK) {"tk_messageBox", NULL, Tk_MessageBoxObjCmd, 0, 1}, #endif {"update", NULL, Tk_UpdateObjCmd, 1, 1}, diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index 8da90f6..e38cabd 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -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: tkMacOSXDialog.c,v 1.4 2003/02/25 16:09:23 das Exp $ + * RCS: @(#) $Id: tkMacOSXDialog.c,v 1.5 2003/07/18 11:04:59 vincentdarley Exp $ */ #include <Carbon/Carbon.h> @@ -58,6 +58,18 @@ typedef struct _OpenFileData { } OpenFileData; +/* + * The following structure is used in the tk_messageBox + * implementation. + */ +typedef struct { + WindowRef windowRef; + int buttonIndex; +} CallbackUserData; + + +static OSStatus AlertHandler _ANSI_ARGS_(( EventHandlerCallRef callRef, + EventRef eventRef, void *userData )); static Boolean MatchOneType _ANSI_ARGS_((StringPtr fileNamePtr, OSType fileType, OpenFileData *myofdPtr, FileFilter *filterPtr)); static pascal Boolean OpenFileFilterProc(AEDesc* theItem, void* info, @@ -1226,3 +1238,383 @@ TkAboutDlg() return; } + +/* + *---------------------------------------------------------------------- + * + * Tk_MessageBoxObjCmd -- + * + * Implements the tk_messageBox in native Mac OS X style. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * none + * + *---------------------------------------------------------------------- + */ + +int +Tk_MessageBoxObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + Tk_Window tkwin = (Tk_Window) clientData; + AlertStdCFStringAlertParamRec paramCFStringRec; + AlertType alertType; + DialogRef dialogRef; + CFStringRef messageTextCF = NULL; + CFStringRef finemessageTextCF = NULL; + OSErr osError; + SInt16 itemHit; + Boolean haveDefaultOption = false; + Boolean haveParentOption = false; + char *str; + int index; + int defaultButtonIndex; + int defaultNativeButtonIndex; /* 1, 2, 3: right to left. */ + int typeIndex; + int i; + int indexDefaultOption; + int result = TCL_OK; + + static CONST char *movableAlertStrings[] = { + "-default", /* "-finemessage", */ "-icon", + "-message", "-parent", + "-title", "-type", + (char *)NULL + }; + static CONST char *movableTypeStrings[] = { + "abortretryignore", "ok", + "okcancel", "retrycancel", + "yesno", "yesnocancel", + (char *)NULL + }; + static CONST char *movableButtonStrings[] = { + "abort", "retry", "ignore", + "ok", "cancel", "yes", "no", + (char *)NULL + }; + static CONST char *movableIconStrings[] = { + "error", "info", "question", "warning", + (char *)NULL + }; + enum movableAlertOptions { + ALERT_DEFAULT, /* ALERT_FINEMESSAGE, */ ALERT_ICON, + ALERT_MESSAGE, ALERT_PARENT, + ALERT_TITLE, ALERT_TYPE + }; + enum movableTypeOptions { + TYPE_ABORTRETRYIGNORE, TYPE_OK, + TYPE_OKCANCEL, TYPE_RETRYCANCEL, + TYPE_YESNO, TYPE_YESNOCANCEL + }; + enum movableButtonOptions { + TEXT_ABORT, TEXT_RETRY, TEXT_IGNORE, + TEXT_OK, TEXT_CANCEL, TEXT_YES, TEXT_NO + }; + enum movableIconOptions { + ICON_ERROR, ICON_INFO, ICON_QUESTION, ICON_WARNING + }; + + /* + * Need to map from 'movableButtonStrings' 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. + */ + + short buttonIndexAndTypeToNativeButtonIndex[][7] = { + /* abort retry ignore ok cancel yes no */ + {1, 2, 3, 0, 0, 0, 0}, /* abortretryignore */ + {0, 0, 0, 1, 0, 0, 0}, /* ok */ + {0, 0, 0, 1, 2, 0, 0}, /* okcancel */ + {0, 1, 0, 0, 2, 0, 0}, /* retrycancel */ + {0, 0, 0, 0, 0, 1, 2}, /* yesno */ + {0, 0, 0, 0, 3, 1, 2}, /* yesnocancel */ + }; + + /* + * Need also the inverse mapping, from native button (1, 2, 3) to the + * descriptive button text string index. + */ + + short nativeButtonIndexAndTypeToButtonIndex[][4] = { + {-1, 0, 1, 2}, /* abortretryignore */ + {-1, 3, 0, 0}, /* ok */ + {-1, 3, 4, 0}, /* okcancel */ + {-1, 1, 4, 0}, /* retrycancel */ + {-1, 5, 6, 0}, /* yesno */ + {-1, 5, 6, 4}, /* yesnocancel */ + }; + + alertType = kAlertPlainAlert; + typeIndex = TYPE_OK; + + GetStandardAlertDefaultParams( ¶mCFStringRec, kStdCFStringAlertVersionOne ); + paramCFStringRec.movable = true; + paramCFStringRec.helpButton = false; + paramCFStringRec.defaultButton = kAlertStdAlertOKButton; + + for (i = 1; i < objc; i += 2) { + int iconIndex; + char *string; + + if (Tcl_GetIndexFromObj( interp, objv[i], movableAlertStrings, "option", + TCL_EXACT, &index ) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + if (i + 1 == objc) { + string = Tcl_GetStringFromObj( objv[i], NULL ); + Tcl_AppendResult(interp, "value for \"", string, "\" missing", + (char *) NULL); + result = TCL_ERROR; + goto end; + } + + switch (index) { + + case ALERT_DEFAULT: + + /* + * Need to postpone processing of this option until we are + * sure to know the '-type' as well. + */ + + haveDefaultOption = true; + indexDefaultOption = i; + break; + +/* case ALERT_FINEMESSAGE: + str = Tcl_GetStringFromObj( objv[i + 1], NULL ); + finemessageTextCF = CFStringCreateWithCString( NULL, str, kCFStringEncodingUTF8 ); + break; +*/ + case ALERT_ICON: + /* not sure about UTF translation here... */ + if (Tcl_GetIndexFromObj( interp, objv[i + 1], movableIconStrings, + "value", TCL_EXACT, &iconIndex ) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + switch (iconIndex) { + case ICON_ERROR: + alertType = kAlertStopAlert; + break; + case ICON_INFO: + alertType = kAlertNoteAlert; + break; + case ICON_QUESTION: + alertType = kAlertCautionAlert; + break; + case ICON_WARNING: + alertType = kAlertCautionAlert; + break; + } + break; + + case ALERT_MESSAGE: + str = Tcl_GetStringFromObj( objv[i + 1], NULL ); + messageTextCF = CFStringCreateWithCString( NULL, str, kCFStringEncodingUTF8 ); + break; + + case ALERT_PARENT: + str = Tcl_GetStringFromObj( objv[i + 1], NULL ); + tkwin = Tk_NameToWindow( interp, str, tkwin ); + if (tkwin == NULL) { + result = TCL_ERROR; + goto end; + } + haveParentOption= true; + break; + + case ALERT_TITLE: + break; + + case ALERT_TYPE: + /* not sure about UTF translation here... */ + if (Tcl_GetIndexFromObj( interp, objv[i + 1], movableTypeStrings, + "value", TCL_EXACT, &typeIndex ) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + switch (typeIndex) { + case TYPE_ABORTRETRYIGNORE: + paramCFStringRec.defaultText = CFSTR("Abort"); + paramCFStringRec.cancelText = CFSTR("Retry"); + paramCFStringRec.otherText = CFSTR("Ignore"); + break; + case TYPE_OK: + paramCFStringRec.defaultText = CFSTR("OK"); + break; + case TYPE_OKCANCEL: + paramCFStringRec.defaultText = CFSTR("OK"); + paramCFStringRec.cancelText = CFSTR("Cancel"); + break; + case TYPE_RETRYCANCEL: + paramCFStringRec.defaultText = CFSTR("Retry"); + paramCFStringRec.cancelText = CFSTR("Cancel"); + break; + case TYPE_YESNO: + paramCFStringRec.defaultText = CFSTR("Yes"); + paramCFStringRec.cancelText = CFSTR("No"); + break; + case TYPE_YESNOCANCEL: + paramCFStringRec.defaultText = CFSTR("Yes"); + paramCFStringRec.cancelText = CFSTR("No"); + paramCFStringRec.otherText = CFSTR("Cancel"); + break; + } + break; + } + } + + if (haveDefaultOption) { + + /* + * Any '-default' option needs to know the '-type' option, which is why + * we do this here. + */ + + str = Tcl_GetStringFromObj( objv[indexDefaultOption + 1], NULL ); + if (Tcl_GetIndexFromObj( interp, objv[indexDefaultOption + 1], + movableButtonStrings, "value", TCL_EXACT, + &defaultButtonIndex ) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + + /* Need to map from "ok" etc. to 1, 2, 3, right to left. */ + + defaultNativeButtonIndex = + buttonIndexAndTypeToNativeButtonIndex[typeIndex][defaultButtonIndex]; + if (defaultNativeButtonIndex == 0) { + Tcl_SetObjResult( interp, + Tcl_NewStringObj( "Illegel default option", -1 )); + result = TCL_ERROR; + goto end; + } + paramCFStringRec.defaultButton = defaultNativeButtonIndex; + } + SetThemeCursor( kThemeArrowCursor ); + + if (haveParentOption) { + TkWindow *winPtr; + MacDrawable *macWin; + WindowRef windowRef; + EventTargetRef notifyTarget; + EventHandlerUPP handler; + CallbackUserData data; + const EventTypeSpec kEvents[] = { + {kEventClassCommand, kEventProcessCommand} + }; + + winPtr = (TkWindow *) tkwin; + + /* + * Create the underlying Mac window for this Tk window. + */ + + macWin = (MacDrawable *) winPtr->window; + windowRef = GetWindowFromPort( TkMacOSXGetDrawablePort((Drawable) macWin) ); + notifyTarget = GetWindowEventTarget( windowRef ); + osError = CreateStandardSheet( alertType, messageTextCF, + finemessageTextCF, ¶mCFStringRec, + notifyTarget, &dialogRef ); + if(osError != noErr) { + result = TCL_ERROR; + goto end; + } + data.windowRef = windowRef; + data.buttonIndex = 1; + handler = NewEventHandlerUPP( AlertHandler ); + InstallEventHandler( notifyTarget, handler, GetEventTypeCount(kEvents), &kEvents, &data, NULL ); + osError = ShowSheetWindow( GetDialogWindow(dialogRef), windowRef ); + if(osError != noErr) { + result = TCL_ERROR; + goto end; + } + osError = RunAppModalLoopForWindow( windowRef ); + + itemHit = data.buttonIndex; + DisposeEventHandlerUPP( handler ); + } else { + osError = CreateStandardAlert( alertType, messageTextCF, + finemessageTextCF, ¶mCFStringRec, &dialogRef ); + if(osError != noErr) { + result = TCL_ERROR; + goto end; + } + osError = RunStandardAlert( dialogRef, NULL, &itemHit ); + } + if(osError == noErr) { + int ind; + + /* + * Map 'itemHit' (1, 2, 3) to descriptive text string. + */ + + ind = nativeButtonIndexAndTypeToButtonIndex[typeIndex][itemHit]; + Tcl_SetObjResult( interp, + Tcl_NewStringObj( movableButtonStrings[ind], -1 )); + } else { + result = TCL_ERROR; + } + + end: + if (finemessageTextCF != NULL) { + CFRelease( finemessageTextCF ); + } + if (messageTextCF != NULL) { + CFRelease( messageTextCF ); + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * AlertHandler -- + * + * Carbon event handler for the Standard Sheet dialog. + * + * Results: + * OSStatus if event handled or not. + * + * Side effects: + * May set userData. + * + *---------------------------------------------------------------------- + */ + +static OSStatus +AlertHandler( EventHandlerCallRef callRef, EventRef eventRef, void *userData ) +{ + OSStatus result = eventNotHandledErr; + HICommand cmd; + CallbackUserData *dataPtr = (CallbackUserData *) userData; + + GetEventParameter( eventRef, kEventParamDirectObject, typeHICommand, + NULL, sizeof(cmd), NULL, &cmd ); + switch (cmd.commandID) { + case kHICommandOK: + dataPtr->buttonIndex = 1; + result = noErr; + break; + case kHICommandCancel: + dataPtr->buttonIndex = 2; + result = noErr; + break; + case kHICommandOther: + dataPtr->buttonIndex = 3; + result = noErr; + break; + } + if (result == noErr) { + result = QuitAppModalLoopForWindow( dataPtr->windowRef ); + } + return result; +} diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index bfaff7e..a69e871 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -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: tkMacOSXMenu.c,v 1.8 2003/03/12 05:56:21 wolfsuit Exp $ + * RCS: @(#) $Id: tkMacOSXMenu.c,v 1.9 2003/07/18 11:04:59 vincentdarley Exp $ */ #include "tkMacOSXInt.h" #include "tkMenuButton.h" @@ -3427,6 +3427,8 @@ DrawMenuEntryLabel( GDHandle saveDevice; GWorldPtr destPort; #ifdef USE_ATSU + int xLocation; + int yLocation; int runLengths; CFStringRef stringRef; ATSUTextLayout textLayout; @@ -3472,7 +3474,8 @@ DrawMenuEntryLabel( #ifdef USE_ATSU runLengths = 1; length = Tcl_DStringLength(&itemTextDString); - stringRef = CFStringCreateWithCString(NULL, Tcl_DStringValue(&itemTextDString), GetApplicationTextEncoding()); + stringRef = CFStringCreateWithCString(NULL, Tcl_DStringValue(&itemTextDString), + kCFStringEncodingUTF8); if (!stringRef) { fprintf(stderr,"CFStringCreateWithCString failed\n"); } @@ -3494,7 +3497,7 @@ DrawMenuEntryLabel( TkMacOSXSetUpGraphicsPort(gc, destPort); MoveTo((short) leftEdge, (short) baseline); - Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&itemTextDString), + Tcl_UtfToExternalDString(TkMacOSXCarbonEncoding, Tcl_DStringValue(&itemTextDString), Tcl_DStringLength(&itemTextDString), &convertedTextDString); #ifdef USE_ATSU xLocation = leftEdge<<16; diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 2516ef8..6a18426 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -271,11 +271,25 @@ TkMacOSXProcessMouseEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) if (!(TkpIsWindowFloating(medPtr->whichWin)) && (medPtr->whichWin != medPtr->activeNonFloating)) { Tk_Window grabWin = TkMacOSXGetCapture(); + if ((grabWin == NULL)) { + int grabState = TkGrabState((TkWindow*)tkwin); + if (grabState != TK_GRAB_NONE && grabState != TK_GRAB_IN_TREE) { + /* Now we want to set the focus to the local grabWin */ + TkMacOSXSetEatButtonUp(true); + grabWin = (Tk_Window) (((TkWindow*)tkwin)->dispPtr->grabWinPtr); + BringWindowForward(GetWindowFromPort(TkMacOSXGetDrawablePort(((TkWindow*)grabWin)->window))); + statusPtr->stopProcessing = 1; + return false; + } + } if ((grabWin != NULL) && (grabWin != tkwin)) { TkWindow * tkw, * grb; tkw = (TkWindow *)tkwin; grb = (TkWindow *)grabWin; - SysBeep(1); + /* Now we want to set the focus to the global grabWin */ + TkMacOSXSetEatButtonUp(true); + BringWindowForward(GetWindowFromPort(TkMacOSXGetDrawablePort(((TkWindow*)grabWin)->window))); + statusPtr->stopProcessing = 1; return false; } |