diff --git a/src/Avalonia.Controls/PresentationSource/PresentationSource.cs b/src/Avalonia.Controls/PresentationSource/PresentationSource.cs index c2d5516667..60ec963e6f 100644 --- a/src/Avalonia.Controls/PresentationSource/PresentationSource.cs +++ b/src/Avalonia.Controls/PresentationSource/PresentationSource.cs @@ -77,6 +77,12 @@ internal partial class PresentationSource : IPresentationSource, IInputRoot, IDi public void Dispose() { + if (PlatformImpl is { } platformImpl) + { + platformImpl.Input = null; + platformImpl.ScalingChanged -= HandleScalingChanged; + } + _layoutDiagnosticBridge?.Dispose(); _layoutDiagnosticBridge = null; LayoutManager.Dispose(); @@ -84,7 +90,6 @@ internal partial class PresentationSource : IPresentationSource, IInputRoot, IDi // We need to wait for the renderer to complete any in-flight operations Renderer.Dispose(); - PlatformImpl?.ScalingChanged -= HandleScalingChanged; PlatformImpl = null; _pointerOverPreProcessor?.OnCompleted(); _pointerOverPreProcessorSubscription?.Dispose(); diff --git a/tests/Avalonia.Controls.UnitTests/PresentationSourceTests.cs b/tests/Avalonia.Controls.UnitTests/PresentationSourceTests.cs index 97892e9b4c..9a8172d3cf 100644 --- a/tests/Avalonia.Controls.UnitTests/PresentationSourceTests.cs +++ b/tests/Avalonia.Controls.UnitTests/PresentationSourceTests.cs @@ -19,6 +19,20 @@ namespace Avalonia.Controls.UnitTests; public sealed class PresentationSourceTests : ScopedTestBase { + [Fact] + public void Closing_Should_Detach_Platform_Input_Handler() + { + using var app = UnitTestApplication.Start(TestServices.StyledWindow); + var windowImpl = MockWindowingPlatform.CreateWindowMock(); + var window = new Window(windowImpl.Object); + + Assert.NotNull(windowImpl.Object.Input); + + windowImpl.Object.Closed!(); + + Assert.Null(windowImpl.Object.Input); + } + [Fact] public void ChromeHitTest_Prefers_Overlay_Over_Content() {