summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXHLEvents.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXHLEvents.c')
-rw-r--r--macosx/tkMacOSXHLEvents.c85
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...
*/