From 0842236630eff07498bf306655eb6c35d8eba761 Mon Sep 17 00:00:00 2001 From: Julien Lebosquain Date: Tue, 31 Mar 2026 13:48:55 +0200 Subject: [PATCH] Do not use visual children enumerator in TopLevelHost (#21048) * Add failing test for ExtendClientAreaToDecorationsHint in AttachedToVisualTree * Do not use visual children enumerator in TopLevelHost --- src/Avalonia.Controls/TopLevelHost.cs | 18 ++++++++---- .../WindowTests.cs | 29 +++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Controls/TopLevelHost.cs b/src/Avalonia.Controls/TopLevelHost.cs index 9592dd8221..afc4d59e7b 100644 --- a/src/Avalonia.Controls/TopLevelHost.cs +++ b/src/Avalonia.Controls/TopLevelHost.cs @@ -51,11 +51,14 @@ internal partial class TopLevelHost : Control var hasInset = inset != default; var desiredSize = default(Size); - foreach (var child in VisualChildren) + var children = VisualChildren; + var childrenCount = children.Count; + + for (var i = 0; i < childrenCount; i++) { - if (child is Layoutable l) + if (children[i] is Layoutable l) { - if (hasInset && ReferenceEquals(child, _topLevel)) + if (hasInset && ReferenceEquals(l, _topLevel)) { // In forced mode, measure the TopLevel with reduced size var contentSize = new Size( @@ -89,11 +92,14 @@ internal partial class TopLevelHost : Control var inset = _decorationInset; var hasInset = inset != default; - foreach (var child in VisualChildren) + var children = VisualChildren; + var childrenCount = children.Count; + + for (var i = 0; i < childrenCount; i++) { - if (child is Layoutable l) + if (children[i] is Layoutable l) { - if (hasInset && ReferenceEquals(child, _topLevel)) + if (hasInset && ReferenceEquals(l, _topLevel)) { // In forced mode, arrange the TopLevel within the inset area var contentSize = new Size( diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index 63cc2db193..3b2386b1d5 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -710,6 +710,35 @@ namespace Avalonia.Controls.UnitTests Assert.False(visualRoot.HasMirrorTransform); } + [Fact] + public void Extending_Client_Area_To_Decorations_When_Attached_To_Visual_Tree_Works() + { + var extended = false; + + var windowImpl = MockWindowingPlatform.CreateWindowMock(); + windowImpl.Setup(w => w.NeedsManagedDecorations).Returns(() => extended); + windowImpl.Setup(w => w.RequestedDrawnDecorations).Returns(PlatformRequestedDrawnDecoration.TitleBar); + + using var app = UnitTestApplication.Start(TestServices.StyledWindow.With( + windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object))); + + var border = new Border(); + + var window = new Window + { + Content = border + }; + + border.AttachedToVisualTree += + (_, _) => + { + extended = true; + windowImpl.Object.ExtendClientAreaToDecorationsChanged?.Invoke(true); + }; + + window.Show(); + } + public class SizingTests : ScopedTestBase { [Fact]