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/ui/cocoa/accelerators_cocoa.h" | 5 #include "chrome/browser/ui/cocoa/accelerators_cocoa.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 | 8 |
| 9 #include "base/logging.h" |
9 #include "base/memory/singleton.h" | 10 #include "base/memory/singleton.h" |
10 #include "chrome/app/chrome_command_ids.h" | 11 #include "chrome/app/chrome_command_ids.h" |
11 #import "ui/base/accelerators/platform_accelerator_cocoa.h" | 12 #import "ui/base/accelerators/platform_accelerator_cocoa.h" |
| 13 #import "ui/base/cocoa/cocoa_event_utils.h" |
| 14 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
12 | 15 |
13 namespace { | 16 namespace { |
14 | 17 |
| 18 // These accelerators are not associated with a command_id. |
| 19 const struct AcceleratorListing { |
| 20 NSUInteger modifiers; // The Cocoa modifiers. |
| 21 ui::KeyboardCode key_code; // The key used for cross-platform compatibility. |
| 22 } kAcceleratorList [] = { |
| 23 {NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_H}, |
| 24 {NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_W}, |
| 25 {NSCommandKeyMask | NSAlternateKeyMask | NSShiftKeyMask, ui::VKEY_V}, |
| 26 {NSCommandKeyMask, ui::VKEY_E}, |
| 27 {NSCommandKeyMask, ui::VKEY_J}, |
| 28 {NSCommandKeyMask, ui::VKEY_OEM_1}, |
| 29 {NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_OEM_1}, |
| 30 {NSCommandKeyMask, ui::VKEY_OEM_COMMA}, |
| 31 {NSCommandKeyMask | NSControlKeyMask, ui::VKEY_SPACE}, |
| 32 }; |
| 33 |
15 const struct AcceleratorMapping { | 34 const struct AcceleratorMapping { |
16 int command_id; | 35 int command_id; |
17 NSString* key; | 36 NSUInteger modifiers; // The Cocoa modifiers. |
18 NSUInteger modifiers; | 37 ui::KeyboardCode key_code; // The key used for cross-platform compatibility. |
19 } kAcceleratorMap[] = { | 38 } kAcceleratorMap[] = { |
20 { IDC_CLEAR_BROWSING_DATA, @"\x8", NSCommandKeyMask | NSShiftKeyMask }, | 39 // Accelerators used in the toolbar menu. |
21 { IDC_COPY, @"c", NSCommandKeyMask }, | 40 {IDC_CLEAR_BROWSING_DATA, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_BACK}, |
22 { IDC_CUT, @"x", NSCommandKeyMask }, | 41 {IDC_COPY, NSCommandKeyMask, ui::VKEY_C}, |
23 { IDC_DEV_TOOLS, @"i", NSCommandKeyMask | NSAlternateKeyMask }, | 42 {IDC_CUT, NSCommandKeyMask, ui::VKEY_X}, |
24 { IDC_DEV_TOOLS_CONSOLE, @"j", NSCommandKeyMask | NSAlternateKeyMask }, | 43 {IDC_DEV_TOOLS, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_I}, |
25 { IDC_FIND, @"f", NSCommandKeyMask }, | 44 {IDC_DEV_TOOLS_CONSOLE, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_J}, |
26 { IDC_FULLSCREEN, @"f", NSCommandKeyMask | NSShiftKeyMask }, | 45 {IDC_FIND, NSCommandKeyMask, ui::VKEY_F}, |
27 { IDC_NEW_INCOGNITO_WINDOW, @"n", NSCommandKeyMask | NSShiftKeyMask }, | 46 {IDC_FULLSCREEN, NSCommandKeyMask | NSControlKeyMask, ui::VKEY_F}, |
28 { IDC_NEW_TAB, @"t", NSCommandKeyMask }, | 47 {IDC_NEW_INCOGNITO_WINDOW, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_N}, |
29 { IDC_NEW_WINDOW, @"n", NSCommandKeyMask }, | 48 {IDC_NEW_TAB, NSCommandKeyMask, ui::VKEY_T}, |
30 { IDC_OPTIONS, @",", NSCommandKeyMask }, | 49 {IDC_NEW_WINDOW, NSCommandKeyMask, ui::VKEY_N}, |
31 { IDC_PASTE, @"v", NSCommandKeyMask }, | 50 {IDC_PASTE, NSCommandKeyMask, ui::VKEY_V}, |
32 { IDC_PRINT, @"p", NSCommandKeyMask }, | 51 {IDC_PRINT, NSCommandKeyMask, ui::VKEY_P}, |
33 { IDC_RESTORE_TAB, @"t", NSCommandKeyMask | NSShiftKeyMask }, | 52 {IDC_RESTORE_TAB, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_T}, |
34 { IDC_SAVE_PAGE, @"s", NSCommandKeyMask }, | 53 {IDC_SAVE_PAGE, NSCommandKeyMask, ui::VKEY_S}, |
35 { IDC_SHOW_BOOKMARK_BAR, @"b", NSCommandKeyMask | NSShiftKeyMask }, | 54 {IDC_SHOW_BOOKMARK_BAR, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_B}, |
36 { IDC_SHOW_BOOKMARK_MANAGER, @"b", NSCommandKeyMask | NSAlternateKeyMask }, | 55 {IDC_SHOW_BOOKMARK_MANAGER, NSCommandKeyMask | NSAlternateKeyMask, |
37 { IDC_BOOKMARK_PAGE, @"d", NSCommandKeyMask }, | 56 ui::VKEY_B}, |
38 { IDC_SHOW_DOWNLOADS, @"j", NSCommandKeyMask | NSShiftKeyMask }, | 57 {IDC_BOOKMARK_PAGE, NSCommandKeyMask, ui::VKEY_D}, |
39 { IDC_SHOW_HISTORY, @"y", NSCommandKeyMask }, | 58 {IDC_SHOW_DOWNLOADS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_J}, |
40 { IDC_VIEW_SOURCE, @"u", NSCommandKeyMask | NSAlternateKeyMask }, | 59 {IDC_SHOW_HISTORY, NSCommandKeyMask, ui::VKEY_Y}, |
41 { IDC_ZOOM_MINUS, @"-", NSCommandKeyMask }, | 60 {IDC_VIEW_SOURCE, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_U}, |
42 { IDC_ZOOM_PLUS, @"+", NSCommandKeyMask } | 61 {IDC_ZOOM_MINUS, NSCommandKeyMask, ui::VKEY_OEM_MINUS}, |
| 62 {IDC_ZOOM_PLUS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_OEM_PLUS}, |
| 63 |
| 64 // Accelerators used in MainMenu.xib, but not the toolbar menu. |
| 65 {IDC_HIDE_APP, NSCommandKeyMask, ui::VKEY_H}, |
| 66 {IDC_EXIT, NSCommandKeyMask, ui::VKEY_Q}, |
| 67 {IDC_OPEN_FILE, NSCommandKeyMask, ui::VKEY_O}, |
| 68 {IDC_FOCUS_LOCATION, NSCommandKeyMask, ui::VKEY_L}, |
| 69 {IDC_CLOSE_WINDOW, NSCommandKeyMask, ui::VKEY_W}, |
| 70 {IDC_EMAIL_PAGE_LOCATION, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_I}, |
| 71 {IDC_ADVANCED_PRINT, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_P}, |
| 72 {IDC_CONTENT_CONTEXT_UNDO, NSCommandKeyMask, ui::VKEY_Z}, |
| 73 {IDC_CONTENT_CONTEXT_REDO, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_Z}, |
| 74 {IDC_CONTENT_CONTEXT_CUT, NSCommandKeyMask, ui::VKEY_X}, |
| 75 {IDC_CONTENT_CONTEXT_COPY, NSCommandKeyMask, ui::VKEY_C}, |
| 76 {IDC_CONTENT_CONTEXT_PASTE, NSCommandKeyMask, ui::VKEY_V}, |
| 77 {IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE, |
| 78 NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_V}, |
| 79 {IDC_CONTENT_CONTEXT_SELECTALL, NSCommandKeyMask, ui::VKEY_A}, |
| 80 {IDC_FOCUS_SEARCH, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_F}, |
| 81 {IDC_FIND_NEXT, NSCommandKeyMask, ui::VKEY_G}, |
| 82 {IDC_FIND_PREVIOUS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_G}, |
| 83 {IDC_ZOOM_PLUS, NSCommandKeyMask, ui::VKEY_OEM_PLUS}, |
| 84 {IDC_ZOOM_MINUS, NSCommandKeyMask, ui::VKEY_OEM_MINUS}, |
| 85 {IDC_STOP, NSCommandKeyMask, ui::VKEY_OEM_PERIOD}, |
| 86 {IDC_RELOAD, NSCommandKeyMask, ui::VKEY_R}, |
| 87 {IDC_RELOAD_IGNORING_CACHE, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_R}, |
| 88 {IDC_PRESENTATION_MODE, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_F}, |
| 89 {IDC_ZOOM_NORMAL, NSCommandKeyMask, ui::VKEY_0}, |
| 90 {IDC_HOME, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_H}, |
| 91 {IDC_BACK, NSCommandKeyMask, ui::VKEY_OEM_4}, |
| 92 {IDC_FORWARD, NSCommandKeyMask, ui::VKEY_OEM_6}, |
| 93 {IDC_BOOKMARK_ALL_TABS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_D}, |
| 94 {IDC_MINIMIZE_WINDOW, NSCommandKeyMask, ui::VKEY_M}, |
| 95 {IDC_SELECT_NEXT_TAB, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_RIGHT}, |
| 96 {IDC_SELECT_PREVIOUS_TAB, NSCommandKeyMask | NSAlternateKeyMask, |
| 97 ui::VKEY_LEFT}, |
| 98 {IDC_TABPOSE, NSCommandKeyMask | NSControlKeyMask, ui::VKEY_T}, |
| 99 {IDC_HELP_PAGE_VIA_MENU, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_OEM_2}, |
43 }; | 100 }; |
44 | 101 |
| 102 // Create a Cocoa platform accelerator given a cross platform |key_code| and |
| 103 // the |cocoa_modifiers|. |
| 104 scoped_ptr<ui::PlatformAccelerator> PlatformAcceleratorFromKeyCode( |
| 105 ui::KeyboardCode key_code, |
| 106 NSUInteger cocoa_modifiers) { |
| 107 unichar character; |
| 108 unichar char_no_modifiers; |
| 109 int result = ui::MacKeyCodeForWindowsKeyCode( |
| 110 key_code, cocoa_modifiers, &character, &char_no_modifiers); |
| 111 DCHECK(result != -1); |
| 112 NSString* key_equivalent = [NSString stringWithFormat:@"%C", character]; |
| 113 |
| 114 return scoped_ptr<ui::PlatformAccelerator>( |
| 115 new ui::PlatformAcceleratorCocoa(key_equivalent, cocoa_modifiers)); |
| 116 } |
| 117 |
| 118 // Create a cross platform accelerator given a cross platform |key_code| and |
| 119 // the |cocoa_modifiers|. |
| 120 ui::Accelerator AcceleratorFromKeyCode(ui::KeyboardCode key_code, |
| 121 NSUInteger cocoa_modifiers) { |
| 122 int cross_platform_modifiers = ui::EventFlagsFromModifiers(cocoa_modifiers); |
| 123 ui::Accelerator accelerator(key_code, cross_platform_modifiers); |
| 124 |
| 125 scoped_ptr<ui::PlatformAccelerator> platform_accelerator = |
| 126 PlatformAcceleratorFromKeyCode(key_code, cocoa_modifiers); |
| 127 accelerator.set_platform_accelerator(platform_accelerator.Pass()); |
| 128 return accelerator; |
| 129 } |
| 130 |
45 } // namespace | 131 } // namespace |
46 | 132 |
47 AcceleratorsCocoa::AcceleratorsCocoa() { | 133 AcceleratorsCocoa::AcceleratorsCocoa() { |
48 for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) { | 134 for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) { |
49 const AcceleratorMapping& entry = kAcceleratorMap[i]; | 135 const AcceleratorMapping& entry = kAcceleratorMap[i]; |
50 ui::Accelerator accelerator(ui::VKEY_UNKNOWN, 0); | 136 ui::Accelerator accelerator = |
51 scoped_ptr<ui::PlatformAccelerator> platform_accelerator( | 137 AcceleratorFromKeyCode(entry.key_code, entry.modifiers); |
52 new ui::PlatformAcceleratorCocoa(entry.key, entry.modifiers)); | |
53 accelerator.set_platform_accelerator(platform_accelerator.Pass()); | |
54 accelerators_.insert(std::make_pair(entry.command_id, accelerator)); | 138 accelerators_.insert(std::make_pair(entry.command_id, accelerator)); |
55 } | 139 } |
| 140 |
| 141 for (size_t i = 0; i < arraysize(kAcceleratorList); ++i) { |
| 142 const AcceleratorListing& entry = kAcceleratorList[i]; |
| 143 ui::Accelerator accelerator = |
| 144 AcceleratorFromKeyCode(entry.key_code, entry.modifiers); |
| 145 accelerator_vector_.push_back(accelerator); |
| 146 } |
56 } | 147 } |
57 | 148 |
58 AcceleratorsCocoa::~AcceleratorsCocoa() {} | 149 AcceleratorsCocoa::~AcceleratorsCocoa() {} |
59 | 150 |
60 // static | 151 // static |
61 AcceleratorsCocoa* AcceleratorsCocoa::GetInstance() { | 152 AcceleratorsCocoa* AcceleratorsCocoa::GetInstance() { |
62 return Singleton<AcceleratorsCocoa>::get(); | 153 return Singleton<AcceleratorsCocoa>::get(); |
63 } | 154 } |
64 | 155 |
65 const ui::Accelerator* AcceleratorsCocoa::GetAcceleratorForCommand( | 156 const ui::Accelerator* AcceleratorsCocoa::GetAcceleratorForCommand( |
66 int command_id) { | 157 int command_id) { |
67 AcceleratorMap::iterator it = accelerators_.find(command_id); | 158 AcceleratorMap::iterator it = accelerators_.find(command_id); |
68 if (it == accelerators_.end()) | 159 if (it == accelerators_.end()) |
69 return NULL; | 160 return NULL; |
70 return &it->second; | 161 return &it->second; |
71 } | 162 } |
| 163 |
| 164 const ui::Accelerator* AcceleratorsCocoa::GetAcceleratorForHotKey( |
| 165 NSString* key_equivalent, NSUInteger modifiers) const { |
| 166 for (AcceleratorVector::const_iterator it = accelerator_vector_.begin(); |
| 167 it != accelerator_vector_.end(); |
| 168 ++it) { |
| 169 const ui::Accelerator& accelerator = *it; |
| 170 const ui::PlatformAcceleratorCocoa* platform_accelerator = |
| 171 static_cast<const ui::PlatformAcceleratorCocoa*>( |
| 172 accelerator.platform_accelerator()); |
| 173 unichar character; |
| 174 unichar char_no_modifiers; |
| 175 int result = |
| 176 ui::MacKeyCodeForWindowsKeyCode(accelerator.key_code(), |
| 177 platform_accelerator->modifier_mask(), |
| 178 &character, |
| 179 &char_no_modifiers); |
| 180 if (result == -1) |
| 181 return NULL; |
| 182 |
| 183 // Check for a match in the modifiers and key_equivalent. |
| 184 NSUInteger mask = platform_accelerator->modifier_mask(); |
| 185 BOOL maskEqual = |
| 186 (mask == modifiers) || ((mask & (~NSShiftKeyMask)) == modifiers); |
| 187 NSString* string = [NSString stringWithFormat:@"%C", character]; |
| 188 if ([string isEqual:key_equivalent] && maskEqual) |
| 189 return &*it; |
| 190 } |
| 191 |
| 192 return NULL; |
| 193 } |
OLD | NEW |