Skip to content

Commit 8796739

Browse files
fix: detach platform input when presentation source closes (#21782)
* test: cover platform input detachment on close Closed top levels retain the presentation source as the platform input callback. A late platform input event can therefore target an already disposed visual tree.\n\nThe regression test requires top-level closure to clear ITopLevelImpl.Input. * fix: detach platform input when presentation source closes Win32 can deliver WM_CAPTURECHANGED while destroying a popup that owns mouse capture. The platform then calls the input handler retained by the disposed presentation source, which logs a warning and can route input into a detached visual tree.\n\nClear the platform input callback at the start of presentation source disposal, alongside the existing scaling event unsubscription. --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
1 parent 6b06217 commit 8796739

2 files changed

Lines changed: 20 additions & 1 deletion

File tree

src/Avalonia.Controls/PresentationSource/PresentationSource.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,19 @@ public InputElement RootVisual
7777

7878
public void Dispose()
7979
{
80+
if (PlatformImpl is { } platformImpl)
81+
{
82+
platformImpl.Input = null;
83+
platformImpl.ScalingChanged -= HandleScalingChanged;
84+
}
85+
8086
_layoutDiagnosticBridge?.Dispose();
8187
_layoutDiagnosticBridge = null;
8288
LayoutManager.Dispose();
8389
Renderer.SceneInvalidated -= SceneInvalidated;
8490
// We need to wait for the renderer to complete any in-flight operations
8591
Renderer.Dispose();
8692

87-
PlatformImpl?.ScalingChanged -= HandleScalingChanged;
8893
PlatformImpl = null;
8994
_pointerOverPreProcessor?.OnCompleted();
9095
_pointerOverPreProcessorSubscription?.Dispose();

tests/Avalonia.Controls.UnitTests/PresentationSourceTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ namespace Avalonia.Controls.UnitTests;
1919

2020
public sealed class PresentationSourceTests : ScopedTestBase
2121
{
22+
[Fact]
23+
public void Closing_Should_Detach_Platform_Input_Handler()
24+
{
25+
using var app = UnitTestApplication.Start(TestServices.StyledWindow);
26+
var windowImpl = MockWindowingPlatform.CreateWindowMock();
27+
var window = new Window(windowImpl.Object);
28+
29+
Assert.NotNull(windowImpl.Object.Input);
30+
31+
windowImpl.Object.Closed!();
32+
33+
Assert.Null(windowImpl.Object.Input);
34+
}
35+
2236
[Fact]
2337
public void ChromeHitTest_Prefers_Overlay_Over_Content()
2438
{

0 commit comments

Comments
 (0)