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

Unified 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: Address comments. Created 5 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: ui/base/cocoa/command_dispatcher.mm
diff --git a/ui/base/cocoa/command_dispatcher.mm b/ui/base/cocoa/command_dispatcher.mm
new file mode 100644
index 0000000000000000000000000000000000000000..86c368659286728ce1a3422f626ec0c227d66b8b
--- /dev/null
+++ b/ui/base/cocoa/command_dispatcher.mm
@@ -0,0 +1,125 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
tapted 2015/08/26 03:04:49 Maybe we can even trick `git cl upload` to diff th
jackhou1 2015/08/26 06:24:43 Done.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/base/cocoa/command_dispatcher.h"
+
+#include "base/logging.h"
+
+namespace {
+
+// Duplicate the given key event, but changing the associated window.
+NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) {
+ NSEventType event_type = [event type];
+
+ // Convert the event's location from the original window's coordinates into
+ // our own.
+ NSPoint location = [event locationInWindow];
+ location = [[event window] convertBaseToScreen:location];
+ location = [window convertScreenToBase:location];
+
+ // Various things *only* apply to key down/up.
+ bool is_a_repeat = false;
+ NSString* characters = nil;
+ NSString* charactors_ignoring_modifiers = nil;
+ if (event_type == NSKeyDown || event_type == NSKeyUp) {
+ is_a_repeat = [event isARepeat];
+ characters = [event characters];
+ charactors_ignoring_modifiers = [event charactersIgnoringModifiers];
+ }
+
+ // This synthesis may be slightly imperfect: we provide nil for the context,
+ // since I (viettrungluu) am sceptical that putting in the original context
+ // (if one is given) is valid.
+ return [NSEvent keyEventWithType:event_type
+ location:location
+ modifierFlags:[event modifierFlags]
+ timestamp:[event timestamp]
+ windowNumber:[window windowNumber]
+ context:nil
+ characters:characters
+ charactersIgnoringModifiers:charactors_ignoring_modifiers
+ isARepeat:is_a_repeat
+ keyCode:[event keyCode]];
+}
+
+} // namespace
+
+@implementation CommandDispatcherImpl
+
+- (id)initWithOwner:(NSWindow<CommandDispatcher>*)owner {
+ if ((self = [super init])) {
+ owner_ = owner;
+ }
+ return self;
+}
+
+- (void)setDelegate:(id<CommandDispatcherDelegate>)delegate {
+ delegate_.reset([delegate retain]);
+}
+
+- (BOOL)performKeyEquivalent:(NSEvent*)event {
+ if ([delegate_ handledByExtensionCommand:event
+ isRedispatch:redispatchingEvent_])
+ return YES;
+
+ if (redispatchingEvent_)
+ return NO;
+
+ // Give the web site a chance to handle the event. If it doesn't want to
tapted 2015/08/26 03:04:49 the web site -> a CommandDispatcherTarget (e.g. a
jackhou1 2015/08/26 06:24:43 Done.
+ // handle it, it will call us back with one of the |handle*| methods above.
+ NSResponder* r = [owner_ firstResponder];
+ if ([r conformsToProtocol:@protocol(CommandDispatcherTarget)])
+ return [r performKeyEquivalent:event];
+
+ if ([delegate_ prePerformKeyEquivalent:event window:owner_])
+ return YES;
+
+ if ([owner_ defaultPerformKeyEquivalent:event])
+ return YES;
+
+ return [delegate_ postPerformKeyEquivalent:event window:owner_];
+}
+
+- (BOOL)redispatchKeyEvent:(NSEvent*)event {
+ DCHECK(event);
+ NSEventType eventType = [event type];
+ if (eventType != NSKeyDown && eventType != NSKeyUp &&
+ eventType != NSFlagsChanged) {
+ NOTREACHED();
+ return YES; // Pretend it's been handled in an effort to limit damage.
+ }
+
+ // Ordinarily, the event's window should be this window. However, when
tapted 2015/08/26 03:04:49 this window -> |owner_|
jackhou1 2015/08/26 06:24:43 Done.
+ // switching between normal and fullscreen mode, we switch out the window, and
+ // the event's window might be the previous window (or even an earlier one if
+ // the renderer is running slowly and several mode switches occur). In this
+ // rare case, we synthesize a new key event so that its associate window
+ // (number) is our own.
tapted 2015/08/26 03:04:49 our own -> our |owner_|'s
jackhou1 2015/08/26 06:24:43 Done.
+ if ([event window] != owner_)
+ event = KeyEventForWindow(owner_, event);
+
+ // Redispatch the event.
+ eventHandled_ = YES;
+ redispatchingEvent_ = YES;
+ [NSApp sendEvent:event];
+ redispatchingEvent_ = NO;
+
+ // If the event was not handled by [NSApp sendEvent:], the sendEvent:
+ // method below will be called, and because |redispatchingEvent_| is YES,
+ // |eventHandled_| will be set to NO.
+ return eventHandled_;
+}
+
+- (BOOL)preSendEvent:(NSEvent*)event {
+ if (redispatchingEvent_) {
+ // If we get here, then the event was not handled by NSApplication.
+ eventHandled_ = NO;
+ // Return YES to stop native -sendEvent handling.
+ return YES;
+ }
+
+ return NO;
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698