Browse Source

Fixes #3964. Null Reference in DoDrawBorderAndPadding (#3971)

* Fixes #3964. Null Reference in DoDrawBorderAndPadding

* Fix unit test.

* Ensures closing all opened menus that belong to another top when a new modal top is opened.

* Reformat

---------

Co-authored-by: Tig <[email protected]>
BDisp 4 tháng trước cách đây
mục cha
commit
e76ec720a5

+ 5 - 1
Terminal.Gui/Application/Application.Run.cs

@@ -89,7 +89,11 @@ public static partial class Application // Run (Begin, Run, End, Stop)
         //#endif
 
         // Ensure the mouse is ungrabbed.
-        MouseGrabView = null;
+        if (MouseGrabView is { })
+        {
+            UngrabMouse ();
+            MouseGrabView = null;
+        }
 
         var rs = new RunState (toplevel);
 

+ 10 - 0
Terminal.Gui/Views/Menu/Menu.cs

@@ -17,6 +17,7 @@ internal sealed class Menu : View
         }
 
         Application.MouseEvent += Application_RootMouseEvent;
+        Application.UnGrabbedMouse += Application_UnGrabbedMouse;
 
         // Things this view knows how to do
         AddCommand (Command.Up, () => MoveUp ());
@@ -235,6 +236,7 @@ internal sealed class Menu : View
         }
 
         Application.MouseEvent -= Application_RootMouseEvent;
+        Application.UnGrabbedMouse -= Application_UnGrabbedMouse;
         base.Dispose (disposing);
     }
 
@@ -522,6 +524,14 @@ internal sealed class Menu : View
         }
     }
 
+    private void Application_UnGrabbedMouse (object? sender, ViewEventArgs a)
+    {
+        if (_host.IsMenuOpen)
+        {
+            _host.CloseAllMenus ();
+        }
+    }
+
     private void CloseAllMenus ()
     {
         Application.UngrabMouse ();

+ 9 - 26
Tests/UnitTests/Views/MenuBarTests.cs

@@ -2562,47 +2562,30 @@ Edit
         Assert.Equal ("_Edit", miCurrent.Parent.Title);
         Assert.Equal ("_Paste", miCurrent.Title);
 
-        for (var i = 2; i >= -1; i--)
+        for (var i = 4; i >= -1; i--)
         {
-            if (i == -1)
-            {
-                // Edit menu is open. Click on the menu at Y = -1, which is outside the menu.
-                Assert.False (
-                              mCurrent.NewMouseEvent (
-                                                      new () { Position = new (10, i), Flags = MouseFlags.ReportMousePosition, View = menu }
-                                                     )
-                             );
-            }
-            else
-            {
-                // Edit menu is open. Click on the menu at Y = i.
-                Assert.True (
-                             mCurrent.NewMouseEvent (
-                                                     new () { Position = new (10, i), Flags = MouseFlags.ReportMousePosition, View = mCurrent }
-                                                    )
-                            );
-            }
+            Application.RaiseMouseEvent (
+                                         new () { ScreenPosition = new (10, i), Flags = MouseFlags.ReportMousePosition }
+                                        );
 
             Assert.True (menu.IsMenuOpen);
+            Assert.Equal (menu, Application.MouseGrabView);
+            Assert.Equal ("_Edit", miCurrent.Parent.Title);
 
-            if (i == 2)
+            if (i == 4)
             {
-                Assert.Equal ("_Edit", miCurrent.Parent.Title);
                 Assert.Equal ("_Paste", miCurrent.Title);
             }
-            else if (i == 1)
+            else if (i == 3)
             {
-                Assert.Equal ("_Edit", miCurrent.Parent.Title);
                 Assert.Equal ("C_ut", miCurrent.Title);
             }
-            else if (i == 0)
+            else if (i == 2)
             {
-                Assert.Equal ("_Edit", miCurrent.Parent.Title);
                 Assert.Equal ("_Copy", miCurrent.Title);
             }
             else
             {
-                Assert.Equal ("_Edit", miCurrent.Parent.Title);
                 Assert.Equal ("_Copy", miCurrent.Title);
             }
         }