diff --git a/Perspex.Input/IInputElement.cs b/Perspex.Input/IInputElement.cs index f3a198b22f..3f24fa4f05 100644 --- a/Perspex.Input/IInputElement.cs +++ b/Perspex.Input/IInputElement.cs @@ -33,6 +33,8 @@ namespace Perspex.Input bool IsFocused { get; } + bool IsHitTestVisible { get; } + bool IsPointerOver { get; } void Focus(); diff --git a/Perspex.Input/IInputManager.cs b/Perspex.Input/IInputManager.cs index 1abfa053f8..c0af275865 100644 --- a/Perspex.Input/IInputManager.cs +++ b/Perspex.Input/IInputManager.cs @@ -18,6 +18,6 @@ namespace Perspex.Input void Process(RawInputEventArgs e); - void SetPointerOver(IPointerDevice device, IVisual visual, Point p); + void SetPointerOver(IPointerDevice device, IInputElement element, Point p); } } diff --git a/Perspex.Input/InputElement.cs b/Perspex.Input/InputElement.cs index af76dece85..a557db86b6 100644 --- a/Perspex.Input/InputElement.cs +++ b/Perspex.Input/InputElement.cs @@ -25,6 +25,9 @@ namespace Perspex.Input public static readonly PerspexProperty IsFocusedProperty = PerspexProperty.Register("IsFocused", false); + public static readonly PerspexProperty IsHitTestVisibleProperty = + PerspexProperty.Register("IsHitTestVisible", true); + public static readonly PerspexProperty IsPointerOverProperty = PerspexProperty.Register("IsPointerOver"); @@ -152,6 +155,12 @@ namespace Perspex.Input private set { this.SetValue(IsFocusedProperty, value); } } + public bool IsHitTestVisible + { + get { return this.GetValue(IsHitTestVisibleProperty); } + set { this.SetValue(IsHitTestVisibleProperty, value); } + } + public bool IsPointerOver { get { return this.GetValue(IsPointerOverProperty); } @@ -171,10 +180,7 @@ namespace Perspex.Input public IInputElement InputHitTest(Point p) { - return this.GetVisualsAt(p) - .OfType() - .Where(x => x.IsEnabledCore) - .FirstOrDefault(); + return this.GetInputElementsAt(p).FirstOrDefault(); } public void Focus() diff --git a/Perspex.Input/InputExtensions.cs b/Perspex.Input/InputExtensions.cs new file mode 100644 index 0000000000..2bbccef080 --- /dev/null +++ b/Perspex.Input/InputExtensions.cs @@ -0,0 +1,38 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2015 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Input +{ + using System; + using System.Collections.Generic; + using System.Linq; + + public static class InputExtensions + { + public static IEnumerable GetInputElementsAt(this IInputElement element, Point p) + { + Contract.Requires(element != null); + + if (element.Bounds.Contains(p) && element.IsHitTestVisible && element.IsEnabledCore) + { + p -= element.Bounds.Position; + + if (element.VisualChildren.Any()) + { + foreach (var child in element.VisualChildren.OfType()) + { + foreach (var result in child.GetInputElementsAt(p)) + { + yield return result; + } + } + } + + yield return element; + } + } + } +} diff --git a/Perspex.Input/InputManager.cs b/Perspex.Input/InputManager.cs index f7e9297ade..4644eb75af 100644 --- a/Perspex.Input/InputManager.cs +++ b/Perspex.Input/InputManager.cs @@ -46,11 +46,9 @@ namespace Perspex.Input this.rawEventReceived.OnNext(e); } - public void SetPointerOver(IPointerDevice device, IVisual visual, Point p) + public void SetPointerOver(IPointerDevice device, IInputElement element, Point p) { - IEnumerable hits = visual.GetVisualsAt(p) - .OfType() - .Where(x => x.IsEnabledCore); + IEnumerable hits = element.GetInputElementsAt(p); foreach (var control in this.pointerOvers.Except(hits).ToList()) { diff --git a/Perspex.Input/Perspex.Input.csproj b/Perspex.Input/Perspex.Input.csproj index 4a157110ca..9603ecde49 100644 --- a/Perspex.Input/Perspex.Input.csproj +++ b/Perspex.Input/Perspex.Input.csproj @@ -68,6 +68,7 @@ +