| 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 } // namespace | 36 bool MatchesEventForKeyboardShortcut(const KeyboardShortcutData& shortcut, |
| 37 | 37 bool command_key, |
| 38 // Basically, there are two kinds of keyboard shortcuts: Ones that should work | 38 bool shift_key, |
| 39 // only if the tab contents is focused (BrowserKeyboardShortcut), and ones that | 39 bool cntrl_key, |
| 40 // should work in all other cases (WindowKeyboardShortcut). In the latter case, | 40 bool opt_key, |
| 41 // we differentiate between shortcuts that are checked before any other view | 41 int vkey_code, |
| 42 // gets the chance to handle them (WindowKeyboardShortcut) or after all views | 42 unichar key_char) { |
| 43 // had a chance but did not handle the keypress event | |
| 44 // (DelayedWindowKeyboardShortcut). | |
| 45 | |
| 46 const KeyboardShortcutData* GetWindowKeyboardShortcutTable( | |
| 47 size_t* num_entries) { | |
| 48 static const KeyboardShortcutData keyboard_shortcuts[] = { | |
| 49 // cmd shift cntrl option | |
| 50 // --- ----- ----- ------ | |
| 51 // '{' / '}' characters should be matched earlier than virtual key code | |
| 52 // (therefore we can match alt-8 as '{' on german keyboards). | |
| 53 {true, false, false, false, 0, '}', IDC_SELECT_NEXT_TAB}, | |
| 54 {true, false, false, false, 0, '{', IDC_SELECT_PREVIOUS_TAB}, | |
| 55 {false, false, true, false, kVK_PageDown, 0, IDC_SELECT_NEXT_TAB}, | |
| 56 {false, false, true, false, kVK_Tab, 0, IDC_SELECT_NEXT_TAB}, | |
| 57 {false, false, true, false, kVK_PageUp, 0, IDC_SELECT_PREVIOUS_TAB}, | |
| 58 {false, true, true, false, kVK_Tab, 0, IDC_SELECT_PREVIOUS_TAB}, | |
| 59 // Cmd-0..8 select the Nth tab, with cmd-9 being "last tab". | |
| 60 {true, false, false, false, kVK_ANSI_1, 0, IDC_SELECT_TAB_0}, | |
| 61 {true, false, false, false, kVK_ANSI_Keypad1, 0, IDC_SELECT_TAB_0}, | |
| 62 {true, false, false, false, kVK_ANSI_2, 0, IDC_SELECT_TAB_1}, | |
| 63 {true, false, false, false, kVK_ANSI_Keypad2, 0, IDC_SELECT_TAB_1}, | |
| 64 {true, false, false, false, kVK_ANSI_3, 0, IDC_SELECT_TAB_2}, | |
| 65 {true, false, false, false, kVK_ANSI_Keypad3, 0, IDC_SELECT_TAB_2}, | |
| 66 {true, false, false, false, kVK_ANSI_4, 0, IDC_SELECT_TAB_3}, | |
| 67 {true, false, false, false, kVK_ANSI_Keypad4, 0, IDC_SELECT_TAB_3}, | |
| 68 {true, false, false, false, kVK_ANSI_5, 0, IDC_SELECT_TAB_4}, | |
| 69 {true, false, false, false, kVK_ANSI_Keypad5, 0, IDC_SELECT_TAB_4}, | |
| 70 {true, false, false, false, kVK_ANSI_6, 0, IDC_SELECT_TAB_5}, | |
| 71 {true, false, false, false, kVK_ANSI_Keypad6, 0, IDC_SELECT_TAB_5}, | |
| 72 {true, false, false, false, kVK_ANSI_7, 0, IDC_SELECT_TAB_6}, | |
| 73 {true, false, false, false, kVK_ANSI_Keypad7, 0, IDC_SELECT_TAB_6}, | |
| 74 {true, false, false, false, kVK_ANSI_8, 0, IDC_SELECT_TAB_7}, | |
| 75 {true, false, false, false, kVK_ANSI_Keypad8, 0, IDC_SELECT_TAB_7}, | |
| 76 {true, false, false, false, kVK_ANSI_9, 0, IDC_SELECT_LAST_TAB}, | |
| 77 {true, false, false, false, kVK_ANSI_Keypad9, 0, IDC_SELECT_LAST_TAB}, | |
| 78 {true, true, false, false, kVK_ANSI_M, 0, IDC_SHOW_AVATAR_MENU}, | |
| 79 {true, false, false, true, kVK_ANSI_L, 0, IDC_SHOW_DOWNLOADS}, | |
| 80 }; | |
| 81 | |
| 82 *num_entries = arraysize(keyboard_shortcuts); | |
| 83 | |
| 84 return keyboard_shortcuts; | |
| 85 } | |
| 86 | |
| 87 const KeyboardShortcutData* GetDelayedWindowKeyboardShortcutTable( | |
| 88 size_t* num_entries) { | |
| 89 static const KeyboardShortcutData keyboard_shortcuts[] = { | |
| 90 //cmd shift cntrl option | |
| 91 //--- ----- ----- ------ | |
| 92 {false, false, false, false, kVK_Escape, 0, IDC_STOP}, | |
| 93 }; | |
| 94 | |
| 95 *num_entries = arraysize(keyboard_shortcuts); | |
| 96 | |
| 97 return keyboard_shortcuts; | |
| 98 } | |
| 99 | |
| 100 const KeyboardShortcutData* GetBrowserKeyboardShortcutTable( | |
| 101 size_t* num_entries) { | |
| 102 static const KeyboardShortcutData keyboard_shortcuts[] = { | |
| 103 //cmd shift cntrl option | |
| 104 //--- ----- ----- ------ | |
| 105 {true, false, false, false, kVK_LeftArrow, 0, IDC_BACK}, | |
| 106 {true, false, false, false, kVK_RightArrow, 0, IDC_FORWARD}, | |
| 107 {false, false, false, false, kVK_Delete, 0, IDC_BACKSPACE_BACK}, | |
| 108 {false, true, false, false, kVK_Delete, 0, IDC_BACKSPACE_FORWARD}, | |
| 109 {true, true, false, false, 0, 'c', IDC_DEV_TOOLS_INSPECT}, | |
| 110 }; | |
| 111 | |
| 112 *num_entries = arraysize(keyboard_shortcuts); | |
| 113 | |
| 114 return keyboard_shortcuts; | |
| 115 } | |
| 116 | |
| 117 static bool MatchesEventForKeyboardShortcut( | |
| 118 const KeyboardShortcutData& shortcut, | |
| 119 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, | |
| 120 int vkey_code, unichar key_char) { | |
| 121 // Expects that one of |key_char| or |vkey_code| is 0. | 43 // Expects that one of |key_char| or |vkey_code| is 0. |
| 122 DCHECK((shortcut.key_char == 0) ^ (shortcut.vkey_code == 0)); | 44 DCHECK((shortcut.key_char == 0) ^ (shortcut.vkey_code == 0)); |
| 123 if (shortcut.key_char) { | 45 if (shortcut.key_char) { |
| 124 // Shortcuts that have a |key_char| and have |opt_key| set are mistakes, | 46 // 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|. | 47 // since |opt_key| is not checked when there is a |key_char|. |
| 126 DCHECK(!shortcut.opt_key); | 48 DCHECK(!shortcut.opt_key); |
| 127 // The given shortcut key is to be matched by a keyboard character. | 49 // The given shortcut key is to be matched by a keyboard character. |
| 128 // In this case we ignore shift and opt (alt) key modifiers, because | 50 // In this case we ignore shift and opt (alt) key modifiers, because |
| 129 // the character may be generated by a combination with those keys. | 51 // the character may be generated by a combination with those keys. |
| 130 if (shortcut.command_key == command_key && | 52 if (shortcut.command_key == command_key && |
| 131 shortcut.cntrl_key == cntrl_key && | 53 shortcut.cntrl_key == cntrl_key && |
| 132 shortcut.key_char == key_char) | 54 shortcut.key_char == key_char) |
| 133 return true; | 55 return true; |
| 134 } else if (shortcut.vkey_code) { | 56 } else if (shortcut.vkey_code) { |
| 135 // The given shortcut key is to be matched by a virtual key code. | 57 // The given shortcut key is to be matched by a virtual key code. |
| 136 if (shortcut.command_key == command_key && | 58 if (shortcut.command_key == command_key && |
| 137 shortcut.shift_key == shift_key && | 59 shortcut.shift_key == shift_key && |
| 138 shortcut.cntrl_key == cntrl_key && | 60 shortcut.cntrl_key == cntrl_key && |
| 139 shortcut.opt_key == opt_key && | 61 shortcut.opt_key == opt_key && |
| 140 shortcut.vkey_code == vkey_code) | 62 shortcut.vkey_code == vkey_code) |
| 141 return true; | 63 return true; |
| 142 } else { | 64 } else { |
| 143 NOTREACHED(); // Shouldn't happen. | 65 NOTREACHED(); // Shouldn't happen. |
| 144 } | 66 } |
| 145 return false; | 67 return false; |
| 146 } | 68 } |
| 147 | 69 |
| 148 static int CommandForKeyboardShortcut( | 70 int CommandForKeyboardShortcut(const std::vector<KeyboardShortcutData>& table, |
| 149 const KeyboardShortcutData* (*get_keyboard_shortcut_table)(size_t*), | 71 bool command_key, |
| 150 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, | 72 bool shift_key, |
| 151 int vkey_code, unichar key_char) { | 73 bool cntrl_key, |
| 152 | 74 bool opt_key, |
| 75 int vkey_code, |
| 76 unichar key_char) { |
| 153 // Scan through keycodes and see if it corresponds to one of the global | 77 // Scan through keycodes and see if it corresponds to one of the global |
| 154 // shortcuts on file. | 78 // shortcuts on file. |
| 155 // | 79 // |
| 156 // TODO(jeremy): Change this into a hash table once we get enough | 80 // TODO(jeremy): Change this into a hash table once we get enough |
| 157 // entries in the array to make a difference. | 81 // entries in the array to make a difference. |
| 158 // (When turning this into a hash table, note that the current behavior | 82 // (When turning this into a hash table, note that the current behavior |
| 159 // relies on the order of the table (see the comment for '{' / '}' above). | 83 // relies on the order of the table (see the comment for '{' / '}' above). |
| 160 size_t num_shortcuts = 0; | 84 for (const auto& shortcut : table) { |
| 161 const KeyboardShortcutData *it = get_keyboard_shortcut_table(&num_shortcuts); | 85 if (MatchesEventForKeyboardShortcut(shortcut, command_key, shift_key, |
| 162 for (size_t i = 0; i < num_shortcuts; ++i, ++it) { | 86 cntrl_key, opt_key, vkey_code, |
| 163 if (MatchesEventForKeyboardShortcut(*it, command_key, shift_key, cntrl_key, | 87 key_char)) |
| 164 opt_key, vkey_code, key_char)) | 88 return shortcut.chrome_command; |
| 165 return it->chrome_command; | |
| 166 } | 89 } |
| 167 | 90 |
| 168 return -1; | 91 return -1; |
| 169 } | 92 } |
| 170 | 93 |
| 94 } // namespace |
| 95 |
| 171 int CommandForWindowKeyboardShortcut( | 96 int CommandForWindowKeyboardShortcut( |
| 172 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, | 97 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, |
| 173 int vkey_code, unichar key_char) { | 98 int vkey_code, unichar key_char) { |
| 174 return CommandForKeyboardShortcut(GetWindowKeyboardShortcutTable, | 99 return CommandForKeyboardShortcut(GetWindowKeyboardShortcutTable(), |
| 175 command_key, shift_key, | 100 command_key, shift_key, |
| 176 cntrl_key, opt_key, vkey_code, | 101 cntrl_key, opt_key, vkey_code, |
| 177 key_char); | 102 key_char); |
| 178 } | 103 } |
| 179 | 104 |
| 180 int CommandForDelayedWindowKeyboardShortcut( | 105 int CommandForDelayedWindowKeyboardShortcut( |
| 181 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, | 106 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, |
| 182 int vkey_code, unichar key_char) { | 107 int vkey_code, unichar key_char) { |
| 183 return CommandForKeyboardShortcut(GetDelayedWindowKeyboardShortcutTable, | 108 return CommandForKeyboardShortcut(GetDelayedWindowKeyboardShortcutTable(), |
| 184 command_key, shift_key, | 109 command_key, shift_key, |
| 185 cntrl_key, opt_key, vkey_code, | 110 cntrl_key, opt_key, vkey_code, |
| 186 key_char); | 111 key_char); |
| 187 } | 112 } |
| 188 | 113 |
| 189 int CommandForBrowserKeyboardShortcut( | 114 int CommandForBrowserKeyboardShortcut( |
| 190 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, | 115 bool command_key, bool shift_key, bool cntrl_key, bool opt_key, |
| 191 int vkey_code, unichar key_char) { | 116 int vkey_code, unichar key_char) { |
| 192 return CommandForKeyboardShortcut(GetBrowserKeyboardShortcutTable, | 117 return CommandForKeyboardShortcut(GetBrowserKeyboardShortcutTable(), |
| 193 command_key, shift_key, | 118 command_key, shift_key, |
| 194 cntrl_key, opt_key, vkey_code, | 119 cntrl_key, opt_key, vkey_code, |
| 195 key_char); | 120 key_char); |
| 196 } | 121 } |
| 197 | 122 |
| 198 int CommandForKeyEvent(NSEvent* event) { | 123 int CommandForKeyEvent(NSEvent* event) { |
| 199 if ([event type] != NSKeyDown) | 124 if ([event type] != NSKeyDown) |
| 200 return -1; | 125 return -1; |
| 201 | 126 |
| 202 // Look in menu. | 127 // Look in menu. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 } | 219 } |
| 295 } | 220 } |
| 296 | 221 |
| 297 // opt/alt modifier is set (e.g. on german layout we want '{' for opt-8). | 222 // opt/alt modifier is set (e.g. on german layout we want '{' for opt-8). |
| 298 if ([event modifierFlags] & NSAlternateKeyMask) | 223 if ([event modifierFlags] & NSAlternateKeyMask) |
| 299 return rawChar; | 224 return rawChar; |
| 300 } | 225 } |
| 301 | 226 |
| 302 return noModifiersChar; | 227 return noModifiersChar; |
| 303 } | 228 } |
| OLD | NEW |