OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014 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. |
| 4 |
| 5 #import <Cocoa/Cocoa.h> |
| 6 |
| 7 #include "base/logging.h" |
| 8 #import "chrome/browser/ui/cocoa/accelerators_cocoa.h" |
| 9 #include "chrome/test/base/in_process_browser_test.h" |
| 10 #include "ui/base/accelerators/platform_accelerator_cocoa.h" |
| 11 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
| 12 #include "testing/gtest_mac.h" |
| 13 |
| 14 typedef InProcessBrowserTest AcceleratorsCocoaBrowserTest; |
| 15 |
| 16 namespace { |
| 17 |
| 18 // Adds all NSMenuItems with an accelerator to the array. |
| 19 void AddAcceleratorItemsToArray(NSMenu* menu, NSMutableArray* array) { |
| 20 for (NSMenuItem* item in [menu itemArray]) { |
| 21 NSMenu* submenu = item.submenu; |
| 22 if (submenu) |
| 23 AddAcceleratorItemsToArray(submenu, array); |
| 24 |
| 25 if (item.keyEquivalent.length > 0) |
| 26 [array addObject:item]; |
| 27 } |
| 28 } |
| 29 |
| 30 // Returns the NSMenuItem that has the given keyEquivalent and modifiers, or |
| 31 // nil. |
| 32 NSMenuItem* MenuContainsAccelerator(NSMenu* menu, |
| 33 NSString* key_equivalent, |
| 34 NSUInteger modifiers) { |
| 35 for (NSMenuItem* item in [menu itemArray]) { |
| 36 NSMenu* submenu = item.submenu; |
| 37 if (submenu) { |
| 38 NSMenuItem* result = |
| 39 MenuContainsAccelerator(submenu, key_equivalent, modifiers); |
| 40 if (result) |
| 41 return result; |
| 42 } |
| 43 |
| 44 if ([item.keyEquivalent isEqual:key_equivalent]) { |
| 45 BOOL maskEqual = |
| 46 (modifiers == item.keyEquivalentModifierMask) || |
| 47 ((modifiers & (~NSShiftKeyMask)) == item.keyEquivalentModifierMask); |
| 48 if (maskEqual) |
| 49 return item; |
| 50 } |
| 51 } |
| 52 return nil; |
| 53 } |
| 54 |
| 55 } // namespace |
| 56 |
| 57 // Checks that each NSMenuItem in the main menu has a corresponding accelerator, |
| 58 // and the keyEquivalent/modifiers match. |
| 59 IN_PROC_BROWSER_TEST_F(AcceleratorsCocoaBrowserTest, |
| 60 MainMenuAcceleratorsInMapping) { |
| 61 NSMenu* menu = [NSApp mainMenu]; |
| 62 NSMutableArray* array = [NSMutableArray array]; |
| 63 AddAcceleratorItemsToArray(menu, array); |
| 64 |
| 65 for (NSMenuItem* item in array) { |
| 66 NSInteger command_id = item.tag; |
| 67 AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance(); |
| 68 const ui::Accelerator* accelerator; |
| 69 |
| 70 // If the tag is zero, then the NSMenuItem must use a custom selector. |
| 71 // Check that the accelerator is present as an un-mapped accelerator. |
| 72 if (command_id == 0) { |
| 73 accelerator = keymap->GetAcceleratorForHotKey( |
| 74 item.keyEquivalent, item.keyEquivalentModifierMask); |
| 75 |
| 76 EXPECT_TRUE(accelerator); |
| 77 return; |
| 78 } |
| 79 |
| 80 // If the tag isn't zero, then it must correspond to an IDC_* command. |
| 81 accelerator = keymap->GetAcceleratorForCommand(command_id); |
| 82 EXPECT_TRUE(accelerator); |
| 83 if (!accelerator) |
| 84 continue; |
| 85 |
| 86 // Get the Cocoa key_equivalent associated with the accelerator. |
| 87 const ui::PlatformAcceleratorCocoa* platform_accelerator = |
| 88 static_cast<const ui::PlatformAcceleratorCocoa*>( |
| 89 accelerator->platform_accelerator()); |
| 90 NSString* key_equivalent = platform_accelerator->characters(); |
| 91 |
| 92 // Check that the menu item's keyEquivalent matches the one from the |
| 93 // Cocoa accelerator map. |
| 94 EXPECT_NSEQ(key_equivalent, item.keyEquivalent); |
| 95 |
| 96 // Check that the menu item's modifier mask matches the one stored in the |
| 97 // accelerator. A mask that include NSShiftKeyMask may not include the |
| 98 // relevant bit (the information is reflected in the keyEquivalent of the |
| 99 // NSMenuItem). |
| 100 NSUInteger mask = platform_accelerator->modifier_mask(); |
| 101 BOOL maskEqual = |
| 102 (mask == item.keyEquivalentModifierMask) || |
| 103 ((mask & (~NSShiftKeyMask)) == item.keyEquivalentModifierMask); |
| 104 EXPECT_TRUE(maskEqual); |
| 105 } |
| 106 } |
| 107 |
| 108 // Check that each accelerator with a command_id has an associated NSMenuItem |
| 109 // in the main menu. If the selector is commandDispatch:, then the tag must |
| 110 // match the command_id. |
| 111 IN_PROC_BROWSER_TEST_F(AcceleratorsCocoaBrowserTest, |
| 112 MappingAcceleratorsInMainMenu) { |
| 113 AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance(); |
| 114 for (AcceleratorsCocoa::AcceleratorMap::iterator it = |
| 115 keymap->accelerators_.begin(); |
| 116 it != keymap->accelerators_.end(); |
| 117 ++it) { |
| 118 const ui::PlatformAcceleratorCocoa* platform_accelerator = |
| 119 static_cast<const ui::PlatformAcceleratorCocoa*>( |
| 120 it->second.platform_accelerator()); |
| 121 |
| 122 // Check that there exists a corresponding NSMenuItem. |
| 123 NSMenuItem* item = |
| 124 MenuContainsAccelerator([NSApp mainMenu], |
| 125 platform_accelerator->characters(), |
| 126 platform_accelerator->modifier_mask()); |
| 127 EXPECT_TRUE(item); |
| 128 |
| 129 // If the menu uses a commandDispatch:, the tag must match the command id! |
| 130 if (item.action == @selector(commandDispatch:)) |
| 131 EXPECT_EQ(item.tag, it->first); |
| 132 } |
| 133 } |
OLD | NEW |