diff options
Diffstat (limited to 'chromium/ui/base/cocoa/command_dispatcher.mm')
-rw-r--r-- | chromium/ui/base/cocoa/command_dispatcher.mm | 49 |
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; |