csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
4.6 KiB
190 lines
4.6 KiB
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
|
|
#include "common.h"
|
|
|
|
class PlatformThreadingInterface;
|
|
@interface Signaler : NSObject
|
|
-(void) setParent: (PlatformThreadingInterface*)parent;
|
|
-(void) signal: (int) priority;
|
|
-(Signaler*) init;
|
|
@end
|
|
|
|
|
|
@interface ActionCallback : NSObject
|
|
- (ActionCallback*) initWithCallback: (IAvnActionCallback*) callback;
|
|
- (void) action;
|
|
@end
|
|
|
|
@implementation ActionCallback
|
|
{
|
|
ComPtr<IAvnActionCallback> _callback;
|
|
|
|
}
|
|
- (ActionCallback*) initWithCallback: (IAvnActionCallback*) callback
|
|
{
|
|
_callback = callback;
|
|
return self;
|
|
}
|
|
|
|
- (void) action
|
|
{
|
|
_callback->Run();
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
class TimerWrapper : public ComUnknownObject
|
|
{
|
|
NSTimer* _timer;
|
|
public:
|
|
TimerWrapper(IAvnActionCallback* callback, int ms)
|
|
{
|
|
auto cb = [[ActionCallback alloc] initWithCallback:callback];
|
|
_timer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)(double)ms/1000 target:cb selector:@selector(action) userInfo:nullptr repeats:true];
|
|
}
|
|
|
|
virtual ~TimerWrapper()
|
|
{
|
|
[_timer invalidate];
|
|
}
|
|
};
|
|
|
|
|
|
|
|
class PlatformThreadingInterface : public ComSingleObject<IAvnPlatformThreadingInterface, &IID_IAvnPlatformThreadingInterface>
|
|
{
|
|
private:
|
|
Signaler* _signaler;
|
|
|
|
class LoopCancellation : public ComSingleObject<IAvnLoopCancellation, &IID_IAvnLoopCancellation>
|
|
{
|
|
public:
|
|
FORWARD_IUNKNOWN()
|
|
bool Cancelled = 0;
|
|
virtual void Cancel()
|
|
{
|
|
Cancelled = 1;
|
|
}
|
|
};
|
|
|
|
public:
|
|
FORWARD_IUNKNOWN()
|
|
ComPtr<IAvnSignaledCallback> SignaledCallback;
|
|
|
|
PlatformThreadingInterface()
|
|
{
|
|
_signaler = [Signaler new];
|
|
[_signaler setParent:this];
|
|
}
|
|
|
|
~PlatformThreadingInterface()
|
|
{
|
|
if(_signaler)
|
|
[_signaler setParent: NULL];
|
|
_signaler = NULL;
|
|
}
|
|
|
|
virtual bool GetCurrentThreadIsLoopThread()
|
|
{
|
|
return [[NSThread currentThread] isMainThread];
|
|
}
|
|
virtual void SetSignaledCallback(IAvnSignaledCallback* cb)
|
|
{
|
|
SignaledCallback = cb;
|
|
}
|
|
virtual IAvnLoopCancellation* CreateLoopCancellation()
|
|
{
|
|
return new LoopCancellation();
|
|
}
|
|
|
|
virtual void RunLoop(IAvnLoopCancellation* cancel)
|
|
{
|
|
@autoreleasepool {
|
|
auto can = dynamic_cast<LoopCancellation*>(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");
|
|
}
|
|
}
|
|
|
|
virtual void Signal(int priority)
|
|
{
|
|
[_signaler signal:priority];
|
|
}
|
|
|
|
virtual IUnknown* StartTimer(int priority, int ms, IAvnActionCallback* callback)
|
|
{
|
|
@autoreleasepool {
|
|
|
|
return new TimerWrapper(callback, ms);
|
|
}
|
|
}
|
|
};
|
|
|
|
@implementation Signaler
|
|
|
|
PlatformThreadingInterface* _parent = 0;
|
|
bool _signaled = 0;
|
|
NSArray<NSString*>* _modes;
|
|
|
|
-(Signaler*) init
|
|
{
|
|
if(self = [super init])
|
|
{
|
|
_modes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode, NSRunLoopCommonModes, NSConnectionReplyMode, nil];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(void) perform
|
|
{
|
|
@synchronized (self) {
|
|
_signaled = false;
|
|
if(_parent != NULL && _parent->SignaledCallback != NULL)
|
|
_parent->SignaledCallback->Signaled(0, false);
|
|
}
|
|
}
|
|
|
|
-(void) setParent:(PlatformThreadingInterface *)parent
|
|
{
|
|
@synchronized (self) {
|
|
_parent = parent;
|
|
}
|
|
}
|
|
|
|
-(void) signal: (int) priority
|
|
{
|
|
|
|
@synchronized (self) {
|
|
if(_signaled)
|
|
return;
|
|
_signaled = true;
|
|
[self performSelector:@selector(perform) onThread:[NSThread mainThread] withObject:NULL waitUntilDone:false modes:_modes];
|
|
}
|
|
|
|
}
|
|
@end
|
|
|
|
|
|
extern IAvnPlatformThreadingInterface* CreatePlatformThreading()
|
|
{
|
|
return new PlatformThreadingInterface();
|
|
}
|
|
|