Browse Source

Filter pointer pressed events from disabled sub-menu items

Pointer clicks on disabled and non-interactive items in sub-menus
are bubbled up to the sub-menu's parent, causing the sub-menu popup
to be closed when it is expected to remain open. This scenario is
identified and filtered out by searching for a popup in the logical
tree between the source and the handler. Fixes #6412.
pull/6818/head
Simon Haines 4 years ago
parent
commit
fcbe456cb9
  1. 6
      src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
  2. 17
      tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs

6
src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs

@ -1,4 +1,5 @@
using System;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Interactivity;
@ -376,7 +377,10 @@ namespace Avalonia.Controls.Platform
{
if (item.IsSubMenuOpen)
{
if (item.IsTopLevel)
// PointerPressed events may bubble from disabled items in sub-menus. In this case,
// keep the sub-menu open.
var popup = (e.Source as ILogical)?.FindLogicalAncestorOfType<Popup>();
if (item.IsTopLevel && popup == null)
{
CloseMenu(item);
}

17
tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs

@ -1,5 +1,6 @@
using System;
using Avalonia.Controls.Platform;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
@ -540,6 +541,22 @@ namespace Avalonia.Controls.UnitTests.Platform
Mock.Get(item).Verify(x => x.MoveSelection(NavigationDirection.First, true), Times.Never);
Assert.True(e.Handled);
}
[Fact]
public void PointerPressed_On_Disabled_Item_Doesnt_Close_SubMenu()
{
var target = new DefaultMenuInteractionHandler(false);
var menu = Mock.Of<IMenu>();
var parentItem = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.IsSubMenuOpen == true && x.Parent == menu);
var popup = new Popup();
var e = CreatePressed(popup);
((ISetLogicalParent)popup).SetParent(parentItem);
target.PointerPressed(parentItem, e);
Mock.Get(parentItem).Verify(x => x.Close(), Times.Never);
Assert.True(e.Handled);
}
}
public class ContextMenu

Loading…
Cancel
Save