summaryrefslogtreecommitdiff
path: root/chromium/ui/base/cocoa/command_dispatcher.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/base/cocoa/command_dispatcher.mm')
-rw-r--r--chromium/ui/base/cocoa/command_dispatcher.mm49
1 files changed, 45 insertions, 4 deletions
diff --git a/chromium/ui/base/cocoa/command_dispatcher.mm b/chromium/ui/base/cocoa/command_dispatcher.mm
index efe7a1862ce..1ae7b1707a7 100644
--- a/chromium/ui/base/cocoa/command_dispatcher.mm
+++ b/chromium/ui/base/cocoa/command_dispatcher.mm
@@ -23,6 +23,44 @@
- (NSWindow<CommandDispatchingWindow>*)bubbleParent;
@end
+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 = ui::ConvertPointFromWindowToScreen([event window], location);
+ location = ui::ConvertPointFromScreenToWindow(window, 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 CommandDispatcher {
@private
@@ -169,10 +207,13 @@
return YES; // Pretend it's been handled in an effort to limit damage.
}
- // TODO(lgrey): This is a temporary sanity check since the code that was
- // here previously did *not* assume this. Remove shortly after this lands if
- // nothing blew up.
- DCHECK_EQ([event window], _owner);
+ // Sometimes, an event will be redispatched from a child window to a parent
+ // window to allow the parent window a chance to handle it. In that case, fix
+ // up the native event to reference the correct window. Failure to do this can
+ // cause infinite redispatch loops; see https://crbug.com/1085578 for more
+ // details.
+ if ([event window] != _owner)
+ event = KeyEventForWindow(_owner, event);
// Redispatch the event.
_eventHandled = YES;