Selaa lähdekoodia

Merge pull request #3553 from AvaloniaUI/fixes/3550-menu-sizing

Prevent reentrancy in LayoutManager.ExecuteInitialLayoutPass
Steven Kirk 5 vuotta sitten
vanhempi
sitoutus
239fa15823

+ 10 - 2
src/Avalonia.Layout/LayoutManager.cs

@@ -132,8 +132,16 @@ namespace Avalonia.Layout
         /// <inheritdoc/>
         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

+ 33 - 0
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);
+        }
     }
 }