diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index f314629d02..1853d67019 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -184,7 +184,7 @@ namespace Avalonia.Controls
///
/// Gets the renderer for the window.
///
- public IRenderer Renderer { get; }
+ public IRenderer Renderer { get; private set; }
///
/// Gets the access key handler for the window.
@@ -381,6 +381,8 @@ namespace Avalonia.Controls
private void HandleClosed()
{
Closed?.Invoke(this, EventArgs.Empty);
+ Renderer?.Dispose();
+ Renderer = null;
_applicationLifecycle.OnExit -= OnApplicationExiting;
}
diff --git a/tests/Avalonia.LeakTests/ControlTests.cs b/tests/Avalonia.LeakTests/ControlTests.cs
index 1e257a698c..23670257ff 100644
--- a/tests/Avalonia.LeakTests/ControlTests.cs
+++ b/tests/Avalonia.LeakTests/ControlTests.cs
@@ -11,6 +11,7 @@ using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Diagnostics;
using Avalonia.Layout;
+using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.UnitTests;
@@ -301,6 +302,33 @@ namespace Avalonia.LeakTests
}
}
+
+ [Fact]
+ public void RendererIsDisposed()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var renderer = new Mock();
+ renderer.Setup(x => x.Dispose());
+ var impl = new Mock();
+ impl.SetupGet(x => x.Scaling).Returns(1);
+ impl.SetupProperty(x => x.Closed);
+ impl.Setup(x => x.Dispose()).Callback(() => impl.Object.Closed());
+
+ AvaloniaLocator.CurrentMutable.Bind()
+ .ToConstant(new MockWindowingPlatform(() => impl.Object));
+ AvaloniaLocator.CurrentMutable.Bind()
+ .ToConstant(new MockRendererFactory(renderer.Object));
+ var window = new Window()
+ {
+ Content = new Button()
+ };
+ window.Show();
+ window.Close();
+ renderer.Verify(r => r.Dispose());
+ }
+ }
+
private static void PurgeMoqReferences()
{
// Moq holds onto references in its mock of IRenderer in case we want to check if a method has been called;
diff --git a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
index 7a84243953..f7878ab91a 100644
--- a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
+++ b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
@@ -55,6 +55,7 @@
+
diff --git a/tests/Avalonia.UnitTests/MockRendererFactory.cs b/tests/Avalonia.UnitTests/MockRendererFactory.cs
new file mode 100644
index 0000000000..e62012b13c
--- /dev/null
+++ b/tests/Avalonia.UnitTests/MockRendererFactory.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Rendering;
+
+namespace Avalonia.UnitTests
+{
+ public class MockRendererFactory : IRendererFactory
+ {
+ private readonly Func _cb;
+
+ public MockRendererFactory(Func cb = null)
+ {
+ _cb = cb;
+ }
+
+ public MockRendererFactory(IRenderer renderer) : this((_, __) => renderer)
+ {
+
+ }
+
+ public IRenderer CreateRenderer(IRenderRoot root, IRenderLoop renderLoop)
+ {
+ return _cb?.Invoke(root, renderLoop);
+ }
+ }
+}