From 40e777acc11fe906f0d719771ba6059b6aaa91b3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 22 Nov 2025 01:39:11 +0000
Subject: [PATCH] Add OpenMenu() method to MenuBar for dropdown list support
Co-authored-by: tig <585482+tig@users.noreply.github.com>
---
Terminal.Gui/Views/Menu/MenuBar.cs | 24 +++++++++
Tests/UnitTests/Views/MenuBarTests.cs | 76 +++++++++++++++++++++++++++
2 files changed, 100 insertions(+)
diff --git a/Terminal.Gui/Views/Menu/MenuBar.cs b/Terminal.Gui/Views/Menu/MenuBar.cs
index 67312b01e..f446a1157 100644
--- a/Terminal.Gui/Views/Menu/MenuBar.cs
+++ b/Terminal.Gui/Views/Menu/MenuBar.cs
@@ -225,6 +225,30 @@ public class MenuBar : Menu, IDesignable
///
public bool IsOpen () { return SubViews.OfType ().Count (sv => sv is { PopoverMenuOpen: true }) > 0; }
+ ///
+ /// Opens the first menu item with a . This is useful for programmatically opening
+ /// the menu, for example when using the MenuBar as a dropdown list.
+ ///
+ /// if a menu was opened; otherwise.
+ ///
+ ///
+ /// This method activates the MenuBar and shows the first MenuBarItem that has a PopoverMenu.
+ /// The first menu item in the PopoverMenu will be selected and focused.
+ ///
+ ///
+ public bool OpenMenu ()
+ {
+ if (SubViews.OfType ().FirstOrDefault (mbi => mbi.PopoverMenu is { }) is { } first)
+ {
+ Active = true;
+ ShowItem (first);
+
+ return true;
+ }
+
+ return false;
+ }
+
private bool _active;
///
diff --git a/Tests/UnitTests/Views/MenuBarTests.cs b/Tests/UnitTests/Views/MenuBarTests.cs
index b15501a07..f67fcb779 100644
--- a/Tests/UnitTests/Views/MenuBarTests.cs
+++ b/Tests/UnitTests/Views/MenuBarTests.cs
@@ -718,4 +718,80 @@ public class MenuBarTests ()
Application.End (rs);
top.Dispose ();
}
+
+ [Fact]
+ [AutoInitShutdown]
+ public void OpenMenu_Opens_First_MenuBarItem ()
+ {
+ // Arrange
+ var top = new Toplevel ()
+ {
+ App = ApplicationImpl.Instance
+ };
+
+ var menuBar = new MenuBar () { Id = "menuBar" };
+ top.Add (menuBar);
+
+ var menuItem1 = new MenuItem { Id = "menuItem1", Title = "Item _1" };
+ var menuItem2 = new MenuItem { Id = "menuItem2", Title = "Item _2" };
+ var menu = new Menu ([menuItem1, menuItem2]) { Id = "menu" };
+ var menuBarItem = new MenuBarItem { Id = "menuBarItem", Title = "_File" };
+ var menuBarItemPopover = new PopoverMenu ();
+
+ menuBar.Add (menuBarItem);
+ menuBarItem.PopoverMenu = menuBarItemPopover;
+ menuBarItemPopover.Root = menu;
+
+ SessionToken rs = Application.Begin (top);
+ Assert.False (menuBar.Active);
+ Assert.False (menuBar.IsOpen ());
+
+ // Act
+ bool result = menuBar.OpenMenu ();
+
+ // Assert
+ Assert.True (result);
+ Assert.True (menuBar.Active);
+ Assert.True (menuBar.IsOpen ());
+ Assert.True (menuBar.CanFocus);
+ Assert.True (menuBarItem.PopoverMenu.Visible);
+ Assert.True (menuBarItem.PopoverMenu.HasFocus);
+ Assert.Equal (menuItem1, menu.SelectedMenuItem);
+
+ Application.End (rs);
+ top.Dispose ();
+ }
+
+ [Fact]
+ [AutoInitShutdown]
+ public void OpenMenu_Returns_False_When_No_MenuBarItem_With_PopoverMenu ()
+ {
+ // Arrange
+ var top = new Toplevel ()
+ {
+ App = ApplicationImpl.Instance
+ };
+
+ var menuBar = new MenuBar () { Id = "menuBar" };
+ top.Add (menuBar);
+
+ var menuBarItem = new MenuBarItem { Id = "menuBarItem", Title = "_File" };
+ menuBar.Add (menuBarItem);
+ // Note: No PopoverMenu set
+
+ SessionToken rs = Application.Begin (top);
+ Assert.False (menuBar.Active);
+ Assert.False (menuBar.IsOpen ());
+
+ // Act
+ bool result = menuBar.OpenMenu ();
+
+ // Assert
+ Assert.False (result);
+ Assert.False (menuBar.Active);
+ Assert.False (menuBar.IsOpen ());
+
+ Application.End (rs);
+ top.Dispose ();
+ }
}