Skip to content

Commit 15eadd7

Browse files
committed
Fix tmenu in MacVim and submenu handling in TouchBar
Fix `tmenu` to work when it's called after the menu has already been created, by implementing `gui_mch_menu_set_tip`. This works for menus, tool bar, and Touch Bar (see #1084 which added tmenu support for TouchBar). Also, fix Touch Bar's submenu handling to reuse more common shared function. Previously enabling/disabling/removing Touch Bar submenu items didn't work as it had a hard-coded length check.
1 parent f88fb5e commit 15eadd7

4 files changed

Lines changed: 128 additions & 34 deletions

File tree

src/MacVim/MMVimController.m

Lines changed: 109 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ - (void)addMenuItemWithDescriptor:(NSArray *)desc
132132
isAlternate:(BOOL)isAlternate;
133133
- (void)removeMenuItemWithDescriptor:(NSArray *)desc;
134134
- (void)enableMenuItemWithDescriptor:(NSArray *)desc state:(BOOL)on;
135+
- (void)updateMenuItemTooltipWithDescriptor:(NSArray *)desc tip:(NSString *)tip;
135136
- (void)addToolbarItemToDictionaryWithLabel:(NSString *)title
136137
toolTip:(NSString *)tip icon:(NSString *)icon;
137138
- (void)addToolbarItemWithLabel:(NSString *)label
@@ -144,6 +145,12 @@ - (void)addTouchbarItemWithLabel:(NSString *)label
144145
isSubMenu:(BOOL)submenu
145146
desc:(NSArray *)desc
146147
atTouchBar:(MMTouchBarInfo *)touchbarInfo;
148+
- (void)updateTouchbarItemLabel:(NSString *)label
149+
tip:(NSString *)tip
150+
atTouchBarItem:(MMTouchBarItemInfo*)item;
151+
- (BOOL)touchBarItemForDescriptor:(NSArray *)desc
152+
touchBar:(MMTouchBarInfo **)touchBarPtr
153+
touchBarItem:(MMTouchBarItemInfo **)touchBarItemPtr;
147154
- (void)popupMenuWithDescriptor:(NSArray *)desc
148155
atRow:(NSNumber *)row
149156
column:(NSNumber *)col;
@@ -752,6 +759,10 @@ - (void)handleMessage:(int)msgid data:(NSData *)data
752759
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
753760
[self enableMenuItemWithDescriptor:[attrs objectForKey:@"descriptor"]
754761
state:[[attrs objectForKey:@"enable"] boolValue]];
762+
} else if (UpdateMenuItemTooltipMsgID == msgid) {
763+
NSDictionary *attrs = [NSDictionary dictionaryWithData:data];
764+
[self updateMenuItemTooltipWithDescriptor:[attrs objectForKey:@"descriptor"]
765+
tip:[attrs objectForKey:@"tip"]];
755766
} else if (ShowToolbarMsgID == msgid) {
756767
const void *bytes = [data bytes];
757768
int enable = *((int*)bytes); bytes += sizeof(int);
@@ -1025,10 +1036,11 @@ - (void)savePanelDidEnd:(NSSavePanel *)panel code:(int)code
10251036
{
10261037
NSString *path = nil;
10271038
#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10)
1028-
if (code == NSModalResponseOK) {
1039+
if (code == NSModalResponseOK)
10291040
#else
1030-
if (code == NSOKButton) {
1041+
if (code == NSOKButton)
10311042
#endif
1043+
{
10321044
NSURL *url = [panel URL];
10331045
if ([url isFileURL])
10341046
path = [url path];
@@ -1214,16 +1226,9 @@ - (void)addMenuWithDescriptor:(NSArray *)desc atIndex:(int)idx
12141226
if ([desc count] >= 3) // Unfortunately currently Apple does not support nested popover's so we can only do one level nesting
12151227
return;
12161228

1217-
MMTouchBarInfo *submenuTouchbar = touchbarInfo;
1218-
for (int i = 1; i < [desc count] - 1; i++) {
1219-
NSString *submenuName = [desc objectAtIndex:i];
1220-
MMTouchBarItemInfo *submenu = [[submenuTouchbar itemDict] objectForKey:submenuName];
1221-
if ([submenu childTouchbar]) {
1222-
submenuTouchbar = [submenu childTouchbar];
1223-
} else {
1224-
ASLogWarn(@"No Touch Bar submenu with id '%@'", submenuName);
1225-
return;
1226-
}
1229+
MMTouchBarInfo *submenuTouchbar = nil;
1230+
if (![self touchBarItemForDescriptor:desc touchBar:&submenuTouchbar touchBarItem:nil]) {
1231+
return;
12271232
}
12281233
// Icon is not supported for Touch Bar submenu for now, as "amenu" does not have a way of specifying "icon=<icon_path>" for submenus.
12291234
NSString *title = [desc lastObject];
@@ -1289,17 +1294,11 @@ - (void)addMenuItemWithDescriptor:(NSArray *)desc
12891294
return;
12901295

12911296
if (NSClassFromString(@"NSTouchBar")) {
1292-
MMTouchBarInfo *submenuTouchbar = touchbarInfo;
1293-
for (int i = 1; i < [desc count] - 1; i++) {
1294-
NSString *submenuName = [desc objectAtIndex:i];
1295-
MMTouchBarItemInfo *submenu = [[submenuTouchbar itemDict] objectForKey:submenuName];
1296-
if ([submenu childTouchbar]) {
1297-
submenuTouchbar = [submenu childTouchbar];
1298-
} else {
1299-
ASLogWarn(@"No Touch Bar submenu with id '%@'", submenuName);
1300-
return;
1301-
}
1297+
MMTouchBarInfo *submenuTouchbar = nil;
1298+
if (![self touchBarItemForDescriptor:desc touchBar:&submenuTouchbar touchBarItem:nil]) {
1299+
return;
13021300
}
1301+
13031302
[self addTouchbarItemWithLabel:title icon:icon tip:tip atIndex:idx isSubMenu:NO desc:desc atTouchBar:submenuTouchbar];
13041303
}
13051304
#endif
@@ -1370,11 +1369,14 @@ - (void)removeMenuItemWithDescriptor:(NSArray *)desc
13701369
if ([rootName isEqual:MMTouchbarMenuName]){
13711370
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2
13721371
if (NSClassFromString(@"NSTouchBar")) {
1373-
if ([desc count] == 2) {
1374-
[[touchbarInfo itemOrder] removeObject:title];
1375-
[[touchbarInfo itemDict] removeObjectForKey:title];
1376-
[windowController setTouchBar:nil];
1372+
MMTouchBarInfo *submenuTouchbar = nil;
1373+
if (![self touchBarItemForDescriptor:desc touchBar:&submenuTouchbar touchBarItem:nil]) {
1374+
return;
13771375
}
1376+
1377+
[[submenuTouchbar itemOrder] removeObject:title];
1378+
[[submenuTouchbar itemDict] removeObjectForKey:title];
1379+
[windowController setTouchBar:nil];
13781380
}
13791381
#endif
13801382
return;
@@ -1417,11 +1419,12 @@ - (void)enableMenuItemWithDescriptor:(NSArray *)desc state:(BOOL)on
14171419
if ([rootName isEqual:MMTouchbarMenuName]) {
14181420
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2
14191421
if (NSClassFromString(@"NSTouchBar")) {
1420-
if ([desc count] == 2) {
1421-
NSString *title = [desc lastObject];
1422-
[[touchbarInfo.itemDict objectForKey:title] setEnabled:on];
1423-
[windowController setTouchBar:nil];
1422+
MMTouchBarItemInfo *touchbarItem = nil;
1423+
if (![self touchBarItemForDescriptor:desc touchBar:nil touchBarItem:&touchbarItem]) {
1424+
return;
14241425
}
1426+
[touchbarItem setEnabled:on];
1427+
[windowController setTouchBar:nil];
14251428
}
14261429
#endif
14271430
return;
@@ -1433,6 +1436,38 @@ - (void)enableMenuItemWithDescriptor:(NSArray *)desc state:(BOOL)on
14331436
// wants to.
14341437
[[self menuItemForDescriptor:desc] setTag:on];
14351438
}
1439+
1440+
- (void)updateMenuItemTooltipWithDescriptor:(NSArray *)desc
1441+
tip:(NSString *)tip
1442+
{
1443+
if (!(desc && [desc count] > 0)) return;
1444+
1445+
NSString *rootName = [desc objectAtIndex:0];
1446+
if ([rootName isEqual:MMToolbarMenuName]) {
1447+
if (toolbar && [desc count] == 2) {
1448+
NSString *title = [desc lastObject];
1449+
[[toolbar itemWithItemIdentifier:title] setToolTip:tip];
1450+
}
1451+
return;
1452+
}
1453+
1454+
if ([rootName isEqual:MMTouchbarMenuName]) {
1455+
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2
1456+
if (NSClassFromString(@"NSTouchBar")) {
1457+
MMTouchBarItemInfo *touchbarItem = nil;
1458+
if (![self touchBarItemForDescriptor:desc touchBar:nil touchBarItem:&touchbarItem]) {
1459+
return;
1460+
}
1461+
NSString *title = [desc lastObject];
1462+
[self updateTouchbarItemLabel:title tip:tip atTouchBarItem:touchbarItem];
1463+
[windowController setTouchBar:nil];
1464+
}
1465+
#endif
1466+
return;
1467+
}
1468+
1469+
[[self menuItemForDescriptor:desc] setToolTip:tip];
1470+
}
14361471

14371472
- (void)addToolbarItemToDictionaryWithLabel:(NSString *)title
14381473
toolTip:(NSString *)tip
@@ -1575,6 +1610,50 @@ - (void)addTouchbarItemWithLabel:(NSString *)label
15751610

15761611
[windowController setTouchBar:nil];
15771612
}
1613+
1614+
- (void)updateTouchbarItemLabel:(NSString *)label
1615+
tip:(NSString *)tip
1616+
atTouchBarItem:(MMTouchBarItemInfo*)item
1617+
{
1618+
// The logic here should match that in addTouchbarItemWithLabel: as otherwise we will
1619+
// get weird results when adding/removing tooltips.
1620+
BOOL useTip = tip && [tip length] != 0;
1621+
NSString *buttonTitle = useTip ? tip : label;
1622+
NSCustomTouchBarItem *touchbarItem = (NSCustomTouchBarItem*)item.touchbarItem;
1623+
MMTouchBarButton *button = (MMTouchBarButton*)touchbarItem.view;
1624+
[button setTitle:buttonTitle];
1625+
if (button.image) {
1626+
if (useTip) {
1627+
[button setImagePosition:NSImageLeft];
1628+
} else {
1629+
[button setImagePosition:NSImageOnly];
1630+
}
1631+
} else {
1632+
[button setImagePosition:NSNoImage];
1633+
}
1634+
}
1635+
1636+
- (BOOL)touchBarItemForDescriptor:(NSArray *)desc
1637+
touchBar:(MMTouchBarInfo **)touchBarPtr
1638+
touchBarItem:(MMTouchBarItemInfo **)touchBarItemPtr
1639+
{
1640+
MMTouchBarInfo *submenuTouchbar = touchbarInfo;
1641+
for (int i = 1; i < [desc count] - 1; i++) {
1642+
NSString *submenuName = [desc objectAtIndex:i];
1643+
MMTouchBarItemInfo *submenu = [[submenuTouchbar itemDict] objectForKey:submenuName];
1644+
if ([submenu childTouchbar]) {
1645+
submenuTouchbar = [submenu childTouchbar];
1646+
} else {
1647+
ASLogWarn(@"No Touch Bar submenu with id '%@'", submenuName);
1648+
return NO;
1649+
}
1650+
}
1651+
if (touchBarPtr)
1652+
*touchBarPtr = submenuTouchbar;
1653+
if (touchBarItemPtr)
1654+
*touchBarItemPtr = [[submenuTouchbar itemDict] objectForKey:[desc lastObject]];
1655+
return YES;
1656+
}
15781657
#endif
15791658
- (void)popupMenuWithDescriptor:(NSArray *)desc
15801659
atRow:(NSNumber *)row

src/MacVim/MacVim.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ extern const char * const MMVimMsgIDStrings[];
203203
MSG(RemoveMenuItemMsgID) \
204204
MSG(EnableMenuItemMsgID) \
205205
MSG(ExecuteMenuMsgID) \
206+
MSG(UpdateMenuItemTooltipMsgID) \
206207
MSG(ShowToolbarMsgID) \
207208
MSG(ToggleToolbarMsgID) \
208209
MSG(CreateScrollbarMsgID) \

src/MacVim/gui_macvim.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,22 @@
894894
}
895895

896896

897+
/*
898+
* Update a menu's tooltip.
899+
*/
900+
void
901+
gui_mch_menu_set_tip(vimmenu_T *menu)
902+
{
903+
char_u *tip = menu->strings[MENU_INDEX_TIP];
904+
NSArray *desc = descriptor_for_menu(menu);
905+
[[MMBackend sharedInstance] queueMessage:UpdateMenuItemTooltipMsgID properties:
906+
[NSDictionary dictionaryWithObjectsAndKeys:
907+
desc, @"descriptor",
908+
[NSString stringWithVimString:tip], @"tip",
909+
nil]];
910+
}
911+
912+
897913
/*
898914
* This is called when a :popup command is executed.
899915
*/

src/menu.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -814,8 +814,7 @@ add_menu_path(
814814
}
815815
}
816816
#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN) \
817-
&& !defined(FEAT_GUI_MACVIM) \
818-
&& (defined(FEAT_BEVAL_GUI) || defined(FEAT_GUI_GTK))
817+
&& (defined(FEAT_BEVAL_GUI) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MACVIM))
819818
// Need to update the menu tip.
820819
if (modes & MENU_TIP_MODE)
821820
gui_mch_menu_set_tip(menu);
@@ -1010,8 +1009,7 @@ remove_menu(
10101009
{
10111010
free_menu_string(menu, MENU_INDEX_TIP);
10121011
#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN) \
1013-
&& !defined(FEAT_GUI_MACVIM) \
1014-
&& (defined(FEAT_BEVAL_GUI) || defined(FEAT_GUI_GTK))
1012+
&& (defined(FEAT_BEVAL_GUI) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MACVIM))
10151013
// Need to update the menu tip.
10161014
if (gui.in_use)
10171015
gui_mch_menu_set_tip(menu);

0 commit comments

Comments
 (0)