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 |