diff --git a/Terminal.Gui/Views/Menu/MenuBar.cs b/Terminal.Gui/Views/Menu/MenuBar.cs index 416acb653..9ae2709f0 100644 --- a/Terminal.Gui/Views/Menu/MenuBar.cs +++ b/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); + } } /// @@ -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 (Application.MouseGrabView != me.View) + { + View v = me.View; + Application.GrabMouse (v); + + return true; + } + if (me.View != current) { - View v = current; - Application.UngrabMouse (); - - if (((Menu)me.View).Host.SuperView is { } && ((Menu)me.View).Host.SuperView!.InternalSubViews.Contains(me.View)) - { - v = me.View; - } - + 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; } diff --git a/Tests/UnitTests/Views/ContextMenuTests.cs b/Tests/UnitTests/Views/ContextMenuTests.cs index 17a60e572..e68f5e729 100644 --- a/Tests/UnitTests/Views/ContextMenuTests.cs +++ b/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 })); - 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); + menu = (Menu)top.SubViews.First (v => v is Menu); Assert.Equal (menu, Application.MouseGrabView); - Assert.True (menu.IsMenuOpen); + 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 (menu, Application.MouseGrabView); + 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); diff --git a/Tests/UnitTests/Views/MenuBarTests.cs b/Tests/UnitTests/Views/MenuBarTests.cs index e5428e7b0..b65fdf996 100644 --- a/Tests/UnitTests/Views/MenuBarTests.cs +++ b/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)