Skip to content

Commit

Permalink
Merge pull request AvaloniaUI#8427 from AvaloniaUI/fixes/7381-reparen…
Browse files Browse the repository at this point in the history
…ting-control-crash

Fix crash in deferred renderer when reparenting a control.
  • Loading branch information
maxkatz6 authored and danwalmsley committed Jul 6, 2022
1 parent 0cbcc44 commit 26ee858
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ private static object GetOrCreateChildNode(Scene scene, IVisual child, VisualNod
if (result != null && result.Parent != parent)
{
Deindex(scene, result);
((VisualNode?)result.Parent)?.RemoveChild(result);
result = null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,69 @@ public void Should_Update_When_Control_Moved()
}
}

[Fact]
public void Should_Update_When_Control_Moved_Causing_Layout_Change()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator moveFrom;
Decorator moveTo;
Canvas moveMe;
var tree = new TestRoot
{
Width = 100,
Height = 100,
Child = new DockPanel
{
Children =
{
(moveFrom = new Decorator
{
Child = moveMe = new Canvas
{
Width = 100,
Height = 100,
},
}),
(moveTo = new Decorator()),
}
}
};

tree.Measure(Size.Infinity);
tree.Arrange(new Rect(tree.DesiredSize));

var scene = new Scene(tree);
var sceneBuilder = new SceneBuilder();
sceneBuilder.UpdateAll(scene);

var moveFromNode = (VisualNode)scene.FindNode(moveFrom);
var moveToNode = (VisualNode)scene.FindNode(moveTo);

Assert.Equal(1, moveFromNode.Children.Count);
Assert.Same(moveMe, moveFromNode.Children[0].Visual);
Assert.Empty(moveToNode.Children);

moveFrom.Child = null;
moveTo.Child = moveMe;
tree.LayoutManager.ExecuteLayoutPass();

scene = scene.CloneScene();
moveFromNode = (VisualNode)scene.FindNode(moveFrom);
moveToNode = (VisualNode)scene.FindNode(moveTo);

moveFromNode.SortChildren(scene);
moveToNode.SortChildren(scene);
sceneBuilder.Update(scene, moveFrom);
sceneBuilder.Update(scene, moveTo);
sceneBuilder.Update(scene, moveMe);

Assert.Empty(moveFromNode.Children);
Assert.Equal(1, moveToNode.Children.Count);
Assert.Same(moveMe, moveToNode.Children[0].Visual);
}
}

[Fact]
public void Should_Update_When_Control_Made_Invisible()
{
Expand Down

0 comments on commit 26ee858

Please sign in to comment.