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

Side by Side Diff: chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.mm

Issue 1250403002: [Mac] Move UI item validation to UserInterfaceItemCommandHandler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@commandexecute
Patch Set: Sync Created 5 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/chrome_command_dispatcher_delegate.h" 5 #import "chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #import "base/mac/foundation_util.h"
9 #include "chrome/app/chrome_command_ids.h"
10 #import "chrome/browser/app_controller_mac.h"
11 #include "chrome/browser/fullscreen.h"
8 #include "chrome/browser/global_keyboard_shortcuts_mac.h" 12 #include "chrome/browser/global_keyboard_shortcuts_mac.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
9 #include "chrome/browser/ui/browser_commands.h" 15 #include "chrome/browser/ui/browser_commands.h"
10 #include "chrome/browser/ui/browser_finder.h" 16 #include "chrome/browser/ui/browser_finder.h"
17 #include "chrome/browser/ui/browser_window.h"
11 #import "chrome/browser/ui/cocoa/browser_window_controller_private.h" 18 #import "chrome/browser/ui/cocoa/browser_window_controller_private.h"
12 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" 19 #include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
20 #include "content/public/browser/web_contents.h"
21 #import "ui/base/cocoa/cocoa_base_utils.h"
13 22
14 namespace { 23 namespace {
15 24
16 // Type of functions listed in global_keyboard_shortcuts_mac.h. 25 // Type of functions listed in global_keyboard_shortcuts_mac.h.
17 typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int, unichar); 26 typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int, unichar);
18 27
19 // If the event is for a Browser window, and the key combination has an 28 // If the event is for a Browser window, and the key combination has an
20 // associated command, execute the command. 29 // associated command, execute the command.
21 bool HandleExtraKeyboardShortcut( 30 bool HandleExtraKeyboardShortcut(
22 NSEvent* event, 31 NSEvent* event,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 bool HandleDelayedWindowKeyboardShortcut(NSEvent* event, NSWindow* window) { 63 bool HandleDelayedWindowKeyboardShortcut(NSEvent* event, NSWindow* window) {
55 return HandleExtraKeyboardShortcut(event, window, 64 return HandleExtraKeyboardShortcut(event, window,
56 CommandForDelayedWindowKeyboardShortcut); 65 CommandForDelayedWindowKeyboardShortcut);
57 } 66 }
58 67
59 bool HandleExtraBrowserKeyboardShortcut(NSEvent* event, NSWindow* window) { 68 bool HandleExtraBrowserKeyboardShortcut(NSEvent* event, NSWindow* window) {
60 return HandleExtraKeyboardShortcut(event, window, 69 return HandleExtraKeyboardShortcut(event, window,
61 CommandForBrowserKeyboardShortcut); 70 CommandForBrowserKeyboardShortcut);
62 } 71 }
63 72
73 // Update a toggle state for an item if modified. The item may be an NSMenuItem
74 // or NSButton. Called by -validateUserInterfaceItem:.
75 void UpdateToggleStateWithTag(NSInteger tag, id item, NSWindow* window) {
76 if (![item respondsToSelector:@selector(state)] ||
77 ![item respondsToSelector:@selector(setState:)])
78 return;
79
80 Browser* browser = chrome::FindBrowserWithWindow(window);
81 DCHECK(browser);
82
83 // On Windows this logic happens in bookmark_bar_view.cc. This simply updates
84 // the menu item; it does not display the bookmark bar itself.
85 if (tag == IDC_SHOW_BOOKMARK_BAR) {
86 bool toggled = browser->window()->IsBookmarkBarVisible();
87 NSInteger oldState = [item state];
88 NSInteger newState = toggled ? NSOnState : NSOffState;
89 if (oldState != newState)
90 [item setState:newState];
91 return;
92 }
93
94 // Update the checked/unchecked state of items in the encoding menu.
95 // On Windows, this logic is part of |EncodingMenuModel| in
96 // browser/ui/views/toolbar_view.h.
97 EncodingMenuController encoding_controller;
98 if (!encoding_controller.DoesCommandBelongToEncodingMenu(tag))
99 return;
100
101 Profile* profile = browser->profile();
102 DCHECK(profile);
103 content::WebContents* current_tab =
104 browser->tab_strip_model()->GetActiveWebContents();
105 if (!current_tab)
106 return;
107
108 const std::string encoding = current_tab->GetEncoding();
109
110 bool toggled = encoding_controller.IsItemChecked(profile, encoding, tag);
111 NSInteger oldState = [item state];
112 NSInteger newState = toggled ? NSOnState : NSOffState;
113 if (oldState != newState)
114 [item setState:newState];
115 }
116
64 } // namespace 117 } // namespace
65 118
66 @implementation ChromeCommandDispatcherDelegate 119 @implementation ChromeCommandDispatcherDelegate
67 120
68 - (BOOL)handleExtraKeyboardShortcut:(NSEvent*)event window:(NSWindow*)window { 121 - (BOOL)handleExtraKeyboardShortcut:(NSEvent*)event window:(NSWindow*)window {
69 return HandleExtraBrowserKeyboardShortcut(event, window) || 122 return HandleExtraBrowserKeyboardShortcut(event, window) ||
70 HandleExtraWindowKeyboardShortcut(event, window) || 123 HandleExtraWindowKeyboardShortcut(event, window) ||
71 HandleDelayedWindowKeyboardShortcut(event, window); 124 HandleDelayedWindowKeyboardShortcut(event, window);
72 } 125 }
73 126
(...skipping 25 matching lines...) Expand all
99 // if e.g. the Omnibox has focus). 152 // if e.g. the Omnibox has focus).
100 return HandleExtraWindowKeyboardShortcut(event, window); 153 return HandleExtraWindowKeyboardShortcut(event, window);
101 } 154 }
102 155
103 - (BOOL)postPerformKeyEquivalent:(NSEvent*)event window:(NSWindow*)window { 156 - (BOOL)postPerformKeyEquivalent:(NSEvent*)event window:(NSWindow*)window {
104 // Handle per-window shortcuts like Esc after giving everybody else a chance 157 // Handle per-window shortcuts like Esc after giving everybody else a chance
105 // to handle them 158 // to handle them
106 return HandleDelayedWindowKeyboardShortcut(event, window); 159 return HandleDelayedWindowKeyboardShortcut(event, window);
107 } 160 }
108 161
162 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item
163 window:(NSWindow*)window {
164 SEL action = [item action];
165 if (action != @selector(commandDispatch:) &&
166 action != @selector(commandDispatchUsingKeyModifiers:)) {
167 // By default, interface items are enabled if the object in the responder
168 // chain that implements the action does not implement
169 // -validateUserInterfaceItem. Since we only care about -commandDispatch,
170 // return YES for all other actions
171 return YES;
172 }
173
174 Browser* browser = chrome::FindBrowserWithWindow(window);
175 DCHECK(browser);
176 NSInteger tag = [item tag];
177 if (!chrome::SupportsCommand(browser, tag))
178 return NO;
179
180 // Generate return value (enabled state).
181 BOOL enable = chrome::IsCommandEnabled(browser, tag);
182 switch (tag) {
183 case IDC_CLOSE_TAB:
184 // Disable "close tab" if the receiving window is not tabbed.
185 // We simply check whether the item has a keyboard shortcut set here;
186 // app_controller_mac.mm actually determines whether the item should
187 // be enabled.
188 if (NSMenuItem* menuItem = base::mac::ObjCCast<NSMenuItem>(item))
189 enable &= !![[menuItem keyEquivalent] length];
190 break;
191 case IDC_FULLSCREEN: {
192 if (NSMenuItem* menuItem = base::mac::ObjCCast<NSMenuItem>(item)) {
193 BrowserWindowController* controller = [window windowController];
194 if (chrome::mac::SupportsSystemFullscreen()) {
195 [menuItem setTitle:[controller titleForFullscreenMenuItem]];
tapted 2015/09/03 04:15:38 titleForFullscreenMenuItem is only used by this fu
jackhou1 2015/09/03 06:15:39 Done. The logic for what text to show is currentl
196 } else {
197 [menuItem setHidden:YES];
198 }
199 }
200 break;
201 }
202 case IDC_PRESENTATION_MODE: {
203 if (NSMenuItem* menuItem = base::mac::ObjCCast<NSMenuItem>(item)) {
204 BrowserWindowController* controller = [window windowController];
205 [menuItem setTitle:[controller titleForFullscreenMenuItem]];
206
207 if (chrome::mac::SupportsSystemFullscreen())
208 [menuItem setAlternate:YES];
209 }
210 break;
211 }
212 case IDC_SHOW_SIGNIN: {
213 Profile* original_profile = browser->profile()->GetOriginalProfile();
214 [AppController updateSigninItem:item
215 shouldShow:enable
216 currentProfile:original_profile];
217 break;
218 }
219 case IDC_BOOKMARK_PAGE: {
220 // Extensions have the ability to hide the bookmark page menu item.
221 // This only affects the bookmark page menu item under the main menu.
222 // The bookmark page menu item under the wrench menu has its
223 // visibility controlled by WrenchMenuModel.
224 bool shouldHide =
225 chrome::ShouldRemoveBookmarkThisPageUI(browser->profile());
226 NSMenuItem* menuItem = base::mac::ObjCCast<NSMenuItem>(item);
227 [menuItem setHidden:shouldHide];
228 break;
229 }
230 case IDC_BOOKMARK_ALL_TABS: {
231 // Extensions have the ability to hide the bookmark all tabs menu
232 // item. This only affects the bookmark page menu item under the main
233 // menu. The bookmark page menu item under the wrench menu has its
234 // visibility controlled by WrenchMenuModel.
235 bool shouldHide =
236 chrome::ShouldRemoveBookmarkOpenPagesUI(browser->profile());
237 NSMenuItem* menuItem = base::mac::ObjCCast<NSMenuItem>(item);
238 [menuItem setHidden:shouldHide];
239 break;
240 }
241 default:
242 // Special handling for the contents of the Text Encoding submenu. On
243 // Mac OS, instead of enabling/disabling the top-level menu item, we
244 // enable/disable the submenu's contents (per Apple's HIG).
245 EncodingMenuController encoding_controller;
246 if (encoding_controller.DoesCommandBelongToEncodingMenu(tag)) {
247 enable &=
248 chrome::IsCommandEnabled(browser, IDC_ENCODING_MENU) ? YES : NO;
tapted 2015/09/03 04:15:38 nit: I don't think the YES : NO is necessary. It's
jackhou1 2015/09/03 06:15:39 Done.
249 }
250 }
251
252 // If the item is toggleable, find its toggle state and
253 // try to update it. This is a little awkward, but the alternative is
254 // to check after a commandDispatch, which seems worse.
255 UpdateToggleStateWithTag(tag, item, window);
256
257 return enable;
258 }
259
260 - (void)commandDispatch:(id)sender window:(NSWindow*)window {
261 DCHECK(sender);
262 // Identify the actual BWC to which the command should be dispatched. It might
tapted 2015/09/03 04:15:38 nit: BWC -> Browser?
jackhou1 2015/09/03 06:15:39 Done.
263 // belong to a background window, yet this controller gets it because it is
tapted 2015/09/03 04:15:38 controller -> dispatcher? (or something?)
jackhou1 2015/09/03 06:15:39 Done.
264 // the foreground window's controller and thus in the responder chain. Some
265 // senders don't have this problem (for example, menus only operate on the
266 // foreground window), so this is only an issue for senders that are part of
267 // windows.
268 NSWindow* targetWindow = window;
269 if ([sender respondsToSelector:@selector(window)])
270 targetWindow = [sender window];
271 Browser* browser = chrome::FindBrowserWithWindow(targetWindow);
272 DCHECK(browser);
273
274 // When system fullscreen is available, it supercedes presentation mode.
275 int tag = [sender tag];
276 if (tag == IDC_PRESENTATION_MODE && chrome::mac::SupportsSystemFullscreen())
277 tag = IDC_FULLSCREEN;
278
279 chrome::ExecuteCommand(browser, tag);
280 }
281
282 - (void)commandDispatchUsingKeyModifiers:(id)sender window:(NSWindow*)window {
283 DCHECK(sender);
284
285 if (![sender isEnabled]) {
286 // This code is reachable e.g. if the user mashes the back button, queuing
287 // up a bunch of events before the button's enabled state is updated:
288 // http://crbug.com/63254
289 return;
290 }
291
292 // See comment above for why we do this.
tapted 2015/09/03 04:15:38 Perhaps a FindBrowserForSender() function in an an
jackhou1 2015/09/03 06:15:39 Done.
293 NSWindow* targetWindow = window;
294 if ([sender respondsToSelector:@selector(window)])
295 targetWindow = [sender window];
296 Browser* browser = chrome::FindBrowserWithWindow(targetWindow);
297 DCHECK(browser);
298
299 NSInteger command = [sender tag];
300 NSUInteger modifierFlags = [[NSApp currentEvent] modifierFlags];
301 if ((command == IDC_RELOAD) &&
302 (modifierFlags & (NSShiftKeyMask | NSControlKeyMask))) {
303 command = IDC_RELOAD_IGNORING_CACHE;
304 // Mask off Shift and Control so they don't affect the disposition below.
305 modifierFlags &= ~(NSShiftKeyMask | NSControlKeyMask);
306 }
307 if (![[sender window] isMainWindow]) {
308 // Remove the command key from the flags, it means "keep the window in
309 // the background" in this case.
310 modifierFlags &= ~NSCommandKeyMask;
311 }
312 chrome::ExecuteCommandWithDisposition(
313 browser, command, ui::WindowOpenDispositionFromNSEventWithFlags(
314 [NSApp currentEvent], modifierFlags));
315 }
316
109 @end // ChromeCommandDispatchDelegate 317 @end // ChromeCommandDispatchDelegate
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698