diff options
author | erikchen@chromium.org <erikchen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-12 21:17:52 +0000 |
---|---|---|
committer | erikchen@chromium.org <erikchen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-12 21:17:52 +0000 |
commit | 7326eb9a5cbc1acbd8831d9170beacb0d1a23a4f (patch) | |
tree | 1cdf365e32ad0a291ccd1c2e2d0d49ef9f4ca198 | |
parent | f93a6c6b376fe2ce3bb26698b6c4cb4cd0e36c28 (diff) | |
download | chromium_src-7326eb9a5cbc1acbd8831d9170beacb0d1a23a4f.zip chromium_src-7326eb9a5cbc1acbd8831d9170beacb0d1a23a4f.tar.gz chromium_src-7326eb9a5cbc1acbd8831d9170beacb0d1a23a4f.tar.bz2 |
mac: Create a static mapping of accelerators in the main menu.
This change allows for two new functionalities:
1. Compare a mac accelerator with an extension accelerator.
2. Determine whether an accelerator is a standard main-menu accelerator without
a dynamic query of the main menu.
Accelerators generated from the extension manifest use cross-platform
key_codes/modifiers. Previously, there was no canonical way to get an
accelerator from the mac main menu. There was a mapping of accelerators from
the toolbar menu, but those accelerators only included mac key_codes/modifiers,
and not cross-platform key_codes/modifiers.
This CL creates a static mapping of all accelerators used in the main menu and
toolbar menu. The mapping includes the command_id, the cross-platform key_code,
and the Cocoa modifiers. The cross-platform modifiers and the Cocoa
keyEquivalent are generated on demand.
BUG=342484
Review URL: https://codereview.chromium.org/152643007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@250793 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/ui/cocoa/accelerators_cocoa.h | 18 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/accelerators_cocoa.mm | 180 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/accelerators_cocoa_browsertest.mm | 133 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | ui/base/accelerators/platform_accelerator_cocoa.h | 3 | ||||
-rw-r--r-- | ui/base/cocoa/cocoa_event_utils.h | 3 | ||||
-rw-r--r-- | ui/base/cocoa/cocoa_event_utils.mm | 7 | ||||
-rw-r--r-- | ui/events/keycodes/keyboard_code_conversion_mac.h | 4 | ||||
-rw-r--r-- | ui/events/keycodes/keyboard_code_conversion_mac.mm | 12 |
9 files changed, 317 insertions, 44 deletions
diff --git a/chrome/browser/ui/cocoa/accelerators_cocoa.h b/chrome/browser/ui/cocoa/accelerators_cocoa.h index cc1840c..e29eefb 100644 --- a/chrome/browser/ui/cocoa/accelerators_cocoa.h +++ b/chrome/browser/ui/cocoa/accelerators_cocoa.h @@ -5,8 +5,12 @@ #ifndef CHROME_BROWSER_UI_COCOA_ACCELERATORS_COCOA_H_ #define CHROME_BROWSER_UI_COCOA_ACCELERATORS_COCOA_H_ +#import <Cocoa/Cocoa.h> + #include <map> +#include <vector> +#include "base/gtest_prod_util.h" #include "ui/base/accelerators/accelerator.h" template <typename T> struct DefaultSingletonTraits; @@ -26,6 +30,7 @@ template <typename T> struct DefaultSingletonTraits; class AcceleratorsCocoa { public: typedef std::map<int, ui::Accelerator> AcceleratorMap; + typedef std::vector<ui::Accelerator> AcceleratorVector; typedef AcceleratorMap::const_iterator const_iterator; const_iterator const begin() { return accelerators_.begin(); } @@ -33,17 +38,30 @@ class AcceleratorsCocoa { // Returns NULL if there is no accelerator for the command. const ui::Accelerator* GetAcceleratorForCommand(int command_id); + // Searches the list of accelerators without a command_id for an accelerator + // that matches the given |key_equivalent| and |modifiers|. + const ui::Accelerator* GetAcceleratorForHotKey(NSString* key_equivalent, + NSUInteger modifiers) const; // Returns the singleton instance. static AcceleratorsCocoa* GetInstance(); private: friend struct DefaultSingletonTraits<AcceleratorsCocoa>; + FRIEND_TEST_ALL_PREFIXES(AcceleratorsCocoaBrowserTest, + MappingAcceleratorsInMainMenu); AcceleratorsCocoa(); ~AcceleratorsCocoa(); + // A map from command_id to Accelerator. The accelerator is fully filled out, + // and its platform_accelerator is also fully filled out. + // Contains accelerators from both the wrench menu and the main menu. AcceleratorMap accelerators_; + // A list of accelerators used in the main menu that have no associated + // command_id. The accelerator is fully filled out, and its + // platform_accelerator is also fully filled out. + AcceleratorVector accelerator_vector_; DISALLOW_COPY_AND_ASSIGN(AcceleratorsCocoa); }; diff --git a/chrome/browser/ui/cocoa/accelerators_cocoa.mm b/chrome/browser/ui/cocoa/accelerators_cocoa.mm index 154be6f..b4ee271 100644 --- a/chrome/browser/ui/cocoa/accelerators_cocoa.mm +++ b/chrome/browser/ui/cocoa/accelerators_cocoa.mm @@ -6,53 +6,144 @@ #import <Cocoa/Cocoa.h> +#include "base/logging.h" #include "base/memory/singleton.h" #include "chrome/app/chrome_command_ids.h" #import "ui/base/accelerators/platform_accelerator_cocoa.h" +#import "ui/base/cocoa/cocoa_event_utils.h" +#import "ui/events/keycodes/keyboard_code_conversion_mac.h" namespace { +// These accelerators are not associated with a command_id. +const struct AcceleratorListing { + NSUInteger modifiers; // The Cocoa modifiers. + ui::KeyboardCode key_code; // The key used for cross-platform compatibility. +} kAcceleratorList [] = { + {NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_H}, + {NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_W}, + {NSCommandKeyMask | NSAlternateKeyMask | NSShiftKeyMask, ui::VKEY_V}, + {NSCommandKeyMask, ui::VKEY_E}, + {NSCommandKeyMask, ui::VKEY_J}, + {NSCommandKeyMask, ui::VKEY_OEM_1}, + {NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_OEM_1}, + {NSCommandKeyMask, ui::VKEY_OEM_COMMA}, + {NSCommandKeyMask | NSControlKeyMask, ui::VKEY_SPACE}, +}; + const struct AcceleratorMapping { int command_id; - NSString* key; - NSUInteger modifiers; + NSUInteger modifiers; // The Cocoa modifiers. + ui::KeyboardCode key_code; // The key used for cross-platform compatibility. } kAcceleratorMap[] = { - { IDC_CLEAR_BROWSING_DATA, @"\x8", NSCommandKeyMask | NSShiftKeyMask }, - { 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_RESTORE_TAB, @"t", NSCommandKeyMask | NSShiftKeyMask }, - { IDC_SAVE_PAGE, @"s", NSCommandKeyMask }, - { IDC_SHOW_BOOKMARK_BAR, @"b", NSCommandKeyMask | NSShiftKeyMask }, - { IDC_SHOW_BOOKMARK_MANAGER, @"b", NSCommandKeyMask | NSAlternateKeyMask }, - { IDC_BOOKMARK_PAGE, @"d", NSCommandKeyMask }, - { 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 } + // Accelerators used in the toolbar menu. + {IDC_CLEAR_BROWSING_DATA, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_BACK}, + {IDC_COPY, NSCommandKeyMask, ui::VKEY_C}, + {IDC_CUT, NSCommandKeyMask, ui::VKEY_X}, + {IDC_DEV_TOOLS, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_I}, + {IDC_DEV_TOOLS_CONSOLE, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_J}, + {IDC_FIND, NSCommandKeyMask, ui::VKEY_F}, + {IDC_FULLSCREEN, NSCommandKeyMask | NSControlKeyMask, ui::VKEY_F}, + {IDC_NEW_INCOGNITO_WINDOW, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_N}, + {IDC_NEW_TAB, NSCommandKeyMask, ui::VKEY_T}, + {IDC_NEW_WINDOW, NSCommandKeyMask, ui::VKEY_N}, + {IDC_PASTE, NSCommandKeyMask, ui::VKEY_V}, + {IDC_PRINT, NSCommandKeyMask, ui::VKEY_P}, + {IDC_RESTORE_TAB, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_T}, + {IDC_SAVE_PAGE, NSCommandKeyMask, ui::VKEY_S}, + {IDC_SHOW_BOOKMARK_BAR, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_B}, + {IDC_SHOW_BOOKMARK_MANAGER, NSCommandKeyMask | NSAlternateKeyMask, + ui::VKEY_B}, + {IDC_BOOKMARK_PAGE, NSCommandKeyMask, ui::VKEY_D}, + {IDC_SHOW_DOWNLOADS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_J}, + {IDC_SHOW_HISTORY, NSCommandKeyMask, ui::VKEY_Y}, + {IDC_VIEW_SOURCE, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_U}, + {IDC_ZOOM_MINUS, NSCommandKeyMask, ui::VKEY_OEM_MINUS}, + {IDC_ZOOM_PLUS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_OEM_PLUS}, + + // Accelerators used in MainMenu.xib, but not the toolbar menu. + {IDC_HIDE_APP, NSCommandKeyMask, ui::VKEY_H}, + {IDC_EXIT, NSCommandKeyMask, ui::VKEY_Q}, + {IDC_OPEN_FILE, NSCommandKeyMask, ui::VKEY_O}, + {IDC_FOCUS_LOCATION, NSCommandKeyMask, ui::VKEY_L}, + {IDC_CLOSE_WINDOW, NSCommandKeyMask, ui::VKEY_W}, + {IDC_EMAIL_PAGE_LOCATION, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_I}, + {IDC_ADVANCED_PRINT, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_P}, + {IDC_CONTENT_CONTEXT_UNDO, NSCommandKeyMask, ui::VKEY_Z}, + {IDC_CONTENT_CONTEXT_REDO, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_Z}, + {IDC_CONTENT_CONTEXT_CUT, NSCommandKeyMask, ui::VKEY_X}, + {IDC_CONTENT_CONTEXT_COPY, NSCommandKeyMask, ui::VKEY_C}, + {IDC_CONTENT_CONTEXT_PASTE, NSCommandKeyMask, ui::VKEY_V}, + {IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE, + NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_V}, + {IDC_CONTENT_CONTEXT_SELECTALL, NSCommandKeyMask, ui::VKEY_A}, + {IDC_FOCUS_SEARCH, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_F}, + {IDC_FIND_NEXT, NSCommandKeyMask, ui::VKEY_G}, + {IDC_FIND_PREVIOUS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_G}, + {IDC_ZOOM_PLUS, NSCommandKeyMask, ui::VKEY_OEM_PLUS}, + {IDC_ZOOM_MINUS, NSCommandKeyMask, ui::VKEY_OEM_MINUS}, + {IDC_STOP, NSCommandKeyMask, ui::VKEY_OEM_PERIOD}, + {IDC_RELOAD, NSCommandKeyMask, ui::VKEY_R}, + {IDC_RELOAD_IGNORING_CACHE, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_R}, + {IDC_PRESENTATION_MODE, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_F}, + {IDC_ZOOM_NORMAL, NSCommandKeyMask, ui::VKEY_0}, + {IDC_HOME, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_H}, + {IDC_BACK, NSCommandKeyMask, ui::VKEY_OEM_4}, + {IDC_FORWARD, NSCommandKeyMask, ui::VKEY_OEM_6}, + {IDC_BOOKMARK_ALL_TABS, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_D}, + {IDC_MINIMIZE_WINDOW, NSCommandKeyMask, ui::VKEY_M}, + {IDC_SELECT_NEXT_TAB, NSCommandKeyMask | NSAlternateKeyMask, ui::VKEY_RIGHT}, + {IDC_SELECT_PREVIOUS_TAB, NSCommandKeyMask | NSAlternateKeyMask, + ui::VKEY_LEFT}, + {IDC_TABPOSE, NSCommandKeyMask | NSControlKeyMask, ui::VKEY_T}, + {IDC_HELP_PAGE_VIA_MENU, NSCommandKeyMask | NSShiftKeyMask, ui::VKEY_OEM_2}, }; +// Create a Cocoa platform accelerator given a cross platform |key_code| and +// the |cocoa_modifiers|. +scoped_ptr<ui::PlatformAccelerator> PlatformAcceleratorFromKeyCode( + ui::KeyboardCode key_code, + NSUInteger cocoa_modifiers) { + unichar character; + unichar char_no_modifiers; + int result = ui::MacKeyCodeForWindowsKeyCode( + key_code, cocoa_modifiers, &character, &char_no_modifiers); + DCHECK(result != -1); + NSString* key_equivalent = [NSString stringWithFormat:@"%C", character]; + + return scoped_ptr<ui::PlatformAccelerator>( + new ui::PlatformAcceleratorCocoa(key_equivalent, cocoa_modifiers)); +} + +// Create a cross platform accelerator given a cross platform |key_code| and +// the |cocoa_modifiers|. +ui::Accelerator AcceleratorFromKeyCode(ui::KeyboardCode key_code, + NSUInteger cocoa_modifiers) { + int cross_platform_modifiers = ui::EventFlagsFromModifiers(cocoa_modifiers); + ui::Accelerator accelerator(key_code, cross_platform_modifiers); + + scoped_ptr<ui::PlatformAccelerator> platform_accelerator = + PlatformAcceleratorFromKeyCode(key_code, cocoa_modifiers); + accelerator.set_platform_accelerator(platform_accelerator.Pass()); + return accelerator; +} + } // namespace AcceleratorsCocoa::AcceleratorsCocoa() { for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) { const AcceleratorMapping& entry = kAcceleratorMap[i]; - ui::Accelerator accelerator(ui::VKEY_UNKNOWN, 0); - scoped_ptr<ui::PlatformAccelerator> platform_accelerator( - new ui::PlatformAcceleratorCocoa(entry.key, entry.modifiers)); - accelerator.set_platform_accelerator(platform_accelerator.Pass()); + ui::Accelerator accelerator = + AcceleratorFromKeyCode(entry.key_code, entry.modifiers); accelerators_.insert(std::make_pair(entry.command_id, accelerator)); } + + for (size_t i = 0; i < arraysize(kAcceleratorList); ++i) { + const AcceleratorListing& entry = kAcceleratorList[i]; + ui::Accelerator accelerator = + AcceleratorFromKeyCode(entry.key_code, entry.modifiers); + accelerator_vector_.push_back(accelerator); + } } AcceleratorsCocoa::~AcceleratorsCocoa() {} @@ -69,3 +160,34 @@ const ui::Accelerator* AcceleratorsCocoa::GetAcceleratorForCommand( return NULL; return &it->second; } + +const ui::Accelerator* AcceleratorsCocoa::GetAcceleratorForHotKey( + NSString* key_equivalent, NSUInteger modifiers) const { + for (AcceleratorVector::const_iterator it = accelerator_vector_.begin(); + it != accelerator_vector_.end(); + ++it) { + const ui::Accelerator& accelerator = *it; + const ui::PlatformAcceleratorCocoa* platform_accelerator = + static_cast<const ui::PlatformAcceleratorCocoa*>( + accelerator.platform_accelerator()); + unichar character; + unichar char_no_modifiers; + int result = + ui::MacKeyCodeForWindowsKeyCode(accelerator.key_code(), + platform_accelerator->modifier_mask(), + &character, + &char_no_modifiers); + if (result == -1) + return NULL; + + // Check for a match in the modifiers and key_equivalent. + NSUInteger mask = platform_accelerator->modifier_mask(); + BOOL maskEqual = + (mask == modifiers) || ((mask & (~NSShiftKeyMask)) == modifiers); + NSString* string = [NSString stringWithFormat:@"%C", character]; + if ([string isEqual:key_equivalent] && maskEqual) + return &*it; + } + + return NULL; +} diff --git a/chrome/browser/ui/cocoa/accelerators_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/accelerators_cocoa_browsertest.mm new file mode 100644 index 0000000..ce3f277 --- /dev/null +++ b/chrome/browser/ui/cocoa/accelerators_cocoa_browsertest.mm @@ -0,0 +1,133 @@ +// Copyright 2014 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 "base/logging.h" +#import "chrome/browser/ui/cocoa/accelerators_cocoa.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "ui/base/accelerators/platform_accelerator_cocoa.h" +#import "ui/events/keycodes/keyboard_code_conversion_mac.h" +#include "testing/gtest_mac.h" + +typedef InProcessBrowserTest AcceleratorsCocoaBrowserTest; + +namespace { + +// Adds all NSMenuItems with an accelerator to the array. +void AddAcceleratorItemsToArray(NSMenu* menu, NSMutableArray* array) { + for (NSMenuItem* item in [menu itemArray]) { + NSMenu* submenu = item.submenu; + if (submenu) + AddAcceleratorItemsToArray(submenu, array); + + if (item.keyEquivalent.length > 0) + [array addObject:item]; + } +} + +// Returns the NSMenuItem that has the given keyEquivalent and modifiers, or +// nil. +NSMenuItem* MenuContainsAccelerator(NSMenu* menu, + NSString* key_equivalent, + NSUInteger modifiers) { + for (NSMenuItem* item in [menu itemArray]) { + NSMenu* submenu = item.submenu; + if (submenu) { + NSMenuItem* result = + MenuContainsAccelerator(submenu, key_equivalent, modifiers); + if (result) + return result; + } + + if ([item.keyEquivalent isEqual:key_equivalent]) { + BOOL maskEqual = + (modifiers == item.keyEquivalentModifierMask) || + ((modifiers & (~NSShiftKeyMask)) == item.keyEquivalentModifierMask); + if (maskEqual) + return item; + } + } + return nil; +} + +} // namespace + +// Checks that each NSMenuItem in the main menu has a corresponding accelerator, +// and the keyEquivalent/modifiers match. +IN_PROC_BROWSER_TEST_F(AcceleratorsCocoaBrowserTest, + MainMenuAcceleratorsInMapping) { + NSMenu* menu = [NSApp mainMenu]; + NSMutableArray* array = [NSMutableArray array]; + AddAcceleratorItemsToArray(menu, array); + + for (NSMenuItem* item in array) { + NSInteger command_id = item.tag; + AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance(); + const ui::Accelerator* accelerator; + + // If the tag is zero, then the NSMenuItem must use a custom selector. + // Check that the accelerator is present as an un-mapped accelerator. + if (command_id == 0) { + accelerator = keymap->GetAcceleratorForHotKey( + item.keyEquivalent, item.keyEquivalentModifierMask); + + EXPECT_TRUE(accelerator); + return; + } + + // If the tag isn't zero, then it must correspond to an IDC_* command. + accelerator = keymap->GetAcceleratorForCommand(command_id); + EXPECT_TRUE(accelerator); + if (!accelerator) + continue; + + // Get the Cocoa key_equivalent associated with the accelerator. + const ui::PlatformAcceleratorCocoa* platform_accelerator = + static_cast<const ui::PlatformAcceleratorCocoa*>( + accelerator->platform_accelerator()); + NSString* key_equivalent = platform_accelerator->characters(); + + // Check that the menu item's keyEquivalent matches the one from the + // Cocoa accelerator map. + EXPECT_NSEQ(key_equivalent, item.keyEquivalent); + + // Check that the menu item's modifier mask matches the one stored in the + // accelerator. A mask that include NSShiftKeyMask may not include the + // relevant bit (the information is reflected in the keyEquivalent of the + // NSMenuItem). + NSUInteger mask = platform_accelerator->modifier_mask(); + BOOL maskEqual = + (mask == item.keyEquivalentModifierMask) || + ((mask & (~NSShiftKeyMask)) == item.keyEquivalentModifierMask); + EXPECT_TRUE(maskEqual); + } +} + +// Check that each accelerator with a command_id has an associated NSMenuItem +// in the main menu. If the selector is commandDispatch:, then the tag must +// match the command_id. +IN_PROC_BROWSER_TEST_F(AcceleratorsCocoaBrowserTest, + MappingAcceleratorsInMainMenu) { + AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance(); + for (AcceleratorsCocoa::AcceleratorMap::iterator it = + keymap->accelerators_.begin(); + it != keymap->accelerators_.end(); + ++it) { + const ui::PlatformAcceleratorCocoa* platform_accelerator = + static_cast<const ui::PlatformAcceleratorCocoa*>( + it->second.platform_accelerator()); + + // Check that there exists a corresponding NSMenuItem. + NSMenuItem* item = + MenuContainsAccelerator([NSApp mainMenu], + platform_accelerator->characters(), + platform_accelerator->modifier_mask()); + EXPECT_TRUE(item); + + // If the menu uses a commandDispatch:, the tag must match the command id! + if (item.action == @selector(commandDispatch:)) + EXPECT_EQ(item.tag, it->first); + } +} diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 1831c23..42cf8c5 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1452,6 +1452,7 @@ 'browser/ui/browser_navigator_browsertest.cc', 'browser/ui/browser_navigator_browsertest.h', 'browser/ui/browser_navigator_browsertest_chromeos.cc', + 'browser/ui/cocoa/accelerators_cocoa_browsertest.mm', 'browser/ui/cocoa/applescript/browsercrapplication+applescript_test.mm', 'browser/ui/cocoa/applescript/window_applescript_test.mm', 'browser/ui/cocoa/apps/app_shim_menu_controller_mac_browsertest.mm', diff --git a/ui/base/accelerators/platform_accelerator_cocoa.h b/ui/base/accelerators/platform_accelerator_cocoa.h index 926089a..3f72cac 100644 --- a/ui/base/accelerators/platform_accelerator_cocoa.h +++ b/ui/base/accelerators/platform_accelerator_cocoa.h @@ -23,7 +23,10 @@ class UI_BASE_EXPORT PlatformAcceleratorCocoa : public PlatformAccelerator { virtual scoped_ptr<PlatformAccelerator> CreateCopy() const OVERRIDE; virtual bool Equals(const PlatformAccelerator& rhs) const OVERRIDE; + // The keyEquivalent of the NSMenuItem associated with the accelerator. NSString* characters() const { return characters_.get(); } + // The keyEquivalentModifierMask of the NSMenuItem associated with the + // accelerator. NSUInteger modifier_mask() const { return modifier_mask_; } private: diff --git a/ui/base/cocoa/cocoa_event_utils.h b/ui/base/cocoa/cocoa_event_utils.h index fda1448..e53930b 100644 --- a/ui/base/cocoa/cocoa_event_utils.h +++ b/ui/base/cocoa/cocoa_event_utils.h @@ -15,6 +15,9 @@ namespace ui { // Retrieves a bitsum of ui::EventFlags represented by |event|, UI_BASE_EXPORT int EventFlagsFromNSEvent(NSEvent* event); +// Converts the Cocoa |modifiers| bitsum into a ui::EventFlags bitsum. +UI_BASE_EXPORT int EventFlagsFromModifiers(NSUInteger modifiers); + // Retrieves a bitsum of ui::EventFlags represented by |event|, // but instead use the modifier flags given by |modifiers|, // which is the same format as |-NSEvent modifierFlags|. This allows diff --git a/ui/base/cocoa/cocoa_event_utils.mm b/ui/base/cocoa/cocoa_event_utils.mm index 55c885e..87165f4 100644 --- a/ui/base/cocoa/cocoa_event_utils.mm +++ b/ui/base/cocoa/cocoa_event_utils.mm @@ -43,13 +43,18 @@ int EventFlagsFromNSEvent(NSEvent* event) { return EventFlagsFromNSEventWithModifiers(event, modifiers); } -int EventFlagsFromNSEventWithModifiers(NSEvent* event, NSUInteger modifiers) { +int EventFlagsFromModifiers(NSUInteger modifiers) { int flags = 0; flags |= (modifiers & NSAlphaShiftKeyMask) ? ui::EF_CAPS_LOCK_DOWN : 0; flags |= (modifiers & NSShiftKeyMask) ? ui::EF_SHIFT_DOWN : 0; flags |= (modifiers & NSControlKeyMask) ? ui::EF_CONTROL_DOWN : 0; flags |= (modifiers & NSAlternateKeyMask) ? ui::EF_ALT_DOWN : 0; flags |= (modifiers & NSCommandKeyMask) ? ui::EF_COMMAND_DOWN : 0; + return flags; +} + +int EventFlagsFromNSEventWithModifiers(NSEvent* event, NSUInteger modifiers) { + int flags = EventFlagsFromModifiers(modifiers); flags |= isLeftButtonEvent(event) ? ui::EF_LEFT_MOUSE_BUTTON : 0; flags |= isRightButtonEvent(event) ? ui::EF_RIGHT_MOUSE_BUTTON : 0; flags |= isMiddleButtonEvent(event) ? ui::EF_MIDDLE_MOUSE_BUTTON : 0; diff --git a/ui/events/keycodes/keyboard_code_conversion_mac.h b/ui/events/keycodes/keyboard_code_conversion_mac.h index 719c922..fee3981 100644 --- a/ui/events/keycodes/keyboard_code_conversion_mac.h +++ b/ui/events/keycodes/keyboard_code_conversion_mac.h @@ -16,8 +16,8 @@ namespace ui { // We use windows virtual keycodes throughout our keyboard event related code, // including unit tests. But Mac uses a different set of virtual keycodes. // This function converts a windows virtual keycode into Mac's virtual key code -// and corresponding unicode character. |flags| is the modifiers mask such -// as NSControlKeyMask, NSShiftKeyMask, etc. +// and corresponding unicode character. |flags| is the Cocoa modifiers mask +// such as NSControlKeyMask, NSShiftKeyMask, etc. // When success, the corresponding Mac's virtual key code will be returned. // The corresponding unicode character will be stored in |character|, and the // corresponding unicode character ignoring the modifiers will be stored in diff --git a/ui/events/keycodes/keyboard_code_conversion_mac.mm b/ui/events/keycodes/keyboard_code_conversion_mac.mm index fdda790..e354e58 100644 --- a/ui/events/keycodes/keyboard_code_conversion_mac.mm +++ b/ui/events/keycodes/keyboard_code_conversion_mac.mm @@ -521,18 +521,6 @@ int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode, } } - // Control characters. - if (flags & NSControlKeyMask) { - if (keycode >= VKEY_A && keycode <= VKEY_Z) - *character = 1 + keycode - VKEY_A; - else if (macKeycode == kVK_ANSI_LeftBracket) - *character = 27; - else if (macKeycode == kVK_ANSI_Backslash) - *character = 28; - else if (macKeycode == kVK_ANSI_RightBracket) - *character = 29; - } - // TODO(suzhe): Support characters for Option key bindings. return macKeycode; } |