Pārlūkot izejas kodu

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.
Simon Haines 4 gadi atpakaļ
vecāks
revīzija
fcbe456cb9

+ 5 - 1
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 - 0
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