Chromium Code Reviews| Index: ui/base/cocoa/command_dispatcher.mm |
| diff --git a/ui/base/cocoa/command_dispatcher.mm b/ui/base/cocoa/command_dispatcher.mm |
| index 46a351b4ce8c09b399011bf36313ac34db9fb6ec..e6660c3871ad94a7b9a0f997195fa3b4d2b4bacb 100644 |
| --- a/ui/base/cocoa/command_dispatcher.mm |
| +++ b/ui/base/cocoa/command_dispatcher.mm |
| @@ -6,6 +6,19 @@ |
| #include "base/logging.h" |
| #include "ui/base/cocoa/cocoa_base_utils.h" |
| +#import "ui/base/cocoa/user_interface_item_command_handler.h" |
| + |
| +// Expose -[NSWindow hasKeyAppearance], which determines whether the traffic |
| +// lights on the window are "lit". CommandDispatcher uses this property on a |
| +// parent window to decide whether keys and commands should bubble up. |
| +@interface NSWindow (PrivateAPI) |
| +- (BOOL)hasKeyAppearance; |
| +@end |
| + |
| +@interface CommandDispatcher () |
| +// The parent to bubble events to, or nil. |
| +- (NSWindow<CommandDispatchingWindow>*)bubbleParent; |
| +@end |
| namespace { |
| @@ -73,10 +86,13 @@ NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) { |
| // Give a CommandDispatcherTarget (e.g. a web site) a chance to handle the |
| // event. If it doesn't want to handle it, it will call us back with |
| - // -redispatchKeyEvent:. |
| - NSResponder* r = [owner_ firstResponder]; |
| - if ([r conformsToProtocol:@protocol(CommandDispatcherTarget)]) |
| - return [r performKeyEquivalent:event]; |
| + // -redispatchKeyEvent:. Only allow this behavior when dispatching key events |
| + // on the key window. |
| + if ([owner_ isKeyWindow]) { |
| + NSResponder* r = [owner_ firstResponder]; |
| + if ([r conformsToProtocol:@protocol(CommandDispatcherTarget)]) |
| + return [r performKeyEquivalent:event]; |
| + } |
| if ([delegate_ prePerformKeyEquivalent:event window:owner_]) |
| return YES; |
| @@ -84,7 +100,35 @@ NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) { |
| if ([owner_ defaultPerformKeyEquivalent:event]) |
| return YES; |
| - return [delegate_ postPerformKeyEquivalent:event window:owner_]; |
| + if ([delegate_ postPerformKeyEquivalent:event window:owner_]) |
| + return YES; |
| + |
| + // Allow commands to "bubble up" to CommandDispatchers in parent windows, if |
| + // they were not handled here. |
| + return [[self bubbleParent] performKeyEquivalent:event]; |
| +} |
| + |
| +- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item |
| + forHandler:(id<UserInterfaceItemCommandHandler>)handler { |
| + // Since this class implements these selectors, |super| will always say they |
| + // are enabled. Only use [super] to validate other selectors. If there is no |
| + // command handler, defer to AppController. |
| + if ([item action] == @selector(commandDispatch:) || |
| + [item action] == @selector(commandDispatchUsingKeyModifiers:)) { |
| + if (handler) |
|
Robert Sesek
2017/02/01 14:27:20
Why the discrepancy in handling the result of vali
tapted
2017/02/01 23:36:01
The problem is that (unlike performKeyEquivalent)
|
| + return [handler validateUserInterfaceItem:item window:owner_]; |
| + |
| + id appController = [NSApp delegate]; |
| + DCHECK([appController |
| + conformsToProtocol:@protocol(NSUserInterfaceValidations)]); |
| + if ([appController validateUserInterfaceItem:item]) |
| + return YES; |
| + } |
| + |
| + if ([owner_ defaultValidateUserInterfaceItem:item]) |
| + return YES; |
| + |
| + return [[self bubbleParent] validateUserInterfaceItem:item]; |
| } |
| - (BOOL)redispatchKeyEvent:(NSEvent*)event { |
| @@ -128,4 +172,28 @@ NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) { |
| return NO; |
| } |
| +- (void)dispatch:(id)sender |
| + forHandler:(id<UserInterfaceItemCommandHandler>)handler { |
|
tapted
2017/02/01 10:35:01
I might be able to store this in the CommandDispat
|
| + if (handler) |
| + [handler commandDispatch:sender window:owner_]; |
| + else |
| + [[self bubbleParent] commandDispatch:sender]; |
| +} |
| + |
| +- (void)dispatchUsingKeyModifiers:(id)sender |
| + forHandler:(id<UserInterfaceItemCommandHandler>)handler { |
| + if (handler) |
| + [handler commandDispatchUsingKeyModifiers:sender window:owner_]; |
| + else |
| + [[self bubbleParent] commandDispatchUsingKeyModifiers:sender]; |
| +} |
| + |
| +- (NSWindow<CommandDispatchingWindow>*)bubbleParent { |
| + NSWindow* parent = [owner_ parentWindow]; |
| + if (parent && [parent hasKeyAppearance] && |
| + [parent conformsToProtocol:@protocol(CommandDispatchingWindow)]) |
| + return static_cast<NSWindow<CommandDispatchingWindow>*>(parent); |
| + return nil; |
| +} |
| + |
| @end |