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

Side by Side Diff: ui/base/cocoa/command_dispatcher.mm

Issue 1255783002: [Mac] Factor out keyboard shortcut handling from ChromeEventProcessingWindow. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@execute
Patch Set: Minor comment fix. 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
« no previous file with comments | « ui/base/cocoa/command_dispatcher.h ('k') | ui/base/ui_base.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 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_event_processing_window.h" 5 #import "ui/base/cocoa/command_dispatcher.h"
6 6
7 #include "base/logging.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"
13 #import "content/public/browser/render_widget_host_view_mac_base.h"
14 8
15 namespace { 9 namespace {
16 10
17 // Type of functions listed in global_keyboard_shortcuts_mac.h.
18 typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int, unichar);
19
20 // If the event is for a Browser window, and the key combination has an
21 // associated command, execute the command.
22 bool HandleExtraKeyboardShortcut(
23 NSEvent* event,
24 NSWindow* window,
25 KeyToCommandMapper command_for_keyboard_shortcut) {
26 // Extract info from |event|.
27 NSUInteger modifers = [event modifierFlags];
28 const bool command = modifers & NSCommandKeyMask;
29 const bool shift = modifers & NSShiftKeyMask;
30 const bool control = modifers & NSControlKeyMask;
31 const bool option = modifers & NSAlternateKeyMask;
32 const int key_code = [event keyCode];
33 const unichar key_char = KeyCharacterForEvent(event);
34
35 int cmd = command_for_keyboard_shortcut(command, shift, control, option,
36 key_code, key_char);
37
38 if (cmd == -1)
39 return false;
40
41 // Only handle event if this is a browser window.
42 Browser* browser = chrome::FindBrowserWithWindow(window);
43 if (!browser)
44 return false;
45
46 chrome::ExecuteCommand(browser, cmd);
47 return true;
48 }
49
50 bool HandleExtraWindowKeyboardShortcut(NSEvent* event, NSWindow* window) {
51 return HandleExtraKeyboardShortcut(event, window,
52 CommandForWindowKeyboardShortcut);
53 }
54
55 bool HandleDelayedWindowKeyboardShortcut(NSEvent* event, NSWindow* window) {
56 return HandleExtraKeyboardShortcut(event, window,
57 CommandForDelayedWindowKeyboardShortcut);
58 }
59
60 bool HandleExtraBrowserKeyboardShortcut(NSEvent* event, NSWindow* window) {
61 return HandleExtraKeyboardShortcut(event, window,
62 CommandForBrowserKeyboardShortcut);
63 }
64
65 // Duplicate the given key event, but changing the associated window. 11 // Duplicate the given key event, but changing the associated window.
66 NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) { 12 NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) {
67 NSEventType event_type = [event type]; 13 NSEventType event_type = [event type];
68 14
69 // Convert the event's location from the original window's coordinates into 15 // Convert the event's location from the original window's coordinates into
70 // our own. 16 // our own.
71 NSPoint location = [event locationInWindow]; 17 NSPoint location = [event locationInWindow];
72 location = [[event window] convertBaseToScreen:location]; 18 location = [[event window] convertBaseToScreen:location];
73 location = [window convertScreenToBase:location]; 19 location = [window convertScreenToBase:location];
74 20
(...skipping 17 matching lines...) Expand all
92 windowNumber:[window windowNumber] 38 windowNumber:[window windowNumber]
93 context:nil 39 context:nil
94 characters:characters 40 characters:characters
95 charactersIgnoringModifiers:charactors_ignoring_modifiers 41 charactersIgnoringModifiers:charactors_ignoring_modifiers
96 isARepeat:is_a_repeat 42 isARepeat:is_a_repeat
97 keyCode:[event keyCode]]; 43 keyCode:[event keyCode]];
98 } 44 }
99 45
100 } // namespace 46 } // namespace
101 47
102 @implementation ChromeEventProcessingWindow 48 @implementation CommandDispatcher {
49 @private
50 BOOL redispatchingEvent_;
51 BOOL eventHandled_;
52 NSWindow<CommandDispatchingWindow>* owner_; // Weak, owns us.
53 }
103 54
104 - (BOOL)handleExtraKeyboardShortcut:(NSEvent*)event { 55 @synthesize delegate = delegate_;
105 return HandleExtraBrowserKeyboardShortcut(event, self) || 56
106 HandleExtraWindowKeyboardShortcut(event, self) || 57 - (instancetype)initWithOwner:(NSWindow<CommandDispatchingWindow>*)owner {
107 HandleDelayedWindowKeyboardShortcut(event, self); 58 if ((self = [super init])) {
59 owner_ = owner;
60 }
61 return self;
108 } 62 }
109 63
110 - (BOOL)performKeyEquivalent:(NSEvent*)event { 64 - (BOOL)performKeyEquivalent:(NSEvent*)event {
111 // Some extension commands have higher priority than web content, and some 65 if ([delegate_ eventHandledByExtensionCommand:event
112 // have lower priority. Regardless of whether the event is being 66 isRedispatch:redispatchingEvent_]) {
113 // redispatched, let the extension system try to handle the event. 67 return YES;
114 NSWindow* window = event.window;
115 if (window) {
116 BrowserWindowController* controller = [window windowController];
117 if ([controller respondsToSelector:@selector(handledByExtensionCommand:
118 priority:)]) {
119 ui::AcceleratorManager::HandlerPriority priority =
120 redispatchingEvent_ ? ui::AcceleratorManager::kNormalPriority
121 : ui::AcceleratorManager::kHighPriority;
122 if ([controller handledByExtensionCommand:event priority:priority])
123 return YES;
124 }
125 } 68 }
126 69
127 if (redispatchingEvent_) 70 if (redispatchingEvent_)
128 return NO; 71 return NO;
129 72
130 // Give the web site a chance to handle the event. If it doesn't want to 73 // Give a CommandDispatcherTarget (e.g. a web site) a chance to handle the
131 // handle it, it will call us back with one of the |handle*| methods above. 74 // event. If it doesn't want to handle it, it will call us back with one of
132 NSResponder* r = [self firstResponder]; 75 // the |handle*| methods above.
Robert Sesek 2015/08/28 19:25:32 No more handle methods.
jackhou 2015/08/31 07:26:18 Done.
133 if ([r conformsToProtocol:@protocol(RenderWidgetHostViewMacBase)]) 76 NSResponder* r = [owner_ firstResponder];
77 if ([r conformsToProtocol:@protocol(CommandDispatcherTarget)])
134 return [r performKeyEquivalent:event]; 78 return [r performKeyEquivalent:event];
135 79
136 // Handle per-window shortcuts like cmd-1, but do not handle browser-level 80 if ([delegate_ prePerformKeyEquivalent:event window:owner_])
137 // shortcuts like cmd-left (else, cmd-left would do history navigation even
138 // if e.g. the Omnibox has focus).
139 if (HandleExtraWindowKeyboardShortcut(event, self))
140 return YES; 81 return YES;
141 82
142 if ([super performKeyEquivalent:event]) 83 if ([owner_ defaultPerformKeyEquivalent:event])
143 return YES; 84 return YES;
144 85
145 // Handle per-window shortcuts like Esc after giving everybody else a chance 86 return [delegate_ postPerformKeyEquivalent:event window:owner_];
146 // to handle them
147 return HandleDelayedWindowKeyboardShortcut(event, self);
148 } 87 }
149 88
150 - (BOOL)redispatchKeyEvent:(NSEvent*)event { 89 - (BOOL)redispatchKeyEvent:(NSEvent*)event {
151 DCHECK(event); 90 DCHECK(event);
152 NSEventType eventType = [event type]; 91 NSEventType eventType = [event type];
153 if (eventType != NSKeyDown && 92 if (eventType != NSKeyDown && eventType != NSKeyUp &&
154 eventType != NSKeyUp &&
155 eventType != NSFlagsChanged) { 93 eventType != NSFlagsChanged) {
156 NOTREACHED(); 94 NOTREACHED();
157 return YES; // Pretend it's been handled in an effort to limit damage. 95 return YES; // Pretend it's been handled in an effort to limit damage.
158 } 96 }
159 97
160 // Ordinarily, the event's window should be this window. However, when 98 // Ordinarily, the event's window should be |owner_|. However, when switching
161 // switching between normal and fullscreen mode, we switch out the window, and 99 // between normal and fullscreen mode, we switch out the window, and the
162 // the event's window might be the previous window (or even an earlier one if 100 // event's window might be the previous window (or even an earlier one if the
163 // the renderer is running slowly and several mode switches occur). In this 101 // renderer is running slowly and several mode switches occur). In this rare
164 // rare case, we synthesize a new key event so that its associate window 102 // case, we synthesize a new key event so that its associate window (number)
165 // (number) is our own. 103 // is our |owner_|'s.
166 if ([event window] != self) 104 if ([event window] != owner_)
167 event = KeyEventForWindow(self, event); 105 event = KeyEventForWindow(owner_, event);
168 106
169 // Redispatch the event. 107 // Redispatch the event.
170 eventHandled_ = YES; 108 eventHandled_ = YES;
171 redispatchingEvent_ = YES; 109 redispatchingEvent_ = YES;
172 [NSApp sendEvent:event]; 110 [NSApp sendEvent:event];
173 redispatchingEvent_ = NO; 111 redispatchingEvent_ = NO;
174 112
175 // If the event was not handled by [NSApp sendEvent:], the sendEvent: 113 // If the event was not handled by [NSApp sendEvent:], the sendEvent:
176 // method below will be called, and because |redispatchingEvent_| is YES, 114 // method below will be called, and because |redispatchingEvent_| is YES,
177 // |eventHandled_| will be set to NO. 115 // |eventHandled_| will be set to NO.
178 return eventHandled_; 116 return eventHandled_;
179 } 117 }
180 118
181 - (void)sendEvent:(NSEvent*)event { 119 - (BOOL)preSendEvent:(NSEvent*)event {
182 if (!redispatchingEvent_) 120 if (redispatchingEvent_) {
183 [super sendEvent:event]; 121 // If we get here, then the event was not handled by NSApplication.
184 else
185 eventHandled_ = NO; 122 eventHandled_ = NO;
123 // Return YES to stop native -sendEvent handling.
124 return YES;
125 }
126
127 return NO;
186 } 128 }
187 129
188 @end // ChromeEventProcessingWindow 130 @end
OLDNEW
« no previous file with comments | « ui/base/cocoa/command_dispatcher.h ('k') | ui/base/ui_base.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698