From 9c70782a0ffacfa8e50d5915782f48a93bc253ab Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sun, 28 Apr 2019 11:48:21 -0400 Subject: [PATCH] Added uiMain() and friends on macOS and refined the tests. So now we'll need to add a timeout mechanism because that sendEvent: stuff really is still neeeded and I'd like to prevent shenanigans later. --- darwin/main.m | 54 +++++++++++++++++++++++++++++++++++++++++++++- test/initmain.c | 27 +++++++++++++++++------ zOLD_darwin/main.m | 38 -------------------------------- 3 files changed, 74 insertions(+), 45 deletions(-) diff --git a/darwin/main.m b/darwin/main.m index 80e31957..1c2c7255 100644 --- a/darwin/main.m +++ b/darwin/main.m @@ -7,7 +7,34 @@ @implementation uiprivApplication @end -static NSApplication *uiprivApp; +@interface uiprivApplicationDelegate : NSObject +@end + +static uiprivApplication *uiprivApp; +static uiprivApplicationDelegate *uiprivAppDelegate; + +@implementation uiprivApplicationDelegate + +#if 0 +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app +{ + // for debugging + NSLog(@"in applicationShouldTerminate:"); + if (uiprivShouldQuit()) { + canQuit = YES; + // this will call terminate:, which is the same as uiQuit() + return NSTerminateNow; + } + return NSTerminateCancel; +} +#endif + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app +{ + return NO; +} + +@end #define errNSAppAlreadyInitialized "NSApp is not of type uiprivApplication; was likely already initialized beforehand" @@ -25,6 +52,31 @@ int uiInit(void *options, uiInitError *err) if (![NSApp isKindOfClass:[uiprivApplication class]]) return uiprivInitReturnError(err, errNSAppAlreadyInitialized); + // don't check for a NO return; something (launch services?) causes running from application bundles to always return NO when asking to change activation policy, even if the change is to the same activation policy! + // see https://github.com/andlabs/ui/issues/6 + [uiprivApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + + uiprivAppDelegate = [uiprivApplicationDelegate new]; + [uiprivApp setDelegate:uiprivAppDelegate]; + uiprivMarkInitialized(); return 1; } + +void uiMain(void) +{ + [uiprivApp run]; +} + +void uiQuit(void) +{ + [uiprivApp stop:uiprivApp]; +} + +// thanks to mikeash in irc.freenode.net/#macdev for suggesting the use of Grand Central Dispatch for this +void uiQueueMain(void (*f)(void *data), void *data) +{ + // dispatch_get_main_queue() is a serial queue so it will not execute multiple uiQueueMain() functions concurrently + // the signature of f matches dispatch_function_t + dispatch_async_f(dispatch_get_main_queue(), data, f); +} diff --git a/test/initmain.c b/test/initmain.c index c0915865..c98de7d6 100644 --- a/test/initmain.c +++ b/test/initmain.c @@ -52,8 +52,28 @@ static void queued(void *data) int *flag = (int *) data; *flag = 1; + uiQuit(); } +testingTest(QueueMain) +{ + int flag = 0; + + uiQueueMain(queued, &flag); + uiMain(); + if (flag != 1) + testingTErrorf(t, "uiQueueMain didn't set flag properly: got %d, want 1", flag); +} + +testingTest(QueueMain_Sequence) +{ + // TODO +} + +// TODO testingTest(QueueMain_DifferentThread) +// TODO testingTest(QueueMain_DifferentThreadSequence) + +#if 0 static void timer(void *data) { int *n = (int *) data; @@ -62,12 +82,7 @@ static void timer(void *data) *n++; } -testingTest(QueueMain) -{ -} - -// TODO testingTest(QueueMain_DifferentThread) - testingTest(Timer) { } +#endif diff --git a/zOLD_darwin/main.m b/zOLD_darwin/main.m index 0d02d642..91c6d1a6 100644 --- a/zOLD_darwin/main.m +++ b/zOLD_darwin/main.m @@ -87,23 +87,6 @@ static BOOL stepsIsRunning; [super dealloc]; } -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app -{ - // for debugging - NSLog(@"in applicationShouldTerminate:"); - if (uiprivShouldQuit()) { - canQuit = YES; - // this will call terminate:, which is the same as uiQuit() - return NSTerminateNow; - } - return NSTerminateCancel; -} - -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app -{ - return NO; -} - @end uiInitOptions uiprivOptions; @@ -112,12 +95,6 @@ const char *uiInit(uiInitOptions *o) { @autoreleasepool { uiprivOptions = *o; - app = [[uiprivApplicationClass sharedApplication] retain]; - // don't check for a NO return; something (launch services?) causes running from application bundles to always return NO when asking to change activation policy, even if the change is to the same activation policy! - // see https://github.com/andlabs/ui/issues/6 - [uiprivNSApp() setActivationPolicy:NSApplicationActivationPolicyRegular]; - delegate = [uiprivAppDelegate new]; - [uiprivNSApp() setDelegate:delegate]; uiprivInitAlloc(); uiprivLoadFutures(); @@ -228,21 +205,6 @@ int uiprivMainStep(uiprivNextEventArgs *nea, BOOL (^interceptEvent)(NSEvent *e)) } } -void uiQuit(void) -{ - canQuit = YES; - [uiprivNSApp() terminate:uiprivNSApp()]; -} - -// thanks to mikeash in irc.freenode.net/#macdev for suggesting the use of Grand Central Dispatch for this -// LONGTERM will dispatch_get_main_queue() break after _CFRunLoopSetCurrent()? -void uiQueueMain(void (*f)(void *data), void *data) -{ - // dispatch_get_main_queue() is a serial queue so it will not execute multiple uiQueueMain() functions concurrently - // the signature of f matches dispatch_function_t - dispatch_async_f(dispatch_get_main_queue(), data, f); -} - @interface uiprivTimerDelegate : NSObject { int (*f)(void *data); void *data;