Browse Source

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>
pull/21812/head
Nathan Nguyen 2 months ago
committed by GitHub
parent
commit
c8da7f891e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 7
      src/Avalonia.Controls/PresentationSource/PresentationSource.cs
  2. 14
      tests/Avalonia.Controls.UnitTests/PresentationSourceTests.cs

7
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();

14
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()
{

Loading…
Cancel
Save