Browse Source

Accept root in IRenderer.HitTest.

Fixes #1221.
Steven Kirk 8 years ago
parent
commit
880cf657ec

+ 2 - 2
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@@ -106,7 +106,7 @@ namespace Avalonia.Rendering
         public void Dispose() => Stop();
 
         /// <inheritdoc/>
-        public IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter)
+        public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter)
         {
             if (_renderLoop == null && (_dirty == null || _dirty.Count > 0))
             {
@@ -114,7 +114,7 @@ namespace Avalonia.Rendering
                 UpdateScene();
             }
 
-            return _scene?.HitTest(p, filter) ?? Enumerable.Empty<IVisual>();
+            return _scene?.HitTest(p, root, filter) ?? Enumerable.Empty<IVisual>();
         }
 
         /// <inheritdoc/>

+ 6 - 2
src/Avalonia.Visuals/Rendering/IRenderer.cs

@@ -33,9 +33,13 @@ namespace Avalonia.Rendering
         /// Hit tests a location to find the visuals at the specified point.
         /// </summary>
         /// <param name="p">The point, in client coordinates.</param>
-        /// <param name="filter">An optional filter.</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
+        /// children will be excluded from the results.
+        /// </param>
         /// <returns>The visuals at the specified point, topmost first.</returns>
-        IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter);
+        IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter);
 
         /// <summary>
         /// Called when a resize notification is received by the control being rendered.

+ 2 - 2
src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs

@@ -136,9 +136,9 @@ namespace Avalonia.Rendering
         }
 
         /// <inheritdoc/>
-        public IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter)
+        public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter)
         {
-            return HitTest(_root, p, filter);
+            return HitTest(root, p, filter);
         }
 
         /// <inheritdoc/>

+ 5 - 2
src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs

@@ -3,6 +3,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using Avalonia.VisualTree;
 
 namespace Avalonia.Rendering.SceneGraph
@@ -113,11 +114,13 @@ namespace Avalonia.Rendering.SceneGraph
         /// Gets the visuals at a point in the scene.
         /// </summary>
         /// <param name="p">The point.</param>
+        /// <param name="root">The root of the subtree to search.</param>
         /// <param name="filter">A filter. May be null.</param>
         /// <returns>The visuals at the specified point.</returns>
-        public IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter)
+        public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter)
         {
-            return HitTest(Root, p, null, filter);
+            var node = FindNode(root);
+            return (node != null) ? HitTest(node, p, null, filter) : Enumerable.Empty<IVisual>();
         }
 
         /// <summary>

+ 1 - 1
src/Avalonia.Visuals/VisualTree/VisualExtensions.cs

@@ -133,7 +133,7 @@ namespace Avalonia.VisualTree
 
             var root = visual.GetVisualRoot();
             p = visual.TranslatePoint(p, root);
-            return root.Renderer.HitTest(p, filter);
+            return root.Renderer.HitTest(p, visual, filter);
         }
 
         /// <summary>

+ 2 - 2
tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs

@@ -59,7 +59,7 @@ namespace Avalonia.Input.UnitTests
                     }
                 };
 
