Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / chrome_event_processing_window.mm
blob43d0feb3e9e780e7edcab49776bfd9e51770bc2d
1 // Copyright (c) 2012 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_event_processing_window.h"
7 #include "base/logging.h"
8 #import "chrome/browser/ui/cocoa/browser_command_executor.h"
9 #import "chrome/browser/ui/cocoa/browser_window_controller_private.h"
10 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
11 #include "chrome/browser/global_keyboard_shortcuts_mac.h"
12 #import "content/public/browser/render_widget_host_view_mac_base.h"
14 typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int, unichar);
16 @interface ChromeEventProcessingWindow ()
17 // Duplicate the given key event, but changing the associated window.
18 - (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event;
19 @end
21 @implementation ChromeEventProcessingWindow
23 - (BOOL)handleExtraKeyboardShortcut:(NSEvent*)event fromTable:
24     (KeyToCommandMapper)commandForKeyboardShortcut {
25   // Extract info from |event|.
26   NSUInteger modifers = [event modifierFlags];
27   const bool cmdKey = modifers & NSCommandKeyMask;
28   const bool shiftKey = modifers & NSShiftKeyMask;
29   const bool cntrlKey = modifers & NSControlKeyMask;
30   const bool optKey = modifers & NSAlternateKeyMask;
31   const unichar keyCode = [event keyCode];
32   const unichar keyChar = KeyCharacterForEvent(event);
34   int cmdNum = commandForKeyboardShortcut(cmdKey, shiftKey, cntrlKey, optKey,
35       keyCode, keyChar);
37   if (cmdNum != -1) {
38     id executor = [self delegate];
39     // A bit of sanity.
40     DCHECK([executor conformsToProtocol:@protocol(BrowserCommandExecutor)]);
41     DCHECK([executor respondsToSelector:@selector(executeCommand:)]);
42     [executor executeCommand:cmdNum];
43     return YES;
44   }
45   return NO;
48 - (BOOL)handleExtraWindowKeyboardShortcut:(NSEvent*)event {
49   return [self handleExtraKeyboardShortcut:event
50                                  fromTable:CommandForWindowKeyboardShortcut];
53 - (BOOL)handleDelayedWindowKeyboardShortcut:(NSEvent*)event {
54   return [self handleExtraKeyboardShortcut:event
55                          fromTable:CommandForDelayedWindowKeyboardShortcut];
58 - (BOOL)handleExtraBrowserKeyboardShortcut:(NSEvent*)event {
59   return [self handleExtraKeyboardShortcut:event
60                                  fromTable:CommandForBrowserKeyboardShortcut];
63 - (BOOL)performKeyEquivalent:(NSEvent*)event {
64   // Some extension commands have higher priority than web content, and some
65   // have lower priority. Regardless of whether the event is being
66   // redispatched, let the extension system try to handle the event.
67   NSWindow* window = event.window;
68   if (window) {
69     BrowserWindowController* controller = [window windowController];
70     if ([controller respondsToSelector:@selector(handledByExtensionCommand:
71                                                                   priority:)]) {
72       ui::AcceleratorManager::HandlerPriority priority =
73           redispatchingEvent_ ? ui::AcceleratorManager::kNormalPriority
74                               : ui::AcceleratorManager::kHighPriority;
75       if ([controller handledByExtensionCommand:event priority:priority])
76         return YES;
77     }
78   }
80   if (redispatchingEvent_)
81     return NO;
83   // Give the web site a chance to handle the event. If it doesn't want to
84   // handle it, it will call us back with one of the |handle*| methods above.
85   NSResponder* r = [self firstResponder];
86   if ([r conformsToProtocol:@protocol(RenderWidgetHostViewMacBase)])
87     return [r performKeyEquivalent:event];
89   // If the delegate does not implement the BrowserCommandExecutor protocol,
90   // then we don't need to handle browser specific shortcut keys.
91   if (![[self delegate] conformsToProtocol:@protocol(BrowserCommandExecutor)])
92     return [super performKeyEquivalent:event];
94   // Handle per-window shortcuts like cmd-1, but do not handle browser-level
95   // shortcuts like cmd-left (else, cmd-left would do history navigation even
96   // if e.g. the Omnibox has focus).
97   if ([self handleExtraWindowKeyboardShortcut:event])
98     return YES;
100   if ([super performKeyEquivalent:event])
101     return YES;
103   // Handle per-window shortcuts like Esc after giving everybody else a chance
104   // to handle them
105   return [self handleDelayedWindowKeyboardShortcut:event];
108 - (BOOL)redispatchKeyEvent:(NSEvent*)event {
109   DCHECK(event);
110   NSEventType eventType = [event type];
111   if (eventType != NSKeyDown &&
112       eventType != NSKeyUp &&
113       eventType != NSFlagsChanged) {
114     NOTREACHED();
115     return YES;  // Pretend it's been handled in an effort to limit damage.
116   }
118   // Ordinarily, the event's window should be this window. However, when
119   // switching between normal and fullscreen mode, we switch out the window, and
120   // the event's window might be the previous window (or even an earlier one if
121   // the renderer is running slowly and several mode switches occur). In this
122   // rare case, we synthesize a new key event so that its associate window
123   // (number) is our own.
124   if ([event window] != self)
125     event = [self keyEventForWindow:self fromKeyEvent:event];
127   // Redispatch the event.
128   eventHandled_ = YES;
129   redispatchingEvent_ = YES;
130   [NSApp sendEvent:event];
131   redispatchingEvent_ = NO;
133   // If the event was not handled by [NSApp sendEvent:], the sendEvent:
134   // method below will be called, and because |redispatchingEvent_| is YES,
135   // |eventHandled_| will be set to NO.
136   return eventHandled_;
139 - (void)sendEvent:(NSEvent*)event {
140   if (!redispatchingEvent_)
141     [super sendEvent:event];
142   else
143     eventHandled_ = NO;
146 - (NSEvent*)keyEventForWindow:(NSWindow*)window fromKeyEvent:(NSEvent*)event {
147   NSEventType eventType = [event type];
149   // Convert the event's location from the original window's coordinates into
150   // our own.
151   NSPoint eventLoc = [event locationInWindow];
152   eventLoc = [[event window] convertBaseToScreen:eventLoc];
153   eventLoc = [self convertScreenToBase:eventLoc];
155   // Various things *only* apply to key down/up.
156   BOOL eventIsARepeat = NO;
157   NSString* eventCharacters = nil;
158   NSString* eventUnmodCharacters = nil;
159   if (eventType == NSKeyDown || eventType == NSKeyUp) {
160     eventIsARepeat = [event isARepeat];
161     eventCharacters = [event characters];
162     eventUnmodCharacters = [event charactersIgnoringModifiers];
163   }
165   // This synthesis may be slightly imperfect: we provide nil for the context,
166   // since I (viettrungluu) am sceptical that putting in the original context
167   // (if one is given) is valid.
168   return [NSEvent keyEventWithType:eventType
169                           location:eventLoc
170                      modifierFlags:[event modifierFlags]
171                          timestamp:[event timestamp]
172                       windowNumber:[window windowNumber]
173                            context:nil
174                         characters:eventCharacters
175        charactersIgnoringModifiers:eventUnmodCharacters
176                          isARepeat:eventIsARepeat
177                            keyCode:[event keyCode]];
180 @end  // ChromeEventProcessingWindow