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 |