-                renderer.Setup(x => x.HitTest(It.IsAny<Point>(), It.IsAny<Func<IVisual, bool>>()))
+                renderer.Setup(x => x.HitTest(It.IsAny<Point>(), It.IsAny<IVisual>(), It.IsAny<Func<IVisual, bool>>()))
                     .Returns(new[] { decorator });
 
                 inputManager.ProcessInput(new RawMouseEventArgs(
@@ -75,7 +75,7 @@ namespace Avalonia.Input.UnitTests
                 Assert.False(canvas.IsPointerOver);
                 Assert.True(root.IsPointerOver);
 
-                renderer.Setup(x => x.HitTest(It.IsAny<Point>(), It.IsAny<Func<IVisual, bool>>()))
+                renderer.Setup(x => x.HitTest(It.IsAny<Point>(), It.IsAny<IVisual>(), It.IsAny<Func<IVisual, bool>>()))
                     .Returns(new[] { canvas });
 
                 inputManager.ProcessInput(new RawMouseEventArgs(

+ 1 - 1
tests/Avalonia.LeakTests/ControlTests.cs

@@ -357,7 +357,7 @@ namespace Avalonia.LeakTests
             {
             }
 
-            public IEnumerable<IVisual> HitTest(Point p, Func<IVisual, bool> filter) => null;
+            public IEnumerable<IVisual> HitTest(Point p, IVisual root, Func<IVisual, bool> filter) => null;
 
             public void Paint(Rect rect)
             {

+ 16 - 16
tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests_HitTesting.cs

@@ -42,7 +42,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Measure(Size.Infinity);
                 root.Arrange(new Rect(root.DesiredSize));
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
 
                 Assert.Equal(new[] { root.Child }, result);
             }
@@ -70,7 +70,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Measure(Size.Infinity);
                 root.Arrange(new Rect(root.DesiredSize));
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
 
                 Assert.Empty(result);
             }
@@ -107,7 +107,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Measure(Size.Infinity);
                 root.Arrange(new Rect(root.DesiredSize));
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
 
                 Assert.Empty(result);
             }
@@ -136,7 +136,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Measure(Size.Infinity);
                 root.Arrange(new Rect(root.DesiredSize));
 
-                var result = root.Renderer.HitTest(new Point(10, 10), null);
+                var result = root.Renderer.HitTest(new Point(10, 10), root, null);
 
                 Assert.Empty(result);
             }
@@ -180,7 +180,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Measure(Size.Infinity);
                 root.Arrange(new Rect(container.DesiredSize));
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
 
                 Assert.Equal(new[] { container.Children[1], container.Children[0] }, result);
             }
@@ -234,7 +234,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Measure(Size.Infinity);
                 root.Arrange(new Rect(container.DesiredSize));
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
 
                 Assert.Equal(new[] { container.Children[2], container.Children[0], container.Children[1] }, result);
             }
@@ -283,7 +283,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 container.Measure(Size.Infinity);
                 container.Arrange(new Rect(container.DesiredSize));
 
-                var result = root.Renderer.HitTest(new Point(120, 120), null);
+                var result = root.Renderer.HitTest(new Point(120, 120), root, null);
 
                 Assert.Equal(new IVisual[] { target, container }, result);
             }
@@ -331,7 +331,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Measure(Size.Infinity);
                 root.Arrange(new Rect(container.DesiredSize));
 
-                var result = root.Renderer.HitTest(new Point(50, 50), null);
+                var result = root.Renderer.HitTest(new Point(50, 50), root, null);
 
                 Assert.Equal(new[] { container }, result);
             }
@@ -404,11 +404,11 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Measure(Size.Infinity);
                 root.Arrange(new Rect(container.DesiredSize));
 
-                var result = root.Renderer.HitTest(new Point(50, 150), null).First();
+                var result = root.Renderer.HitTest(new Point(50, 150), root, null).First();
 
                 Assert.Equal(item1, result);
 
-                result = root.Renderer.HitTest(new Point(50, 50), null).First();
+                result = root.Renderer.HitTest(new Point(50, 50), root, null).First();
 
                 Assert.Equal(target, result);
 
@@ -419,10 +419,10 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 container.InvalidateArrange();
                 container.Arrange(new Rect(container.DesiredSize));
 
-                result = root.Renderer.HitTest(new Point(50, 150), null).First();
+                result = root.Renderer.HitTest(new Point(50, 150), root, null).First();
                 Assert.Equal(item2, result);
 
-                result = root.Renderer.HitTest(new Point(50, 50), null).First();
+                result = root.Renderer.HitTest(new Point(50, 50), root, null).First();
                 Assert.Equal(target, result);
             }
         }
@@ -452,10 +452,10 @@ namespace Avalonia.Visuals.UnitTests.Rendering
 
                 var context = new DrawingContext(Mock.Of<IDrawingContextImpl>());
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
                 Assert.Equal(new[] { path }, result);
 
-                result = root.Renderer.HitTest(new Point(10, 10), null);
+                result = root.Renderer.HitTest(new Point(10, 10), root, null);
                 Assert.Empty(result);
             }
         }
