Browse Source

Fixes #3986. ContextMenus now broken in v2 net and win drivers (#3987)

BDisp 4 months ago
parent
commit
76a14d456d

+ 25 - 12
Terminal.Gui/Views/Menu/MenuBar.cs

@@ -441,7 +441,15 @@ public class MenuBar : View, IDesignable
             return;
         }
 
-        Application.GrabMouse (this);
+        if (_isContextMenuLoading)
+        {
+            Application.GrabMouse (_openMenu);
+            _isContextMenuLoading = false;
+        }
+        else
+        {
+            Application.GrabMouse (this);
+        }
     }
 
     /// <inheritdoc/>
@@ -493,6 +501,11 @@ public class MenuBar : View, IDesignable
 
     internal void CleanUp ()
     {
+        if (_isCleaning)
+        {
+            return;
+        }
+
         _isCleaning = true;
 
         if (_openMenu is { })
@@ -1448,9 +1461,9 @@ public class MenuBar : View, IDesignable
                             Activate (i);
                         }
                     }
-                    else if (me.Flags == MouseFlags.Button1Pressed
-                             || me.Flags == MouseFlags.Button1DoubleClicked
-                             || me.Flags == MouseFlags.Button1TripleClicked)
+                    else if (me.Flags.HasFlag (MouseFlags.Button1Pressed)
+                             || me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
+                             || me.Flags.HasFlag (MouseFlags.Button1TripleClicked))
                     {
                         if (IsMenuOpen && !Menus [i].IsTopLevel)
                         {
@@ -1534,16 +1547,17 @@ public class MenuBar : View, IDesignable
                     }
                 }
 
-                if (me.View != current)
+                if (Application.MouseGrabView != me.View)
                 {
-                    View v = current;
-                    Application.UngrabMouse ();
+                    View v = me.View;
+                    Application.GrabMouse (v);
 
-                    if (((Menu)me.View).Host.SuperView is { } && ((Menu)me.View).Host.SuperView!.InternalSubViews.Contains(me.View))
-                    {
-                        v = me.View;
-                    }
+                    return true;
+                }
 
+                if (me.View != current)
+                {
+                    View v = me.View;
                     Application.GrabMouse (v);
                     MouseEventArgs nme;
 
@@ -1590,7 +1604,6 @@ public class MenuBar : View, IDesignable
             else
             {
                 _handled = false;
-                _isContextMenuLoading = false;
 
                 return false;
             }

+ 28 - 25
Tests/UnitTests/Views/ContextMenuTests.cs

@@ -76,7 +76,7 @@ public class ContextMenuTests (ITestOutputHelper output)
                                          ]
                                         );
 
-        var menu = new MenuBar
+        var menuBar = new MenuBar
         {
             Menus =
             [
@@ -86,24 +86,26 @@ public class ContextMenuTests (ITestOutputHelper output)
         };
 
         var top = new Toplevel ();
-        top.Add (menu);
+        top.Add (menuBar);
         Application.Begin (top);
 
         Assert.Null (Application.MouseGrabView);
 
         cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
-        Assert.Equal (cm.MenuBar, Application.MouseGrabView);
-        Assert.False (menu.IsMenuOpen);
-        Assert.True (menu.NewKeyDownEvent (menu.Key));
-        Assert.False (ContextMenu.IsShow);
+        Menu menu = (Menu)top.SubViews.First (v => v is Menu);
         Assert.Equal (menu, Application.MouseGrabView);
-        Assert.True (menu.IsMenuOpen);
+        Assert.False (menuBar.IsMenuOpen);
+        Assert.True (menuBar.NewKeyDownEvent (menuBar.Key));
+        Assert.False (ContextMenu.IsShow);
+        Assert.Equal (menuBar, Application.MouseGrabView);
+        Assert.True (menuBar.IsMenuOpen);
 
         cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
-        Assert.Equal (cm.MenuBar, Application.MouseGrabView);
-        Assert.False (menu.IsMenuOpen);
+        menu = (Menu)top.SubViews.First (v => v is Menu);
+        Assert.Equal (menu, Application.MouseGrabView);
+        Assert.False (menuBar.IsMenuOpen);
 #if SUPPORT_ALT_TO_ACTIVATE_MENU
         Assert.True (Application.Top.ProcessKeyUp (new (Key.AltMask)));
         Assert.False (ContextMenu.IsShow);
@@ -113,16 +115,17 @@ public class ContextMenuTests (ITestOutputHelper output)
 
         cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
-        Assert.Equal (cm.MenuBar, Application.MouseGrabView);
-        Assert.False (menu.IsMenuOpen);
-        Assert.False (menu.NewMouseEvent (new MouseEventArgs { Position = new (1, 0), Flags = MouseFlags.ReportMousePosition, View = menu }));
+        menu = (Menu)top.SubViews.First (v => v is Menu);
+        Assert.Equal (menu, Application.MouseGrabView);
+        Assert.False (menuBar.IsMenuOpen);
+        Assert.False (menuBar.NewMouseEvent (new MouseEventArgs { Position = new (1, 0), Flags = MouseFlags.ReportMousePosition, View = menuBar }));
         Assert.True (ContextMenu.IsShow);
-        Assert.Equal (cm.MenuBar, Application.MouseGrabView);
-        Assert.False (menu.IsMenuOpen);
-        Assert.True (menu.NewMouseEvent (new MouseEventArgs { Position = new (1, 0), Flags = MouseFlags.Button1Clicked, View = menu }));
-        Assert.False (ContextMenu.IsShow);
         Assert.Equal (menu, Application.MouseGrabView);
-        Assert.True (menu.IsMenuOpen);
+        Assert.False (menuBar.IsMenuOpen);
+        Assert.True (menuBar.NewMouseEvent (new MouseEventArgs { Position = new (1, 0), Flags = MouseFlags.Button1Clicked, View = menuBar }));
+        Assert.False (ContextMenu.IsShow);
+        Assert.Equal (menuBar, Application.MouseGrabView);
+        Assert.True (menuBar.IsMenuOpen);
         top.Dispose ();
     }
 
