Browse Source

Merge pull request #11233 from AvaloniaUI/fixes/7706-scrollbar-stuck

Fix scrollbar getting stuck in certain situations
pull/11247/head
Max Katz 3 years ago
committed by GitHub
parent
commit
cc2d755449
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      src/Avalonia.Base/Layout/LayoutManager.cs
  2. 33
      tests/Avalonia.Base.UnitTests/Layout/LayoutManagerTests.cs

27
src/Avalonia.Base/Layout/LayoutManager.cs

@ -21,6 +21,7 @@ namespace Avalonia.Layout
private readonly Layoutable _owner;
private readonly LayoutQueue<Layoutable> _toMeasure = new LayoutQueue<Layoutable>(v => !v.IsMeasureValid);
private readonly LayoutQueue<Layoutable> _toArrange = new LayoutQueue<Layoutable>(v => !v.IsArrangeValid);
private readonly List<Layoutable> _toArrangeAfterMeasure = new();
private readonly Action _executeLayoutPass;
private List<EffectiveViewportChangedListener>? _effectiveViewportChangedListeners;
private bool _disposed;
@ -266,9 +267,14 @@ namespace Avalonia.Layout
if (!control.IsArrangeValid)
{
Arrange(control);
if (Arrange(control) == ArrangeResult.AncestorMeasureInvalid)
_toArrangeAfterMeasure.Add(control);
}
}
foreach (var i in _toArrangeAfterMeasure)
InvalidateArrange(i);
_toArrangeAfterMeasure.Clear();
}
private bool Measure(Layoutable control)
@ -304,19 +310,19 @@ namespace Avalonia.Layout
return true;
}
private bool Arrange(Layoutable control)
private ArrangeResult Arrange(Layoutable control)
{
if (!control.IsVisible || !control.IsAttachedToVisualTree)
return false;
return ArrangeResult.NotVisible;
if (control.VisualParent is Layoutable parent)
{
if (!Arrange(parent))
return false;
if (Arrange(parent) is var parentResult && parentResult != ArrangeResult.Arranged)
return parentResult;
}
if (!control.IsMeasureValid)
return false;
return ArrangeResult.AncestorMeasureInvalid;
if (!control.IsArrangeValid)
{
@ -332,7 +338,7 @@ namespace Avalonia.Layout
}
}
return true;
return ArrangeResult.Arranged;
}
private void QueueLayoutPass()
@ -435,5 +441,12 @@ namespace Avalonia.Layout
public Layoutable Listener { get; }
public Rect Viewport { get; set; }
}
private enum ArrangeResult
{
Arranged,
NotVisible,
AncestorMeasureInvalid,
}
}
}

33
tests/Avalonia.Base.UnitTests/Layout/LayoutManagerTests.cs

@ -547,5 +547,38 @@ namespace Avalonia.Base.UnitTests.Layout
Assert.True(root.IsMeasureValid);
Assert.True(root.IsArrangeValid);
}
[Fact]
public void GreatGrandparent_Can_Invalidate_Grandparent_Measure_During_Arrange()
{
// Issue #7706 (second part: scrollbar gets stuck)
var child = new LayoutTestControl();
var parent = new LayoutTestControl { Child = child };
var grandparent = new LayoutTestControl { Child = parent };
var greatGrandparent = new LayoutTestControl { Child = grandparent };
var root = new LayoutTestRoot { Child = greatGrandparent };
root.LayoutManager.ExecuteInitialLayoutPass();
greatGrandparent.DoArrangeOverride = (_, s) =>
{
grandparent.InvalidateMeasure();
return s;
};
child.InvalidateArrange();
greatGrandparent.InvalidateArrange();
root.LayoutManager.ExecuteLayoutPass();
Assert.True(child.IsMeasureValid);
Assert.True(child.IsArrangeValid);
Assert.True(parent.IsMeasureValid);
Assert.True(parent.IsArrangeValid);
Assert.True(greatGrandparent.IsMeasureValid);
Assert.True(greatGrandparent.IsArrangeValid);
Assert.True(root.IsMeasureValid);
Assert.True(root.IsArrangeValid);
}
}
}

Loading…
Cancel
Save