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" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 NSInteger menu_tag, | 46 NSInteger menu_tag, |
| 47 NSInteger item_tag) { | 47 NSInteger item_tag) { |
| 48 base::scoped_nsobject<NSMenuItem> item( | 48 base::scoped_nsobject<NSMenuItem> item( |
| 49 [GetItemByTag(menu_tag, item_tag) copy]); | 49 [GetItemByTag(menu_tag, item_tag) copy]); |
| 50 DCHECK(item); | 50 DCHECK(item); |
| 51 [[top_level_item submenu] addItem:item]; | 51 [[top_level_item submenu] addItem:item]; |
| 52 } | 52 } |
| 53 | 53 |
| 54 } // namespace | 54 } // namespace |
| 55 | 55 |
| 56 @interface DoppelgangerMenuItem () | |
| 57 // Get the source item using the tags and create the menu item. | |
| 58 - (id)initWithController:(AppShimMenuController*)controller | |
| 59 menuTag:(NSInteger)menuTag | |
| 60 itemTag:(NSInteger)itemTag | |
| 61 resourceId:(int)resourceId | |
| 62 action:(SEL)action | |
| 63 keyEquivalent:(NSString*)keyEquivalent; | |
| 64 // Returns the menu item. | |
|
tapted
2013/09/03 08:17:25
nit: Maybe declare this as a @property(readonly, n
jackhou1
2013/09/04 01:31:31
Done.
| |
| 65 - (NSMenuItem*)menuItem; | |
| 66 // Set the title using |resourceId_| and unset the source item's key equivalent. | |
| 67 - (void)enableForApp:(const extensions::Extension*) app; | |
|
tapted
2013/09/03 08:17:25
nit: no space before the last `app`
jackhou1
2013/09/04 01:31:31
Done.
| |
| 68 // Restore the source item's key equivalent. | |
| 69 - (void)disable; | |
| 70 @end | |
| 71 | |
| 72 @implementation DoppelgangerMenuItem | |
| 73 | |
| 74 - (NSMenuItem*)menuItem { | |
| 75 return menuItem_; | |
| 76 } | |
| 77 | |
| 78 - (id)initWithController:(AppShimMenuController*)controller | |
| 79 menuTag:(NSInteger)menuTag | |
| 80 itemTag:(NSInteger)itemTag | |
| 81 resourceId:(int)resourceId | |
| 82 action:(SEL)action | |
| 83 keyEquivalent:(NSString*)keyEquivalent { | |
| 84 if ((self = [super init])) { | |
| 85 sourceItem_.reset([GetItemByTag(menuTag, itemTag) retain]); | |
| 86 DCHECK(sourceItem_); | |
| 87 menuItem_.reset([[NSMenuItem alloc] | |
| 88 initWithTitle:@"" | |
| 89 action:action | |
| 90 keyEquivalent:keyEquivalent]); | |
| 91 [menuItem_ setTarget:controller]; | |
| 92 [menuItem_ setTag:itemTag]; | |
| 93 resourceId_ = resourceId; | |
| 94 } | |
| 95 return self; | |
| 96 } | |
| 97 | |
| 98 - (void)enableForApp:(const extensions::Extension*)app { | |
| 99 // It seems that two menu items that have the same key equivalent must also | |
| 100 // have the same action for the keyboard shortcut to work. (This refers to the | |
| 101 // original keyboard shortcut, regardless of any overrides set in OSX). | |
| 102 // In order to let the app menu items have a different action, we remove the | |
| 103 // key equivalent of the original items and restore them later. | |
| 104 [sourceItem_ setKeyEquivalent:@""]; | |
| 105 if (!resourceId_) | |
| 106 return; | |
| 107 | |
| 108 [menuItem_ setTitle:l10n_util::GetNSStringF(resourceId_, | |
| 109 base::UTF8ToUTF16(app->name()))]; | |
| 110 } | |
| 111 | |
| 112 - (void)disable { | |
| 113 // Restore the keyboard shortcut to Chrome. This just needs to be set back to | |
| 114 // the original keyboard shortcut, regardless of any overrides in OSX. The | |
| 115 // overrides still work as they are based on the title of the menu item. | |
| 116 [sourceItem_ setKeyEquivalent:[menuItem_ keyEquivalent]]; | |
| 117 } | |
| 118 | |
| 119 @end | |
| 120 | |
| 56 @interface AppShimMenuController () | 121 @interface AppShimMenuController () |
| 57 // Construct the NSMenuItems for apps. | 122 // Construct the NSMenuItems for apps. |
| 58 - (void)buildAppMenuItems; | 123 - (void)buildAppMenuItems; |
| 59 // Register for NSWindow notifications. | 124 // Register for NSWindow notifications. |
| 60 - (void)registerEventHandlers; | 125 - (void)registerEventHandlers; |
| 61 // If the window is an app window, add or remove menu items. | 126 // If the window is an app window, add or remove menu items. |
| 62 - (void)windowMainStatusChanged:(NSNotification*)notification; | 127 - (void)windowMainStatusChanged:(NSNotification*)notification; |
| 63 // Add menu items for an app and hide Chrome menu items. | 128 // Add menu items for an app and hide Chrome menu items. |
| 64 - (void)addMenuItems:(const extensions::Extension*)app; | 129 - (void)addMenuItems:(const extensions::Extension*)app; |
| 65 // If the window belongs to the currently focused app, remove the menu items and | 130 // If the window belongs to the currently focused app, remove the menu items and |
| 66 // unhide Chrome menu items. | 131 // unhide Chrome menu items. |
| 67 - (void)removeMenuItems:(NSString*)appId; | 132 - (void)removeMenuItems:(NSString*)appId; |
| 68 // If the currently focused window belongs to a platform app, quit the app. | 133 // If the currently focused window belongs to a platform app, quit the app. |
| 69 - (void)quitCurrentPlatformApp; | 134 - (void)quitCurrentPlatformApp; |
| 135 // If the currently focused window belongs to a platform app, hide the app. | |
| 136 - (void)hideCurrentPlatformApp; | |
| 70 @end | 137 @end |
| 71 | 138 |
| 72 @implementation AppShimMenuController | 139 @implementation AppShimMenuController |
| 73 | 140 |
| 74 - (id)init { | 141 - (id)init { |
| 75 if ((self = [super init])) { | 142 if ((self = [super init])) { |
| 76 [self buildAppMenuItems]; | 143 [self buildAppMenuItems]; |
| 77 [self registerEventHandlers]; | 144 [self registerEventHandlers]; |
| 78 } | 145 } |
| 79 return self; | 146 return self; |
| 80 } | 147 } |
| 81 | 148 |
| 82 - (void)dealloc { | 149 - (void)dealloc { |
| 83 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 150 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 84 [super dealloc]; | 151 [super dealloc]; |
| 85 } | 152 } |
| 86 | 153 |
| 87 - (void)buildAppMenuItems { | 154 - (void)buildAppMenuItems { |
| 88 // Find the "Quit Chrome" menu item. | 155 hideDoppelganger_.reset([[DoppelgangerMenuItem alloc] |
| 89 chromeMenuQuitItem_.reset([GetItemByTag(IDC_CHROME_MENU, IDC_EXIT) retain]); | 156 initWithController:self |
| 90 DCHECK(chromeMenuQuitItem_); | 157 menuTag:IDC_CHROME_MENU |
| 158 itemTag:IDC_HIDE_APP | |
| 159 resourceId:IDS_HIDE_APP_MAC | |
| 160 action:@selector(hideCurrentPlatformApp) | |
| 161 keyEquivalent:@"h"]); | |
| 162 quitDoppelganger_.reset([[DoppelgangerMenuItem alloc] | |
| 163 initWithController:self | |
| 164 menuTag:IDC_CHROME_MENU | |
| 165 itemTag:IDC_EXIT | |
| 166 resourceId:IDS_EXIT_MAC | |
| 167 action:@selector(quitCurrentPlatformApp) | |
| 168 keyEquivalent:@"q"]); | |
| 91 | 169 |
| 92 // The app's menu. | 170 // The app's menu. |
| 93 appMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@"" | 171 appMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@"" |
| 94 action:nil | 172 action:nil |
| 95 keyEquivalent:@""]); | 173 keyEquivalent:@""]); |
| 96 base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:@""]); | 174 base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:@""]); |
| 175 [appMenuItem_ setSubmenu:appMenu]; | |
| 97 [appMenu setAutoenablesItems:NO]; | 176 [appMenu setAutoenablesItems:NO]; |
| 98 NSMenuItem* appMenuQuitItem = | 177 |
| 99 [appMenu addItemWithTitle:@"" | 178 [appMenu addItem:[hideDoppelganger_ menuItem]]; |
| 100 action:@selector(quitCurrentPlatformApp) | 179 [appMenu addItem:[NSMenuItem separatorItem]]; |
| 101 keyEquivalent:@"q"]; | 180 [appMenu addItem:[quitDoppelganger_ menuItem]]; |
| 102 [appMenuQuitItem setKeyEquivalentModifierMask: | |
| 103 [chromeMenuQuitItem_ keyEquivalentModifierMask]]; | |
| 104 [appMenuQuitItem setTarget:self]; | |
| 105 [appMenuItem_ setSubmenu:appMenu]; | |
| 106 | 181 |
| 107 // File menu. | 182 // File menu. |
| 108 fileMenuItem_.reset([NewTopLevelItemFrom(IDC_FILE_MENU) retain]); | 183 fileMenuItem_.reset([NewTopLevelItemFrom(IDC_FILE_MENU) retain]); |
| 109 AddDuplicateItem(fileMenuItem_, IDC_FILE_MENU, IDC_CLOSE_WINDOW); | 184 AddDuplicateItem(fileMenuItem_, IDC_FILE_MENU, IDC_CLOSE_WINDOW); |
| 110 | 185 |
| 111 // Edit menu. | 186 // Edit menu. |
| 112 editMenuItem_.reset([NewTopLevelItemFrom(IDC_EDIT_MENU) retain]); | 187 editMenuItem_.reset([NewTopLevelItemFrom(IDC_EDIT_MENU) retain]); |
| 113 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_UNDO); | 188 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_UNDO); |
| 114 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_REDO); | 189 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_REDO); |
| 115 [[editMenuItem_ submenu] addItem:[NSMenuItem separatorItem]]; | 190 [[editMenuItem_ submenu] addItem:[NSMenuItem separatorItem]]; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 return; | 253 return; |
| 179 | 254 |
| 180 [self removeMenuItems:appId_]; | 255 [self removeMenuItems:appId_]; |
| 181 appId_.reset([appId copy]); | 256 appId_.reset([appId copy]); |
| 182 | 257 |
| 183 // Hide Chrome menu items. | 258 // Hide Chrome menu items. |
| 184 NSMenu* mainMenu = [NSApp mainMenu]; | 259 NSMenu* mainMenu = [NSApp mainMenu]; |
| 185 for (NSMenuItem* item in [mainMenu itemArray]) | 260 for (NSMenuItem* item in [mainMenu itemArray]) |
| 186 [item setHidden:YES]; | 261 [item setHidden:YES]; |
| 187 | 262 |
| 188 NSString* localizedQuitApp = | 263 [hideDoppelganger_ enableForApp:app]; |
| 189 l10n_util::GetNSStringF(IDS_EXIT_MAC, base::UTF8ToUTF16(app->name())); | 264 [quitDoppelganger_ enableForApp:app]; |
| 190 NSMenuItem* appMenuQuitItem = [[[appMenuItem_ submenu] itemArray] lastObject]; | |
| 191 [appMenuQuitItem setTitle:localizedQuitApp]; | |
| 192 | |
| 193 // It seems that two menu items that have the same key equivalent must also | |
| 194 // have the same action for the keyboard shortcut to work. (This refers to the | |
| 195 // original keyboard shortcut, regardless of any overrides set in OSX). | |
| 196 // In order to let the appMenuQuitItem have a different action, we remove the | |
| 197 // key equivalent from the chromeMenuQuitItem and restore it later. | |
| 198 [chromeMenuQuitItem_ setKeyEquivalent:@""]; | |
| 199 | 265 |
| 200 [appMenuItem_ setTitle:appId]; | 266 [appMenuItem_ setTitle:appId]; |
| 201 [[appMenuItem_ submenu] setTitle:title]; | 267 [[appMenuItem_ submenu] setTitle:title]; |
| 202 | 268 |
| 203 [mainMenu addItem:appMenuItem_]; | 269 [mainMenu addItem:appMenuItem_]; |
| 204 [mainMenu addItem:fileMenuItem_]; | 270 [mainMenu addItem:fileMenuItem_]; |
| 205 [mainMenu addItem:editMenuItem_]; | 271 [mainMenu addItem:editMenuItem_]; |
| 206 [mainMenu addItem:windowMenuItem_]; | 272 [mainMenu addItem:windowMenuItem_]; |
| 207 } | 273 } |
| 208 | 274 |
| 209 - (void)removeMenuItems:(NSString*)appId { | 275 - (void)removeMenuItems:(NSString*)appId { |
| 210 if (![appId_ isEqualToString:appId]) | 276 if (![appId_ isEqualToString:appId]) |
| 211 return; | 277 return; |
| 212 | 278 |
| 213 appId_.reset(); | 279 appId_.reset(); |
| 214 | 280 |
| 215 NSMenu* mainMenu = [NSApp mainMenu]; | 281 NSMenu* mainMenu = [NSApp mainMenu]; |
| 216 [mainMenu removeItem:appMenuItem_]; | 282 [mainMenu removeItem:appMenuItem_]; |
| 217 [mainMenu removeItem:fileMenuItem_]; | 283 [mainMenu removeItem:fileMenuItem_]; |
| 218 [mainMenu removeItem:editMenuItem_]; | 284 [mainMenu removeItem:editMenuItem_]; |
| 219 [mainMenu removeItem:windowMenuItem_]; | 285 [mainMenu removeItem:windowMenuItem_]; |
| 220 | 286 |
| 221 // Restore the Chrome main menu bar. | 287 // Restore the Chrome main menu bar. |
| 222 for (NSMenuItem* item in [mainMenu itemArray]) | 288 for (NSMenuItem* item in [mainMenu itemArray]) |
| 223 [item setHidden:NO]; | 289 [item setHidden:NO]; |
| 224 | 290 |
| 225 // Restore the keyboard shortcut to Chrome. This just needs to be set back to | 291 [hideDoppelganger_ disable]; |
| 226 // the original keyboard shortcut, regardless of any overrides in OSX. The | 292 [quitDoppelganger_ disable]; |
| 227 // overrides still work as they are based on the title of the menu item. | |
| 228 [chromeMenuQuitItem_ setKeyEquivalent:@"q"]; | |
| 229 } | 293 } |
| 230 | 294 |
| 231 - (void)quitCurrentPlatformApp { | 295 - (void)quitCurrentPlatformApp { |
| 232 apps::ShellWindow* shellWindow = | 296 apps::ShellWindow* shellWindow = |
| 233 apps::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile( | 297 apps::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile( |
| 234 [NSApp keyWindow]); | 298 [NSApp keyWindow]); |
| 235 if (shellWindow) | 299 if (shellWindow) |
| 236 apps::ExtensionAppShimHandler::QuitAppForWindow(shellWindow); | 300 apps::ExtensionAppShimHandler::QuitAppForWindow(shellWindow); |
| 237 } | 301 } |
| 238 | 302 |
| 303 - (void)hideCurrentPlatformApp { | |
| 304 apps::ShellWindow* shellWindow = | |
| 305 apps::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile( | |
| 306 [NSApp keyWindow]); | |
| 307 if (shellWindow) | |
| 308 apps::ExtensionAppShimHandler::HideAppForWindow(shellWindow); | |
| 309 } | |
| 310 | |
| 239 @end | 311 @end |
| OLD | NEW |