Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Unified Diff: chrome/browser/cocoa/nsmenuitem_additions.mm

Issue 319001: Add a function that can check if a menu item would be fired by a keypress. (Closed)
Patch Set: remove done todo, 80cols Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/cocoa/nsmenuitem_additions.h ('k') | chrome/browser/cocoa/nsmenuitem_additions_unittest.mm » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/cocoa/nsmenuitem_additions.mm
diff --git a/chrome/browser/cocoa/nsmenuitem_additions.mm b/chrome/browser/cocoa/nsmenuitem_additions.mm
new file mode 100644
index 0000000000000000000000000000000000000000..2a4ccde59cbfc8a6067b96b7abc2e9626adf276d
--- /dev/null
+++ b/chrome/browser/cocoa/nsmenuitem_additions.mm
@@ -0,0 +1,100 @@
+#import "chrome/browser/cocoa/nsmenuitem_additions.h"
+
+#include <Carbon/Carbon.h>
+
+#include "base/logging.h"
+
+@implementation NSMenuItem(ChromeAdditions)
+
+- (BOOL)cr_firesForKeyEvent:(NSEvent*)event {
+ DCHECK([event type] == NSKeyDown);
+ if (![self isEnabled])
+ return NO;
+
+ // In System Preferences->Keyboard->Keyboard Shortcuts, it is possible to add
+ // arbitrary keyboard shortcuts to applications. It is not documented how this
+ // works in detail, but |NSMenuItem| has a method |userKeyEquivalent| that
+ // sounds related.
+ // However, it looks like |userKeyEquivalent| is equal to |keyEquivalent| when
+ // a user shortcut is set in system preferences, i.e. Cocoa automatically
+ // sets/overwrites |keyEquivalent| as well. Hence, this method can ignore
+ // |userKeyEquivalent| and check |keyEquivalent| only.
+
+ // Menu item key equivalents are nearly all stored without modifiers. The
+ // exception is shift, which is included in the key and not in the modifiers
+ // for printable characters (but not for stuff like arrow keys etc).
+ NSString* eventString = [event charactersIgnoringModifiers];
+ NSUInteger eventModifiers =
+ [event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
+
+ if ([eventString length] == 0 || [[self keyEquivalent] length] == 0)
+ return NO;
+
+ // Turns out esc never fires unless cmd or ctrl is down.
+ if ([event keyCode] == kVK_Escape &&
+ (eventModifiers & (NSControlKeyMask | NSCommandKeyMask)) == 0)
+ return NO;
+
+ // From the |NSMenuItem setKeyEquivalent:| documentation:
+ //
+ // If you want to specify the Backspace key as the key equivalent for a menu
+ // item, use a single character string with NSBackspaceCharacter (defined in
+ // NSText.h as 0x08) and for the Forward Delete key, use NSDeleteCharacter
+ // (defined in NSText.h as 0x7F). Note that these are not the same characters
+ // you get from an NSEvent key-down event when pressing those keys.
+ if ([[self keyEquivalent] characterAtIndex:0] == NSBackspaceCharacter
+ && [eventString characterAtIndex:0] == NSDeleteCharacter) {
+ unichar chr = NSBackspaceCharacter;
+ eventString = [NSString stringWithCharacters:&chr length:1];
+
+ // Make sure "shift" is not removed from modifiers below.
+ eventModifiers |= NSFunctionKeyMask;
+ }
+ if ([[self keyEquivalent] characterAtIndex:0] == NSDeleteCharacter &&
+ [eventString characterAtIndex:0] == NSDeleteFunctionKey) {
+ unichar chr = NSDeleteCharacter;
+ eventString = [NSString stringWithCharacters:&chr length:1];
+
+ // Make sure "shift" is not removed from modifiers below.
+ eventModifiers |= NSFunctionKeyMask;
+ }
+
+ // cmd-opt-a gives some weird char as characters and "a" as
+ // charactersWithoutModifiers with an US layout, but an "a" as characters and
+ // a weird char as "charactersWithoutModifiers" with a cyrillic layout. Oh,
+ // Cocoa! Instead of getting the current layout from Text Input Services,
+ // and then requesting the kTISPropertyUnicodeKeyLayoutData and looking in
+ // there, let's try a pragmatic hack.
+ if ([eventString characterAtIndex:0] > 0x7f &&
+ [[event characters] length] > 0 &&
+ [[event characters] characterAtIndex:0] <= 0x7f)
+ eventString = [event characters];
+
+ // When both |characters| and |charactersIgnoringModifiers| are ascii, we
+ // want to use |characters| if it's a character and
+ // |charactersIgnoringModifiers| else (on dvorak, cmd-shift-z should fire
+ // "cmd-:" instead of "cmd-;", but on dvorak-qwerty, cmd-shift-z should fire
+ // cmd-shift-z instead of cmd-:).
+ if ([eventString characterAtIndex:0] <= 0x7f &&
+ [[event characters] length] > 0 &&
+ [[event characters] characterAtIndex:0] <= 0x7f &&
+ isalpha([[event characters] characterAtIndex:0]))
+ eventString = [event characters];
James Su 2009/10/26 03:10:13 Is it possible to make above two if statements eas
Nico 2009/10/26 03:22:14 No, on the dvorak-qwertycmd layout, cmd-z will sen
+
+ // Clear shift key for printable characters.
+ if ((eventModifiers & (NSNumericPadKeyMask | NSFunctionKeyMask)) == 0 &&
+ [[self keyEquivalent] characterAtIndex:0] != '\r')
+ eventModifiers &= ~NSShiftKeyMask;
+
+ // Clear all non-interesting modifiers
+ eventModifiers &= NSCommandKeyMask |
+ NSControlKeyMask |
+ NSAlternateKeyMask |
+ NSShiftKeyMask;
+
+ return [eventString isEqualToString:[self keyEquivalent]]
+ && eventModifiers == [self keyEquivalentModifierMask];
+}
+
+@end
+
« no previous file with comments | « chrome/browser/cocoa/nsmenuitem_additions.h ('k') | chrome/browser/cocoa/nsmenuitem_additions_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698