Browse Source

Fix subtree input hit test coordinates (#21125)

* Add regression test for subtree input hit testing

* Fix subtree input hit test coordinates
pull/20366/merge
Nathan Nguyen 1 month ago
committed by GitHub
parent
commit
c310fedbbf
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      src/Avalonia.Base/Rendering/IRenderer.cs
  2. 13
      src/Avalonia.Base/VisualTree/VisualExtensions.cs
  3. 49
      tests/Avalonia.Base.UnitTests/Input/InputExtensionsTests.cs

2
src/Avalonia.Base/Rendering/IRenderer.cs

@ -84,7 +84,7 @@ namespace Avalonia.Rendering
/// <para>⚠️ This method is low-level and <b>DOES NOT respect <see cref="Input.InputElement.IsHitTestVisible"/></b>.</para>
/// <para>Use <see cref="Input.InputExtensions"/> to perform input hit testing, or provide your own <paramref name="filter"/> function.</para>
/// </remarks>
/// <param name="p">The point, in client coordinates.</param>
/// <param name="p">The point, in coordinates relative to <paramref name="root"/>.</param>
/// <param name="root">The root of the subtree to search.</param>
/// <param name="filter">
/// A filter predicate. If the predicate returns false then the visual and all its

13
src/Avalonia.Base/VisualTree/VisualExtensions.cs

@ -334,21 +334,12 @@ namespace Avalonia.VisualTree
ThrowHelper.ThrowIfNull(visual, nameof(visual));
var source = visual.GetPresentationSource();
var root = source?.RootVisual;
if (source is null || root is null)
if (source is null)
{
return null;
}
var rootPoint = visual.TranslatePoint(p, (Visual)root);
if (rootPoint.HasValue)
{
return source.HitTester.HitTestFirst(rootPoint.Value, visual, filter);
}
return null;
return source.HitTester.HitTestFirst(p, visual, filter);
}
/// <summary>

49
tests/Avalonia.Base.UnitTests/Input/InputExtensionsTests.cs

@ -0,0 +1,49 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Base.UnitTests.Input;
public class InputExtensionsTests
{
[Fact]
public void InputHitTest_Should_Use_Coordinates_Relative_To_The_Subtree_Root()
{
Border target;
using var services = new CompositorTestServices(new Size(200, 200))
{
TopLevel =
{
Content = new StackPanel
{
Background = Brushes.White,
Children =
{
new Border
{
Width = 100,
Height = 200,
Background = Brushes.Red,
},
(target = new Border
{
Width = 100,
Height = 200,
Background = Brushes.Green,
})
},
Orientation = Orientation.Horizontal,
}
}
};
services.RunJobs();
var result = target.InputHitTest(new Point(50, 50), enabledElementsOnly: false);
Assert.Same(target, result);
}
}
Loading…
Cancel
Save