@@ -299,7 +299,7 @@ - (id)init
299
299
ASLogCrit (@" Failed to register connection with name '%@ '" , name);
300
300
[connection release ]; connection = nil ;
301
301
}
302
-
302
+
303
303
#if !DISABLE_SPARKLE
304
304
// Sparkle is enabled (this is the default). Initialize it. It will
305
305
// automatically check for update.
@@ -321,6 +321,7 @@ - (void)dealloc
321
321
[openSelectionString release ]; openSelectionString = nil ;
322
322
[recentFilesMenuItem release ]; recentFilesMenuItem = nil ;
323
323
[defaultMainMenu release ]; defaultMainMenu = nil ;
324
+ currentMainMenu = nil ;
324
325
[appMenuItemTemplate release ]; appMenuItemTemplate = nil ;
325
326
[updater release ]; updater = nil ;
326
327
@@ -329,6 +330,11 @@ - (void)dealloc
329
330
330
331
- (void )applicationWillFinishLaunching : (NSNotification *)notification
331
332
{
333
+ // This prevents macOS from injecting "Enter Full Screen" menu item.
334
+ // MacVim already has a separate menu item to do that.
335
+ // See https://developer.apple.com/library/archive/releasenotes/AppKit/RN-AppKitOlderNotes/index.html#10_11FullScreen
336
+ [[NSUserDefaults standardUserDefaults ] setBool: NO forKey: @" NSFullScreenMenuItemEverywhere" ];
337
+
332
338
// Remember the default menu so that it can be restored if the user closes
333
339
// all editor windows.
334
340
defaultMainMenu = [[NSApp mainMenu ] retain ];
@@ -862,7 +868,42 @@ - (void)windowControllerWillOpen:(MMWindowController *)windowController
862
868
863
869
- (void )setMainMenu : (NSMenu *)mainMenu
864
870
{
865
- if ([NSApp mainMenu ] == mainMenu) return ;
871
+ if (currentMainMenu == mainMenu) {
872
+ return ;
873
+ }
874
+ currentMainMenu = mainMenu;
875
+ [self refreshMainMenu ];
876
+ }
877
+
878
+ // Refresh the currently active main menu. This call is necessary when any
879
+ // modification was made to the menu, because refreshMainMenu makes a copy of
880
+ // the main menu, meaning that modifications to the original menu wouldn't be
881
+ // reflected until refreshMainMenu is invoked.
882
+ - (void )markMainMenuDirty : (NSMenu *)mainMenu
883
+ {
884
+ if (currentMainMenu != mainMenu) {
885
+ // The menu being updated is not the currently set menu, so just ignore,
886
+ // as this is likely a background Vim window.
887
+ return ;
888
+ }
889
+ if (!mainMenuDirty) {
890
+ // Mark the main menu as dirty and queue up a refresh. We don't immediately
891
+ // execute the refresh so that multiple calls would get batched up in one go.
892
+ mainMenuDirty = YES ;
893
+ [self performSelectorOnMainThread: @selector (refreshMainMenu ) withObject: nil waitUntilDone: NO ];
894
+ }
895
+ }
896
+
897
+ - (void )refreshMainMenu
898
+ {
899
+ mainMenuDirty = NO ;
900
+
901
+ // Make a copy of the menu before we pass to AppKit. The main reason is
902
+ // that setWindowsMenu: below will inject items like "Tile Window to Left
903
+ // of Screen" to the Window menu, and on repeated calls it will keep adding
904
+ // the same item over and over again, without resolving for duplicates. Using
905
+ // copies help keep the source menu clean.
906
+ NSMenu *mainMenu = [currentMainMenu copy ];
866
907
867
908
// If the new menu has a "Recent Files" dummy item, then swap the real item
868
909
// for the dummy. We are forced to do this since Cocoa initializes the
@@ -871,7 +912,7 @@ - (void)setMainMenu:(NSMenu *)mainMenu
871
912
NSMenu *fileMenu = [mainMenu findFileMenu ];
872
913
if (recentFilesMenuItem && fileMenu) {
873
914
int dummyIdx =
874
- [fileMenu indexOfItemWithAction: @selector (recentFilesDummy: )];
915
+ [fileMenu indexOfItemWithAction: @selector (recentFilesDummy: )];
875
916
if (dummyIdx >= 0 ) {
876
917
NSMenuItem *dummyItem = [[fileMenu itemAtIndex: dummyIdx] retain ];
877
918
[fileMenu removeItemAtIndex: dummyIdx];
@@ -889,45 +930,26 @@ - (void)setMainMenu:(NSMenu *)mainMenu
889
930
}
890
931
}
891
932
892
- // Now set the new menu. Notice that we keep one menu for each editor
893
- // window since each editor can have its own set of menus. When swapping
894
- // menus we have to tell Cocoa where the new "MacVim", "Windows", and
895
- // "Services" menu are.
896
- [NSApp setMainMenu: mainMenu];
897
-
898
- // Setting the "MacVim" (or "Application") menu ensures that it is typeset
899
- // in boldface. (The setAppleMenu: method used to be public but is now
900
- // private so this will have to be considered a bit of a hack!)
901
- NSMenu *appMenu = [mainMenu findApplicationMenu ];
902
- [NSApp performSelector: @selector (setAppleMenu: ) withObject: appMenu];
903
-
904
933
#if DISABLE_SPARKLE
934
+ NSMenu *appMenu = [mainMenu findApplicationMenu ];
935
+
905
936
// If Sparkle is disabled, we want to remove the "Check for Updates" menu
906
937
// item since it's no longer useful.
907
938
NSMenuItem *checkForUpdatesItem = [appMenu itemAtIndex:
908
939
[appMenu indexOfItemWithAction: @selector (checkForUpdates: )]];
909
940
checkForUpdatesItem.hidden = true ;
910
941
#endif
911
942
943
+ // Now set the new menu. Notice that we keep one menu for each editor
944
+ // window since each editor can have its own set of menus. When swapping
945
+ // menus we have to tell Cocoa where the new "MacVim", "Windows", and
946
+ // "Services" menu are.
947
+ [NSApp setMainMenu: mainMenu];
948
+
912
949
NSMenu *servicesMenu = [mainMenu findServicesMenu ];
913
950
[NSApp setServicesMenu: servicesMenu];
914
951
915
952
NSMenu *windowsMenu = [mainMenu findWindowsMenu ];
916
- if (windowsMenu) {
917
- // Cocoa isn't clever enough to get rid of items it has added to the
918
- // "Windows" menu so we have to do it ourselves otherwise there will be
919
- // multiple menu items for each window in the "Windows" menu.
920
- // This code assumes that the only items Cocoa add are ones which
921
- // send off the action makeKeyAndOrderFront:. (Cocoa will not add
922
- // another separator item if the last item on the "Windows" menu
923
- // already is a separator, so we needen't worry about separators.)
924
- int i, count = [windowsMenu numberOfItems ];
925
- for (i = count-1 ; i >= 0 ; --i) {
926
- NSMenuItem *item = [windowsMenu itemAtIndex: i];
927
- if ([item action ] == @selector (makeKeyAndOrderFront: ))
928
- [windowsMenu removeItem: item];
929
- }
930
- }
931
953
[NSApp setWindowsMenu: windowsMenu];
932
954
}
933
955
@@ -1220,7 +1242,7 @@ - (IBAction)showVimHelp:(id)sender
1220
1242
@" -c" , @" :h gui_mac" , @" -c" , @" :res" , nil ]
1221
1243
workingDirectory: nil ];
1222
1244
}
1223
-
1245
+
1224
1246
- (IBAction )checkForUpdates:(id )sender
1225
1247
{
1226
1248
#if !DISABLE_SPARKLE
@@ -1816,7 +1838,7 @@ - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
1816
1838
// Only opens files that already exist.
1817
1839
if ([[NSFileManager defaultManager ] fileExistsAtPath: filePath]) {
1818
1840
NSArray *filenames = [NSArray arrayWithObject: filePath];
1819
-
1841
+
1820
1842
// Look for the line and column options.
1821
1843
NSDictionary *args = nil ;
1822
1844
NSString *line = [dict objectForKey: @" line" ];
@@ -1831,7 +1853,7 @@ - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
1831
1853
args = [NSDictionary dictionaryWithObject: line
1832
1854
forKey: @" cursorLine" ];
1833
1855
}
1834
-
1856
+
1835
1857
[self openFiles: filenames withArguments: args];
1836
1858
} else {
1837
1859
NSAlert *alert = [[NSAlert alloc ] init ];
@@ -2198,7 +2220,7 @@ - (void)startWatchingVimDir
2198
2220
2199
2221
NSString *path = [@" ~/.vim" stringByExpandingTildeInPath ];
2200
2222
NSArray *pathsToWatch = [NSArray arrayWithObject: path];
2201
-
2223
+
2202
2224
fsEventStream = FSEventStreamCreate (NULL , &fsEventCallback, NULL ,
2203
2225
(CFArrayRef )pathsToWatch, kFSEventStreamEventIdSinceNow ,
2204
2226
MMEventStreamLatency, kFSEventStreamCreateFlagNone );
0 commit comments