diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 0fd4572088..69b3152e9b 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -2,10 +2,8 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using System.Reflection; using System.Threading; using Avalonia.Controls; -using Avalonia.Controls.Platform; using Avalonia.Controls.Templates; using Avalonia.Input; using Avalonia.Input.Platform; @@ -112,11 +110,6 @@ namespace Avalonia /// public Styles Styles { get; } = new Styles(); - /// - /// Gets the application's render loop. - /// - public IRenderLoop RenderLoop { get; private set; } - /// /// Gets the styling parent of the application, which is null. /// @@ -172,7 +165,6 @@ namespace Avalonia AvaloniaSynchronizationContext.InstallIfNeeded(); FocusManager = new FocusManager(); InputManager = new InputManager(); - RenderLoop = new RenderLoop(60); AvaloniaLocator.CurrentMutable .Bind().ToTransient() @@ -184,7 +176,6 @@ namespace Avalonia .Bind().ToConstant(_styler) .Bind().ToSingleton() .Bind().ToTransient() - .Bind().ToConstant(RenderLoop) .Bind().ToConstant(this); } } diff --git a/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj b/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj index 320590ab5e..18f5c58c61 100644 --- a/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj +++ b/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj @@ -106,7 +106,7 @@ - + diff --git a/src/Avalonia.SceneGraph/Rendering/DefaultRenderLoop.cs b/src/Avalonia.SceneGraph/Rendering/DefaultRenderLoop.cs new file mode 100644 index 0000000000..5210b0a98f --- /dev/null +++ b/src/Avalonia.SceneGraph/Rendering/DefaultRenderLoop.cs @@ -0,0 +1,102 @@ +// 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. + +using System; +using Avalonia.Platform; + +namespace Avalonia.Rendering +{ + /// + /// Defines a default render loop that uses a standard timer. + /// + /// + /// This class may be overridden by platform implementations to use a specialized timer + /// implementation. + /// + public class DefaultRenderLoop : IRenderLoop + { + private IPlatformThreadingInterface _threading; + private int _subscriberCount; + private EventHandler _tick; + private IDisposable _subscription; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The number of frames per second at which the loop should run. + /// + public DefaultRenderLoop(int framesPerSecond) + { + FramesPerSecond = framesPerSecond; + } + + /// + /// Gets the number of frames per second at which the loop runs. + /// + public int FramesPerSecond { get; } + + /// + public event EventHandler Tick + { + add + { + if (_subscriberCount++ == 0) + { + Start(); + } + + _tick += value; + } + + remove + { + if (--_subscriberCount == 0) + { + Stop(); + } + + _tick -= value; + } + } + + /// + /// Starts the timer. + /// + protected void Start() + { + _subscription = StartCore(); + } + + /// + /// Provides the implementation of starting the timer. + /// + /// + /// This can be overridden by platform implementations to use a specialized timer + /// implementation. + /// + protected virtual IDisposable StartCore() + { + if (_threading == null) + { + _threading = AvaloniaLocator.Current.GetService(); + } + + return _threading.StartTimer(TimeSpan.FromSeconds(1.0 / FramesPerSecond), InternalTick); + } + + /// + /// Stops the timer. + /// + protected void Stop() + { + _subscription.Dispose(); + _subscription = null; + } + + private void InternalTick() + { + _tick(this, EventArgs.Empty); + } + } +} diff --git a/src/Avalonia.SceneGraph/Rendering/IRenderLoop.cs b/src/Avalonia.SceneGraph/Rendering/IRenderLoop.cs index 504dc185a2..049ad1665c 100644 --- a/src/Avalonia.SceneGraph/Rendering/IRenderLoop.cs +++ b/src/Avalonia.SceneGraph/Rendering/IRenderLoop.cs @@ -2,8 +2,14 @@ namespace Avalonia.Rendering { + /// + /// Defines the interface implemented by an application render loop. + /// public interface IRenderLoop { + /// + /// Raised when the render loop ticks to signal a new frame should be drawn. + /// event EventHandler Tick; } } \ No newline at end of file diff --git a/src/Avalonia.SceneGraph/Rendering/RenderLoop.cs b/src/Avalonia.SceneGraph/Rendering/RenderLoop.cs deleted file mode 100644 index a7ba01b1bc..0000000000 --- a/src/Avalonia.SceneGraph/Rendering/RenderLoop.cs +++ /dev/null @@ -1,66 +0,0 @@ -// 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. - -using System; -using Avalonia.Platform; - -namespace Avalonia.Rendering -{ - public class RenderLoop : IRenderLoop - { - private readonly int _fps; - private IPlatformThreadingInterface _threading; - private int _subscriberCount; - private EventHandler _tick; - private IDisposable _subscription; - - public RenderLoop(int fps) - { - _fps = fps; - } - - public event EventHandler Tick - { - add - { - if (_subscriberCount++ == 0) - { - Start(); - } - - _tick += value; - } - - remove - { - if (--_subscriberCount == 0) - { - Stop(); - } - - _tick -= value; - } - } - - protected void Start() - { - if (_threading == null) - { - _threading = AvaloniaLocator.Current.GetService(); - } - - _subscription = _threading.StartTimer(TimeSpan.FromSeconds(1.0 / _fps), InternalTick); - } - - protected void Stop() - { - _subscription.Dispose(); - _subscription = null; - } - - private void InternalTick() - { - _tick(this, EventArgs.Empty); - } - } -} diff --git a/src/Gtk/Avalonia.Gtk/GtkPlatform.cs b/src/Gtk/Avalonia.Gtk/GtkPlatform.cs index e79c51915d..aaeba75b50 100644 --- a/src/Gtk/Avalonia.Gtk/GtkPlatform.cs +++ b/src/Gtk/Avalonia.Gtk/GtkPlatform.cs @@ -25,6 +25,7 @@ namespace Avalonia namespace Avalonia.Gtk { using System.IO; + using Rendering; using Gtk = global::Gtk; public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader @@ -53,6 +54,7 @@ namespace Avalonia.Gtk .Bind().ToConstant(GtkMouseDevice.Instance) .Bind().ToConstant(s_instance) .Bind().ToConstant(s_instance) + .Bind().ToConstant(new DefaultRenderLoop(60)) .Bind().ToSingleton() .Bind().ToConstant(s_instance); _uiThread = Thread.CurrentThread; diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index 4aa1346a98..9b65e64e00 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -16,6 +16,7 @@ using Avalonia.Win32.Input; using Avalonia.Win32.Interop; using Avalonia.Controls; using System.IO; +using Avalonia.Rendering; namespace Avalonia { @@ -65,6 +66,7 @@ namespace Avalonia.Win32 .Bind().ToConstant(WindowsMouseDevice.Instance) .Bind().ToConstant(s_instance) .Bind().ToConstant(s_instance) + .Bind().ToConstant(new DefaultRenderLoop(60)) .Bind().ToSingleton() .Bind().ToConstant(s_instance) .Bind().ToConstant(s_instance);