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 |