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;
}