diff options
-rw-r--r-- | app/app_base.gypi | 1 | ||||
-rw-r--r-- | app/menus/accelerator_cocoa.h | 58 | ||||
-rw-r--r-- | chrome/browser/cocoa/accelerators_cocoa.h | 40 | ||||
-rw-r--r-- | chrome/browser/cocoa/accelerators_cocoa.mm | 56 | ||||
-rw-r--r-- | chrome/browser/cocoa/accelerators_cocoa_unittest.mm | 27 | ||||
-rw-r--r-- | chrome/browser/cocoa/menu_controller.mm | 6 | ||||
-rw-r--r-- | chrome/browser/cocoa/toolbar_controller.mm | 22 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 2 | ||||
-rwxr-xr-x | chrome/chrome_tests.gypi | 1 |
9 files changed, 210 insertions, 3 deletions
diff --git a/app/app_base.gypi b/app/app_base.gypi index 5cd97ee..facbd4c 100644 --- a/app/app_base.gypi +++ b/app/app_base.gypi @@ -158,6 +158,7 @@ 'linear_animation.h', 'menus/accelerator.h', 'menus/accelerator_gtk.h', + 'menus/accelerator_cocoa.h', 'menus/menu_model.cc', 'menus/menu_model.h', 'menus/simple_menu_model.cc', diff --git a/app/menus/accelerator_cocoa.h b/app/menus/accelerator_cocoa.h new file mode 100644 index 0000000..1866b4a --- /dev/null +++ b/app/menus/accelerator_cocoa.h @@ -0,0 +1,58 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef APP_MENUS_ACCELERATOR_COCOA_H_ +#define APP_MENUS_ACCELERATOR_COCOA_H_ + +#include <Foundation/Foundation.h> + +#include "app/menus/accelerator.h" +#include "base/scoped_nsobject.h" + +namespace menus { + +// This is a subclass of the cross-platform Accelerator, but with more direct +// support for Cocoa key equivalents. Note that the typical use case for this +// class is to initialize it with a string literal, which is why it sends +// |-copy| to the |key_code| paramater in the constructor. +class AcceleratorCocoa : public Accelerator { + public: + AcceleratorCocoa(NSString* key_code, NSUInteger mask) + : Accelerator(base::VKEY_UNKNOWN, mask), + characters_([key_code copy]) { + } + + AcceleratorCocoa(const AcceleratorCocoa& accelerator) + : Accelerator(accelerator) { + characters_.reset([accelerator.characters_ copy]); + } + + AcceleratorCocoa() : Accelerator() {} + virtual ~AcceleratorCocoa() {} + + AcceleratorCocoa& operator=(const AcceleratorCocoa& accelerator) { + if (this != &accelerator) { + *static_cast<Accelerator*>(this) = accelerator; + characters_.reset([accelerator.characters_ copy]); + } + return *this; + } + + bool operator==(const AcceleratorCocoa& rhs) const { + return [characters_ isEqualToString:rhs.characters_.get()] && + (modifiers_ == rhs.modifiers_); + } + + NSString* characters() const { + return characters_.get(); + } + + private: + // String of characters for the key equivalent. + scoped_nsobject<NSString> characters_; +}; + +} // namespace menus + +#endif // APP_MENUS_ACCELERATOR_COCOA_H_ diff --git a/chrome/browser/cocoa/accelerators_cocoa.h b/chrome/browser/cocoa/accelerators_cocoa.h new file mode 100644 index 0000000..d4478f2 --- /dev/null +++ b/chrome/browser/cocoa/accelerators_cocoa.h @@ -0,0 +1,40 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_ACCELERATORS_COCOA_H_ +#define CHROME_BROWSER_COCOA_ACCELERATORS_COCOA_H_ + +#include <map> + +#include "app/menus/accelerator_cocoa.h" + +// This class maintains a map of command_ids to AcceleratorCocoa objects (see +// chrome/app/chrome_dll_resource.h). Currently, this only lists the commands +// that are used in the Wrench menu. +// +// It is recommended that this class be used as a singleton so that the key map +// isn't created multiple places. +// +// #import "base/singleton.h" +// ... +// AcceleratorsCocoa* keymap = Singleton<AcceleratorsCocoa>::get(); +// return keymap->GetAcceleratorForCommand(IDC_COPY); +// +class AcceleratorsCocoa { + public: + AcceleratorsCocoa(); + ~AcceleratorsCocoa() {} + + typedef std::map<int, menus::AcceleratorCocoa> AcceleratorCocoaMap; + + // Returns NULL if there is no accelerator for the command. + const menus::AcceleratorCocoa* GetAcceleratorForCommand(int command_id); + + private: + AcceleratorCocoaMap accelerators_; + + DISALLOW_COPY_AND_ASSIGN(AcceleratorsCocoa); +}; + +#endif // CHROME_BROWSER_COCOA_ACCELERATORS_COCOA_H_ diff --git a/chrome/browser/cocoa/accelerators_cocoa.mm b/chrome/browser/cocoa/accelerators_cocoa.mm new file mode 100644 index 0000000..8682997 --- /dev/null +++ b/chrome/browser/cocoa/accelerators_cocoa.mm @@ -0,0 +1,56 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/cocoa/accelerators_cocoa.h" + +#import <Cocoa/Cocoa.h> + +#include "chrome/app/chrome_dll_resource.h" + +namespace { + +const struct AcceleratorMapping { + int command_id; + NSString* key; + NSUInteger modifiers; +} kAcceleratorMap[] = { + { IDC_COPY, @"c", NSCommandKeyMask }, + { IDC_CUT, @"x", NSCommandKeyMask }, + { IDC_DEV_TOOLS, @"i", NSCommandKeyMask | NSAlternateKeyMask }, + { IDC_DEV_TOOLS_CONSOLE, @"j", NSCommandKeyMask | NSAlternateKeyMask }, + { IDC_FIND, @"f", NSCommandKeyMask }, + { IDC_FULLSCREEN, @"f", NSCommandKeyMask | NSShiftKeyMask }, + { IDC_NEW_INCOGNITO_WINDOW, @"n", NSCommandKeyMask | NSShiftKeyMask }, + { IDC_NEW_TAB, @"t", NSCommandKeyMask }, + { IDC_NEW_WINDOW, @"n", NSCommandKeyMask }, + { IDC_OPTIONS, @",", NSCommandKeyMask }, + { IDC_PASTE, @"v", NSCommandKeyMask }, + { IDC_PRINT, @"p", NSCommandKeyMask }, + { IDC_SAVE_PAGE, @"s", NSCommandKeyMask }, + { IDC_SHOW_BOOKMARK_BAR, @"b", NSCommandKeyMask | NSShiftKeyMask }, + { IDC_SHOW_BOOKMARK_MANAGER, @"b", NSCommandKeyMask | NSAlternateKeyMask }, + { IDC_SHOW_DOWNLOADS, @"j", NSCommandKeyMask | NSShiftKeyMask }, + { IDC_SHOW_HISTORY, @"y", NSCommandKeyMask }, + { IDC_VIEW_SOURCE, @"u", NSCommandKeyMask | NSAlternateKeyMask }, + { IDC_ZOOM_MINUS, @"-", NSCommandKeyMask }, + { IDC_ZOOM_PLUS, @"+", NSCommandKeyMask } +}; + +} // namespace + +AcceleratorsCocoa::AcceleratorsCocoa() { + for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) { + const AcceleratorMapping& entry = kAcceleratorMap[i]; + menus::AcceleratorCocoa accelerator(entry.key, entry.modifiers); + accelerators_.insert(std::make_pair(entry.command_id, accelerator)); + } +} + +const menus::AcceleratorCocoa* AcceleratorsCocoa::GetAcceleratorForCommand( + int command_id) { + AcceleratorCocoaMap::iterator it = accelerators_.find(command_id); + if (it == accelerators_.end()) + return NULL; + return &it->second; +} diff --git a/chrome/browser/cocoa/accelerators_cocoa_unittest.mm b/chrome/browser/cocoa/accelerators_cocoa_unittest.mm new file mode 100644 index 0000000..cac5c20 --- /dev/null +++ b/chrome/browser/cocoa/accelerators_cocoa_unittest.mm @@ -0,0 +1,27 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Cocoa/Cocoa.h> + +#include "app/menus/accelerator_cocoa.h" +#include "base/singleton.h" +#include "chrome/app/chrome_dll_resource.h" +#import "chrome/browser/cocoa/accelerators_cocoa.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(AcceleratorsCocoaTest, GetAccelerator) { + AcceleratorsCocoa* keymap = Singleton<AcceleratorsCocoa>::get(); + const menus::AcceleratorCocoa* accelerator = + keymap->GetAcceleratorForCommand(IDC_COPY); + ASSERT_TRUE(accelerator); + EXPECT_TRUE([@"c" isEqualToString:accelerator->characters()]); + EXPECT_EQ(NSCommandKeyMask, accelerator->modifiers()); +} + +TEST(AcceleratorsCocoaTest, GetNullAccelerator) { + AcceleratorsCocoa* keymap = Singleton<AcceleratorsCocoa>::get(); + const menus::AcceleratorCocoa* accelerator = + keymap->GetAcceleratorForCommand(314159265); + EXPECT_FALSE(accelerator); +} diff --git a/chrome/browser/cocoa/menu_controller.mm b/chrome/browser/cocoa/menu_controller.mm index 259c905..a34469e 100644 --- a/chrome/browser/cocoa/menu_controller.mm +++ b/chrome/browser/cocoa/menu_controller.mm @@ -5,6 +5,7 @@ #import "chrome/browser/cocoa/menu_controller.h" #include "app/l10n_util_mac.h" +#include "app/menus/accelerator_cocoa.h" #include "app/menus/simple_menu_model.h" #include "base/logging.h" #include "base/sys_string_conversions.h" @@ -102,6 +103,11 @@ [item setTarget:self]; NSValue* modelObject = [NSValue valueWithPointer:model]; [item setRepresentedObject:modelObject]; // Retains |modelObject|. + menus::AcceleratorCocoa accelerator; + if (model->GetAcceleratorAt(modelIndex, &accelerator)) { + [item setKeyEquivalent:accelerator.characters()]; + [item setKeyEquivalentModifierMask:accelerator.modifiers()]; + } } [menu insertItem:item atIndex:index]; } diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm index a17948d..c015f19 100644 --- a/chrome/browser/cocoa/toolbar_controller.mm +++ b/chrome/browser/cocoa/toolbar_controller.mm @@ -7,13 +7,17 @@ #include <algorithm> #include "app/l10n_util_mac.h" +#include "app/menus/accelerator_cocoa.h" +#include "base/keyboard_codes.h" #include "base/mac_util.h" #include "base/nsimage_cache_mac.h" +#include "base/singleton.h" #include "base/sys_string_conversions.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/autocomplete/autocomplete_edit_view.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" +#import "chrome/browser/cocoa/accelerators_cocoa.h" #import "chrome/browser/cocoa/autocomplete_text_field.h" #import "chrome/browser/cocoa/autocomplete_text_field_editor.h" #import "chrome/browser/cocoa/back_forward_menu_controller.h" @@ -98,9 +102,21 @@ class MenuDelegate : public menus::SimpleMenuModel::Delegate { virtual bool IsCommandIdEnabled(int command_id) const { return browser_->command_updater()->IsCommandEnabled(command_id); } - virtual bool GetAcceleratorForCommandId( - int command_id, - menus::Accelerator* accelerator) { return false; } + virtual bool GetAcceleratorForCommandId(int command_id, + menus::Accelerator* accelerator_generic) { + // Downcast so that when the copy constructor is invoked below, the key + // string gets copied, too. + menus::AcceleratorCocoa* out_accelerator = + static_cast<menus::AcceleratorCocoa*>(accelerator_generic); + AcceleratorsCocoa* keymap = Singleton<AcceleratorsCocoa>::get(); + const menus::AcceleratorCocoa* accelerator = + keymap->GetAcceleratorForCommand(command_id); + if (accelerator) { + *out_accelerator = *accelerator; + return true; + } + return false; + } virtual void ExecuteCommand(int command_id) { browser_->ExecuteCommand(command_id); } diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 608fc8e..5ede262 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -575,6 +575,8 @@ 'browser/cocoa/about_ipc_dialog.mm', 'browser/cocoa/about_window_controller.h', 'browser/cocoa/about_window_controller.mm', + 'browser/cocoa/accelerators_cocoa.h', + 'browser/cocoa/accelerators_cocoa.mm', 'browser/cocoa/animatable_view.h', 'browser/cocoa/animatable_view.mm', 'browser/cocoa/authorization_util.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index d98e4d5..0b6099b 100755 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -629,6 +629,7 @@ # exclude them from non-Mac builds. 'browser/cocoa/about_ipc_controller_unittest.mm', 'browser/cocoa/about_window_controller_unittest.mm', + 'browser/cocoa/accelerators_cocoa_unittest.mm', 'browser/cocoa/animatable_view_unittest.mm', 'browser/cocoa/autocomplete_text_field_cell_unittest.mm', 'browser/cocoa/autocomplete_text_field_editor_unittest.mm', |