Browse Source

Raise pointer events on captured element (#18420)

pull/18430/head
Julien Lebosquain 1 year ago
committed by GitHub
parent
commit
3c7c469018
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 14
      src/Avalonia.Base/Input/PointerOverPreProcessor.cs
  2. 15
      tests/Avalonia.Base.UnitTests/Input/PointerOverTests.cs

14
src/Avalonia.Base/Input/PointerOverPreProcessor.cs

@ -79,7 +79,9 @@ namespace Avalonia.Input
else if (pointerDevice.TryGetPointer(args) is { } pointer &&
pointer.Type != PointerType.Touch)
{
var element = pointer.Captured ?? args.InputHitTestResult.firstEnabledAncestor;
var element = GetEffectivePointerOverElement(
args.InputHitTestResult.firstEnabledAncestor,
pointer.Captured);
SetPointerOver(pointer, args.Root, element, args.Timestamp, args.Position,
new PointerPointProperties(args.InputModifiers, args.Type.ToUpdateKind()),
@ -96,7 +98,10 @@ namespace Avalonia.Input
if (dirtyRect.Contains(clientPoint))
{
var element = pointer.Captured ?? _inputRoot.InputHitTest(clientPoint);
var element = GetEffectivePointerOverElement(
_inputRoot.InputHitTest(clientPoint),
pointer.Captured);
SetPointerOver(pointer, _inputRoot, element, 0, clientPoint, PointerPointProperties.None, KeyModifiers.None);
}
else if (!((Visual)_inputRoot).Bounds.Contains(clientPoint))
@ -106,6 +111,11 @@ namespace Avalonia.Input
}
}
private static IInputElement? GetEffectivePointerOverElement(IInputElement? hitTestElement, IInputElement? captured)
=> captured is not null && hitTestElement != captured ?
null :
hitTestElement;
private void ClearPointerOver()
{
if (_currentPointer is (var pointer, var position))

15
tests/Avalonia.Base.UnitTests/Input/PointerOverTests.cs

@ -120,7 +120,7 @@ namespace Avalonia.Base.UnitTests.Input
}
[Fact]
public void HitTest_Should_Be_Ignored_If_Element_Captured()
public void HitTest_Should_Ignore_Non_Captured_Elements()
{
using var app = UnitTestApplication.Start(new TestServices(inputManager: new InputManager()));
@ -145,8 +145,19 @@ namespace Avalonia.Base.UnitTests.Input
}
}, renderer.Object);
SetHit(renderer, canvas);
pointer.SetupGet(p => p.Captured).Returns(decorator);
// Move the pointer over the canvas: the captured decorator should lose the pointer over state.
SetHit(renderer, canvas);
impl.Object.Input!(CreateRawPointerMovedArgs(device, root));
Assert.False(decorator.IsPointerOver);
Assert.False(border.IsPointerOver);
Assert.False(canvas.IsPointerOver);
Assert.False(root.IsPointerOver);
// Move back the pointer over the decorator: raise events normally for it since it's captured.
SetHit(renderer, decorator);
impl.Object.Input!(CreateRawPointerMovedArgs(device, root));
Assert.True(decorator.IsPointerOver);

Loading…
Cancel
Save