diff --git a/src/Avalonia.Base/Rendering/RenderLoop.cs b/src/Avalonia.Base/Rendering/RenderLoop.cs index 9af9c54443..ae46a16471 100644 --- a/src/Avalonia.Base/Rendering/RenderLoop.cs +++ b/src/Avalonia.Base/Rendering/RenderLoop.cs @@ -101,6 +101,8 @@ namespace Avalonia.Rendering /// public bool RunsInBackground => _timer.RunsInBackground; + internal IRenderTimer Timer => _timer; + /// public void Wakeup() { diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index 7903a62d8f..6be81dd2d9 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -44,7 +44,7 @@ namespace Avalonia.Win32 private static Win32PlatformOptions? s_options; private static Compositor? s_compositor; internal const int TIMERID_DISPATCHER = 1; - + private const int DefaultFramesPerSecond = 60; private WndProc? _wndProcDelegate; private IntPtr _hwnd; private Win32DispatcherImpl _dispatcher; @@ -87,7 +87,7 @@ namespace Avalonia.Win32 Dispatcher.InitializeUIThreadDispatcher(s_instance._dispatcher); - var renderTimer = options.ShouldRenderOnUIThread ? new UiThreadRenderTimer(60) : new DefaultRenderTimer(60); + IRenderTimer renderTimer = options.ShouldRenderOnUIThread ? new UiThreadRenderTimer(DefaultFramesPerSecond) : new SleepLoopRenderTimer(DefaultFramesPerSecond); var clipboardImpl = new ClipboardImpl(); var clipboard = new Clipboard(clipboardImpl); @@ -133,7 +133,9 @@ namespace Avalonia.Win32 if (OleContext.Current != null) AvaloniaLocator.CurrentMutable.Bind().ToSingleton(); - + + UpdateTimerFps(); + s_compositor = new Compositor( platformGraphics); AvaloniaLocator.CurrentMutable.Bind().ToConstant(s_compositor); } @@ -196,6 +198,16 @@ namespace Avalonia.Win32 return DefWindowProc(hWnd, msg, wParam, lParam); } + internal static void UpdateTimerFps() + { + var maxDisplayFrequency = Math.Max(60, Instance.Screen?.AllScreens?.Max(s => (s as WinScreen)?.Frequency) ?? 0); + if (AvaloniaLocator.Current.GetService() is DefaultRenderLoop defaultRenderLoop && + defaultRenderLoop.Timer is SleepLoopRenderTimer sleepLoopRenderTimer) + { + sleepLoopRenderTimer.DesiredFps = maxDisplayFrequency; + } + } + private void CreateMessageWindow() { // Ensure that the delegate doesn't get garbage collected by storing it as a field. diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 42938620d9..f0140204a4 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Runtime.InteropServices; using Avalonia.Automation.Peers; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Input.Raw; +using Avalonia.Rendering; using Avalonia.Threading; using Avalonia.Win32.Automation; using Avalonia.Win32.Automation.Interop; @@ -873,6 +875,9 @@ namespace Avalonia.Win32 case WindowsMessage.WM_DISPLAYCHANGE: { Screen?.OnChanged(); + + Win32Platform.UpdateTimerFps(); + return IntPtr.Zero; }