• Erik Chen's avatar
    Unification of macOS keyEquivalent (hotkey) handling. · 8f2f9568
    Erik Chen authored
    This CL makes the CommandDispatcher class responsible for all NSMenu-related
    keyEquivalent handling. The logic is now shared by both Views and Cocoa. This
    fixes many Views bugs, and some Cocoa bugs.
    
    Previously, there several different pieces of logic for handling NSMenu-related
    keyEquivalents.
    
    * If a RenderWidgetHostViewCocoa was the firstResponder, then all the logic in
      CommandDispatcher was skipped.
      * In both Cocoa and Views, there was logic in content/ via RenderWidget*
        classes that would short-circuit but also fail to handle the keyEquivalent.
        [e.g. if renderer process was killed].
        * In Cocoa, content/ would call into
          BrowserWindowCocoa::PreHandleKeyboardEvent(). This had mostly the right
          behavior, except it missed out on edge-case logic in CommandDispatcher.
        * In Views, content/ would call into BrowserView::PreHandleKeyboardEvent.
          This relied on AcceleratorTable to lookup the command for a keyEquivalent.
          This entire class is unusable for keyEquivalents because it holds a static
          mapping, whereas on macOS, the mapping is user configurable and dynamic.
      * If the hotkey was not immediately consumed, it would be passed to the
        renderer process. If the renderer process chose not to consume the hotkey,
        the browser process would get it again.
        * In Cocoa, the event would be redispatched to CommandDispatcher. This had
          the right behavior.
        * In Views, the event would be sent to AcceleratorTable again, once again
          having the wrong behavior.
    * If any other class was firstResponder, then the logic in CommandDispatcher
      would trigger.
    
    This CL makes CommandDispatcher the only place to handle NSMenu-related
    keyEquivalents. This allows us to centralize the logic, including workarounds.
    
    New logic:
    
    * The CommandDispatcherDelegate is given an opportunity to process the
      keyEquivalent via prePerformKeyEquivalent:. If the keyEquivalent is reserved
      by the browser, it is immediately handled.
    * Next, the firstResponder is given a chance to process the keyEquivalent. If
      the firstResponder is a RenderWidgetHostViewCocoa, this goes through the same
      code paths as above, except BrowserWindowCocoa::PreHandleKeyboardEvent() is
      mostly a no-op.
    * Then, the CommandDispatcherDelegate gets another chance to process the
      keyEquivalent via postPerformKeyEquivalent:.
    
    If the firstResponder was a RenderWidgetHostViewCocoa which asynchronously chose
    to not process the event, then both Cocoa and Views will take the returning
    event and call redispatchEvent:, which will also call into
    -[CommandDispatcherDelegate postPerformKeyEquivalent:].
    
    Change-Id: If724e125c6acf64ddd9f1d9cc296e761ffb2a886
    Bug: 846893, 836947, 845465, 47134
    Reviewed-on: https://chromium-review.googlesource.com/1082818
    Commit-Queue: Erik Chen <erikchen@chromium.org>
    Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
    Reviewed-by: default avatarTrent Apted <tapted@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#565490}
    8f2f9568
browser_frame_ash.cc 5.97 KB