Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: chrome/browser/ui/cocoa/apps/app_shim_menu_controller_mac.mm

Issue 23005021: Replicate standard menus for apps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update tests Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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, action, and key equivalent.
30 NSMenuItem* DuplicateTopLevelItem(NSInteger menu_tag) {
31 NSMenuItem* original = [[NSApp mainMenu] itemWithTag:menu_tag];
32 base::scoped_nsobject<NSMenuItem> item([[NSMenuItem alloc]
33 initWithTitle:[original title]
34 action:[original action]
35 keyEquivalent:[original keyEquivalent]]);
tapted 2013/08/29 06:06:19 Can top-level items have key equivalents, or actio
jackhou1 2013/08/29 06:30:03 Done.
36 if ([original hasSubmenu]) {
tapted 2013/08/29 06:06:19 DCHECK? I think later code assumes that a submenu
jackhou1 2013/08/29 06:30:03 Done.
37 base::scoped_nsobject<NSMenu> sub_menu([[NSMenu alloc]
38 initWithTitle:[[original submenu] title]]);
39 [item setSubmenu:sub_menu];
40 }
41 return item.autorelease();
42 }
43
44 // Finds an item using |menu_tag| and |item_tag| and adds a duplicate of it to
45 // the submenu of |top_level_item|.
46 NSMenuItem* AddDuplicateItem(NSMenuItem* top_level_item,
tapted 2013/08/29 06:06:19 return void?
jackhou1 2013/08/29 06:30:03 Done.
47 NSInteger menu_tag,
48 NSInteger item_tag) {
49 base::scoped_nsobject<NSMenuItem> item(
50 [GetItemByTag(menu_tag, item_tag) copy]);
51 [[top_level_item submenu] addItem:item];
52 return item;
53 }
54
55 } // namespace
56
18 @interface AppShimMenuController () 57 @interface AppShimMenuController ()
19 // Construct the NSMenuItems for apps. 58 // Construct the NSMenuItems for apps.
20 - (void)buildAppMenuItems; 59 - (void)buildAppMenuItems;
21 // Register for NSWindow notifications. 60 // Register for NSWindow notifications.
22 - (void)registerEventHandlers; 61 - (void)registerEventHandlers;
23 // If the window is an app window, add or remove menu items. 62 // If the window is an app window, add or remove menu items.
24 - (void)windowMainStatusChanged:(NSNotification*)notification; 63 - (void)windowMainStatusChanged:(NSNotification*)notification;
25 // Add menu items for an app and hide Chrome menu items. 64 // Add menu items for an app and hide Chrome menu items.
26 - (void)addMenuItems:(const extensions::Extension*)app; 65 - (void)addMenuItems:(const extensions::Extension*)app;
27 // If the window belongs to the currently focused app, remove the menu items and 66 // If the window belongs to the currently focused app, remove the menu items and
(...skipping 13 matching lines...) Expand all
41 return self; 80 return self;
42 } 81 }
43 82
44 - (void)dealloc { 83 - (void)dealloc {
45 [[NSNotificationCenter defaultCenter] removeObserver:self]; 84 [[NSNotificationCenter defaultCenter] removeObserver:self];
46 [super dealloc]; 85 [super dealloc];
47 } 86 }
48 87
49 - (void)buildAppMenuItems { 88 - (void)buildAppMenuItems {
50 // Find the "Quit Chrome" menu item. 89 // Find the "Quit Chrome" menu item.
51 NSMenu* chromeMenu = [[[NSApp mainMenu] itemAtIndex:0] submenu]; 90 NSMenuItem* chromeMenuQuitItem = GetItemByTag(IDC_CHROME_MENU, IDC_EXIT);
tapted 2013/08/29 06:06:19 nit: probably don't need this temporary any more
jackhou1 2013/08/29 06:30:03 Done.
52 for (NSMenuItem* item in [chromeMenu itemArray]) { 91 chromeMenuQuitItem_.reset([chromeMenuQuitItem retain]);
53 if ([item action] == @selector(terminate:)) {
54 chromeMenuQuitItem_.reset([item retain]);
55 break;
56 }
57 }
58 DCHECK(chromeMenuQuitItem_); 92 DCHECK(chromeMenuQuitItem_);
59 93
94 // The app's menu.
60 appMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@"" 95 appMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@""
61 action:nil 96 action:nil
62 keyEquivalent:@""]); 97 keyEquivalent:@""]);
63 base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:@""]); 98 base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:@""]);
64 [appMenu setAutoenablesItems:NO]; 99 [appMenu setAutoenablesItems:NO];
65 NSMenuItem* appMenuQuitItem = 100 NSMenuItem* appMenuQuitItem =
66 [appMenu addItemWithTitle:@"" 101 [appMenu addItemWithTitle:@""
67 action:@selector(quitCurrentPlatformApp) 102 action:@selector(quitCurrentPlatformApp)
68 keyEquivalent:@"q"]; 103 keyEquivalent:@"q"];
69 [appMenuQuitItem setKeyEquivalentModifierMask: 104 [appMenuQuitItem setKeyEquivalentModifierMask:
70 [chromeMenuQuitItem_ keyEquivalentModifierMask]]; 105 [chromeMenuQuitItem_ keyEquivalentModifierMask]];
71 [appMenuQuitItem setTarget:self]; 106 [appMenuQuitItem setTarget:self];
72 [appMenuItem_ setSubmenu:appMenu]; 107 [appMenuItem_ setSubmenu:appMenu];
108
109 // File menu.
110 fileMenuItem_.reset([DuplicateTopLevelItem(IDC_FILE_MENU) retain]);
111 AddDuplicateItem(fileMenuItem_, IDC_FILE_MENU, IDC_CLOSE_WINDOW);
112
113 // Edit menu.
114 editMenuItem_.reset([DuplicateTopLevelItem(IDC_EDIT_MENU) retain]);
115 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_UNDO);
116 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_REDO);
117 [[editMenuItem_ submenu] addItem:[NSMenuItem separatorItem]];
118 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_CUT);
119 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_COPY);
120 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_PASTE);
121 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_DELETE);
122 AddDuplicateItem(editMenuItem_, IDC_EDIT_MENU, IDC_CONTENT_CONTEXT_SELECTALL);
123
124 // Window menu.
125 windowMenuItem_.reset([DuplicateTopLevelItem(IDC_WINDOW_MENU) retain]);
126 AddDuplicateItem(windowMenuItem_, IDC_WINDOW_MENU, IDC_MINIMIZE);
127 AddDuplicateItem(windowMenuItem_, IDC_WINDOW_MENU, IDC_MAXIMIZE);
128 [[windowMenuItem_ submenu] addItem:[NSMenuItem separatorItem]];
129 AddDuplicateItem(windowMenuItem_, IDC_WINDOW_MENU, IDC_ALL_WINDOWS_FRONT);
73 } 130 }
74 131
75 - (void)registerEventHandlers { 132 - (void)registerEventHandlers {
76 [[NSNotificationCenter defaultCenter] 133 [[NSNotificationCenter defaultCenter]
77 addObserver:self 134 addObserver:self
78 selector:@selector(windowMainStatusChanged:) 135 selector:@selector(windowMainStatusChanged:)
79 name:NSWindowDidBecomeMainNotification 136 name:NSWindowDidBecomeMainNotification
80 object:nil]; 137 object:nil];
81 138
82 [[NSNotificationCenter defaultCenter] 139 [[NSNotificationCenter defaultCenter]
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 194
138 // It seems that two menu items that have the same key equivalent must also 195 // 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 196 // 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). 197 // original keyboard shortcut, regardless of any overrides set in OSX).
141 // In order to let the appMenuQuitItem have a different action, we remove the 198 // In order to let the appMenuQuitItem have a different action, we remove the
142 // key equivalent from the chromeMenuQuitItem and restore it later. 199 // key equivalent from the chromeMenuQuitItem and restore it later.
143 [chromeMenuQuitItem_ setKeyEquivalent:@""]; 200 [chromeMenuQuitItem_ setKeyEquivalent:@""];
144 201
145 [appMenuItem_ setTitle:appId]; 202 [appMenuItem_ setTitle:appId];
146 [[appMenuItem_ submenu] setTitle:title]; 203 [[appMenuItem_ submenu] setTitle:title];
204
147 [mainMenu addItem:appMenuItem_]; 205 [mainMenu addItem:appMenuItem_];
206 [mainMenu addItem:fileMenuItem_];
207 [mainMenu addItem:editMenuItem_];
208 [mainMenu addItem:windowMenuItem_];
148 } 209 }
149 210
150 - (void)removeMenuItems:(NSString*)appId { 211 - (void)removeMenuItems:(NSString*)appId {
151 if (![appId_ isEqualToString:appId]) 212 if (![appId_ isEqualToString:appId])
152 return; 213 return;
153 214
154 appId_.reset(); 215 appId_.reset();
155 216
156 NSMenu* mainMenu = [NSApp mainMenu]; 217 NSMenu* mainMenu = [NSApp mainMenu];
157 [mainMenu removeItem:appMenuItem_]; 218 [mainMenu removeItem:appMenuItem_];
219 [mainMenu removeItem:fileMenuItem_];
220 [mainMenu removeItem:editMenuItem_];
221 [mainMenu removeItem:windowMenuItem_];
158 222
159 // Restore the Chrome main menu bar. 223 // Restore the Chrome main menu bar.
160 for (NSMenuItem* item in [mainMenu itemArray]) 224 for (NSMenuItem* item in [mainMenu itemArray])
161 [item setHidden:NO]; 225 [item setHidden:NO];
162 226
163 // Restore the keyboard shortcut to Chrome. This just needs to be set back to 227 // 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 228 // 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. 229 // overrides still work as they are based on the title of the menu item.
166 [chromeMenuQuitItem_ setKeyEquivalent:@"q"]; 230 [chromeMenuQuitItem_ setKeyEquivalent:@"q"];
167 } 231 }
168 232
169 - (void)quitCurrentPlatformApp { 233 - (void)quitCurrentPlatformApp {
170 apps::ShellWindow* shellWindow = 234 apps::ShellWindow* shellWindow =
171 apps::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile( 235 apps::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile(
172 [NSApp keyWindow]); 236 [NSApp keyWindow]);
173 if (shellWindow) 237 if (shellWindow)
174 apps::ExtensionAppShimHandler::QuitAppForWindow(shellWindow); 238 apps::ExtensionAppShimHandler::QuitAppForWindow(shellWindow);
175 } 239 }
176 240
177 @end 241 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698