@@ -1423,7 +1426,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.Equal (6, win.SubViews.Count);
         Assert.True (tf2.ContextMenu.MenuBar.IsMenuOpen);
         Assert.True (win.Focused is Menu);
-        Assert.True (Application.MouseGrabView is MenuBar);
+        Assert.True (Application.MouseGrabView is Menu);
         Assert.Equal (tf2, Application._cachedViewsUnderMouse.LastOrDefault ());
 
         // Click on tf1 to focus it, which cause context menu being closed
@@ -2026,15 +2029,15 @@ public class ContextMenuTests (ITestOutputHelper output)
             // Right Button
             case 3:
                 Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button3Pressed });
-                Assert.False (menuBar.IsMenuOpen);
+                Assert.True (menuBar.IsMenuOpen);
                 Application.MainLoop.RunIteration ();
                 Assert.False (actionRaised);
                 Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button3Released });
-                Assert.False (menuBar.IsMenuOpen);
+                Assert.True (menuBar.IsMenuOpen);
                 Application.MainLoop.RunIteration ();
                 Assert.False (actionRaised);
                 Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 2), Flags = MouseFlags.Button3Clicked });
-                Assert.False (menuBar.IsMenuOpen);
+                Assert.True (menuBar.IsMenuOpen);
                 Application.MainLoop.RunIteration ();
                 Assert.False (actionRaised);
 
@@ -2042,7 +2045,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         }
 
         // ContextMenu
-        Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 2), Flags = cm.MouseFlags });
+        Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 4), Flags = cm.MouseFlags });
         Assert.False (menuBar.IsMenuOpen);
         Assert.True (cm.MenuBar!.IsMenuOpen);
 
@@ -2050,15 +2053,15 @@ public class ContextMenuTests (ITestOutputHelper output)
         {
             // Left Button
             case 1:
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button1Pressed });
+                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 6), Flags = MouseFlags.Button1Pressed });
                 Assert.True (cm.MenuBar!.IsMenuOpen);
                 Application.MainLoop.RunIteration ();
                 Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button1Released });
+                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 6), Flags = MouseFlags.Button1Released });
                 Assert.True (cm.MenuBar!.IsMenuOpen);
                 Application.MainLoop.RunIteration ();
                 Assert.False (actionRaised);
-                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 4), Flags = MouseFlags.Button1Clicked });
+                Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 6), Flags = MouseFlags.Button1Clicked });
                 Assert.False (cm.MenuBar!.IsMenuOpen);
                 Application.MainLoop.RunIteration ();
                 Assert.True (actionRaised);

+ 20 - 10
Tests/UnitTests/Views/MenuBarTests.cs

@@ -2518,7 +2518,7 @@ Edit
         MenuItem miCurrent = null;
         Menu mCurrent = null;
 
-        var menu = new MenuBar
+        var menuBar = new MenuBar
         {
             Menus =
             [
@@ -2533,22 +2533,22 @@ Edit
             ]
         };
 
-        menu.MenuOpened += (s, e) =>
+        menuBar.MenuOpened += (s, e) =>
                            {
                                miCurrent = e.MenuItem;
-                               mCurrent = menu.OpenCurrentMenu;
+                               mCurrent = menuBar.OpenCurrentMenu;
                            };
         var top = new Toplevel ();
-        top.Add (menu);
+        top.Add (menuBar);
         Application.Begin (top);
 
         // Click on Edit
         Assert.True (
-                     menu.NewMouseEvent (
-                                         new () { Position = new (10, 0), Flags = MouseFlags.Button1Pressed, View = menu }
+                     menuBar.NewMouseEvent (
+                                         new () { Position = new (10, 0), Flags = MouseFlags.Button1Pressed, View = menuBar }
                                         )
                     );
-        Assert.True (menu.IsMenuOpen);
+        Assert.True (menuBar.IsMenuOpen);
         Assert.Equal ("_Edit", miCurrent.Parent.Title);
         Assert.Equal ("_Copy", miCurrent.Title);
 
@@ -2558,7 +2558,7 @@ Edit
                                              new () { Position = new (10, 2), Flags = MouseFlags.ReportMousePosition, View = mCurrent }
                                             )
                     );
-        Assert.True (menu.IsMenuOpen);
+        Assert.True (menuBar.IsMenuOpen);
         Assert.Equal ("_Edit", miCurrent.Parent.Title);
         Assert.Equal ("_Paste", miCurrent.Title);
 
@@ -2568,8 +2568,18 @@ Edit
                                          new () { ScreenPosition = new (10, i), Flags = MouseFlags.ReportMousePosition }
                                         );
 
-            Assert.True (menu.IsMenuOpen);
-            Assert.Equal (menu, Application.MouseGrabView);
+            Assert.True (menuBar.IsMenuOpen);
+            Menu menu = (Menu)top.SubViews.First (v => v is Menu);
+
+            if (i is < 0 or > 0)
+            {
+                Assert.Equal (menu, Application.MouseGrabView);
+            }
+            else
+            {
+                Assert.Equal (menuBar, Application.MouseGrabView);
+            }
+
             Assert.Equal ("_Edit", miCurrent.Parent.Title);
 
             if (i == 4)