Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #import "chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.h" | 5 #import "chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.h" |
| 6 | 6 |
| 7 #include "apps/app_shim/extension_app_shim_handler_mac.h" | 7 #include "apps/app_shim/extension_app_shim_handler_mac.h" |
| 8 #include "apps/shell_window.h" | 8 #include "apps/shell_window.h" |
| 9 #include "apps/shell_window_registry.h" | 9 #include "apps/shell_window_registry.h" |
| 10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| 11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "chrome/app/chrome_command_ids.h" | |
| 12 #import "chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h" | 13 #import "chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h" |
| 13 #include "chrome/common/extensions/extension.h" | 14 #include "chrome/common/extensions/extension.h" |
| 14 #include "grit/generated_resources.h" | 15 #include "grit/generated_resources.h" |
| 15 #include "ui/base/l10n/l10n_util.h" | 16 #include "ui/base/l10n/l10n_util.h" |
| 16 #include "ui/base/l10n/l10n_util_mac.h" | 17 #include "ui/base/l10n/l10n_util_mac.h" |
| 17 | 18 |
| 19 namespace { | |
| 20 | |
| 21 // Gets an item from the main menu given the tag of the top level item | |
| 22 // |menu_tag| and the tag of the item |item_tag|. | |
| 23 NSMenuItem* GetItemByTag(NSInteger menu_tag, NSInteger item_tag) { | |
| 24 return [[[[NSApp mainMenu] itemWithTag:menu_tag] submenu] | |
| 25 itemWithTag:item_tag]; | |
| 26 } | |
| 27 | |
| 28 // Finds a top level menu item using |menu_tag| and creates a new NSMenuItem | |
| 29 // with the same title. | |
| 30 NSMenuItem* DuplicateTopLevelItem(NSInteger menu_tag) { | |
|
Nico
2013/08/29 17:19:38
Files that return a retained object should have a
jackhou1
2013/08/30 01:30:41
Done.
| |
| 31 NSMenuItem* original = [[NSApp mainMenu] itemWithTag:menu_tag]; | |
| 32 base::scoped_nsobject<NSMenuItem> item([[NSMenuItem alloc] | |
| 33 initWithTitle:[original title] | |
| 34 action:nil | |
| 35 keyEquivalent:@""]); | |
| 36 DCHECK([original hasSubmenu]); | |
| 37 base::scoped_nsobject<NSMenu> sub_menu([[NSMenu alloc] | |
| 38 initWithTitle:[[original submenu] title]]); | |
| 39 [item setSubmenu:sub_menu]; | |
| 40 return item.autorelease(); | |
| 41 } | |
| 42 | |
| 43 // Finds an item using |menu_tag| and |item_tag| and adds a duplicate of it to | |
| 44 // the submenu of |top_level_item|. | |
| 45 void AddDuplicateItem(NSMenuItem* top_level_item, | |
| 46 NSInteger menu_tag, | |
| 47 NSInteger item_tag) { | |
| 48 base::scoped_nsobject<NSMenuItem> item( | |
| 49 [GetItemByTag(menu_tag, item_tag) copy]); | |
|
Nico
2013/08/29 17:19:38
Do you want to DCHECK item here? If items with tha
jackhou1
2013/08/30 01:30:41
Done.
| |
| 50 [[top_level_item submenu] addItem:item]; | |
| 51 } | |
| 52 | |
| 53 } // namespace | |
| 54 | |
| 18 @interface AppShimMenuController () | 55 @interface AppShimMenuController () |
| 19 // Construct the NSMenuItems for apps. | 56 // Construct the NSMenuItems for apps. |
| 20 - (void)buildAppMenuItems; | 57 - (void)buildAppMenuItems; |
| 21 // Register for NSWindow notifications. | 58 // Register for NSWindow notifications. |
| 22 - (void)registerEventHandlers; | 59 - (void)registerEventHandlers; |
| 23 // If the window is an app window, add or remove menu items. | 60 // If the window is an app window, add or remove menu items. |
| 24 - (void)windowMainStatusChanged:(NSNotification*)notification; | 61 - (void)windowMainStatusChanged:(NSNotification*)notification; |
| 25 // Add menu items for an app and hide Chrome menu items. | 62 // Add menu items for an app and hide Chrome menu items. |
| 26 - (void)addMenuItems:(const extensions::Extension*)app; | 63 - (void)addMenuItems:(const extensions::Extension*)app; |
| 27 // If the window belongs to the currently focused app, remove the menu items and | 64 // If the window belongs to the currently focused app, remove the menu items and |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 41 return self; | 78 return self; |
| 42 } | 79 } |
| 43 | 80 |
| 44 - (void)dealloc { | 81 - (void)dealloc { |
| 45 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 82 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 46 [super dealloc]; | 83 [super dealloc]; |
| 47 } | 84 } |
| 48 | 85 |
| 49 - (void)buildAppMenuItems { | 86 - (void)buildAppMenuItems { |
| 50 // Find the "Quit Chrome" menu item. | 87 // Find the "Quit Chrome" menu item. |
| 51 NSMenu* chromeMenu = [[[NSApp mainMenu] itemAtIndex:0] submenu]; | 88 chromeMenuQuitItem_.reset([GetItemByTag(IDC_CHROME_MENU, IDC_EXIT) retain]); |
| 52 for (NSMenuItem* item in [chromeMenu itemArray]) { | |
| 53 if ([item action] == @selector(terminate:)) { | |
| 54 chromeMenuQuitItem_.reset([item retain]); | |
| 55 break; | |
| 56 } | |
| 57 } | |
| 58 DCHECK(chromeMenuQuitItem_); | 89 DCHECK(chromeMenuQuitItem_); |
| 59 | 90 |
| 91 // The app's menu. | |
| 60 appMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@"" | 92 appMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@"" |
| 61 action:nil | 93 action:nil |
| 62 keyEquivalent:@""]); | 94 keyEquivalent:@""]); |
| 63 base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:@""]); | 95 base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:@""]); |
| 64 [appMenu setAutoenablesItems:NO]; | 96 [appMenu setAutoenablesItems:NO]; |
| 65 NSMenuItem* appMenuQuitItem = | 97 NSMenuItem* appMenuQuitItem = |
| 66 [appMenu addItemWithTitle:@"" | 98 [appMenu addItemWithTitle:@"" |
| 67 action:@selector(quitCurrentPlatformApp) | 99 action:@selector(quitCurrentPlatformApp) |
| 68 keyEquivalent:@"q"]; | 100 keyEquivalent:@"q"]; |
| 69 [appMenuQuitItem setKeyEquivalentModifierMask: | 101 [appMenuQuitItem setKeyEquivalentModifierMask: |
| 70 [chromeMenuQuitItem_ keyEquivalentModifierMask]]; | 102 [chromeMenuQuitItem_ keyEquivalentModifierMask]]; |
| 71 [appMenuQuitItem setTarget:self]; | 103 [appMenuQuitItem setTarget:self]; |
| 72 [appMenuItem_ setSubmenu:appMenu]; | 104 [appMenuItem_ setSubmenu:appMenu]; |
| 105 | |
| 106 // File menu. | |
| 107 fileMenuItem_.reset([DuplicateTopLevelItem(IDC_FILE_MENU) retain]); | |
| 108 AddDuplicateItem(fileMenuItem_, IDC_FILE_MENU, IDC_CLOSE_WINDOW); | |
| 109 | |
| 110 // Edit menu. | |
| 111 editMenuItem_.reset([DuplicateTopLevelItem(IDC_EDIT_MENU) retain]); | |
| 112 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_UNDO); | |
| 113 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_REDO); | |
| 114 [[editMenuItem_ submenu] addItem:[NSMenuItem separatorItem]]; | |
| 115 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_CUT); | |
| 116 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_COPY); | |
| 117 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_PASTE); | |
| 118 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_DELETE); | |
| 119 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_SELECTALL); | |
| 120 | |
| 121 // Window menu. | |
| 122 windowMenuItem_.reset([DuplicateTopLevelItem(IDC_WINDOW_MENU) retain]); | |
| 123 AddDuplicateItem(windowMenuItem_, IDC_WINDOW_MENU, IDC_MINIMIZE_WINDOW); | |
| 124 AddDuplicateItem(windowMenuItem_, IDC_WINDOW_MENU, IDC_MAXIMIZE_WINDOW); | |
| 125 [[windowMenuItem_ submenu] addItem:[NSMenuItem separatorItem]]; | |
| 126 AddDuplicateItem(windowMenuItem_, IDC_WINDOW_MENU, IDC_ALL_WINDOWS_FRONT); | |
| 73 } | 127 } |
| 74 | 128 |
| 75 - (void)registerEventHandlers { | 129 - (void)registerEventHandlers { |
| 76 [[NSNotificationCenter defaultCenter] | 130 [[NSNotificationCenter defaultCenter] |
| 77 addObserver:self | 131 addObserver:self |
| 78 selector:@selector(windowMainStatusChanged:) | 132 selector:@selector(windowMainStatusChanged:) |
| 79 name:NSWindowDidBecomeMainNotification | 133 name:NSWindowDidBecomeMainNotification |
| 80 object:nil]; | 134 object:nil]; |
| 81 | 135 |
| 82 [[NSNotificationCenter defaultCenter] | 136 [[NSNotificationCenter defaultCenter] |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 | 191 |
| 138 // It seems that two menu items that have the same key equivalent must also | 192 // It seems that two menu items that have the same key equivalent must also |
| 139 // have the same action for the keyboard shortcut to work. (This refers to the | 193 // have the same action for the keyboard shortcut to work. (This refers to the |
| 140 // original keyboard shortcut, regardless of any overrides set in OSX). | 194 // original keyboard shortcut, regardless of any overrides set in OSX). |
| 141 // In order to let the appMenuQuitItem have a different action, we remove the | 195 // In order to let the appMenuQuitItem have a different action, we remove the |
| 142 // key equivalent from the chromeMenuQuitItem and restore it later. | 196 // key equivalent from the chromeMenuQuitItem and restore it later. |
| 143 [chromeMenuQuitItem_ setKeyEquivalent:@""]; | 197 [chromeMenuQuitItem_ setKeyEquivalent:@""]; |
| 144 | 198 |
| 145 [appMenuItem_ setTitle:appId]; | 199 [appMenuItem_ setTitle:appId]; |
| 146 [[appMenuItem_ submenu] setTitle:title]; | 200 [[appMenuItem_ submenu] setTitle:title]; |
| 201 | |
| 147 [mainMenu addItem:appMenuItem_]; | 202 [mainMenu addItem:appMenuItem_]; |
| 203 [mainMenu addItem:fileMenuItem_]; | |
| 204 [mainMenu addItem:editMenuItem_]; | |
| 205 [mainMenu addItem:windowMenuItem_]; | |
| 148 } | 206 } |
| 149 | 207 |
| 150 - (void)removeMenuItems:(NSString*)appId { | 208 - (void)removeMenuItems:(NSString*)appId { |
| 151 if (![appId_ isEqualToString:appId]) | 209 if (![appId_ isEqualToString:appId]) |
| 152 return; | 210 return; |
| 153 | 211 |
| 154 appId_.reset(); | 212 appId_.reset(); |
| 155 | 213 |
| 156 NSMenu* mainMenu = [NSApp mainMenu]; | 214 NSMenu* mainMenu = [NSApp mainMenu]; |
| 157 [mainMenu removeItem:appMenuItem_]; | 215 [mainMenu removeItem:appMenuItem_]; |
| 216 [mainMenu removeItem:fileMenuItem_]; | |
| 217 [mainMenu removeItem:editMenuItem_]; | |
| 218 [mainMenu removeItem:windowMenuItem_]; | |
| 158 | 219 |
| 159 // Restore the Chrome main menu bar. | 220 // Restore the Chrome main menu bar. |
| 160 for (NSMenuItem* item in [mainMenu itemArray]) | 221 for (NSMenuItem* item in [mainMenu itemArray]) |
| 161 [item setHidden:NO]; | 222 [item setHidden:NO]; |
| 162 | 223 |
| 163 // Restore the keyboard shortcut to Chrome. This just needs to be set back to | 224 // Restore the keyboard shortcut to Chrome. This just needs to be set back to |
| 164 // the original keyboard shortcut, regardless of any overrides in OSX. The | 225 // the original keyboard shortcut, regardless of any overrides in OSX. The |
| 165 // overrides still work as they are based on the title of the menu item. | 226 // overrides still work as they are based on the title of the menu item. |
| 166 [chromeMenuQuitItem_ setKeyEquivalent:@"q"]; | 227 [chromeMenuQuitItem_ setKeyEquivalent:@"q"]; |
| 167 } | 228 } |
| 168 | 229 |
| 169 - (void)quitCurrentPlatformApp { | 230 - (void)quitCurrentPlatformApp { |
| 170 apps::ShellWindow* shellWindow = | 231 apps::ShellWindow* shellWindow = |
| 171 apps::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile( | 232 apps::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile( |
| 172 [NSApp keyWindow]); | 233 [NSApp keyWindow]); |
| 173 if (shellWindow) | 234 if (shellWindow) |
| 174 apps::ExtensionAppShimHandler::QuitAppForWindow(shellWindow); | 235 apps::ExtensionAppShimHandler::QuitAppForWindow(shellWindow); |
| 175 } | 236 } |
| 176 | 237 |
| 177 @end | 238 @end |
| OLD | NEW |