summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.MacOS/CADisplayLinkTicker.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.MacOS/CADisplayLinkTicker.cs')
-rw-r--r--Xamarin.Forms.Platform.MacOS/CADisplayLinkTicker.cs78
1 files changed, 78 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.MacOS/CADisplayLinkTicker.cs b/Xamarin.Forms.Platform.MacOS/CADisplayLinkTicker.cs
new file mode 100644
index 00000000..1e965ff5
--- /dev/null
+++ b/Xamarin.Forms.Platform.MacOS/CADisplayLinkTicker.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Concurrent;
+using System.Threading;
+using Foundation;
+using Xamarin.Forms.Internals;
+using CoreVideo;
+using AppKit;
+using CoreAnimation;
+
+namespace Xamarin.Forms.Platform.MacOS
+{
+ // ReSharper disable once InconsistentNaming
+ internal class CADisplayLinkTicker : Ticker
+ {
+ readonly BlockingCollection<Action> _queue = new BlockingCollection<Action>();
+ CVDisplayLink _link;
+
+ public CADisplayLinkTicker()
+ {
+ var thread = new Thread(StartThread);
+ thread.Start();
+ }
+
+ internal new static CADisplayLinkTicker Default => Ticker.Default as CADisplayLinkTicker;
+
+ public void Invoke(Action action)
+ {
+ _queue.Add(action);
+ }
+
+ protected override void DisableTimer()
+ {
+ _link?.Stop();
+ _link?.Dispose();
+ _link = null;
+ }
+
+ protected override void EnableTimer()
+ {
+ _link = new CVDisplayLink();
+ _link.SetOutputCallback(DisplayLinkOutputCallback);
+ _link.Start();
+ }
+
+ public CVReturn DisplayLinkOutputCallback(CVDisplayLink displayLink, ref CVTimeStamp inNow,
+ ref CVTimeStamp inOutputTime, CVOptionFlags flagsIn, ref CVOptionFlags flagsOut)
+ {
+ // There is no autorelease pool when this method is called because it will be called from a background thread
+ // It's important to create one or you will leak objects
+ // ReSharper disable once UnusedVariable
+ using (var pool = new NSAutoreleasePool())
+ {
+ Device.BeginInvokeOnMainThread(() => SendSignals());
+ }
+ return CVReturn.Success;
+ }
+
+ void StartThread()
+ {
+ while (true)
+ {
+ Action action = _queue.Take();
+ bool previous = NSApplication.CheckForIllegalCrossThreadCalls;
+ NSApplication.CheckForIllegalCrossThreadCalls = false;
+
+ CATransaction.Begin();
+ action.Invoke();
+
+ while (_queue.TryTake(out action))
+ action.Invoke();
+ CATransaction.Commit();
+
+ NSApplication.CheckForIllegalCrossThreadCalls = previous;
+ }
+ // ReSharper disable once FunctionNeverReturns
+ }
+ }
+} \ No newline at end of file