Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / chrome_command_dispatcher_delegate.mm
blob6d3cd88777924595c3554a6767da7a36d40e2e66
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
3 // found in the LICENSE file.
5 #import "chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.h"
7 #include "base/logging.h"
8 #include "chrome/browser/global_keyboard_shortcuts_mac.h"
9 #include "chrome/browser/ui/browser_commands.h"
10 #include "chrome/browser/ui/browser_finder.h"
11 #import "chrome/browser/ui/cocoa/browser_window_controller_private.h"
12 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
14 namespace {
16 // Type of functions listed in global_keyboard_shortcuts_mac.h.
17 typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int, unichar);
19 // If the event is for a Browser window, and the key combination has an
20 // associated command, execute the command.
21 bool HandleExtraKeyboardShortcut(
22     NSEvent* event,
23     NSWindow* window,
24     KeyToCommandMapper command_for_keyboard_shortcut) {
25   // Extract info from |event|.
26   NSUInteger modifers = [event modifierFlags];
27   const bool command = modifers & NSCommandKeyMask;
28   const bool shift = modifers & NSShiftKeyMask;
29   const bool control = modifers & NSControlKeyMask;
30   const bool option = modifers & NSAlternateKeyMask;
31   const int key_code = [event keyCode];
32   const unichar key_char = KeyCharacterForEvent(event);
34   int cmd = command_for_keyboard_shortcut(command, shift, control, option,
35                                           key_code, key_char);
37   if (cmd == -1)
38     return false;
40   // Only handle event if this is a browser window.
41   Browser* browser = chrome::FindBrowserWithWindow(window);
42   if (!browser)
43     return false;
45   chrome::ExecuteCommand(browser, cmd);
46   return true;
49 bool HandleExtraWindowKeyboardShortcut(NSEvent* event, NSWindow* window) {
50   return HandleExtraKeyboardShortcut(event, window,
51                                      CommandForWindowKeyboardShortcut);
54 bool HandleDelayedWindowKeyboardShortcut(NSEvent* event, NSWindow* window) {
55   return HandleExtraKeyboardShortcut(event, window,
56                                      CommandForDelayedWindowKeyboardShortcut);
59 bool HandleExtraBrowserKeyboardShortcut(NSEvent* event, NSWindow* window) {
60   return HandleExtraKeyboardShortcut(event, window,
61                                      CommandForBrowserKeyboardShortcut);
64 }  // namespace
66 @implementation ChromeCommandDispatcherDelegate
68 - (BOOL)handleExtraKeyboardShortcut:(NSEvent*)event window:(NSWindow*)window {
69   return HandleExtraBrowserKeyboardShortcut(event, window) ||
70          HandleExtraWindowKeyboardShortcut(event, window) ||
71          HandleDelayedWindowKeyboardShortcut(event, window);
74 - (BOOL)eventHandledByExtensionCommand:(NSEvent*)event
75                           isRedispatch:(BOOL)isRedispatch {
76   // Some extension commands have higher priority than web content, and some
77   // have lower priority. Regardless of whether the event is being redispatched,
78   // let the extension system try to handle the event. In case this is a
79   // redispatched event, [event window] gives the correct window.
80   if ([event window]) {
81     BrowserWindowController* controller = [[event window] windowController];
82     // |controller| is only set in Cocoa. In toolkit-views extension commands
83     // are handled by BrowserView.
84     if ([controller respondsToSelector:@selector(handledByExtensionCommand:
85                                                                   priority:)]) {
86       ui::AcceleratorManager::HandlerPriority priority =
87           isRedispatch ? ui::AcceleratorManager::kNormalPriority
88                        : ui::AcceleratorManager::kHighPriority;
89       if ([controller handledByExtensionCommand:event priority:priority])
90         return YES;
91     }
92   }
93   return NO;
96 - (BOOL)prePerformKeyEquivalent:(NSEvent*)event window:(NSWindow*)window {
97   // Handle per-window shortcuts like cmd-1, but do not handle browser-level
98   // shortcuts like cmd-left (else, cmd-left would do history navigation even
99   // if e.g. the Omnibox has focus).
100   return HandleExtraWindowKeyboardShortcut(event, window);
103 - (BOOL)postPerformKeyEquivalent:(NSEvent*)event window:(NSWindow*)window {
104   // Handle per-window shortcuts like Esc after giving everybody else a chance
105   // to handle them
106   return HandleDelayedWindowKeyboardShortcut(event, window);
109 @end  // ChromeCommandDispatchDelegate