Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / accelerators_cocoa.mm
blobee41e6e727ce303faef21406f9698fd806a4199e
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
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/cocoa/accelerators_cocoa.h"
7 #import <Cocoa/Cocoa.h>
9 #include "base/logging.h"
10 #include "base/memory/singleton.h"
11 #include "chrome/app/chrome_command_ids.h"
12 #import "ui/base/accelerators/platform_accelerator_cocoa.h"
13 #import "ui/events/cocoa/cocoa_event_utils.h"
14 #import "ui/events/keycodes/keyboard_code_conversion_mac.h"
16 namespace {
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},
34 const struct AcceleratorMapping {
35   int command_id;
36   NSUInteger modifiers;  // The Cocoa modifiers.
37   ui::KeyboardCode key_code;  // The key used for cross-platform compatibility.
38 } kAcceleratorMap[] = {
39   // Accelerators used in the toolbar menu.
40   {IDC_CLEAR_BROWSING_DATA, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_BACK},
41   {IDC_COPY, NSCommandKeyMask, ui::VKEY_C},
42   {IDC_CUT, NSCommandKeyMask, ui::VKEY_X},
43   {IDC_DEV_TOOLS, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_I},
44   {IDC_DEV_TOOLS_CONSOLE, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_J},
45   {IDC_FIND, NSCommandKeyMask, ui::VKEY_F},
46   {IDC_FULLSCREEN, NSCommandKeyMask | NSControlKeyMask, ui::VKEY_F},
47   {IDC_NEW_INCOGNITO_WINDOW, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_N},
48   {IDC_NEW_TAB, NSCommandKeyMask, ui::VKEY_T},
49   {IDC_NEW_WINDOW, NSCommandKeyMask, ui::VKEY_N},
50   {IDC_PASTE, NSCommandKeyMask, ui::VKEY_V},
51   {IDC_PRINT, NSCommandKeyMask, ui::VKEY_P},
52   {IDC_RESTORE_TAB, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_T},
53   {IDC_SAVE_PAGE, NSCommandKeyMask, ui::VKEY_S},
54   {IDC_SHOW_BOOKMARK_BAR, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_B},
55   {IDC_SHOW_BOOKMARK_MANAGER, NSCommandKeyMask | NSAlternateKeyMask,
56    ui::VKEY_B},
57   {IDC_BOOKMARK_PAGE, NSCommandKeyMask, ui::VKEY_D},
58   {IDC_SHOW_DOWNLOADS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_J},
59   {IDC_SHOW_HISTORY, NSCommandKeyMask, ui::VKEY_Y},
60   {IDC_VIEW_SOURCE, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_U},
61   {IDC_ZOOM_MINUS, NSCommandKeyMask, ui::VKEY_OEM_MINUS},
62   {IDC_ZOOM_PLUS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_OEM_PLUS},
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 #if defined(ENABLE_BASIC_PRINTING)
72   {IDC_BASIC_PRINT, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_P},
73 #endif  // ENABLE_BASIC_PRINTING
74   {IDC_CONTENT_CONTEXT_UNDO, NSCommandKeyMask, ui::VKEY_Z},
75   {IDC_CONTENT_CONTEXT_REDO, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_Z},
76   {IDC_CONTENT_CONTEXT_CUT, NSCommandKeyMask, ui::VKEY_X},
77   {IDC_CONTENT_CONTEXT_COPY, NSCommandKeyMask, ui::VKEY_C},
78   {IDC_CONTENT_CONTEXT_PASTE, NSCommandKeyMask, ui::VKEY_V},
79   {IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE,
80    NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_V},
81   {IDC_CONTENT_CONTEXT_SELECTALL, NSCommandKeyMask, ui::VKEY_A},
82   {IDC_FOCUS_SEARCH, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_F},
83   {IDC_FIND_NEXT, NSCommandKeyMask, ui::VKEY_G},
84   {IDC_FIND_PREVIOUS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_G},
85   {IDC_ZOOM_PLUS, NSCommandKeyMask, ui::VKEY_OEM_PLUS},
86   {IDC_ZOOM_MINUS, NSCommandKeyMask, ui::VKEY_OEM_MINUS},
87   {IDC_STOP, NSCommandKeyMask, ui::VKEY_OEM_PERIOD},
88   {IDC_RELOAD, NSCommandKeyMask, ui::VKEY_R},
89   {IDC_RELOAD_IGNORING_CACHE, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_R},
90   {IDC_PRESENTATION_MODE, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_F},
91   {IDC_ZOOM_NORMAL, NSCommandKeyMask, ui::VKEY_0},
92   {IDC_HOME, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_H},
93   {IDC_BACK, NSCommandKeyMask, ui::VKEY_OEM_4},
94   {IDC_FORWARD, NSCommandKeyMask, ui::VKEY_OEM_6},
95   {IDC_BOOKMARK_ALL_TABS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_D},
96   {IDC_MINIMIZE_WINDOW, NSCommandKeyMask, ui::VKEY_M},
97   {IDC_SELECT_NEXT_TAB, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_RIGHT},
98   {IDC_SELECT_PREVIOUS_TAB, NSCommandKeyMask | NSAlternateKeyMask,
99    ui::VKEY_LEFT},
100   {IDC_HELP_PAGE_VIA_MENU, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_OEM_2},
103 // Create a Cocoa platform accelerator given a cross platform |key_code| and
104 // the |cocoa_modifiers|.
105 scoped_ptr<ui::PlatformAccelerator> PlatformAcceleratorFromKeyCode(
106     ui::KeyboardCode key_code,
107     NSUInteger cocoa_modifiers) {
108   unichar shifted_character;
109   int result = ui::MacKeyCodeForWindowsKeyCode(key_code, cocoa_modifiers,
110                                                &shifted_character, nullptr);
111   DCHECK(result != -1);
112   NSString* key_equivalent =
113       [NSString stringWithFormat:@"%C", shifted_character];
115   return scoped_ptr<ui::PlatformAccelerator>(
116       new ui::PlatformAcceleratorCocoa(key_equivalent, cocoa_modifiers));
119 // Create a cross platform accelerator given a cross platform |key_code| and
120 // the |cocoa_modifiers|.
121 ui::Accelerator AcceleratorFromKeyCode(ui::KeyboardCode key_code,
122                                        NSUInteger cocoa_modifiers) {
123   int cross_platform_modifiers = ui::EventFlagsFromModifiers(cocoa_modifiers);
124   ui::Accelerator accelerator(key_code, cross_platform_modifiers);
126   scoped_ptr<ui::PlatformAccelerator> platform_accelerator =
127       PlatformAcceleratorFromKeyCode(key_code, cocoa_modifiers);
128   accelerator.set_platform_accelerator(platform_accelerator.Pass());
129   return accelerator;
132 }  // namespace
134 AcceleratorsCocoa::AcceleratorsCocoa() {
135   for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) {
136     const AcceleratorMapping& entry = kAcceleratorMap[i];
137     ui::Accelerator accelerator =
138         AcceleratorFromKeyCode(entry.key_code, entry.modifiers);
139     accelerators_.insert(std::make_pair(entry.command_id, accelerator));
140   }
142   for (size_t i = 0; i < arraysize(kAcceleratorList); ++i) {
143     const AcceleratorListing& entry = kAcceleratorList[i];
144     ui::Accelerator accelerator =
145         AcceleratorFromKeyCode(entry.key_code, entry.modifiers);
146     accelerator_vector_.push_back(accelerator);
147   }
150 AcceleratorsCocoa::~AcceleratorsCocoa() {}
152 // static
153 AcceleratorsCocoa* AcceleratorsCocoa::GetInstance() {
154   return base::Singleton<AcceleratorsCocoa>::get();
157 const ui::Accelerator* AcceleratorsCocoa::GetAcceleratorForCommand(
158     int command_id) {
159   AcceleratorMap::iterator it = accelerators_.find(command_id);
160   if (it == accelerators_.end())
161     return NULL;
162   return &it->second;
165 const ui::Accelerator* AcceleratorsCocoa::GetAcceleratorForHotKey(
166     NSString* key_equivalent, NSUInteger modifiers) const {
167   for (AcceleratorVector::const_iterator it = accelerator_vector_.begin();
168        it != accelerator_vector_.end();
169        ++it) {
170     const ui::Accelerator& accelerator = *it;
171     const ui::PlatformAcceleratorCocoa* platform_accelerator =
172         static_cast<const ui::PlatformAcceleratorCocoa*>(
173             accelerator.platform_accelerator());
174     unichar shifted_character;
175     int result = ui::MacKeyCodeForWindowsKeyCode(
176         accelerator.key_code(), platform_accelerator->modifier_mask(),
177         &shifted_character, nullptr);
178     if (result == -1)
179       return NULL;
181     // Check for a match in the modifiers and key_equivalent.
182     NSUInteger mask = platform_accelerator->modifier_mask();
183     BOOL maskEqual =
184         (mask == modifiers) || ((mask & (~NSShiftKeyMask)) == modifiers);
185     NSString* string = [NSString stringWithFormat:@"%C", shifted_character];
186     if ([string isEqual:key_equivalent] && maskEqual)
187       return &*it;
188   }
190   return NULL;