Skip to content

Commit

Permalink
Merge pull request AvaloniaUI#8236 from AvaloniaUI/fix-popup-leak
Browse files Browse the repository at this point in the history
Fix FlyoutBase/ContextMenu memory leak
  • Loading branch information
danwalmsley committed Jun 1, 2022
1 parent e27f8ab commit 81698eb
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/Avalonia.Controls/ContextMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,11 @@ private static void ControlDetachedFromVisualTree(object sender, VisualTreeAttac
if (sender is Control control
&& control.ContextMenu is ContextMenu contextMenu)
{
if (contextMenu._popup?.Parent == control)
{
((ISetLogicalParent)contextMenu._popup).SetParent(null);
}

contextMenu.Close();
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Avalonia.Controls/Flyouts/FlyoutBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ protected virtual bool HideCore(bool canCancel = true)

IsOpen = false;
Popup.IsOpen = false;

((ISetLogicalParent)Popup).SetParent(null);

// Ensure this isn't active
_transientDisposable?.Dispose();
_transientDisposable = null;
Expand Down
21 changes: 21 additions & 0 deletions tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,27 @@ public void Can_Set_Clear_ContextMenu_Property()
}
}

[Fact]
public void Should_Reset_Popup_Parent_On_Target_Detached()
{
using (Application())
{
var userControl = new UserControl();
var window = PreparedWindow(userControl);
window.Show();

var menu = new ContextMenu();
userControl.ContextMenu = menu;
menu.Open();

var popup = Assert.IsType<Popup>(menu.Parent);
Assert.NotNull(popup.Parent);

window.Content = null;
Assert.Null(popup.Parent);
}
}

[Fact]
public void Context_Menu_In_Resources_Can_Be_Shared()
{
Expand Down
25 changes: 25 additions & 0 deletions tests/Avalonia.Controls.UnitTests/FlyoutTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,26 @@ public void KeyUp_Raised_On_Flyout_Closes_Opened_ContextFlyout()
}
}

[Fact]
public void Should_Reset_Popup_Parent_On_Target_Detached()
{
using (CreateServicesWithFocus())
{
var userControl = new UserControl();
var window = PreparedWindow(userControl);
window.Show();

var flyout = new TestFlyout();
flyout.ShowAt(userControl);

var popup = Assert.IsType<Popup>(flyout.Popup);
Assert.NotNull(popup.Parent);

window.Content = null;
Assert.Null(popup.Parent);
}
}

[Fact]
public void ContextFlyout_Can_Be_Set_In_Styles()
{
Expand Down Expand Up @@ -549,5 +569,10 @@ private PointerPressedEventArgs CreatePointerPressedEventArgs(Window source, Poi
new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed),
KeyModifiers.None);
}

public class TestFlyout : Flyout
{
public new Popup Popup => base.Popup;
}
}
}

0 comments on commit 81698eb

Please sign in to comment.