Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 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 "ui/base/cocoa/command_dispatcher.h" | 5 #import "ui/base/cocoa/command_dispatcher.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "ui/base/cocoa/cocoa_base_utils.h" | 8 #include "ui/base/cocoa/cocoa_base_utils.h" |
| 9 #import "ui/base/cocoa/user_interface_item_command_handler.h" | |
| 10 | |
| 11 // Expose -[NSWindow hasKeyAppearance], which determines whether the traffic | |
| 12 // lights on the window are "lit". CommandDispatcher uses this property on a | |
| 13 // parent window to decide whether keys and commands should bubble up. | |
| 14 @interface NSWindow (PrivateAPI) | |
| 15 - (BOOL)hasKeyAppearance; | |
| 16 @end | |
| 17 | |
| 18 @interface CommandDispatcher () | |
| 19 // The parent to bubble events to, or nil. | |
| 20 - (NSWindow<CommandDispatchingWindow>*)bubbleParent; | |
| 21 @end | |
| 9 | 22 |
| 10 namespace { | 23 namespace { |
| 11 | 24 |
| 12 // Duplicate the given key event, but changing the associated window. | 25 // Duplicate the given key event, but changing the associated window. |
| 13 NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) { | 26 NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) { |
| 14 NSEventType event_type = [event type]; | 27 NSEventType event_type = [event type]; |
| 15 | 28 |
| 16 // Convert the event's location from the original window's coordinates into | 29 // Convert the event's location from the original window's coordinates into |
| 17 // our own. | 30 // our own. |
| 18 NSPoint location = [event locationInWindow]; | 31 NSPoint location = [event locationInWindow]; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 if ([delegate_ eventHandledByExtensionCommand:event | 79 if ([delegate_ eventHandledByExtensionCommand:event |
| 67 isRedispatch:redispatchingEvent_]) { | 80 isRedispatch:redispatchingEvent_]) { |
| 68 return YES; | 81 return YES; |
| 69 } | 82 } |
| 70 | 83 |
| 71 if (redispatchingEvent_) | 84 if (redispatchingEvent_) |
| 72 return NO; | 85 return NO; |
| 73 | 86 |
| 74 // Give a CommandDispatcherTarget (e.g. a web site) a chance to handle the | 87 // Give a CommandDispatcherTarget (e.g. a web site) a chance to handle the |
| 75 // event. If it doesn't want to handle it, it will call us back with | 88 // event. If it doesn't want to handle it, it will call us back with |
| 76 // -redispatchKeyEvent:. | 89 // -redispatchKeyEvent:. Only allow this behavior when dispatching key events |
| 77 NSResponder* r = [owner_ firstResponder]; | 90 // on the key window. |
| 78 if ([r conformsToProtocol:@protocol(CommandDispatcherTarget)]) | 91 if ([owner_ isKeyWindow]) { |
| 79 return [r performKeyEquivalent:event]; | 92 NSResponder* r = [owner_ firstResponder]; |
| 93 if ([r conformsToProtocol:@protocol(CommandDispatcherTarget)]) | |
| 94 return [r performKeyEquivalent:event]; | |
| 95 } | |
| 80 | 96 |
| 81 if ([delegate_ prePerformKeyEquivalent:event window:owner_]) | 97 if ([delegate_ prePerformKeyEquivalent:event window:owner_]) |
| 82 return YES; | 98 return YES; |
| 83 | 99 |
| 84 if ([owner_ defaultPerformKeyEquivalent:event]) | 100 if ([owner_ defaultPerformKeyEquivalent:event]) |
| 85 return YES; | 101 return YES; |
| 86 | 102 |
| 87 return [delegate_ postPerformKeyEquivalent:event window:owner_]; | 103 if ([delegate_ postPerformKeyEquivalent:event window:owner_]) |
| 104 return YES; | |
| 105 | |
| 106 // Allow commands to "bubble up" to CommandDispatchers in parent windows, if | |
| 107 // they were not handled here. | |
| 108 return [[self bubbleParent] performKeyEquivalent:event]; | |
| 109 } | |
| 110 | |
| 111 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item | |
| 112 forHandler:(id<UserInterfaceItemCommandHandler>)handler { | |
| 113 // Since this class implements these selectors, |super| will always say they | |
| 114 // are enabled. Only use [super] to validate other selectors. If there is no | |
| 115 // command handler, defer to AppController. | |
| 116 if ([item action] == @selector(commandDispatch:) || | |
| 117 [item action] == @selector(commandDispatchUsingKeyModifiers:)) { | |
| 118 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)
| |
| 119 return [handler validateUserInterfaceItem:item window:owner_]; | |
| 120 | |
| 121 id appController = [NSApp delegate]; | |
| 122 DCHECK([appController | |
| 123 conformsToProtocol:@protocol(NSUserInterfaceValidations)]); | |
| 124 if ([appController validateUserInterfaceItem:item]) | |
| 125 return YES; | |
| 126 } | |
| 127 | |
| 128 if ([owner_ defaultValidateUserInterfaceItem:item]) | |
| 129 return YES; | |
| 130 | |
| 131 return [[self bubbleParent] validateUserInterfaceItem:item]; | |
| 88 } | 132 } |
| 89 | 133 |
| 90 - (BOOL)redispatchKeyEvent:(NSEvent*)event { | 134 - (BOOL)redispatchKeyEvent:(NSEvent*)event { |
| 91 DCHECK(event); | 135 DCHECK(event); |
| 92 NSEventType eventType = [event type]; | 136 NSEventType eventType = [event type]; |
| 93 if (eventType != NSKeyDown && eventType != NSKeyUp && | 137 if (eventType != NSKeyDown && eventType != NSKeyUp && |
| 94 eventType != NSFlagsChanged) { | 138 eventType != NSFlagsChanged) { |
| 95 NOTREACHED(); | 139 NOTREACHED(); |
| 96 return YES; // Pretend it's been handled in an effort to limit damage. | 140 return YES; // Pretend it's been handled in an effort to limit damage. |
| 97 } | 141 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 121 if (redispatchingEvent_) { | 165 if (redispatchingEvent_) { |
| 122 // If we get here, then the event was not handled by NSApplication. | 166 // If we get here, then the event was not handled by NSApplication. |
| 123 eventHandled_ = NO; | 167 eventHandled_ = NO; |
| 124 // Return YES to stop native -sendEvent handling. | 168 // Return YES to stop native -sendEvent handling. |
| 125 return YES; | 169 return YES; |
| 126 } | 170 } |
| 127 | 171 |
| 128 return NO; | 172 return NO; |
| 129 } | 173 } |
| 130 | 174 |
| 175 - (void)dispatch:(id)sender | |
| 176 forHandler:(id<UserInterfaceItemCommandHandler>)handler { | |
|
tapted
2017/02/01 10:35:01
I might be able to store this in the CommandDispat
| |
| 177 if (handler) | |
| 178 [handler commandDispatch:sender window:owner_]; | |
| 179 else | |
| 180 [[self bubbleParent] commandDispatch:sender]; | |
| 181 } | |
| 182 | |
| 183 - (void)dispatchUsingKeyModifiers:(id)sender | |
| 184 forHandler:(id<UserInterfaceItemCommandHandler>)handler { | |
| 185 if (handler) | |
| 186 [handler commandDispatchUsingKeyModifiers:sender window:owner_]; | |
| 187 else | |
| 188 [[self bubbleParent] commandDispatchUsingKeyModifiers:sender]; | |
| 189 } | |
| 190 | |
| 191 - (NSWindow<CommandDispatchingWindow>*)bubbleParent { | |
| 192 NSWindow* parent = [owner_ parentWindow]; | |
| 193 if (parent && [parent hasKeyAppearance] && | |
| 194 [parent conformsToProtocol:@protocol(CommandDispatchingWindow)]) | |
| 195 return static_cast<NSWindow<CommandDispatchingWindow>*>(parent); | |
| 196 return nil; | |
| 197 } | |
| 198 | |
| 131 @end | 199 @end |
| OLD | NEW |