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 <AppKit/NSEvent.h> | 5 #import <AppKit/AppKit.h> |
6 #include <Carbon/Carbon.h> | 6 #include <Carbon/Carbon.h> |
7 | 7 |
8 #include "chrome/browser/global_keyboard_shortcuts_mac.h" | 8 #include "chrome/browser/global_keyboard_shortcuts_mac.h" |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "chrome/app/chrome_command_ids.h" | 12 #include "chrome/app/chrome_command_ids.h" |
| 13 #import "chrome/browser/ui/cocoa/nsmenuitem_additions.h" |
| 14 |
| 15 namespace { |
| 16 |
| 17 // Returns the menu item associated with |key| in |menu|, or nil if not found. |
| 18 NSMenuItem* FindMenuItem(NSEvent* key, NSMenu* menu) { |
| 19 NSMenuItem* result = nil; |
| 20 |
| 21 for (NSMenuItem* item in [menu itemArray]) { |
| 22 NSMenu* submenu = [item submenu]; |
| 23 if (submenu) { |
| 24 if (submenu != [NSApp servicesMenu]) |
| 25 result = FindMenuItem(key, submenu); |
| 26 } else if ([item cr_firesForKeyEventIfEnabled:key]) { |
| 27 result = item; |
| 28 } |
| 29 |
| 30 if (result) |
| 31 break; |
| 32 } |
| 33 |
| 34 return result; |
| 35 } |
| 36 |
| 37 } // namespace |
13 | 38 |
14 // Basically, there are two kinds of keyboard shortcuts: Ones that should work | 39 // Basically, there are two kinds of keyboard shortcuts: Ones that should work |
15 // only if the tab contents is focused (BrowserKeyboardShortcut), and ones that | 40 // only if the tab contents is focused (BrowserKeyboardShortcut), and ones that |
16 // should work in all other cases (WindowKeyboardShortcut). In the latter case, | 41 // should work in all other cases (WindowKeyboardShortcut). In the latter case, |
17 // we differentiate between shortcuts that are checked before any other view | 42 // we differentiate between shortcuts that are checked before any other view |
18 // gets the chance to handle them (WindowKeyboardShortcut) or after all views | 43 // gets the chance to handle them (WindowKeyboardShortcut) or after all views |
19 // had a chance but did not handle the keypress event | 44 // had a chance but did not handle the keypress event |
20 // (DelayedWindowKeyboardShortcut). | 45 // (DelayedWindowKeyboardShortcut). |
21 | 46 |
22 const KeyboardShortcutData* GetWindowKeyboardShortcutTable( | 47 const KeyboardShortcutData* GetWindowKeyboardShortcutTable( |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 187 |
163 int CommandForBrowserKeyboardShortcut( | 188 int CommandForBrowserKeyboardShortcut( |
164 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, | 189 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, |
165 int vkey_code, unichar key_char) { | 190 int vkey_code, unichar key_char) { |
166 return CommandForKeyboardShortcut(GetBrowserKeyboardShortcutTable, | 191 return CommandForKeyboardShortcut(GetBrowserKeyboardShortcutTable, |
167 command_key, shift_key, | 192 command_key, shift_key, |
168 cntrl_key, opt_key, vkey_code, | 193 cntrl_key, opt_key, vkey_code, |
169 key_char); | 194 key_char); |
170 } | 195 } |
171 | 196 |
| 197 int CommandForKeyEvent(NSEvent* event) { |
| 198 if ([event type] != NSKeyDown) |
| 199 return -1; |
| 200 |
| 201 // Look in menu. |
| 202 NSMenuItem* item = FindMenuItem(event, [NSApp mainMenu]); |
| 203 if (item && [item action] == @selector(commandDispatch:) && [item tag] > 0) |
| 204 return [item tag]; |
| 205 |
| 206 // "Close window" doesn't use the |commandDispatch:| mechanism. Menu items |
| 207 // that do not correspond to IDC_ constants need no special treatment however, |
| 208 // as they can't be blacklisted in |
| 209 // |BrowserCommandController::IsReservedCommandOrKey()| anyhow. |
| 210 if (item && [item action] == @selector(performClose:)) |
| 211 return IDC_CLOSE_WINDOW; |
| 212 |
| 213 // "Exit" doesn't use the |commandDispatch:| mechanism either. |
| 214 if (item && [item action] == @selector(terminate:)) |
| 215 return IDC_EXIT; |
| 216 |
| 217 // Look in secondary keyboard shortcuts. |
| 218 NSUInteger modifiers = [event modifierFlags]; |
| 219 const bool cmdKey = (modifiers & NSCommandKeyMask) != 0; |
| 220 const bool shiftKey = (modifiers & NSShiftKeyMask) != 0; |
| 221 const bool cntrlKey = (modifiers & NSControlKeyMask) != 0; |
| 222 const bool optKey = (modifiers & NSAlternateKeyMask) != 0; |
| 223 const int keyCode = [event keyCode]; |
| 224 const unichar keyChar = KeyCharacterForEvent(event); |
| 225 |
| 226 int cmdNum = CommandForWindowKeyboardShortcut( |
| 227 cmdKey, shiftKey, cntrlKey, optKey, keyCode, keyChar); |
| 228 if (cmdNum != -1) |
| 229 return cmdNum; |
| 230 |
| 231 cmdNum = CommandForBrowserKeyboardShortcut( |
| 232 cmdKey, shiftKey, cntrlKey, optKey, keyCode, keyChar); |
| 233 if (cmdNum != -1) |
| 234 return cmdNum; |
| 235 |
| 236 return -1; |
| 237 } |
| 238 |
172 unichar KeyCharacterForEvent(NSEvent* event) { | 239 unichar KeyCharacterForEvent(NSEvent* event) { |
173 NSString* eventString = [event charactersIgnoringModifiers]; | 240 NSString* eventString = [event charactersIgnoringModifiers]; |
174 NSString* characters = [event characters]; | 241 NSString* characters = [event characters]; |
175 | 242 |
176 if ([eventString length] != 1) | 243 if ([eventString length] != 1) |
177 return 0; | 244 return 0; |
178 | 245 |
179 if ([characters length] != 1) | 246 if ([characters length] != 1) |
180 return [eventString characterAtIndex:0]; | 247 return [eventString characterAtIndex:0]; |
181 | 248 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 } | 293 } |
227 } | 294 } |
228 | 295 |
229 // opt/alt modifier is set (e.g. on german layout we want '{' for opt-8). | 296 // opt/alt modifier is set (e.g. on german layout we want '{' for opt-8). |
230 if ([event modifierFlags] & NSAlternateKeyMask) | 297 if ([event modifierFlags] & NSAlternateKeyMask) |
231 return rawChar; | 298 return rawChar; |
232 } | 299 } |
233 | 300 |
234 return noModifiersChar; | 301 return noModifiersChar; |
235 } | 302 } |
OLD | NEW |