diff options
Diffstat (limited to 'macosx/tkMacOSXHLEvents.c')
-rw-r--r-- | macosx/tkMacOSXHLEvents.c | 85 |
1 files changed, 64 insertions, 21 deletions
diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c index e2ff0f1..f405a53 100644 --- a/macosx/tkMacOSXHLEvents.c +++ b/macosx/tkMacOSXHLEvents.c @@ -39,6 +39,7 @@ typedef struct AppleEventInfo { const char *procedure; Tcl_DString command; NSAppleEventDescriptor *replyEvent; /* Only used for DoScriptText. */ + int retryCount; } AppleEventInfo; /* @@ -53,11 +54,11 @@ static void ProcessAppleEvent(ClientData clientData); * Names of the procedures which can be used to process AppleEvents. */ -static const char* openDocumentProc = "::tk::mac::OpenDocument"; -static const char* launchURLProc = "::tk::mac::LaunchURL"; -static const char* printDocProc = "::tk::mac::PrintDocument"; -static const char* scriptFileProc = "::tk::mac::DoScriptFile"; -static const char* scriptTextProc = "::tk::mac::DoScriptText"; +static const char openDocumentProc[] = "::tk::mac::OpenDocument"; +static const char launchURLProc[] = "::tk::mac::LaunchURL"; +static const char printDocProc[] = "::tk::mac::PrintDocument"; +static const char scriptFileProc[] = "::tk::mac::DoScriptFile"; +static const char scriptTextProc[] = "::tk::mac::DoScriptText"; #pragma mark TKApplication(TKHLEvents) @@ -68,6 +69,11 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText"; [self handleQuitApplicationEvent:Nil withReplyEvent:Nil]; } +- (void) superTerminate: (id) sender +{ + [super terminate:nil]; +} + - (void) preferences: (id) sender { (void)sender; @@ -230,6 +236,13 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText"; AEInfo->procedure = openDocumentProc; AEInfo->replyEvent = nil; Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo); + AEInfo->retryCount = 0; + + if (Tcl_FindCommand(_eventInterp, "::tk::mac::OpenDocuments", NULL, 0)){ + ProcessAppleEvent((ClientData)AEInfo); + } else { + Tcl_CreateTimerHandler(500, ProcessAppleEvent, (ClientData)AEInfo); + } } - (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event @@ -249,6 +262,8 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText"; AEInfo->procedure = printDocProc; AEInfo->replyEvent = nil; Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo); + AEInfo->retryCount = 0; + ProcessAppleEvent((ClientData)AEInfo); } - (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event @@ -310,6 +325,8 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText"; AEInfo->procedure = scriptFileProc; AEInfo->replyEvent = nil; Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo); + AEInfo->retryCount = 0; + ProcessAppleEvent((ClientData)AEInfo); } } } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type, @@ -325,19 +342,22 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText"; if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type, data, actual, NULL)) { - AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo)); - Tcl_DString *scriptTextCommand = &AEInfo->command; - Tcl_DStringInit(scriptTextCommand); - Tcl_DStringAppend(scriptTextCommand, scriptTextProc, -1); + data[actual] = '\0'; + AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo)); + Tcl_DString *scriptTextCommand = &AEInfo->command; + Tcl_DStringInit(scriptTextCommand); + Tcl_DStringAppend(scriptTextCommand, scriptTextProc, -1); Tcl_DStringAppendElement(scriptTextCommand, data); AEInfo->interp = _eventInterp; AEInfo->procedure = scriptTextProc; + AEInfo->retryCount = 0; if (Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) { AEInfo->replyEvent = replyEvent; - ProcessAppleEvent((ClientData)AEInfo); + ProcessAppleEvent(AEInfo); } else { AEInfo->replyEvent = nil; - Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo); + Tcl_DoWhenIdle(ProcessAppleEvent, AEInfo); + ProcessAppleEvent(AEInfo); } } } @@ -361,6 +381,8 @@ static const char* scriptTextProc = "::tk::mac::DoScriptText"; AEInfo->procedure = launchURLProc; AEInfo->replyEvent = nil; Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo); + AEInfo->retryCount = 0; + ProcessAppleEvent((ClientData)AEInfo); } @end @@ -395,15 +417,30 @@ static void ProcessAppleEvent( { int code; AppleEventInfo *AEInfo = (AppleEventInfo*) clientData; - if (!AEInfo->interp || - !Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) { + + if (!AEInfo->interp) { + return; + } + + /* + * Apple events that are delivered during the app startup can arrive + * before the Tcl procedure for handling the events has been defined. + * If the command is not found we create a timer handler to process + * the event later, hopefully after the command has been created. + * We retry up to 2 times before giving up. + */ + + if (!Tcl_FindCommand(AEInfo->interp, AEInfo->procedure, NULL, 0)) { + if (AEInfo->retryCount < 2) { + AEInfo->retryCount++; + Tcl_CreateTimerHandler(200, ProcessAppleEvent, clientData); + } else { + ckfree(clientData); + } return; } code = Tcl_EvalEx(AEInfo->interp, Tcl_DStringValue(&AEInfo->command), Tcl_DStringLength(&AEInfo->command), TCL_EVAL_GLOBAL); - if (code != TCL_OK) { - Tcl_BackgroundException(AEInfo->interp, code); - } if (AEInfo->replyEvent && code >= 0) { int reslen; @@ -418,7 +455,10 @@ static void ProcessAppleEvent( AEPutParamPtr((AppleEvent*)[AEInfo->replyEvent aeDesc], keyErrorNumber, typeSInt32, (Ptr) &code, sizeof(int)); } + } else if (code != TCL_OK) { + Tcl_BackgroundException(AEInfo->interp, code); } + Tcl_DStringFree(&AEInfo->command); ckfree(clientData); } @@ -442,11 +482,10 @@ static void ProcessAppleEvent( void TkMacOSXInitAppleEvents( - Tcl_Interp *dummy) /* not used */ + TCL_UNUSED(Tcl_Interp *)) { NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager]; static Boolean initialized = FALSE; - (void)dummy; if (!initialized) { initialized = TRUE; @@ -553,14 +592,18 @@ TkMacOSXDoHLEvent( static int ReallyKillMe( Tcl_Event *eventPtr, - int flags) + TCL_UNUSED(int)) { Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp; int quit = Tcl_FindCommand(interp, "::tk::mac::Quit", NULL, 0)!=NULL; - int code = Tcl_EvalEx(interp, quit ? "::tk::mac::Quit" : "exit", -1, TCL_EVAL_GLOBAL); - (void)flags; + if (!quit) { + Tcl_Exit(0); + } + + int code = Tcl_EvalEx(interp, "::tk::mac::Quit", -1, TCL_EVAL_GLOBAL); if (code != TCL_OK) { + /* * Should be never reached... */ |