From fc3278d171e6bd76b05ec9ef994181faf02ef66b Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 12 Feb 2020 09:17:33 +0100 Subject: [PATCH] Merge pull request #3553 from AvaloniaUI/fixes/3550-menu-sizing Prevent reentrancy in LayoutManager.ExecuteInitialLayoutPass --- src/Avalonia.Layout/LayoutManager.cs | 12 +++++-- .../LayoutManagerTests.cs | 33 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Layout/LayoutManager.cs b/src/Avalonia.Layout/LayoutManager.cs index 855f123748..917f5408d9 100644 --- a/src/Avalonia.Layout/LayoutManager.cs +++ b/src/Avalonia.Layout/LayoutManager.cs @@ -126,8 +126,16 @@ namespace Avalonia.Layout /// public void ExecuteInitialLayoutPass(ILayoutRoot root) { - Measure(root); - Arrange(root); + try + { + _running = true; + Measure(root); + Arrange(root); + } + finally + { + _running = false; + } // Running the initial layout pass may have caused some control to be invalidated // so run a full layout pass now (this usually due to scrollbars; its not known diff --git a/tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs b/tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs index 3f20c9a76a..0165b91844 100644 --- a/tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs +++ b/tests/Avalonia.Layout.UnitTests/LayoutManagerTests.cs @@ -374,5 +374,38 @@ namespace Avalonia.Layout.UnitTests Assert.True(control.Measured); Assert.True(control.IsMeasureValid); } + + [Fact] + public void Calling_ExecuteLayoutPass_From_ExecuteInitialLayoutPass_Does_Not_Break_Measure() + { + // Test for issue #3550. + var control = new LayoutTestControl(); + var root = new LayoutTestRoot { Child = control }; + var count = 0; + + root.LayoutManager.ExecuteInitialLayoutPass(root); + control.Measured = false; + + control.DoMeasureOverride = (l, s) => + { + if (count++ == 0) + { + control.InvalidateMeasure(); + root.LayoutManager.ExecuteLayoutPass(); + return new Size(100, 100); + } + else + { + return new Size(200, 200); + } + }; + + root.InvalidateMeasure(); + control.InvalidateMeasure(); + root.LayoutManager.ExecuteInitialLayoutPass(root); + + Assert.Equal(new Size(200, 200), control.Bounds.Size); + Assert.Equal(new Size(200, 200), control.DesiredSize); + } } }