Skip to content

Commit 91442bb

Browse files
committed
Fixes #3968. Menu appears in wrong place when opened in a subview
1 parent e76ec72 commit 91442bb

File tree

5 files changed

+89
-68
lines changed

5 files changed

+89
-68
lines changed

Terminal.Gui/Views/Menu/ContextMenu.cs

+30-12
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public void Dispose ()
104104
if (_menuBar is { })
105105
{
106106
_menuBar.MenuAllClosed -= MenuBar_MenuAllClosed;
107+
_container?.Remove (_menuBar);
107108
}
108109
Application.UngrabMouse ();
109110
_menuBar?.Dispose ();
@@ -177,16 +178,16 @@ public void Show (MenuBarItem? menuItems)
177178
}
178179

179180
MenuItems = menuItems;
180-
_container = Application.Top;
181+
_container = GetTopSuperView (Host);
181182
_container!.Closing += Container_Closing;
182183
_container.Deactivate += Container_Deactivate;
183184
_container.Disposing += Container_Disposing;
184-
Rectangle frame = Application.Screen;
185+
Rectangle viewport = _container.Viewport;
185186
Point position = Position;
186187

187188
if (Host is { })
188189
{
189-
Point pos = Host.ViewportToScreen (frame).Location;
190+
Point pos = Host.Frame.Location;
190191
pos.Y += Host.Frame.Height > 0 ? Host.Frame.Height - 1 : 0;
191192

192193
if (position != pos)
@@ -197,11 +198,11 @@ public void Show (MenuBarItem? menuItems)
197198

198199
Rectangle rect = Menu.MakeFrame (position.X, position.Y, MenuItems.Children);
199200

200-
if (rect.Right >= frame.Right)
201+
if (rect.Right >= viewport.Right)
201202
{
202-
if (frame.Right - rect.Width >= 0 || !ForceMinimumPosToZero)
203+
if (viewport.Right - rect.Width >= 0 || !ForceMinimumPosToZero)
203204
{
204-
position.X = frame.Right - rect.Width;
205+
position.X = viewport.Right - rect.Width;
205206
}
206207
else if (ForceMinimumPosToZero)
207208
{
@@ -213,17 +214,17 @@ public void Show (MenuBarItem? menuItems)
213214
position.X = 0;
214215
}
215216

216-
if (rect.Bottom >= frame.Bottom)
217+
if (rect.Bottom >= viewport.Bottom)
217218
{
218-
if (frame.Bottom - rect.Height - 1 >= 0 || !ForceMinimumPosToZero)
219+
if (viewport.Bottom - rect.Height - 1 >= 0 || !ForceMinimumPosToZero)
219220
{
220221
if (Host is null)
221222
{
222-
position.Y = frame.Bottom - rect.Height - 1;
223+
position.Y = viewport.Bottom - rect.Height - 1;
223224
}
224225
else
225226
{
226-
Point pos = Host.ViewportToScreen (frame).Location;
227+
Point pos = Host.Frame.Location;
227228
position.Y = pos.Y - rect.Height - 1;
228229
}
229230
}
@@ -251,12 +252,29 @@ public void Show (MenuBarItem? menuItems)
251252
_menuBar._isContextMenuLoading = true;
252253
_menuBar.MenuAllClosed += MenuBar_MenuAllClosed;
253254

254-
_menuBar.BeginInit ();
255-
_menuBar.EndInit ();
255+
_container.Add (_menuBar);
256256
IsShow = true;
257257
_menuBar.OpenMenu ();
258258
}
259259

260+
internal static Toplevel? GetTopSuperView (View? view)
261+
{
262+
if (view is Toplevel toplevel)
263+
{
264+
return toplevel;
265+
}
266+
267+
for (View? sv = view?.SuperView; sv != null; sv = sv.SuperView)
268+
{
269+
if (sv is Toplevel top)
270+
{
271+
return top;
272+
}
273+
}
274+
275+
return (Toplevel?)view?.SuperView ?? Application.Top;
276+
}
277+
260278
private void Container_Closing (object? sender, ToplevelClosingEventArgs obj) { Hide (); }
261279
private void Container_Deactivate (object? sender, ToplevelEventArgs e) { Hide (); }
262280
private void Container_Disposing (object? sender, EventArgs e) { Dispose (); }

Terminal.Gui/Views/Menu/MenuBar.cs

+15-28
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public MenuBar ()
7373
Y = 0;
7474
Width = Dim.Fill ();
7575
Height = 1; // BUGBUG: Views should avoid setting Height as doing so implies Frame.Size == GetContentSize ().
76-
Menus = new MenuBarItem [] { };
76+
Menus = [];
7777

7878
//CanFocus = true;
7979
_selected = -1;
@@ -556,10 +556,10 @@ internal void CloseAllMenus ()
556556

557557
private void CloseOtherOpenedMenuBar ()
558558
{
559-
if (Application.Top is { })
559+
if (SuperView is { })
560560
{
561561
// Close others menu bar opened
562-
Menu? menu = Application.Top.SubViews.FirstOrDefault (v => v is Menu m && m.Host != this && m.Host.IsMenuOpen) as Menu;
562+
Menu? menu = SuperView.SubViews.FirstOrDefault (v => v is Menu m && m.Host != this && m.Host.IsMenuOpen) as Menu;
563563
menu?.Host.CleanUp ();
564564
}
565565
}
@@ -595,7 +595,7 @@ internal bool CloseMenu (bool reopen, bool isSubMenu, bool ignoreUseSubMenusSing
595595
case false:
596596
if (_openMenu is { })
597597
{
598-
Application.Top?.Remove (_openMenu);
598+
SuperView?.Remove (_openMenu);
599599
}
600600

601601
SetNeedsDraw ();
@@ -634,7 +634,7 @@ internal bool CloseMenu (bool reopen, bool isSubMenu, bool ignoreUseSubMenusSing
634634

635635
if (OpenCurrentMenu is { })
636636
{
637-
Application.Top?.Remove (OpenCurrentMenu);
637+
SuperView?.Remove (OpenCurrentMenu);
638638
if (Application.MouseGrabView == OpenCurrentMenu)
639639
{
640640
Application.UngrabMouse ();
@@ -822,7 +822,7 @@ internal void OpenMenu (int index, int sIndex = -1, MenuBarItem? subMenu = null!
822822

823823
if (_openMenu is { })
824824
{
825-
Application.Top?.Remove (_openMenu);
825+
SuperView?.Remove (_openMenu);
826826
if (Application.MouseGrabView == _openMenu)
827827
{
828828
Application.UngrabMouse ();
@@ -838,34 +838,23 @@ internal void OpenMenu (int index, int sIndex = -1, MenuBarItem? subMenu = null!
838838
pos += Menus [i].TitleLength + (Menus [i].Help.GetColumns () > 0 ? Menus [i].Help.GetColumns () + 2 : 0) + _leftPadding + _rightPadding;
839839
}
840840

841-
var locationOffset = Point.Empty;
842841

843-
// if SuperView is null then it's from a ContextMenu
844-
if (SuperView is null)
845-
{
846-
locationOffset = GetScreenOffset ();
847-
}
848842

849-
if (SuperView is { } && SuperView != Application.Top)
850-
{
851-
locationOffset.X += SuperView.Border.Thickness.Left;
852-
locationOffset.Y += SuperView.Border.Thickness.Top;
853-
}
854843

855844
_openMenu = new ()
856845
{
857846
Host = this,
858-
X = Frame.X + pos + locationOffset.X,
859-
Y = Frame.Y + 1 + locationOffset.Y,
847+
X = Frame.X + pos,
848+
Y = Frame.Y + 1,
860849
BarItems = Menus [index],
861850
Parent = null
862851
};
863852
OpenCurrentMenu = _openMenu;
864853
OpenCurrentMenu._previousSubFocused = _openMenu;
865854

866-
if (Application.Top is { })
855+
if (SuperView is { })
867856
{
868-
Application.Top.Add (_openMenu);
857+
SuperView.Add (_openMenu);
869858
// _openMenu.SetRelativeLayout (Application.Screen.Size);
870859
}
871860
else
@@ -894,13 +883,11 @@ internal void OpenMenu (int index, int sIndex = -1, MenuBarItem? subMenu = null!
894883

895884
if (!UseSubMenusSingleFrame)
896885
{
897-
locationOffset = GetLocationOffset ();
898-
899886
OpenCurrentMenu = new ()
900887
{
901888
Host = this,
902-
X = last!.Frame.Left + last.Frame.Width + locationOffset.X,
903-
Y = last.Frame.Top + locationOffset.Y + last._currentChild,
889+
X = last!.Frame.Left + last.Frame.Width,
890+
Y = last.Frame.Top + last._currentChild + 1,
904891
BarItems = subMenu,
905892
Parent = last
906893
};
@@ -931,7 +918,7 @@ internal void OpenMenu (int index, int sIndex = -1, MenuBarItem? subMenu = null!
931918

932919
OpenCurrentMenu._previousSubFocused = last._previousSubFocused;
933920
_openSubMenu.Add (OpenCurrentMenu);
934-
Application.Top?.Add (OpenCurrentMenu);
921+
SuperView?.Add (OpenCurrentMenu);
935922

936923
if (!OpenCurrentMenu.IsInitialized)
937924
{
@@ -1014,7 +1001,7 @@ internal void RemoveAllOpensSubMenus ()
10141001
{
10151002
foreach (Menu item in _openSubMenu)
10161003
{
1017-
Application.Top!.Remove (item);
1004+
SuperView?.Remove (item);
10181005
if (Application.MouseGrabView == item)
10191006
{
10201007
Application.UngrabMouse ();
@@ -1263,7 +1250,7 @@ private void RemoveSubMenu (int index, bool ignoreUseSubMenusSingleFrame = false
12631250
if (_openSubMenu is { })
12641251
{
12651252
menu = _openSubMenu [i];
1266-
Application.Top!.Remove (menu);
1253+
SuperView!.Remove (menu);
12671254
_openSubMenu.Remove (menu);
12681255

12691256
if (Application.MouseGrabView == menu)

0 commit comments

Comments
 (0)