Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #import "chrome/browser/cocoa/nsmenuitem_additions.h" | |
| 2 | |
| 3 #include <Carbon/Carbon.h> | |
| 4 | |
| 5 #include "base/logging.h" | |
| 6 | |
| 7 @implementation NSMenuItem(ChromeAdditions) | |
| 8 | |
| 9 - (BOOL)cr_firesForKeyEvent:(NSEvent*)event { | |
| 10 DCHECK([event type] == NSKeyDown); | |
| 11 if (![self isEnabled]) | |
| 12 return NO; | |
| 13 | |
| 14 // In System Preferences->Keyboard->Keyboard Shortcuts, it is possible to add | |
| 15 // arbitrary keyboard shortcuts to applications. It is not documented how this | |
| 16 // works in detail, but |NSMenuItem| has a method |userKeyEquivalent| that | |
| 17 // sounds related. | |
| 18 // However, it looks like |userKeyEquivalent| is equal to |keyEquivalent| when | |
| 19 // a user shortcut is set in system preferences, i.e. Cocoa automatically | |
| 20 // sets/overwrites |keyEquivalent| as well. Hence, this method can ignore | |
| 21 // |userKeyEquivalent| and check |keyEquivalent| only. | |
| 22 | |
| 23 // Menu item key equivalents are nearly all stored without modifiers. The | |
| 24 // exception is shift, which is included in the key and not in the modifiers | |
| 25 // for printable characters (but not for stuff like arrow keys etc). | |
| 26 NSString* eventString = [event charactersIgnoringModifiers]; | |
| 27 NSUInteger eventModifiers = | |
| 28 [event modifierFlags] & NSDeviceIndependentModifierFlagsMask; | |
| 29 | |
| 30 if ([eventString length] == 0 || [[self keyEquivalent] length] == 0) | |
| 31 return NO; | |
| 32 | |
| 33 // Turns out esc never fires unless cmd or ctrl is down. | |
| 34 if ([event keyCode] == kVK_Escape && | |
| 35 (eventModifiers & (NSControlKeyMask | NSCommandKeyMask)) == 0) | |
| 36 return NO; | |
| 37 | |
| 38 // From the |NSMenuItem setKeyEquivalent:| documentation: | |
| 39 // | |
| 40 // If you want to specify the Backspace key as the key equivalent for a menu | |
| 41 // item, use a single character string with NSBackspaceCharacter (defined in | |
| 42 // NSText.h as 0x08) and for the Forward Delete key, use NSDeleteCharacter | |
| 43 // (defined in NSText.h as 0x7F). Note that these are not the same characters | |
| 44 // you get from an NSEvent key-down event when pressing those keys. | |
| 45 if ([[self keyEquivalent] characterAtIndex:0] == NSBackspaceCharacter | |
| 46 && [eventString characterAtIndex:0] == NSDeleteCharacter) { | |
| 47 unichar chr = NSBackspaceCharacter; | |
| 48 eventString = [NSString stringWithCharacters:&chr length:1]; | |
| 49 | |
| 50 // Make sure "shift" is not removed from modifiers below. | |
| 51 eventModifiers |= NSFunctionKeyMask; | |
| 52 } | |
| 53 if ([[self keyEquivalent] characterAtIndex:0] == NSDeleteCharacter && | |
| 54 [eventString characterAtIndex:0] == NSDeleteFunctionKey) { | |
| 55 unichar chr = NSDeleteCharacter; | |
| 56 eventString = [NSString stringWithCharacters:&chr length:1]; | |
| 57 | |
| 58 // Make sure "shift" is not removed from modifiers below. | |
| 59 eventModifiers |= NSFunctionKeyMask; | |
| 60 } | |
| 61 | |
| 62 // cmd-opt-a gives some weird char as characters and "a" as | |
| 63 // charactersWithoutModifiers with an US layout, but an "a" as characters and | |
| 64 // a weird char as "charactersWithoutModifiers" with a cyrillic layout. Oh, | |
| 65 // Cocoa! Instead of getting the current layout from Text Input Services, | |
| 66 // and then requesting the kTISPropertyUnicodeKeyLayoutData and looking in | |
| 67 // there, let's try a pragmatic hack. | |
| 68 if ([eventString characterAtIndex:0] > 0x7f && | |
| 69 [[event characters] length] > 0 && | |
| 70 [[event characters] characterAtIndex:0] <= 0x7f) | |
| 71 eventString = [event characters]; | |
| 72 | |
| 73 // When both |characters| and |charactersIgnoringModifiers| are ascii, we | |
| 74 // want to use |characters| if it's a character and | |
| 75 // |charactersIgnoringModifiers| else (on dvorak, cmd-shift-z should fire | |
| 76 // "cmd-:" instead of "cmd-;", but on dvorak-qwerty, cmd-shift-z should fire | |
| 77 // cmd-shift-z instead of cmd-:). | |
| 78 if ([eventString characterAtIndex:0] <= 0x7f && | |
| 79 [[event characters] length] > 0 && | |
| 80 [[event characters] characterAtIndex:0] <= 0x7f && | |
| 81 isalpha([[event characters] characterAtIndex:0])) | |
| 82 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
| |
| 83 | |
| 84 // Clear shift key for printable characters. | |
| 85 if ((eventModifiers & (NSNumericPadKeyMask | NSFunctionKeyMask)) == 0 && | |
| 86 [[self keyEquivalent] characterAtIndex:0] != '\r') | |
| 87 eventModifiers &= ~NSShiftKeyMask; | |
| 88 | |
| 89 // Clear all non-interesting modifiers | |
| 90 eventModifiers &= NSCommandKeyMask | | |
| 91 NSControlKeyMask | | |
| 92 NSAlternateKeyMask | | |
| 93 NSShiftKeyMask; | |
| 94 | |
| 95 return [eventString isEqualToString:[self keyEquivalent]] | |
| 96 && eventModifiers == [self keyEquivalentModifierMask]; | |
| 97 } | |
| 98 | |
| 99 @end | |
| 100 | |
| OLD | NEW |