diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs index 1dfa2d7af2..08b795e9a1 100644 --- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs +++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs @@ -120,7 +120,7 @@ namespace Avalonia.Controls.Primitives info.Subscription = _tracker.Track(adorned).Subscribe(x => { - info.Bounds = x; + info.Bounds = x.Value; InvalidateArrange(); }); } diff --git a/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs b/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs index 0bb5bf63f8..416cdb9855 100644 --- a/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs +++ b/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs @@ -142,11 +142,28 @@ namespace Avalonia.Rendering var childClipRect = clipRect.Translate(-childBounds.Position); context.Render(child, childClipRect); } + else + { + ClearTransformedBounds(child); + } } ReturnListToPool(lst); } } + + if (!visual.IsVisible) + { + ClearTransformedBounds(visual); + } + } + + private static void ClearTransformedBounds(IVisual visual) + { + foreach (var e in visual.GetSelfAndVisualDescendents()) + { + BoundsTracker.SetTransformedBounds((Visual)visual, null); + } } private static void ReturnListToPool(List lst) diff --git a/src/Avalonia.SceneGraph/VisualTree/BoundsTracker.cs b/src/Avalonia.SceneGraph/VisualTree/BoundsTracker.cs index 4ad67c45b7..42c4e3c98e 100644 --- a/src/Avalonia.SceneGraph/VisualTree/BoundsTracker.cs +++ b/src/Avalonia.SceneGraph/VisualTree/BoundsTracker.cs @@ -9,33 +9,43 @@ namespace Avalonia.VisualTree /// Tracks the bounds of a control. /// /// - /// This class is used by Adorners to track the control that the adorner is attached to. + /// This class is used to track a controls's bounds for hit testing. + /// TODO: This shouldn't be implemented as an attached property: it would be more performant + /// to just store bounds in some sort of central repository. /// public class BoundsTracker { - private static AttachedProperty TransformedBoundsProperty = - AvaloniaProperty.RegisterAttached("TransformedBounds"); + /// + /// Defines the TransformedBounds attached property. + /// + private static AttachedProperty TransformedBoundsProperty = + AvaloniaProperty.RegisterAttached("TransformedBounds"); /// /// Starts tracking the specified visual. /// /// The visual. /// An observable that returns the tracked bounds. - public IObservable Track(Visual visual) + public IObservable Track(Visual visual) { return visual.GetObservable(TransformedBoundsProperty); } - internal static void SetTransformedBounds(Visual visual, TransformedBounds bounds) + /// + /// Sets the transformed bounds of the visual. + /// + /// The visual. + /// The transformed bounds. + internal static void SetTransformedBounds(Visual visual, TransformedBounds? value) { - visual.SetValue(TransformedBoundsProperty, bounds); + visual.SetValue(TransformedBoundsProperty, value); } /// /// Gets the transformed bounds of the visual. /// /// The visual. - /// The transformed bounds. - public static TransformedBounds GetTransformedBounds(Visual visual) => visual.GetValue(TransformedBoundsProperty); + /// The transformed bounds or null if the visual is not visible. + public static TransformedBounds? GetTransformedBounds(Visual visual) => visual.GetValue(TransformedBoundsProperty); } } diff --git a/src/Avalonia.SceneGraph/VisualTree/VisualExtensions.cs b/src/Avalonia.SceneGraph/VisualTree/VisualExtensions.cs index a2e6e1e29f..e7876b762f 100644 --- a/src/Avalonia.SceneGraph/VisualTree/VisualExtensions.cs +++ b/src/Avalonia.SceneGraph/VisualTree/VisualExtensions.cs @@ -104,7 +104,7 @@ namespace Avalonia.VisualTree if (filter?.Invoke(visual) != false) { - bool containsPoint = BoundsTracker.GetTransformedBounds((Visual)visual).Contains(p); + bool containsPoint = BoundsTracker.GetTransformedBounds((Visual)visual)?.Contains(p) == true; if ((containsPoint || !visual.ClipToBounds) && visual.VisualChildren.Any()) { diff --git a/tests/Avalonia.SceneGraph.UnitTests/VisualTree/BoundsTrackerTests.cs b/tests/Avalonia.SceneGraph.UnitTests/VisualTree/BoundsTrackerTests.cs index 75eb9c3a50..93b8a088d8 100644 --- a/tests/Avalonia.SceneGraph.UnitTests/VisualTree/BoundsTrackerTests.cs +++ b/tests/Avalonia.SceneGraph.UnitTests/VisualTree/BoundsTrackerTests.cs @@ -46,11 +46,11 @@ namespace Avalonia.SceneGraph.UnitTests.VisualTree context.Render(tree); var track = target.Track(control); - var results = new List(); + var results = new List(); track.Subscribe(results.Add); - Assert.Equal(new Rect(0, 0, 15, 15), results[0].Bounds); - Assert.Equal(Matrix.CreateTranslation(42, 42), results[0].Transform); + Assert.Equal(new Rect(0, 0, 15, 15), results[0].Value.Bounds); + Assert.Equal(Matrix.CreateTranslation(42, 42), results[0].Value.Transform); } } }