From 8cb5eedcda7e06f76bc0be81dd4cd17f154033a8 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Thu, 5 Sep 2019 16:14:13 +0300 Subject: [PATCH] Use [NSApp run] instead of a custom run loop --- native/Avalonia.Native/inc/avalonia-native.h | 2 +- native/Avalonia.Native/src/OSX/app.mm | 24 ++++++++ native/Avalonia.Native/src/OSX/common.h | 2 +- native/Avalonia.Native/src/OSX/main.mm | 3 +- .../src/OSX/platformthreading.mm | 59 +++++++++++-------- 5 files changed, 61 insertions(+), 29 deletions(-) create mode 100644 native/Avalonia.Native/src/OSX/app.mm diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index a35f4f3eeb..36e16c24d1 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -280,7 +280,7 @@ AVNCOM(IAvnPlatformThreadingInterface, 0b) : IUnknown virtual bool GetCurrentThreadIsLoopThread() = 0; virtual void SetSignaledCallback(IAvnSignaledCallback* cb) = 0; virtual IAvnLoopCancellation* CreateLoopCancellation() = 0; - virtual void RunLoop(IAvnLoopCancellation* cancel) = 0; + virtual HRESULT RunLoop(IAvnLoopCancellation* cancel) = 0; // Can't pass int* to sharpgentools for some reason virtual void Signal(int priority) = 0; virtual IUnknown* StartTimer(int priority, int ms, IAvnActionCallback* callback) = 0; diff --git a/native/Avalonia.Native/src/OSX/app.mm b/native/Avalonia.Native/src/OSX/app.mm new file mode 100644 index 0000000000..7d45720a8b --- /dev/null +++ b/native/Avalonia.Native/src/OSX/app.mm @@ -0,0 +1,24 @@ +#include "common.h" +@interface AvnAppDelegate : NSObject +@end + +@implementation AvnAppDelegate +- (void)applicationWillFinishLaunching:(NSNotification *)notification +{ + +} + +- (void)applicationDidFinishLaunching:(NSNotification *)notification +{ + [NSApp activateIgnoringOtherApps:true]; +} + +@end + +extern void InitializeAvnApp() +{ + NSApplication* app = [NSApplication sharedApplication]; + id delegate = [AvnAppDelegate new]; + [app setDelegate:delegate]; + +} diff --git a/native/Avalonia.Native/src/OSX/common.h b/native/Avalonia.Native/src/OSX/common.h index f748dd59ad..a716af1e2c 100644 --- a/native/Avalonia.Native/src/OSX/common.h +++ b/native/Avalonia.Native/src/OSX/common.h @@ -19,7 +19,7 @@ extern IAvnClipboard* CreateClipboard(); extern IAvnCursorFactory* CreateCursorFactory(); extern IAvnGlFeature* GetGlFeature(); extern IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(NSWindow* window, NSView* view); - +extern void InitializeAvnApp(); extern NSPoint ToNSPoint (AvnPoint p); extern AvnPoint ToAvnPoint (NSPoint p); extern AvnPoint ConvertPointY (AvnPoint p); diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm index 5043246c53..fec5b9b662 100644 --- a/native/Avalonia.Native/src/OSX/main.mm +++ b/native/Avalonia.Native/src/OSX/main.mm @@ -64,8 +64,9 @@ public: { @autoreleasepool{ [[ThreadingInitializer new] do]; - return S_OK; } + InitializeAvnApp(); + return S_OK; }; virtual IAvnMacOptions* GetMacOptions() override diff --git a/native/Avalonia.Native/src/OSX/platformthreading.mm b/native/Avalonia.Native/src/OSX/platformthreading.mm index 0c814b2088..297097584a 100644 --- a/native/Avalonia.Native/src/OSX/platformthreading.mm +++ b/native/Avalonia.Native/src/OSX/platformthreading.mm @@ -57,16 +57,36 @@ class PlatformThreadingInterface : public ComSingleObject { public: FORWARD_IUNKNOWN() - bool Cancelled = 0; - virtual void Cancel() override + bool Running = false; + bool Cancelled = false; + virtual void Cancel() { - Cancelled = 1; + Cancelled = true; + if(Running) + { + Running = false; + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSApplication sharedApplication] stop:nil]; + NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined + location:NSMakePoint(0, 0) + modifierFlags:0 + timestamp:0 + windowNumber:0 + context:nil + subtype:0 + data1:0 + data2:0]; + [NSApp postEvent:event atStart:YES]; + }); + } } + }; public: @@ -99,30 +119,17 @@ public: return new LoopCancellation(); } - virtual void RunLoop(IAvnLoopCancellation* cancel) override + virtual HRESULT RunLoop(IAvnLoopCancellation* cancel) override { - @autoreleasepool { - auto can = dynamic_cast(cancel); - [[NSApplication sharedApplication] activateIgnoringOtherApps:true]; - while(true) - { - @autoreleasepool - { - if(can != NULL && can->Cancelled) - return; - NSEvent* ev = [[NSApplication sharedApplication] - nextEventMatchingMask:NSEventMaskAny - untilDate: [NSDate dateWithTimeIntervalSinceNow:1] - inMode:NSDefaultRunLoopMode - dequeue:true]; - if(can != NULL && can->Cancelled) - return; - if(ev != NULL) - [[NSApplication sharedApplication] sendEvent:ev]; - } - } - NSDebugLog(@"RunLoop exited"); - } + auto can = dynamic_cast(cancel); + if(can->Cancelled) + return S_OK; + if(_wasRunningAtLeastOnce) + return E_FAIL; + can->Running = true; + _wasRunningAtLeastOnce = true; + [NSApp run]; + return S_OK; } virtual void Signal(int priority) override