Merge pull request #1308 from ychin/menu-enabled-state-fix

Fix menu items like Edit.Cut/Copy not disabled in normal mode
This commit is contained in:
Yee Cheng Chin
2022-10-08 11:26:22 -07:00
committed by GitHub
10 changed files with 82 additions and 17 deletions
+17
View File
@@ -17,6 +17,7 @@
NSTextInput
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14
, NSFontChanging
, NSMenuItemValidation
#endif
>
{
@@ -62,6 +63,22 @@
//
- (void)changeFont:(id)sender;
//
// NSMenuItemValidation
//
- (BOOL)validateMenuItem:(NSMenuItem *)item;
//
// Public macaction's
// Note: New items here need to be handled in validateMenuItem: as well.
//
- (IBAction)cut:(id)sender;
- (IBAction)copy:(id)sender;
- (IBAction)paste:(id)sender;
- (IBAction)undo:(id)sender;
- (IBAction)redo:(id)sender;
- (IBAction)selectAll:(id)sender;
//
// MMTextStorage methods
//
+17
View File
@@ -1140,6 +1140,23 @@ static void grid_free(Grid *grid) {
}
}
/// Specifies whether the menu item should be enabled/disabled.
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
if ([item action] == @selector(cut:)
|| [item action] == @selector(copy:)
|| [item action] == @selector(paste:)
|| [item action] == @selector(undo:)
|| [item action] == @selector(redo:)
|| [item action] == @selector(selectAll:))
return [item tag];
// This class should not have any special macOS menu itmes, so theoretically
// all of them should just return item.tag, but just in case macOS decides
// to inject some menu items to the parent NSView class without us knowing,
// we let the superclass handle this.
return YES;
}
//
// NOTE: The menu items cut/copy/paste/undo/redo/select all/... must be bound
+5
View File
@@ -47,4 +47,9 @@
- (BOOL)canBecomeMainWindow;
- (void)applicationDidChangeScreenParameters:(NSNotification *)notification;
// Public macaction's.
// Note: New items here need to be handled in validateMenuItem: as well.
- (void)performClose:(id)sender;
@end
+6 -3
View File
@@ -444,13 +444,16 @@ enum {
[super performClose:sender];
}
/// Validates whether the menu item should be enabled or not.
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
if ([item action] == @selector(vimMenuItemAction:)
|| [item action] == @selector(performClose:))
// This class only really have one action that's bound from Vim
if ([item action] == @selector(performClose:))
return [item tag];
return YES;
// Since this is a subclass of NSWindow, it has a bunch of auto-populated
// menu from the OS. Just pass it off to the superclass to let it handle it.
return [super validateMenuItem:item];
}
@end // MMFullScreenWindow
+1 -1
View File
@@ -906,7 +906,7 @@
|| [item action] == @selector(selectAll:))
return [item tag];
return YES;
return [super validateMenuItem:item];
}
@end // MMTextView
+9 -4
View File
@@ -1447,10 +1447,15 @@ static BOOL isUnsafeMessage(int msgid);
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.
// We are using auto-enabling of menu items, where instead of directly
// calling setEnabled:, we rely on validateMenuItem: callbacks in each
// target to handle whether they want each menu item to be enabled or not.
// This allows us to more easily control the enabled states of OS-injected
// menu items if we want to. To remember whether we want to enable/disable
// a Vim menu, we use item.tag to remember it. See each validateMenuItem:
// implementation for details.
//
// See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MenuList/Articles/EnablingMenuItems.html
[[self menuItemForDescriptor:desc] setTag:on];
const BOOL isPopup = [MMVimController hasPopupPrefix:rootName];
+4
View File
@@ -33,4 +33,8 @@
- (IBAction)toggleFullScreen:(id)sender;
- (IBAction)realToggleFullScreen:(id)sender;
// Public macaction's.
// Note: New items here need to be handled in validateMenuItem: as well.
- (void)performClose:(id)sender;
@end
+7 -3
View File
@@ -184,13 +184,17 @@ static CGSSetWindowBackgroundBlurRadiusFunction* GetCGSSetWindowBackgroundBlurRa
[super performClose:sender];
}
/// Validates whether the menu item should be enabled or not.
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
if ([item action] == @selector(vimMenuItemAction:)
|| [item action] == @selector(performClose:))
// This class only really have one action that's bound from Vim
if ([item action] == @selector(performClose:)) {
return [item tag];
}
return YES;
// Since this is a subclass of NSWindow, it has a bunch of auto-populated
// menu from the OS. Just pass it off to the superclass to let it handle it.
return [super validateMenuItem:item];
}
- (IBAction)zoom:(id)sender
+12 -1
View File
@@ -17,7 +17,12 @@
@class MMVimController;
@class MMVimView;
@interface MMWindowController : NSWindowController<NSWindowDelegate>
@interface MMWindowController : NSWindowController<
NSWindowDelegate
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14
, NSMenuItemValidation
#endif
>
{
MMVimController *vimController;
MMVimView *vimView;
@@ -104,6 +109,12 @@
- (BOOL)getDefaultTopLeft:(NSPoint*)pt;
- (void)runAfterWindowPresentedUsingBlock:(void (^)(void))block;
//
// NSMenuItemValidation
//
- (BOOL)validateMenuItem:(NSMenuItem *)item;
// Menu items / macactions
- (IBAction)addNewTab:(id)sender;
- (IBAction)toggleToolbar:(id)sender;
- (IBAction)performClose:(id)sender;
+4 -5
View File
@@ -1181,11 +1181,10 @@
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
if ([item action] == @selector(vimMenuItemAction:)
|| [item action] == @selector(performClose:))
return [item tag];
return YES;
// This class is a responsder class and this should get called when we have
// a specific action that we implement exposed as a menu. As such just return
// [item tag] and no need to worry about macOS-injected menus.
return [item tag];
}
// -- NSWindow delegate ------------------------------------------------------