@@ -492,10 +492,10 @@ namespace Avalonia.Visuals.UnitTests.Rendering
 
                 var context = new DrawingContext(Mock.Of<IDrawingContextImpl>());
 
-                var result = root.Renderer.HitTest(new Point(200, 200), null);
+                var result = root.Renderer.HitTest(new Point(200, 200), root, null);
                 Assert.Equal(new IVisual[] { canvas, border }, result);
 
-                result = root.Renderer.HitTest(new Point(110, 110), null);
+                result = root.Renderer.HitTest(new Point(110, 110), root, null);
                 Assert.Empty(result);
             }
         }

+ 11 - 11
tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests_HitTesting.cs

@@ -40,7 +40,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Arrange(new Rect(root.DesiredSize));
                 root.Renderer.Paint(new Rect(root.ClientSize));
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
 
                 Assert.Equal(new[] { root.Child, root }, result);
             }
@@ -78,7 +78,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Arrange(new Rect(root.DesiredSize));
                 root.Renderer.Paint(new Rect(root.ClientSize));
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
 
                 Assert.Equal(new[] { root }, result);
             }
@@ -108,7 +108,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Arrange(new Rect(root.DesiredSize));
                 root.Renderer.Paint(new Rect(root.ClientSize));
 
-                var result = root.Renderer.HitTest(new Point(10, 10), null);
+                var result = root.Renderer.HitTest(new Point(10, 10), root, null);
 
                 Assert.Equal(new[] { root }, result);
             }
@@ -153,7 +153,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Arrange(new Rect(container.DesiredSize));
                 root.Renderer.Paint(new Rect(root.ClientSize));
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
 
                 Assert.Equal(new[] { container.Children[1], container.Children[0], container, root }, result);
             }
@@ -208,7 +208,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Arrange(new Rect(container.DesiredSize));
                 root.Renderer.Paint(new Rect(root.ClientSize));
 
-                var result = root.Renderer.HitTest(new Point(100, 100), null);
+                var result = root.Renderer.HitTest(new Point(100, 100), root, null);
 
                 Assert.Equal(
                     new[] 
@@ -267,7 +267,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 container.Arrange(new Rect(container.DesiredSize));
                 root.Renderer.Paint(new Rect(root.ClientSize));
 
-                var result = root.Renderer.HitTest(new Point(120, 120), null);
+                var result = root.Renderer.HitTest(new Point(120, 120), root, null);
 
                 Assert.Equal(new IVisual[] { target, container }, result);
             }
@@ -316,7 +316,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Arrange(new Rect(container.DesiredSize));
                 root.Renderer.Paint(new Rect(root.ClientSize));
 
-                var result = root.Renderer.HitTest(new Point(50, 50), null);
+                var result = root.Renderer.HitTest(new Point(50, 50), root, null);
 
                 Assert.Equal(new IVisual[] { container, root }, result);
             }
@@ -390,11 +390,11 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 root.Arrange(new Rect(container.DesiredSize));
                 root.Renderer.Paint(new Rect(root.ClientSize));
 
-                var result = root.Renderer.HitTest(new Point(50, 150), null).First();
+                var result = root.Renderer.HitTest(new Point(50, 150), root, null).First();
 
                 Assert.Equal(item1, result);
 
-                result = root.Renderer.HitTest(new Point(50, 50), null).First();
+                result = root.Renderer.HitTest(new Point(50, 50), root, null).First();
 
                 Assert.Equal(target, result);
 
@@ -406,10 +406,10 @@ namespace Avalonia.Visuals.UnitTests.Rendering
                 container.Arrange(new Rect(container.DesiredSize));
                 root.Renderer.Paint(new Rect(root.ClientSize));
 
-                result = root.Renderer.HitTest(new Point(50, 150), null).First();
+                result = root.Renderer.HitTest(new Point(50, 150), root, null).First();
                 Assert.Equal(item2, result);
 
-                result = root.Renderer.HitTest(new Point(50, 50), null).First();
+                result = root.Renderer.HitTest(new Point(50, 50), root, null).First();
                 Assert.Equal(target, result);
             }
         }