PlatformThreadingInterface.cs 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. using System;
  2. using System.Threading;
  3. using Avalonia.Platform;
  4. using Avalonia.Threading;
  5. using MonoMac.AppKit;
  6. using MonoMac.CoreGraphics;
  7. using MonoMac.Foundation;
  8. using MonoMac.ObjCRuntime;
  9. namespace Avalonia.MonoMac
  10. {
  11. class PlatformThreadingInterface : NSObject, IPlatformThreadingInterface
  12. {
  13. private bool _signaled;
  14. private const string SignaledSelectorName = "avaloniauiSignaled";
  15. private readonly Selector _signaledSelector = new Selector(SignaledSelectorName);
  16. public static PlatformThreadingInterface Instance { get; } = new PlatformThreadingInterface();
  17. public bool CurrentThreadIsLoopThread => NSThread.Current.IsMainThread;
  18. public event Action<DispatcherPriority?> Signaled;
  19. public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
  20. => NSTimer.CreateRepeatingScheduledTimer(interval, () => tick());
  21. public void Signal(DispatcherPriority prio)
  22. {
  23. lock (this)
  24. {
  25. if (_signaled)
  26. return;
  27. _signaled = true;
  28. }
  29. PerformSelector(_signaledSelector, NSThread.MainThread, this, false,
  30. new[]
  31. {
  32. NSRunLoop.NSDefaultRunLoopMode, NSRunLoop.NSRunLoopEventTracking, NSRunLoop.NSRunLoopModalPanelMode,
  33. NSRunLoop.NSRunLoopCommonModes, NSRunLoop.NSRunLoopConnectionReplyMode
  34. });
  35. }
  36. [Export(SignaledSelectorName)]
  37. public void CallSignaled()
  38. {
  39. lock (this)
  40. {
  41. if (!_signaled)
  42. return;
  43. _signaled = false;
  44. }
  45. Signaled?.Invoke(null);
  46. }
  47. public void RunLoop(CancellationToken cancellationToken)
  48. {
  49. NSApplication.SharedApplication.ActivateIgnoringOtherApps(true);
  50. var app = NSApplication.SharedApplication;
  51. cancellationToken.Register(() =>
  52. {
  53. app.PostEvent(NSEvent.OtherEvent(NSEventType.ApplicationDefined, default(CGPoint),
  54. default(NSEventModifierMask), 0, 0, null, 0, 0, 0), true);
  55. });
  56. while (!cancellationToken.IsCancellationRequested)
  57. {
  58. var ev = app.NextEvent(NSEventMask.AnyEvent, NSDate.DistantFuture, NSRunLoop.NSDefaultRunLoopMode, true);
  59. if (ev != null)
  60. {
  61. app.SendEvent(ev);
  62. ev.Dispose();
  63. }
  64. }
  65. }
  66. }
  67. }