浏览代码

Fixes #3326. Menu is responding even outside the limits, not moving to the view that has the mouse.

BDisp 1 年之前
父节点
当前提交
534ab2a631
共有 3 个文件被更改,包括 149 次插入6 次删除
  1. 6 4
      Terminal.Gui/Views/Menu/Menu.cs
  2. 121 2
      UnitTests/Views/ContextMenuTests.cs
  3. 22 0
      UnitTests/Views/MenuBarTests.cs

+ 6 - 4
Terminal.Gui/Views/Menu/Menu.cs

@@ -714,7 +714,7 @@ internal sealed class Menu : View
 
     private void Application_RootMouseEvent (object sender, MouseEventEventArgs a)
     {
-        if (a.MouseEvent.View is MenuBar)
+        if (a.MouseEvent.View is { } and (MenuBar or not Menu))
         {
             return;
         }
@@ -724,17 +724,19 @@ internal sealed class Menu : View
             throw new InvalidOperationException ("This shouldn't running on a invisible menu!");
         }
 
-        Point boundsPoint = ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y);
+        View view = a.MouseEvent.View ?? this;
+
+        Point boundsPoint = view.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y);
         var me = new MouseEvent
         {
             X = boundsPoint.X,
             Y = boundsPoint.Y,
             Flags = a.MouseEvent.Flags,
             ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y),
-            View = this
+            View = view
         };
 
-        if (OnMouseEvent (me) || a.MouseEvent.Flags == MouseFlags.Button1Pressed || a.MouseEvent.Flags == MouseFlags.Button1Released)
+        if (view.OnMouseEvent (me) || a.MouseEvent.Flags == MouseFlags.Button1Pressed || a.MouseEvent.Flags == MouseFlags.Button1Released)
         {
             a.MouseEvent.Handled = true;
         }

+ 121 - 2
UnitTests/Views/ContextMenuTests.cs

@@ -1306,9 +1306,10 @@ public class ContextMenuTests
                                                       _output
                                                      );
 
+        // X=5 is the border and so need to use at least one more
         Application.OnMouseEvent (
                                   new MouseEventEventArgs (
-                                                           new MouseEvent { X = 5, Y = 13, Flags = MouseFlags.Button1Clicked }
+                                                           new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.Button1Clicked }
                                                           )
                                  );
 
@@ -1330,7 +1331,7 @@ public class ContextMenuTests
 
         Application.OnMouseEvent (
                                   new MouseEventEventArgs (
-                                                           new MouseEvent { X = 5, Y = 12, Flags = MouseFlags.Button1Clicked }
+                                                           new MouseEvent { X = 6, Y = 12, Flags = MouseFlags.Button1Clicked }
                                                           )
                                  );
 
@@ -1351,6 +1352,124 @@ public class ContextMenuTests
         Application.End (rs);
     }
 
+        [Fact]
+    [AutoInitShutdown]
+    public void UseSubMenusSingleFrame_False_By_Mouse ()
+    {
+        var cm = new ContextMenu
+        {
+            Position = new Point (5, 10),
+            MenuItems = new MenuBarItem (
+                                         "Numbers",
+                                         [
+                                             new MenuItem ("One", "", null),
+                                             new MenuBarItem (
+                                                              "Two",
+                                                              [
+                                                                  new MenuItem (
+                                                                                "Two-Menu 1",
+                                                                                "",
+                                                                                null
+                                                                               ),
+                                                                  new MenuItem ("Two-Menu 2", "", null)
+                                                              ]
+                                                             ),
+                                             new MenuBarItem ("Three",
+                                                              [
+                                                                  new MenuItem (
+                                                                                "Three-Menu 1",
+                                                                                "",
+                                                                                null
+                                                                               ),
+                                                                  new MenuItem ("Three-Menu 2", "", null)
+                                                              ]
+                                                             )
+                                         ]
+                                        )
+        };
+
+        cm.Show ();
+        RunState rs = Application.Begin (Application.Top);
+
+        Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
+
+        TestHelpers.AssertDriverContentsWithFrameAre (
+                                                      @"
+     ┌────────┐
+     │ One    │
+     │ Two   ►│
+     │ Three ►│
+     └────────┘",
+                                                      _output
+                                                     );
+
+        Application.OnMouseEvent (
+                                  new MouseEventEventArgs (
+                                                           new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.ReportMousePosition }
+                                                          )
+                                 );
+
+        var firstIteration = false;
+        Application.RunIteration (ref rs, ref firstIteration);
+        Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
+
+        TestHelpers.AssertDriverContentsWithFrameAre (
+                                                      @"
+     ┌────────┐               
+     │ One    │               
+     │ Two   ►│┌─────────────┐
+     │ Three ►││ Two-Menu 1  │
+     └────────┘│ Two-Menu 2  │
+               └─────────────┘",
+                                                      _output
+                                                     );
+
+        Application.OnMouseEvent (
+                                  new MouseEventEventArgs (
+                                                           new MouseEvent { X = 6, Y = 14, Flags = MouseFlags.ReportMousePosition }
+                                                          )
+                                 );
+
+        firstIteration = false;
+        Application.RunIteration (ref rs, ref firstIteration);
+        Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
+
+        TestHelpers.AssertDriverContentsWithFrameAre (
+                                                      @"
+     ┌────────┐                 
+     │ One    │                 
+     │ Two   ►│                 
+     │ Three ►│┌───────────────┐
+     └────────┘│ Three-Menu 1  │
+               │ Three-Menu 2  │
+               └───────────────┘",
+                                                      _output
+                                                     );
+
+        Application.OnMouseEvent (
+                                  new MouseEventEventArgs (
+                                                           new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.ReportMousePosition }
+                                                          )
+                                 );
+
+        firstIteration = false;
+        Application.RunIteration (ref rs, ref firstIteration);
+        Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
+
+        TestHelpers.AssertDriverContentsWithFrameAre (
+                                                      @"
+     ┌────────┐               
+     │ One    │               
+     │ Two   ►│┌─────────────┐
+     │ Three ►││ Two-Menu 1  │
+     └────────┘│ Two-Menu 2  │
+               └─────────────┘",
+                                                      _output
+                                                     );
+
+        Application.End (rs);
+    }
+
     private ContextMenu Create_ContextMenu_With_Two_MenuItem (int x, int y)
     {
         return new ContextMenu

+ 22 - 0
UnitTests/Views/MenuBarTests.cs

@@ -3658,4 +3658,26 @@ Edit
             Add (menu);
         }
     }
+
+    [Fact]
+    [AutoInitShutdown]
+    public void Click_Another_View_Close_A_Open_Menu ()
+    {
+        var menu = new MenuBar
+        {
+            Menus =
+            [
+                new MenuBarItem ("File", new MenuItem [] { new ("New", "", null) })
+            ]
+        };
+
+        var btnClicked = false;
+        var btn = new Button { Y = 4, Text = "Test" };
+        btn.Accept += (s, e) => btnClicked = true;
+        Application.Top.Add (menu, btn);
+        Application.Begin (Application.Top);
+
+        Application.OnMouseEvent (new (new () { X = 0, Y = 4, Flags = MouseFlags.Button1Clicked }));
+        Assert.True (btnClicked);
+    }
 }