diff --git a/redo/dialog_darwin.m b/redo/dialog_darwin.m index 3e662be..0557018 100644 --- a/redo/dialog_darwin.m +++ b/redo/dialog_darwin.m @@ -18,11 +18,9 @@ char *openFile(void) [op setExtensionHidden:NO]; [op setAllowsOtherFileTypes:YES]; [op setTreatsFilePackagesAsDirectories:YES]; - // disable custom events - // TODO doesn't seem to work - dispatch_suspend(dispatch_get_main_queue()); + beginModal(); ret = [op runModal]; - dispatch_resume(dispatch_get_main_queue()); + endModal(); if (ret != NSFileHandlingPanelOKButton) return NULL; // string freed on the Go side diff --git a/redo/objc_darwin.h b/redo/objc_darwin.h index 53cb65d..f3b7e70 100644 --- a/redo/objc_darwin.h +++ b/redo/objc_darwin.h @@ -41,6 +41,8 @@ extern id getAppDelegate(void); /* used by the other .m files */ extern void uiinit(char **); extern void uimsgloop(void); extern void uistop(void); +extern void beginModal(void); +extern void endModal(void); extern void issue(void *); /* window_darwin.m */ diff --git a/redo/uitask_darwin.m b/redo/uitask_darwin.m index d802911..9d25a61 100644 --- a/redo/uitask_darwin.m +++ b/redo/uitask_darwin.m @@ -129,9 +129,48 @@ void uistop(void) [NSApp postEvent:e atStart:NO]; // let pending events take priority } +// because dispatch_suspend()/dispatch_resume() can't be used with the main queue +static BOOL inmodal = NO; +static void **modalqueue = NULL; +static size_t mqlen = 0; +static size_t mqcap = 0; + +void beginModal(void) +{ + inmodal = YES; + if (modalqueue == NULL) { + mqcap = 128; + modalqueue = (void **) malloc(mqcap * sizeof (void *)); + if (modalqueue == NULL) + abort();//TODO + mqlen = 0; + } +} + +void endModal(void) +{ + size_t i; + + inmodal = NO; + for (i = 0; i < mqlen; i++) + doissue(modalqueue[i]); + mqlen = 0; +} + // thanks to mikeash in irc.freenode.net/#macdev for suggesting the use of Grand Central Dispatch and blocks for this void issue(void *what) { + if (inmodal) { + modalqueue[mqlen] = what; + mqlen++; + if (mqlen >= mqcap) { + mqcap *= 2; + modalqueue = (void **) realloc(modalqueue, mqcap * sizeof (void *)); + if (modalqueue == NULL) + abort();//TODO + } + return; + } dispatch_async(dispatch_get_main_queue(), ^{ doissue(what); });