Browse Source

Merge pull request #8847 from AvaloniaUI/fixes/compositing-renderer-hit-test

Filter-out child elements during hit-testing too
pull/8914/head
Nikita Tsukanov 4 years ago
committed by GitHub
parent
commit
e54388ed6b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
  2. 4
      src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs
  3. 10
      src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs
  4. 2
      src/Avalonia.Base/Rendering/Composition/Visual.cs
  5. 27
      tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs

11
src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs

@ -87,7 +87,16 @@ public class CompositingRenderer : IRendererWithCompositor
/// <inheritdoc/> /// <inheritdoc/>
public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool>? filter) public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool>? filter)
{ {
var res = CompositionTarget.TryHitTest(p, filter); Func<CompositionVisual, bool>? f = null;
if (filter != null)
f = v =>
{
if (v is CompositionDrawListVisual dlv)
return filter(dlv.Visual);
return true;
};
var res = CompositionTarget.TryHitTest(p, f);
if(res == null) if(res == null)
yield break; yield break;
foreach(var v in res) foreach(var v in res)

4
src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs

@ -54,13 +54,11 @@ internal class CompositionDrawListVisual : CompositionContainerVisual
Visual = visual; Visual = visual;
} }
internal override bool HitTest(Point pt, Func<IVisual, bool>? filter) internal override bool HitTest(Point pt)
{ {
var custom = Visual as ICustomHitTest; var custom = Visual as ICustomHitTest;
if (DrawList == null && custom == null) if (DrawList == null && custom == null)
return false; return false;
if (filter != null && !filter(Visual))
return false;
if (custom != null) if (custom != null)
{ {
// Simulate the old behavior // Simulate the old behavior

10
src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs

@ -31,7 +31,7 @@ namespace Avalonia.Rendering.Composition
/// <param name="point"></param> /// <param name="point"></param>
/// <param name="filter"></param> /// <param name="filter"></param>
/// <returns></returns> /// <returns></returns>
public PooledList<CompositionVisual>? TryHitTest(Point point, Func<IVisual, bool>? filter) public PooledList<CompositionVisual>? TryHitTest(Point point, Func<CompositionVisual, bool>? filter)
{ {
Server.Readback.NextRead(); Server.Readback.NextRead();
if (Root == null) if (Root == null)
@ -88,10 +88,14 @@ namespace Avalonia.Rendering.Composition
} }
void HitTestCore(CompositionVisual visual, Point globalPoint, PooledList<CompositionVisual> result, void HitTestCore(CompositionVisual visual, Point globalPoint, PooledList<CompositionVisual> result,
Func<IVisual, bool>? filter) Func<CompositionVisual, bool>? filter)
{ {
if (visual.Visible == false) if (visual.Visible == false)
return; return;
if (filter != null && !filter(visual))
return;
if (!TryTransformTo(visual, globalPoint, out var point)) if (!TryTransformTo(visual, globalPoint, out var point))
return; return;
@ -111,7 +115,7 @@ namespace Avalonia.Rendering.Composition
} }
// Hit-test the current node // Hit-test the current node
if (visual.HitTest(point, filter)) if (visual.HitTest(point))
result.Add(visual); result.Add(visual);
} }

2
src/Avalonia.Base/Rendering/Composition/Visual.cs

@ -53,6 +53,6 @@ namespace Avalonia.Rendering.Composition
internal object? Tag { get; set; } internal object? Tag { get; set; }
internal virtual bool HitTest(Point point, Func<IVisual, bool>? filter) => true; internal virtual bool HitTest(Point point) => true;
} }
} }

27
tests/Avalonia.Base.UnitTests/Rendering/CompositorHitTestingTests.cs

@ -432,6 +432,33 @@ public class CompositorHitTestingTests : CompositorTestsBase
s.AssertHitTest(new Point(5, 10), null, targetRectangle); s.AssertHitTest(new Point(5, 10), null, targetRectangle);
} }
} }
[Fact]
public void HitTest_Filter_Should_Filter_Out_Children()
{
using (var s = new CompositorServices(new Size(200, 200)))
{
Border child, parent;
s.TopLevel.Content = parent = new Border
{
Width = 100,
Height = 100,
Background = Brushes.Red,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Child = child = new Border
{
Background = Brushes.Red,
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
}
};
s.AssertHitTest(new Point(100, 100), null, child, parent);
s.AssertHitTest(new Point(100, 100), v => v != parent);
}
}
private IDisposable TestApplication() private IDisposable TestApplication()
{ {

Loading…
Cancel
Save