OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/global_keyboard_shortcuts_mac.h" | 5 #include "chrome/browser/global_keyboard_shortcuts_mac.h" |
6 | 6 |
7 #import <AppKit/AppKit.h> | 7 #import <AppKit/AppKit.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 15 matching lines...) Expand all Loading... | |
26 result = item; | 26 result = item; |
27 } | 27 } |
28 | 28 |
29 if (result) | 29 if (result) |
30 break; | 30 break; |
31 } | 31 } |
32 | 32 |
33 return result; | 33 return result; |
34 } | 34 } |
35 | 35 |
36 #if DCHECK_IS_ON() | |
37 // The three main shortcut tables have been mostly migrated to | |
38 // accelerator_table.cc, and should be not used to remove redundant use. | |
39 bool IsMacViews() { | |
40 // FIXME(mblsha): What's the best way to check for that, that won't trigger on | |
tapted
2016/10/26 08:40:47
We should just move the tables into separate files
themblsha
2016/10/26 17:10:03
The normal tables are also used by the
-[ChromeC
tapted
2016/10/28 04:59:48
I think we can still use ChromeCommandDispatcherDe
themblsha
2016/10/28 17:32:22
That's a great idea and is much simpler than what
| |
41 // normal Cocoa builds? | |
42 return NSClassFromString(@"NativeWidgetMacNSWindow") != nil; | |
43 } | |
44 #endif // DCHECK_IS_ON() | |
45 | |
36 } // namespace | 46 } // namespace |
37 | 47 |
38 // Basically, there are two kinds of keyboard shortcuts: Ones that should work | 48 // Basically, there are two kinds of keyboard shortcuts: Ones that should work |
39 // only if the tab contents is focused (BrowserKeyboardShortcut), and ones that | 49 // only if the tab contents is focused (BrowserKeyboardShortcut), and ones that |
40 // should work in all other cases (WindowKeyboardShortcut). In the latter case, | 50 // should work in all other cases (WindowKeyboardShortcut). In the latter case, |
41 // we differentiate between shortcuts that are checked before any other view | 51 // we differentiate between shortcuts that are checked before any other view |
42 // gets the chance to handle them (WindowKeyboardShortcut) or after all views | 52 // gets the chance to handle them (WindowKeyboardShortcut) or after all views |
43 // had a chance but did not handle the keypress event | 53 // had a chance but did not handle the keypress event |
44 // (DelayedWindowKeyboardShortcut). | 54 // (DelayedWindowKeyboardShortcut). |
45 | 55 |
46 const KeyboardShortcutData* GetWindowKeyboardShortcutTable( | 56 const KeyboardShortcutData* GetWindowKeyboardShortcutTable( |
47 size_t* num_entries) { | 57 size_t* num_entries) { |
58 DCHECK(!IsMacViews()); | |
48 static const KeyboardShortcutData keyboard_shortcuts[] = { | 59 static const KeyboardShortcutData keyboard_shortcuts[] = { |
49 // cmd shift cntrl option | 60 // cmd shift cntrl option |
50 // --- ----- ----- ------ | 61 // --- ----- ----- ------ |
51 // '{' / '}' characters should be matched earlier than virtual key code | 62 // '{' / '}' characters should be matched earlier than virtual key code |
52 // (therefore we can match alt-8 as '{' on german keyboards). | 63 // (therefore we can match alt-8 as '{' on german keyboards). |
53 {true, false, false, false, 0, '}', IDC_SELECT_NEXT_TAB}, | 64 {true, false, false, false, 0, '}', IDC_SELECT_NEXT_TAB}, |
54 {true, false, false, false, 0, '{', IDC_SELECT_PREVIOUS_TAB}, | 65 {true, false, false, false, 0, '{', IDC_SELECT_PREVIOUS_TAB}, |
55 {false, false, true, false, kVK_PageDown, 0, IDC_SELECT_NEXT_TAB}, | 66 {false, false, true, false, kVK_PageDown, 0, IDC_SELECT_NEXT_TAB}, |
56 {false, false, true, false, kVK_Tab, 0, IDC_SELECT_NEXT_TAB}, | 67 {false, false, true, false, kVK_Tab, 0, IDC_SELECT_NEXT_TAB}, |
57 {false, false, true, false, kVK_PageUp, 0, IDC_SELECT_PREVIOUS_TAB}, | 68 {false, false, true, false, kVK_PageUp, 0, IDC_SELECT_PREVIOUS_TAB}, |
(...skipping 21 matching lines...) Expand all Loading... | |
79 {true, false, false, true, kVK_ANSI_L, 0, IDC_SHOW_DOWNLOADS}, | 90 {true, false, false, true, kVK_ANSI_L, 0, IDC_SHOW_DOWNLOADS}, |
80 }; | 91 }; |
81 | 92 |
82 *num_entries = arraysize(keyboard_shortcuts); | 93 *num_entries = arraysize(keyboard_shortcuts); |
83 | 94 |
84 return keyboard_shortcuts; | 95 return keyboard_shortcuts; |
85 } | 96 } |
86 | 97 |
87 const KeyboardShortcutData* GetDelayedWindowKeyboardShortcutTable( | 98 const KeyboardShortcutData* GetDelayedWindowKeyboardShortcutTable( |
88 size_t* num_entries) { | 99 size_t* num_entries) { |
100 DCHECK(!IsMacViews()); | |
89 static const KeyboardShortcutData keyboard_shortcuts[] = { | 101 static const KeyboardShortcutData keyboard_shortcuts[] = { |
90 //cmd shift cntrl option | 102 //cmd shift cntrl option |
91 //--- ----- ----- ------ | 103 //--- ----- ----- ------ |
92 {false, false, false, false, kVK_Escape, 0, IDC_STOP}, | 104 {false, false, false, false, kVK_Escape, 0, IDC_STOP}, |
93 }; | 105 }; |
94 | 106 |
95 *num_entries = arraysize(keyboard_shortcuts); | 107 *num_entries = arraysize(keyboard_shortcuts); |
96 | 108 |
97 return keyboard_shortcuts; | 109 return keyboard_shortcuts; |
98 } | 110 } |
99 | 111 |
100 const KeyboardShortcutData* GetBrowserKeyboardShortcutTable( | 112 const KeyboardShortcutData* GetBrowserKeyboardShortcutTable( |
101 size_t* num_entries) { | 113 size_t* num_entries) { |
114 DCHECK(!IsMacViews()); | |
102 static const KeyboardShortcutData keyboard_shortcuts[] = { | 115 static const KeyboardShortcutData keyboard_shortcuts[] = { |
103 //cmd shift cntrl option | 116 //cmd shift cntrl option |
104 //--- ----- ----- ------ | 117 //--- ----- ----- ------ |
105 {true, false, false, false, kVK_LeftArrow, 0, IDC_BACK}, | 118 {true, false, false, false, kVK_LeftArrow, 0, IDC_BACK}, |
106 {true, false, false, false, kVK_RightArrow, 0, IDC_FORWARD}, | 119 {true, false, false, false, kVK_RightArrow, 0, IDC_FORWARD}, |
107 {false, false, false, false, kVK_Delete, 0, IDC_BACKSPACE_BACK}, | 120 {false, false, false, false, kVK_Delete, 0, IDC_BACKSPACE_BACK}, |
108 {false, true, false, false, kVK_Delete, 0, IDC_BACKSPACE_FORWARD}, | 121 {false, true, false, false, kVK_Delete, 0, IDC_BACKSPACE_FORWARD}, |
109 {true, true, false, false, 0, 'c', IDC_DEV_TOOLS_INSPECT}, | 122 {true, true, false, false, 0, 'c', IDC_DEV_TOOLS_INSPECT}, |
110 }; | 123 }; |
111 | 124 |
112 *num_entries = arraysize(keyboard_shortcuts); | 125 *num_entries = arraysize(keyboard_shortcuts); |
113 | 126 |
114 return keyboard_shortcuts; | 127 return keyboard_shortcuts; |
115 } | 128 } |
116 | 129 |
130 // Lists shortcuts that are impossible to migrate to accelerator_table.cc | |
131 // (crbug.com/25946). | |
132 const KeyboardShortcutData* GetMacViewsKeyboardShortcutTable( | |
133 size_t* num_entries) { | |
134 static const KeyboardShortcutData keyboard_shortcuts[] = { | |
135 // cmd shift cntrl option | |
136 // --- ----- ----- ------ | |
137 // '{' / '}' characters should be matched earlier than virtual key code | |
138 // (therefore we can match alt-8 as '{' on german keyboards). | |
139 {true, false, false, false, 0, '}', IDC_SELECT_NEXT_TAB}, | |
140 {true, false, false, false, 0, '{', IDC_SELECT_PREVIOUS_TAB}, | |
141 }; | |
142 | |
143 *num_entries = arraysize(keyboard_shortcuts); | |
144 | |
145 return keyboard_shortcuts; | |
146 } | |
147 | |
117 static bool MatchesEventForKeyboardShortcut( | 148 static bool MatchesEventForKeyboardShortcut( |
118 const KeyboardShortcutData& shortcut, | 149 const KeyboardShortcutData& shortcut, |
119 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, | 150 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, |
120 int vkey_code, unichar key_char) { | 151 int vkey_code, unichar key_char) { |
121 // Expects that one of |key_char| or |vkey_code| is 0. | 152 // Expects that one of |key_char| or |vkey_code| is 0. |
122 DCHECK((shortcut.key_char == 0) ^ (shortcut.vkey_code == 0)); | 153 DCHECK((shortcut.key_char == 0) ^ (shortcut.vkey_code == 0)); |
123 if (shortcut.key_char) { | 154 if (shortcut.key_char) { |
124 // Shortcuts that have a |key_char| and have |opt_key| set are mistakes, | 155 // Shortcuts that have a |key_char| and have |opt_key| set are mistakes, |
125 // since |opt_key| is not checked when there is a |key_char|. | 156 // since |opt_key| is not checked when there is a |key_char|. |
126 DCHECK(!shortcut.opt_key); | 157 DCHECK(!shortcut.opt_key); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 | 219 |
189 int CommandForBrowserKeyboardShortcut( | 220 int CommandForBrowserKeyboardShortcut( |
190 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, | 221 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, |
191 int vkey_code, unichar key_char) { | 222 int vkey_code, unichar key_char) { |
192 return CommandForKeyboardShortcut(GetBrowserKeyboardShortcutTable, | 223 return CommandForKeyboardShortcut(GetBrowserKeyboardShortcutTable, |
193 command_key, shift_key, | 224 command_key, shift_key, |
194 cntrl_key, opt_key, vkey_code, | 225 cntrl_key, opt_key, vkey_code, |
195 key_char); | 226 key_char); |
196 } | 227 } |
197 | 228 |
198 int CommandForKeyEvent(NSEvent* event) { | 229 int CommandForMacViewsKeyboardShortcut( |
230 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, | |
231 int vkey_code, unichar key_char) { | |
232 return CommandForKeyboardShortcut(GetMacViewsKeyboardShortcutTable, | |
233 command_key, shift_key, | |
234 cntrl_key, opt_key, vkey_code, | |
235 key_char); | |
236 } | |
237 | |
238 int CommandForKeyEvent(NSEvent* event, | |
239 int (^get_secondary_shortcuts_block)(bool cmdKey, | |
240 bool shiftKey, | |
241 bool cntrlKey, | |
242 bool optKey, | |
243 int keyCode, | |
244 unichar keyChar)) { | |
199 if ([event type] != NSKeyDown) | 245 if ([event type] != NSKeyDown) |
200 return -1; | 246 return -1; |
201 | 247 |
202 // Look in menu. | 248 // Look in menu. |
203 NSMenuItem* item = FindMenuItem(event, [NSApp mainMenu]); | 249 NSMenuItem* item = FindMenuItem(event, [NSApp mainMenu]); |
204 if (item && [item action] == @selector(commandDispatch:) && [item tag] > 0) | 250 if (item && [item action] == @selector(commandDispatch:) && [item tag] > 0) |
205 return [item tag]; | 251 return [item tag]; |
206 | 252 |
207 // "Close window" doesn't use the |commandDispatch:| mechanism. Menu items | 253 // "Close window" doesn't use the |commandDispatch:| mechanism. Menu items |
208 // that do not correspond to IDC_ constants need no special treatment however, | 254 // that do not correspond to IDC_ constants need no special treatment however, |
209 // as they can't be blacklisted in | 255 // as they can't be blacklisted in |
210 // |BrowserCommandController::IsReservedCommandOrKey()| anyhow. | 256 // |BrowserCommandController::IsReservedCommandOrKey()| anyhow. |
211 if (item && [item action] == @selector(performClose:)) | 257 if (item && [item action] == @selector(performClose:)) |
212 return IDC_CLOSE_WINDOW; | 258 return IDC_CLOSE_WINDOW; |
213 | 259 |
214 // "Exit" doesn't use the |commandDispatch:| mechanism either. | 260 // "Exit" doesn't use the |commandDispatch:| mechanism either. |
215 if (item && [item action] == @selector(terminate:)) | 261 if (item && [item action] == @selector(terminate:)) |
216 return IDC_EXIT; | 262 return IDC_EXIT; |
217 | 263 |
218 // Look in secondary keyboard shortcuts. | 264 // Look in secondary keyboard shortcuts. |
219 NSUInteger modifiers = [event modifierFlags]; | 265 NSUInteger modifiers = [event modifierFlags]; |
220 const bool cmdKey = (modifiers & NSCommandKeyMask) != 0; | 266 const bool cmdKey = (modifiers & NSCommandKeyMask) != 0; |
221 const bool shiftKey = (modifiers & NSShiftKeyMask) != 0; | 267 const bool shiftKey = (modifiers & NSShiftKeyMask) != 0; |
222 const bool cntrlKey = (modifiers & NSControlKeyMask) != 0; | 268 const bool cntrlKey = (modifiers & NSControlKeyMask) != 0; |
223 const bool optKey = (modifiers & NSAlternateKeyMask) != 0; | 269 const bool optKey = (modifiers & NSAlternateKeyMask) != 0; |
224 const int keyCode = [event keyCode]; | 270 const int keyCode = [event keyCode]; |
225 const unichar keyChar = KeyCharacterForEvent(event); | 271 const unichar keyChar = KeyCharacterForEvent(event); |
226 | 272 |
227 int cmdNum = CommandForWindowKeyboardShortcut( | 273 return get_secondary_shortcuts_block(cmdKey, shiftKey, cntrlKey, optKey, |
228 cmdKey, shiftKey, cntrlKey, optKey, keyCode, keyChar); | 274 keyCode, keyChar); |
229 if (cmdNum != -1) | 275 } |
230 return cmdNum; | |
231 | 276 |
232 cmdNum = CommandForBrowserKeyboardShortcut( | 277 int CommandForKeyEvent(NSEvent* event) { |
233 cmdKey, shiftKey, cntrlKey, optKey, keyCode, keyChar); | 278 return CommandForKeyEvent( |
234 if (cmdNum != -1) | 279 event, ^int(bool cmdKey, bool shiftKey, bool cntrlKey, bool optKey, |
tapted
2016/10/26 08:40:47
I don't think this needs to be a block -- there's
themblsha
2016/10/28 17:32:22
Ah, yes, the implicit capturing of blocks. Probabl
| |
235 return cmdNum; | 280 int keyCode, unichar keyChar) { |
281 int cmdNum = CommandForWindowKeyboardShortcut( | |
282 cmdKey, shiftKey, cntrlKey, optKey, keyCode, keyChar); | |
283 if (cmdNum != -1) | |
284 return cmdNum; | |
236 | 285 |
237 return -1; | 286 cmdNum = CommandForBrowserKeyboardShortcut(cmdKey, shiftKey, cntrlKey, |
287 optKey, keyCode, keyChar); | |
288 return cmdNum; | |
289 }); | |
290 } | |
291 | |
292 int CommandForKeyEventOnMacViews(NSEvent* event) { | |
293 return CommandForKeyEvent( | |
294 event, ^int(bool cmdKey, bool shiftKey, bool cntrlKey, bool optKey, | |
295 int keyCode, unichar keyChar) { | |
296 return CommandForMacViewsKeyboardShortcut(cmdKey, shiftKey, cntrlKey, | |
297 optKey, keyCode, keyChar); | |
298 }); | |
238 } | 299 } |
239 | 300 |
240 unichar KeyCharacterForEvent(NSEvent* event) { | 301 unichar KeyCharacterForEvent(NSEvent* event) { |
241 NSString* eventString = [event charactersIgnoringModifiers]; | 302 NSString* eventString = [event charactersIgnoringModifiers]; |
242 NSString* characters = [event characters]; | 303 NSString* characters = [event characters]; |
243 | 304 |
244 if ([eventString length] != 1) | 305 if ([eventString length] != 1) |
245 return 0; | 306 return 0; |
246 | 307 |
247 if ([characters length] != 1) | 308 if ([characters length] != 1) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
294 } | 355 } |
295 } | 356 } |
296 | 357 |
297 // opt/alt modifier is set (e.g. on german layout we want '{' for opt-8). | 358 // opt/alt modifier is set (e.g. on german layout we want '{' for opt-8). |
298 if ([event modifierFlags] & NSAlternateKeyMask) | 359 if ([event modifierFlags] & NSAlternateKeyMask) |
299 return rawChar; | 360 return rawChar; |
300 } | 361 } |
301 | 362 |
302 return noModifiersChar; | 363 return noModifiersChar; |
303 } | 364 } |
OLD | NEW |