Skip to content

Commit 530e084

Browse files
HealsCodescmsj
authored andcommitted
Reuse [statusItem menu] if possible (fixes #1923)
This change allows calls to hs.menubar:setMenu() to update the menu even if it is currently visible. The original code would delete the old menu and set a new NSMenu instance however macOS will not show a new menu while the old - now empty one - is still open.
1 parent 82dd24c commit 530e084

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

extensions/menubar/libmenubar.m

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,22 @@ void erase_all_menu_parts(lua_State *L, NSStatusItem *statusItem) {
381381
return;
382382
}
383383

384+
// Prepare an existing menu on a menubar item for reuse or create a new menu
385+
NSMenu* create_or_reuse_menu(lua_State *L, NSStatusItem *statusItem, NSString *menuTitle) {
386+
NSMenu *menu = [statusItem menu];
387+
if (menu) {
388+
erase_menu_delegate(L, menu);
389+
erase_menu_items(L, menu);
390+
391+
[statusItem setMenu:nil];
392+
[menu setTitle:menuTitle];
393+
return menu;
394+
}
395+
396+
// no existing menu
397+
return [[NSMenu alloc] initWithTitle:menuTitle];
398+
}
399+
384400
// Create and push a lua geometry rect
385401
static void geom_pushrect(lua_State* L, NSRect rect) {
386402
lua_newtable(L);
@@ -753,13 +769,11 @@ static int menubarSetMenu(lua_State *L) {
753769
NSMenu *menu = nil;
754770
HSMenubarItemMenuDelegate *delegate = nil;
755771

756-
// We always need to start by erasing any preexisting menu stuff
757-
erase_all_menu_parts(L, statusItem);
758-
759772
switch (lua_type(L, 2)) {
760773
case LUA_TTABLE:
761774
// This is a static menu, so we can just parse the table and the menu will be populated
762-
menu = [[NSMenu alloc] initWithTitle:@"HammerspoonMenuItemStaticMenu"];
775+
menu = create_or_reuse_menu(L, statusItem, @"HammerspoonMenuItemStaticMenu");
776+
763777
if (menu) {
764778
[menu setAutoenablesItems:NO];
765779
parse_table(L, 2, menu, menuBarItem->stateBoxImageSize);
@@ -773,7 +787,8 @@ static int menubarSetMenu(lua_State *L) {
773787

774788
case LUA_TFUNCTION:
775789
// This is a dynamic menu, so create a delegate object that will allow us to fetch a table whenever the menu is about to be displayed
776-
menu = [[NSMenu alloc] initWithTitle:@"HammerspoonMenuItemDynamicMenu"];
790+
menu = create_or_reuse_menu(L, statusItem, @"HammerspoonMenuItemDynamicMenu");
791+
777792
if (menu) {
778793
[menu setAutoenablesItems:NO];
779794

@@ -787,7 +802,10 @@ static int menubarSetMenu(lua_State *L) {
787802
break;
788803
}
789804

790-
if (menu) {
805+
if (menu == nil) {
806+
// clear out any previous menu
807+
erase_all_menu_parts(L, statusItem);
808+
} else {
791809
[statusItem setMenu:menu];
792810
if (delegate) {
793811
[menu setDelegate:delegate];

0 commit comments

Comments
 (0)