diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 24ff375441..c5af1bf6a0 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -9415,6 +9415,7 @@ tgetent Compiled with tgetent support, able to use a termcap timers Compiled with |timer_start()| support. title Compiled with window title support |'title'|. toolbar Compiled with support for |gui-toolbar|. +touchbar Compiled with support for Touch Bar in MacVim. transparency Compiled with 'transparency' support. ttyin input is a terminal (tty) ttyout output is a terminal (tty) diff --git a/runtime/doc/gui_mac.txt b/runtime/doc/gui_mac.txt index 89f16785ea..d5f20edf4c 100644 --- a/runtime/doc/gui_mac.txt +++ b/runtime/doc/gui_mac.txt @@ -12,14 +12,15 @@ The MacVim Graphical User Interface *macvim* *gui-macvim* 4. Special colors |macvim-colors| 5. Menus |macvim-menus| 6. Toolbar |macvim-toolbar| - 7. Dialogs |macvim-dialogs| - 8. System services |macvim-services| - 9. mvim:// URL handler |macvim-url-handler| -10. Keyboard shortcuts |macvim-shortcuts| -11. Trackpad gestures |macvim-gestures| -12. International |macvim-international| -13. Known bugs/missing features |macvim-todo| -14. Hints |macvim-hints| + 7. Touch Bar |macvim-touchbar| + 8. Dialogs |macvim-dialogs| + 9. System services |macvim-services| +10. mvim:// URL handler |macvim-url-handler| +11. Keyboard shortcuts |macvim-shortcuts| +12. Trackpad gestures |macvim-gestures| +13. International |macvim-international| +14. Known bugs/missing features |macvim-todo| +15. Hints |macvim-hints| Other relevant documentation: |gui.txt| For generic items of the GUI. @@ -345,7 +346,7 @@ associated: a title, a key equivalent and an action message. When a menu is displayed the title is shown on the left and the key equivalent (if any) is shown on the right. Key equivalents enable you to access a menu item using the keyboard instead of having to use the mouse. When a menu item is clicked -it will send it's associated action message. Actions can be used to instruct +it will send its associated action message. Actions can be used to instruct MacVim to paste some text (paste:), open a new window (newWindow:), etc. Certain actions are standard throughout OS X which is why MacVim must be able to set these for each menu item. (E.g. the menu item "Edit.Paste" must be @@ -467,19 +468,47 @@ empty space which will shink or expand so that the items to the right of it are right-aligned. A space (flexspace) will be created for any toolbar item whose name begins with "-space" ("-flexspace") and ends with "-" -Toolbar icons should be tiff, png or icns, of dimension 32x32 or 24x24 pixels. -The larger size is used when 'tbis' is "medium" or "large", otherwise the -smaller size is used (which is the default). If the icon file only contains -one dimension then Mac OS X will scale the icon to the appropriate dimension -if necessary. To avoid this, use a file format which supports multiple -resolutions (such as icns) and provide both 32x32 and 24x24 versions of the -icon. +Toolbar icons should be tiff, png, icns, or heic, of dimension 32x32 or 24x24 +pixels. The larger size is used when 'tbis' is "medium" or "large", otherwise +the smaller size is used (which is the default). If the icon file only +contains one dimension then Mac OS X will scale the icon to the appropriate +dimension if necessary. To avoid this, use a file format which supports +multiple resolutions (such as icns) and provide both 32x32 and 24x24 versions +of the icon. Note: Only a subset of the builtin toolbar items presently have icons. If no icon can be found a warning triangle is displayed instead. ============================================================================== -7. Dialogs *macvim-dialogs* +7. Touch Bar *macvim-touchbar* + +Touch Bar in MacVim works similar to the toolbar (see |macvim-toolbar|). The +difference is that you use the special menu "TouchBar" instead of "ToolBar": > + :an TouchBar.Hello :echo "Hello" + +The separators work similar to how toolbars work: > + :an TouchBar.-Sep- + :an TouchBar.-space1- + :an TouchBar.-flexspace2- + +The first example is a Vim separator (see |menu-separator|) and injects a +space between two buttons. The second creates a smaller space than a normal +separator and are specified by names that begin with "-space" and ends with +"-". The third creates a flexible empty space which will shrink or expand so +that items after it will be right-aligned, and is specified by names that +begin with "-flexspace" and ends with "-". + +You can specify icons for Touch Bar buttons the same way for toolbar icons. +Touch Bar icons should ideally be 36x36 pixels, and no larger than 44x44 +pixels. You can also use default template icons provided by Apple by using +their template names. An example: > + :an icon=NSTouchBarListViewTemplate TouchBar.ShowList + +This feature only works on Mac devices that come with Touch Bars. On the ones +that don't, nothing will show up. + +============================================================================== +8. Dialogs *macvim-dialogs* Dialogs can be controlled with the keyboard in two ways. By default each button in a dialog is bound to a key. The button that is highlighted by blue @@ -498,7 +527,7 @@ select the current button. The current button is indicated with a blue outline. ============================================================================== -8. System services *macvim-services* +9. System services *macvim-services* MacVim supports two system services. These can be accessed from the MacVim submenu in the Services menu or by right-clicking a selection. For services @@ -516,7 +545,7 @@ The services respect the "Open files from applications" setting in the general preferences. ============================================================================== -9. mvim:// URL handler *mvim://* *macvim-url-handler* +10. mvim:// URL handler *mvim://* *macvim-url-handler* MacVim supports a custom URL handler for "mvim://" URLs. The handler is supposed to be compatible to TextMate's URL scheme as documented at > @@ -537,7 +566,7 @@ will open the file /etc/profile on line 20 when clicked in a web browser. Note that url has to be a file:// url pointing to an existing local file. ============================================================================== -10. Keyboard shortcuts *macvim-shortcuts* +11. Keyboard shortcuts *macvim-shortcuts* Most keyboard shortcuts in MacVim are bound to menu items and can be discovered by looking through the menus (see |macvim-menus| on how to create @@ -617,7 +646,7 @@ sometimes be slightly involved. Here are all the things you need to consider: - A few command key mappings are set up by MacVim, see |cmd-movement|. ============================================================================== -11. Trackpad gestures *macvim-gestures* +12. Trackpad gestures *macvim-gestures* MacVim supports trackpad swipe gestures. By default this can be used to navigate back/forward in the help (try it!). @@ -648,7 +677,7 @@ As another example, here is how to switch buffers by swiping left/right: > See the section on |key-mapping| for more help on how to map keys. ============================================================================== -12. International *macvim-international* +13. International *macvim-international* When editing non-English text it may be convenient to keep separate keyboard layouts for normal and insert mode. This is supported via the 'imd' option on @@ -669,7 +698,7 @@ wrong layout when going back to normal mode, then select the layout you want to use in normal mode and type ":set imd" followed by ":set noimd". ============================================================================== -13. Known bugs/missing features *macvim-todo* +14. Known bugs/missing features *macvim-todo* This list is by no means exhaustive, it only enumerates some of the more prominent bugs/missing features. @@ -693,7 +722,7 @@ This is also the best place for making feature requests as well as for asking general questions about MacVim. ============================================================================== -14. Hints *macvim-hints* +15. Hints *macvim-hints* In this section some general (not necessarily MacVim specific) hints are given. diff --git a/runtime/doc/tags b/runtime/doc/tags index a00037931d..4e5a924f95 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -7428,6 +7428,7 @@ macvim-start gui_mac.txt /*macvim-start* macvim-tablabel gui_mac.txt /*macvim-tablabel* macvim-todo gui_mac.txt /*macvim-todo* macvim-toolbar gui_mac.txt /*macvim-toolbar* +macvim-touchbar gui_mac.txt /*macvim-touchbar* macvim-url-handler gui_mac.txt /*macvim-url-handler* macvim-user-defaults gui_mac.txt /*macvim-user-defaults* macvim-window-title gui_mac.txt /*macvim-window-title* diff --git a/runtime/menu.vim b/runtime/menu.vim index e995be06f5..0e86d07fe3 100644 --- a/runtime/menu.vim +++ b/runtime/menu.vim @@ -1287,4 +1287,27 @@ if has("gui_macvim") macm Help.MacVim\ Website action=openWebsite: endif +if has("touchbar") + " Set up default Touch Bar buttons. + " 1. Smart fullscreen icon that toggles between going full screen or not. + an icon=NSTouchBarEnterFullScreenTemplate 1.10 TouchBar.EnterFullScreen :set fullscreen + + let s:touchbar_fullscreen=0 + func! s:SetupFullScreenTouchBar() + if &fullscreen && s:touchbar_fullscreen == 0 + aun TouchBar.EnterFullScreen + an icon=NSTouchBarExitFullScreenTemplate 1.10 TouchBar.ExitFullScreen :set nofullscreen + let s:touchbar_fullscreen = 1 + elseif !&fullscreen && s:touchbar_fullscreen == 1 + aun TouchBar.ExitFullScreen + an icon=NSTouchBarEnterFullScreenTemplate 1.10 TouchBar.EnterFullScreen :set fullscreen + let s:touchbar_fullscreen = 0 + endif + endfunc + aug FullScreenTouchBar + au! + au VimResized * call SetupFullScreenTouchBar() + aug END +endif + " vim: set sw=2 : diff --git a/src/MacVim/MMVimController.h b/src/MacVim/MMVimController.h index cb5665ccf7..892a4f4149 100644 --- a/src/MacVim/MMVimController.h +++ b/src/MacVim/MMVimController.h @@ -15,8 +15,13 @@ -@interface MMVimController : NSObject +@interface MMVimController : NSObject< + NSToolbarDelegate + , NSOpenSavePanelDelegate +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 + , NSTouchBarDelegate +#endif + > { unsigned identifier; BOOL isInitialized; @@ -28,6 +33,12 @@ // TODO: Move all toolbar code to window controller? NSToolbar *toolbar; NSMutableDictionary *toolbarItemDict; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 + NSTouchBar *touchbar; + NSMutableDictionary *touchbarItemDict; + NSMutableArray *touchbarItemOrder; + NSMutableSet *touchbarDisabledItems; +#endif int pid; NSString *serverName; @@ -65,4 +76,7 @@ - (id)evaluateVimExpressionCocoa:(NSString *)expr errorString:(NSString **)errstr; - (void)processInputQueue:(NSArray *)queue; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 +- (NSTouchBar *)makeTouchBar; +#endif @end diff --git a/src/MacVim/MMVimController.m b/src/MacVim/MMVimController.m index 600b55ca29..ea3311a8c7 100644 --- a/src/MacVim/MMVimController.m +++ b/src/MacVim/MMVimController.m @@ -40,6 +40,9 @@ static NSString *MMDefaultToolbarImageName = @"Attention"; static int MMAlertTextFieldHeight = 22; +static const NSString * const MMToolbarMenuName = @"ToolBar"; +static const NSString * const MMTouchbarMenuName = @"TouchBar"; + // NOTE: By default a message sent to the backend will be dropped if it cannot // be delivered instantly; otherwise there is a possibility that MacVim will // 'beachball' while waiting to deliver DO messages to an unresponsive Vim @@ -130,6 +133,13 @@ - (id)initWithBackend:(id)backend pid:(int)processIdentifier backendProxy = [backend retain]; popupMenuItems = [[NSMutableArray alloc] init]; toolbarItemDict = [[NSMutableDictionary alloc] init]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 + if (NSClassFromString(@"NSTouchBar")) { + touchbarItemDict = [[NSMutableDictionary alloc] init]; + touchbarItemOrder = [[NSMutableArray alloc] init]; + touchbarDisabledItems = [[NSMutableSet alloc] init]; + } +#endif pid = processIdentifier; creationDate = [[NSDate alloc] init]; @@ -178,6 +188,12 @@ - (void)dealloc [toolbarItemDict release]; toolbarItemDict = nil; [toolbar release]; toolbar = nil; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 + [touchbarItemDict release]; touchbarItemDict = nil; + [touchbarItemOrder release]; touchbarItemOrder = nil; + [touchbarDisabledItems release]; touchbarDisabledItems = nil; + [touchbar release]; touchbar = nil; +#endif [popupMenuItems release]; popupMenuItems = nil; [windowController release]; windowController = nil; @@ -488,7 +504,46 @@ - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)theToolbar { return nil; } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 +- (NSTouchBar *)makeTouchBar +{ + touchbar = [[NSTouchBar alloc] init]; + touchbar.delegate = self; + + NSMutableArray *filteredTouchbarItemOrder = [NSMutableArray array]; + for (NSString *label in touchbarItemOrder) { + if (![touchbarDisabledItems containsObject:label]) { + if ([touchbarItemDict objectForKey:label] == nil) { + // The label begins and ends with '-'; decided which kind of separator + // item it is by looking at the prefix. + if ([label hasPrefix:@"-space"]) { + label = NSTouchBarItemIdentifierFixedSpaceSmall; + } else if ([label hasPrefix:@"-flexspace"]) { + label = NSTouchBarItemIdentifierFlexibleSpace; + } else { + label = NSTouchBarItemIdentifierFixedSpaceLarge; + } + } + + [filteredTouchbarItemOrder addObject:label]; + } + } + [filteredTouchbarItemOrder addObject:NSTouchBarItemIdentifierOtherItemsProxy]; + + touchbar.defaultItemIdentifiers = filteredTouchbarItemOrder; + return touchbar; +} + +- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)itemId +{ + NSTouchBarItem *item = [touchbarItemDict objectForKey:itemId]; + if (!item) { + ASLogWarn(@"No touchbar item with id '%@'", itemId); + } + return item; +} +#endif @end // MMVimController @@ -1068,7 +1123,7 @@ - (void)addMenuWithDescriptor:(NSArray *)desc atIndex:(int)idx if (!(desc && [desc count] > 0 && idx >= 0)) return; NSString *rootName = [desc objectAtIndex:0]; - if ([rootName isEqual:@"ToolBar"]) { + if ([rootName isEqual:MMToolbarMenuName]) { // The toolbar only has one menu, we take this as a hint to create a // toolbar, then we return. if (!toolbar) { @@ -1088,6 +1143,9 @@ - (void)addMenuWithDescriptor:(NSArray *)desc atIndex:(int)idx return; } + if ([rootName isEqual:MMTouchbarMenuName]) + return; + // This is either a main menu item or a popup menu item. NSString *title = [desc lastObject]; NSMenuItem *item = [[NSMenuItem alloc] init]; @@ -1133,12 +1191,20 @@ - (void)addMenuItemWithDescriptor:(NSArray *)desc NSString *title = [desc lastObject]; NSString *rootName = [desc objectAtIndex:0]; - if ([rootName isEqual:@"ToolBar"]) { + if ([rootName isEqual:MMToolbarMenuName]) { if (toolbar && [desc count] == 2) [self addToolbarItemWithLabel:title tip:tip icon:icon atIndex:idx]; return; } - + if ([rootName isEqual:MMTouchbarMenuName]) { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 + if (NSClassFromString(@"NSTouchBar")) { + if ([desc count] == 2) + [self addTouchbarItemWithLabel:title icon:icon atIndex:idx]; + } +#endif + return; + } NSMenu *parent = [self parentMenuForDescriptor:desc]; if (!parent) { ASLogWarn(@"Menu item '%@' has no parent", @@ -1189,7 +1255,7 @@ - (void)removeMenuItemWithDescriptor:(NSArray *)desc NSString *title = [desc lastObject]; NSString *rootName = [desc objectAtIndex:0]; - if ([rootName isEqual:@"ToolBar"]) { + if ([rootName isEqual:MMToolbarMenuName]) { if (toolbar) { // Only remove toolbar items, never actually remove the toolbar // itself or strange things may happen. @@ -1201,7 +1267,19 @@ - (void)removeMenuItemWithDescriptor:(NSArray *)desc } return; } - + if ([rootName isEqual:MMTouchbarMenuName]){ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 + if (NSClassFromString(@"NSTouchBar")) { + if ([desc count] == 2) { + [touchbarItemOrder removeObject:title]; + [touchbarItemDict removeObjectForKey:title]; + [touchbarDisabledItems removeObject:title]; + [windowController setTouchBar:nil]; + } + } +#endif + return; + } NSMenuItem *item = [self menuItemForDescriptor:desc]; if (!item) { ASLogWarn(@"Failed to remove menu item, descriptor not found: %@", @@ -1229,18 +1307,35 @@ - (void)enableMenuItemWithDescriptor:(NSArray *)desc state:(BOOL)on if (!(desc && [desc count] > 0)) return; NSString *rootName = [desc objectAtIndex:0]; - if ([rootName isEqual:@"ToolBar"]) { + if ([rootName isEqual:MMToolbarMenuName]) { if (toolbar && [desc count] == 2) { NSString *title = [desc lastObject]; [[toolbar itemWithItemIdentifier:title] setEnabled:on]; } - } else { - // Use tag to set whether item is enabled or disabled instead of - // calling setEnabled:. This way the menus can autoenable themselves - // but at the same time Vim can set if a menu is enabled whenever it - // wants to. - [[self menuItemForDescriptor:desc] setTag:on]; + return; } + + if ([rootName isEqual:MMTouchbarMenuName]) { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 + if (NSClassFromString(@"NSTouchBar")) { + if ([desc count] == 2) { + NSString *title = [desc lastObject]; + if (on) + [touchbarDisabledItems removeObject:title]; + else + [touchbarDisabledItems addObject:title]; + [windowController setTouchBar:nil]; + } + } +#endif + return; + } + + // Use tag to set whether item is enabled or disabled instead of + // calling setEnabled:. This way the menus can autoenable themselves + // but at the same time Vim can set if a menu is enabled whenever it + // wants to. + [[self menuItemForDescriptor:desc] setTag:on]; } - (void)addToolbarItemToDictionaryWithLabel:(NSString *)title @@ -1312,7 +1407,45 @@ - (void)addToolbarItemWithLabel:(NSString *)label [toolbar insertItemWithItemIdentifier:label atIndex:idx]; } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 +- (void)addTouchbarItemWithLabel:(NSString *)label + icon:(NSString *)icon + atIndex:(int)idx +{ + // Check for separator items. + if (!label) { + label = NSTouchBarItemIdentifierFixedSpaceLarge; + } else if ([label length] >= 2 && [label hasPrefix:@"-"] + && [label hasSuffix:@"-"]) { + // These will be converted to fixed/flexible space identifiers later, when "makeTouchBar" is called. + } else { + NSButton* button = [NSButton buttonWithTitle:label target:windowController action:@selector(vimTouchbarItemAction:)]; + NSCustomTouchBarItem *item = + [[NSCustomTouchBarItem alloc] initWithIdentifier:label]; + NSImage *img = [NSImage imageNamed:icon]; + + if (!img) { + img = [[[NSImage alloc] initByReferencingFile:icon] autorelease]; + if (!(img && [img isValid])) + img = nil; + } + if (img) { + [button setImage: img]; + //[button setImagePosition:NSImageLeft]; + [button setImagePosition:NSImageOnly]; + } + + [item setView:button]; + [touchbarItemDict setObject:item forKey:label]; + } + int maxIdx = [touchbarItemOrder count]; + if (maxIdx < idx) idx = maxIdx; + [touchbarItemOrder insertObject:label atIndex:idx]; + + [windowController setTouchBar:nil]; +} +#endif - (void)popupMenuWithDescriptor:(NSArray *)desc atRow:(NSNumber *)row column:(NSNumber *)col diff --git a/src/MacVim/MMWindowController.m b/src/MacVim/MMWindowController.m index c6fa99d795..a9437379ef 100644 --- a/src/MacVim/MMWindowController.m +++ b/src/MacVim/MMWindowController.m @@ -909,6 +909,16 @@ - (IBAction)vimToolbarItemAction:(id)sender [vimController sendMessage:ExecuteMenuMsgID data:[attrs dictionaryAsData]]; } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 +- (IBAction)vimTouchbarItemAction:(id)sender +{ + NSArray *desc = [NSArray arrayWithObjects:@"TouchBar", [sender title], nil]; + NSDictionary *attrs = [NSDictionary dictionaryWithObject:desc + forKey:@"descriptor"]; + [vimController sendMessage:ExecuteMenuMsgID data:[attrs dictionaryAsData]]; +} +#endif + - (IBAction)fontSizeUp:(id)sender { [[NSFontManager sharedFontManager] modifyFont: @@ -1348,6 +1358,13 @@ - (void)runAfterWindowPresentedUsingBlock:(void (^)(void))block [afterWindowPresentedQueue addObject:[block copy]]; } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12_2 +- (NSTouchBar *)makeTouchBar +{ + return [vimController makeTouchBar]; +} +#endif + @end // MMWindowController diff --git a/src/MacVim/gui_macvim.m b/src/MacVim/gui_macvim.m index ed1e9c4168..ce2239122f 100644 --- a/src/MacVim/gui_macvim.m +++ b/src/MacVim/gui_macvim.m @@ -799,6 +799,13 @@ // then a warning icon will be displayed). if (!icon) icon = lookup_toolbar_item(menu->iconidx); + + // Last step is to see if this is a standard Apple template icon. The + // touch bar templates are of the form "NSTouchBar*Template". + if (!icon) + if (menu->iconfile && STRNCMP(menu->iconfile, "NSTouchBar", 10) == 0) { + icon = menu->iconfile; + } } [[MMBackend sharedInstance] queueMessage:AddMenuItemMsgID properties: diff --git a/src/evalfunc.c b/src/evalfunc.c index f6034ee974..fbbf909189 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -6442,6 +6442,9 @@ f_has(typval_T *argvars, typval_T *rettv) #ifdef FEAT_TOOLBAR "toolbar", #endif +#ifdef FEAT_TOUCHBAR + "touchbar", +#endif #ifdef FEAT_TRANSPARENCY "transparency", #endif diff --git a/src/feature.h b/src/feature.h index 022226f918..8aeec378ce 100644 --- a/src/feature.h +++ b/src/feature.h @@ -731,6 +731,10 @@ #if defined(FEAT_TOOLBAR) && !defined(FEAT_MENU) # define FEAT_MENU #endif + +#if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_MACVIM) +# define FEAT_TOUCHBAR +#endif /* * GUI tabline diff --git a/src/menu.c b/src/menu.c index 04353f1519..9656721d4d 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1835,7 +1835,11 @@ menu_is_child_of_popup(vimmenu_T *menu) int menu_is_toolbar(char_u *name) { - return (STRNCMP(name, "ToolBar", 7) == 0); + return (STRNCMP(name, "ToolBar", 7) == 0) + #if defined(FEAT_TOUCHBAR) + || (STRNCMP(name, "TouchBar", 8) == 0) + #endif + ; } /*