Browse Source

refactor: remove global_shortcut_listener from chromium_src/ (#15070)

Jeremy Apthorp 6 years ago
parent
commit
ce26687577

+ 10 - 0
chromium_src/BUILD.gn

@@ -9,6 +9,12 @@ import("//electron/buildflags/buildflags.gni")
 source_set("chrome") {
   visibility = [ "//electron:electron_lib" ]
   sources = [
+    "//chrome/browser/extensions/global_shortcut_listener.cc",
+    "//chrome/browser/extensions/global_shortcut_listener.h",
+    "//chrome/browser/extensions/global_shortcut_listener_mac.h",
+    "//chrome/browser/extensions/global_shortcut_listener_mac.mm",
+    "//chrome/browser/extensions/global_shortcut_listener_win.cc",
+    "//chrome/browser/extensions/global_shortcut_listener_win.h",
     "//chrome/browser/icon_loader.cc",
     "//chrome/browser/icon_loader.h",
     "//chrome/browser/icon_loader_mac.mm",
@@ -43,6 +49,10 @@ source_set("chrome") {
 
   if (is_linux) {
     sources += [ "//chrome/browser/icon_loader_auralinux.cc" ]
+    sources += [
+      "//chrome/browser/extensions/global_shortcut_listener_x11.cc",
+      "//chrome/browser/extensions/global_shortcut_listener_x11.h",
+    ]
   }
 
   if (enable_desktop_capturer) {

+ 0 - 123
chromium_src/chrome/browser/extensions/global_shortcut_listener.cc

@@ -1,123 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/global_shortcut_listener.h"
-
-#include "base/logging.h"
-#include "content/public/browser/browser_thread.h"
-#include "ui/base/accelerators/accelerator.h"
-
-using content::BrowserThread;
-
-namespace extensions {
-
-GlobalShortcutListener::GlobalShortcutListener()
-    : shortcut_handling_suspended_(false) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-GlobalShortcutListener::~GlobalShortcutListener() {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(accelerator_map_.empty());  // Make sure we've cleaned up.
-}
-
-bool GlobalShortcutListener::RegisterAccelerator(
-    const ui::Accelerator& accelerator,
-    Observer* observer) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (IsShortcutHandlingSuspended())
-    return false;
-
-  AcceleratorMap::const_iterator it = accelerator_map_.find(accelerator);
-  if (it != accelerator_map_.end()) {
-    // The accelerator has been registered.
-    return false;
-  }
-
-  if (!RegisterAcceleratorImpl(accelerator)) {
-    // If the platform-specific registration fails, mostly likely the shortcut
-    // has been registered by other native applications.
-    return false;
-  }
-
-  if (accelerator_map_.empty())
-    StartListening();
-
-  accelerator_map_[accelerator] = observer;
-  return true;
-}
-
-void GlobalShortcutListener::UnregisterAccelerator(
-    const ui::Accelerator& accelerator,
-    Observer* observer) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (IsShortcutHandlingSuspended())
-    return;
-
-  AcceleratorMap::iterator it = accelerator_map_.find(accelerator);
-  // We should never get asked to unregister something that we didn't register.
-  DCHECK(it != accelerator_map_.end());
-  // The caller should call this function with the right observer.
-  DCHECK(it->second == observer);
-
-  UnregisterAcceleratorImpl(accelerator);
-  accelerator_map_.erase(it);
-  if (accelerator_map_.empty())
-    StopListening();
-}
-
-void GlobalShortcutListener::UnregisterAccelerators(Observer* observer) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (IsShortcutHandlingSuspended())
-    return;
-
-  AcceleratorMap::iterator it = accelerator_map_.begin();
-  while (it != accelerator_map_.end()) {
-    if (it->second == observer) {
-      AcceleratorMap::iterator to_remove = it++;
-      UnregisterAccelerator(to_remove->first, observer);
-    } else {
-      ++it;
-    }
-  }
-}
-
-void GlobalShortcutListener::SetShortcutHandlingSuspended(bool suspended) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  if (shortcut_handling_suspended_ == suspended)
-    return;
-
-  shortcut_handling_suspended_ = suspended;
-  for (AcceleratorMap::iterator it = accelerator_map_.begin();
-       it != accelerator_map_.end(); ++it) {
-    // On Linux, when shortcut handling is suspended we cannot simply early
-    // return in NotifyKeyPressed (similar to what we do for non-global
-    // shortcuts) because we'd eat the keyboard event thereby preventing the
-    // user from setting the shortcut. Therefore we must unregister while
-    // handling is suspended and register when handling resumes.
-    if (shortcut_handling_suspended_)
-      UnregisterAcceleratorImpl(it->first);
-    else
-      RegisterAcceleratorImpl(it->first);
-  }
-}
-
-bool GlobalShortcutListener::IsShortcutHandlingSuspended() const {
-  return shortcut_handling_suspended_;
-}
-
-void GlobalShortcutListener::NotifyKeyPressed(
-    const ui::Accelerator& accelerator) {
-  AcceleratorMap::iterator iter = accelerator_map_.find(accelerator);
-  if (iter == accelerator_map_.end()) {
-    // This should never occur, because if it does, we have failed to unregister
-    // or failed to clean up the map after unregistering the shortcut.
-    NOTREACHED();
-    return;  // No-one is listening to this key.
-  }
-
-  iter->second->OnKeyPressed(accelerator);
-}
-
-}  // namespace extensions

+ 0 - 99
chromium_src/chrome/browser/extensions/global_shortcut_listener.h

@@ -1,99 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_H_
-#define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_H_
-
-#include <map>
-
-#include "base/macros.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-namespace ui {
-class Accelerator;
-}
-
-namespace extensions {
-
-// Platform-neutral implementation of a class that keeps track of observers and
-// monitors keystrokes. It relays messages to the appropriate observer when a
-// global shortcut has been struck by the user.
-class GlobalShortcutListener {
- public:
-  class Observer {
-   public:
-    // Called when your global shortcut (|accelerator|) is struck.
-    virtual void OnKeyPressed(const ui::Accelerator& accelerator) = 0;
-  };
-
-  virtual ~GlobalShortcutListener();
-
-  static GlobalShortcutListener* GetInstance();
-
-  // Register an observer for when a certain |accelerator| is struck. Returns
-  // true if register successfully, or false if 1) the specificied |accelerator|
-  // has been registered by another caller or other native applications, or
-  // 2) shortcut handling is suspended.
-  //
-  // Note that we do not support recognizing that an accelerator has been
-  // registered by another application on all platforms. This is a per-platform
-  // consideration.
-  bool RegisterAccelerator(const ui::Accelerator& accelerator,
-                           Observer* observer);
-
-  // Stop listening for the given |accelerator|, does nothing if shortcut
-  // handling is suspended.
-  void UnregisterAccelerator(const ui::Accelerator& accelerator,
-                             Observer* observer);
-
-  // Stop listening for all accelerators of the given |observer|, does nothing
-  // if shortcut handling is suspended.
-  void UnregisterAccelerators(Observer* observer);
-
-  // Suspend/Resume global shortcut handling. Note that when suspending,
-  // RegisterAccelerator/UnregisterAccelerator/UnregisterAccelerators are not
-  // allowed to be called until shortcut handling has been resumed.
-  void SetShortcutHandlingSuspended(bool suspended);
-
-  // Returns whether shortcut handling is currently suspended.
-  bool IsShortcutHandlingSuspended() const;
-
- protected:
-  GlobalShortcutListener();
-
-  // Called by platform specific implementations of this class whenever a key
-  // is struck. Only called for keys that have an observer registered.
-  void NotifyKeyPressed(const ui::Accelerator& accelerator);
-
- private:
-  // The following methods are implemented by platform-specific implementations
-  // of this class.
-  //
-  // Start/StopListening are called when transitioning between zero and nonzero
-  // registered accelerators. StartListening will be called after
-  // RegisterAcceleratorImpl and StopListening will be called after
-  // UnregisterAcceleratorImpl.
-  //
-  // For RegisterAcceleratorImpl, implementations return false if registration
-  // did not complete successfully.
-  virtual void StartListening() = 0;
-  virtual void StopListening() = 0;
-  virtual bool RegisterAcceleratorImpl(const ui::Accelerator& accelerator) = 0;
-  virtual void UnregisterAcceleratorImpl(
-      const ui::Accelerator& accelerator) = 0;
-
-  // The map of accelerators that have been successfully registered as global
-  // shortcuts and their observer.
-  typedef std::map<ui::Accelerator, Observer*> AcceleratorMap;
-  AcceleratorMap accelerator_map_;
-
-  // Keeps track of whether shortcut handling is currently suspended.
-  bool shortcut_handling_suspended_;
-
-  DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListener);
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_H_

+ 0 - 108
chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.h

@@ -1,108 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_
-#define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_
-
-#include "chrome/browser/extensions/global_shortcut_listener.h"
-
-#include <Carbon/Carbon.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-#include <map>
-
-#include "base/mac/scoped_nsobject.h"
-
-namespace extensions {
-
-// Mac-specific implementation of the GlobalShortcutListener class that
-// listens for global shortcuts. Handles basic keyboard intercepting and
-// forwards its output to the base class for processing.
-//
-// This class does two things:
-// 1. Intercepts media/volume keys. Uses an event tap for intercepting media
-// keys (PlayPause, NextTrack, PreviousTrack) and volume keys(VolumeUp,
-// VolumeDown, VolumeMute).
-// 2. Binds keyboard shortcuts (hot keys). Carbon RegisterEventHotKey API for
-// binding to non-media key global hot keys (eg. Command-Shift-1).
-class GlobalShortcutListenerMac : public GlobalShortcutListener {
- public:
-  GlobalShortcutListenerMac();
-  ~GlobalShortcutListenerMac() override;
-
- private:
-  typedef int KeyId;
-  typedef std::map<ui::Accelerator, KeyId> AcceleratorIdMap;
-  typedef std::map<KeyId, ui::Accelerator> IdAcceleratorMap;
-  typedef std::map<KeyId, EventHotKeyRef> IdHotKeyRefMap;
-
-  // Keyboard event callbacks.
-  void OnHotKeyEvent(EventHotKeyID hot_key_id);
-  bool OnMediaOrVolumeKeyEvent(int key_code);
-
-  // GlobalShortcutListener implementation.
-  void StartListening() override;
-  void StopListening() override;
-  bool RegisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
-  void UnregisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
-
-  // Mac-specific functions for registering hot keys with modifiers.
-  bool RegisterHotKey(const ui::Accelerator& accelerator, KeyId hot_key_id);
-  void UnregisterHotKey(const ui::Accelerator& accelerator);
-
-  // Enable and disable the media/volume key event tap.
-  void StartWatchingMediaOrVolumeKeys();
-  void StopWatchingMediaOrVolumeKeys();
-
-  // Enable and disable the hot key event handler.
-  void StartWatchingHotKeys();
-  void StopWatchingHotKeys();
-
-  // Whether or not any media/volume keys are currently registered.
-  bool IsAnyMediaOrVolumeKeyRegistered();
-
-  // Whether or not any hot keys are currently registered.
-  bool IsAnyHotKeyRegistered();
-
-  // The callback for when an event tap happens.
-  static CGEventRef EventTapCallback(CGEventTapProxy proxy,
-                                     CGEventType type,
-                                     CGEventRef event,
-                                     void* refcon);
-
-  // The callback for when a hot key event happens.
-  static OSStatus HotKeyHandler(EventHandlerCallRef next_handler,
-                                EventRef event,
-                                void* user_data);
-
-  // Whether this object is listening for global shortcuts.
-  bool is_listening_;
-
-  // The hotkey identifier for the next global shortcut that is added.
-  KeyId hot_key_id_;
-
-  // A map of all hotkeys (media/volume keys and shortcuts) mapping to their
-  // corresponding hotkey IDs. For quickly finding if an accelerator is
-  // registered.
-  AcceleratorIdMap accelerator_ids_;
-
-  // The inverse map for quickly looking up accelerators by hotkey id.
-  IdAcceleratorMap id_accelerators_;
-
-  // Keyboard shortcut IDs to hotkeys map for unregistration.
-  IdHotKeyRefMap id_hot_key_refs_;
-
-  // Event tap for intercepting mac media/volume keys.
-  CFMachPortRef event_tap_;
-  CFRunLoopSourceRef event_tap_source_;
-
-  // Event handler for keyboard shortcut hot keys.
-  EventHandlerRef event_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerMac);
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_

+ 0 - 398
chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm

@@ -1,398 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/global_shortcut_listener_mac.h"
-
-#include <ApplicationServices/ApplicationServices.h>
-#import <Cocoa/Cocoa.h>
-#include <IOKit/hidsystem/ev_keymap.h>
-
-#import "base/mac/foundation_util.h"
-#include "content/public/browser/browser_thread.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/events/event.h"
-#import "ui/events/keycodes/keyboard_code_conversion_mac.h"
-
-using content::BrowserThread;
-using extensions::GlobalShortcutListenerMac;
-
-namespace {
-
-// The media/volume keys subtype. No official docs found, but widely known.
-// http://lists.apple.com/archives/cocoa-dev/2007/Aug/msg00499.html
-const int kSystemDefinedEventMediaAndVolumeKeysSubtype = 8;
-
-ui::KeyboardCode MediaOrVolumeKeyCodeToKeyboardCode(int key_code) {
-  switch (key_code) {
-    case NX_KEYTYPE_PLAY:
-      return ui::VKEY_MEDIA_PLAY_PAUSE;
-    case NX_KEYTYPE_PREVIOUS:
-    case NX_KEYTYPE_REWIND:
-      return ui::VKEY_MEDIA_PREV_TRACK;
-    case NX_KEYTYPE_NEXT:
-    case NX_KEYTYPE_FAST:
-      return ui::VKEY_MEDIA_NEXT_TRACK;
-    case NX_KEYTYPE_SOUND_UP:
-      return ui::VKEY_VOLUME_UP;
-    case NX_KEYTYPE_SOUND_DOWN:
-      return ui::VKEY_VOLUME_DOWN;
-    case NX_KEYTYPE_MUTE:
-      return ui::VKEY_VOLUME_MUTE;
-  }
-  return ui::VKEY_UNKNOWN;
-}
-
-bool IsMediaOrVolumeKey(const ui::Accelerator& accelerator) {
-  if (accelerator.modifiers() != 0)
-    return false;
-  return (accelerator.key_code() == ui::VKEY_MEDIA_NEXT_TRACK ||
-          accelerator.key_code() == ui::VKEY_MEDIA_PREV_TRACK ||
-          accelerator.key_code() == ui::VKEY_MEDIA_PLAY_PAUSE ||
-          accelerator.key_code() == ui::VKEY_MEDIA_STOP ||
-          accelerator.key_code() == ui::VKEY_VOLUME_UP ||
-          accelerator.key_code() == ui::VKEY_VOLUME_DOWN ||
-          accelerator.key_code() == ui::VKEY_VOLUME_MUTE);
-}
-
-}  // namespace
-
-namespace extensions {
-
-// static
-GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  static GlobalShortcutListenerMac* instance = new GlobalShortcutListenerMac();
-  return instance;
-}
-
-GlobalShortcutListenerMac::GlobalShortcutListenerMac()
-    : is_listening_(false),
-      hot_key_id_(0),
-      event_tap_(NULL),
-      event_tap_source_(NULL),
-      event_handler_(NULL) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-GlobalShortcutListenerMac::~GlobalShortcutListenerMac() {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  // By this point, UnregisterAccelerator should have been called for all
-  // keyboard shortcuts. Still we should clean up.
-  if (is_listening_)
-    StopListening();
-
-  // If keys are still registered, make sure we stop the tap. Again, this
-  // should never happen.
-  if (IsAnyMediaOrVolumeKeyRegistered())
-    StopWatchingMediaOrVolumeKeys();
-
-  if (IsAnyHotKeyRegistered())
-    StopWatchingHotKeys();
-}
-
-void GlobalShortcutListenerMac::StartListening() {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  DCHECK(!accelerator_ids_.empty());
-  DCHECK(!id_accelerators_.empty());
-  DCHECK(!is_listening_);
-
-  is_listening_ = true;
-}
-
-void GlobalShortcutListenerMac::StopListening() {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  DCHECK(accelerator_ids_.empty());  // Make sure the set is clean.
-  DCHECK(id_accelerators_.empty());
-  DCHECK(is_listening_);
-
-  is_listening_ = false;
-}
-
-void GlobalShortcutListenerMac::OnHotKeyEvent(EventHotKeyID hot_key_id) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  // This hot key should be registered.
-  DCHECK(id_accelerators_.find(hot_key_id.id) != id_accelerators_.end());
-  // Look up the accelerator based on this hot key ID.
-  const ui::Accelerator& accelerator = id_accelerators_[hot_key_id.id];
-  NotifyKeyPressed(accelerator);
-}
-
-bool GlobalShortcutListenerMac::OnMediaOrVolumeKeyEvent(
-    int media_or_volume_key_code) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  ui::KeyboardCode key_code =
-      MediaOrVolumeKeyCodeToKeyboardCode(media_or_volume_key_code);
-  // Create an accelerator corresponding to the keyCode.
-  ui::Accelerator accelerator(key_code, 0);
-  // Look for a match with a bound hot_key.
-  if (accelerator_ids_.find(accelerator) != accelerator_ids_.end()) {
-    // If matched, callback to the event handling system.
-    NotifyKeyPressed(accelerator);
-    return true;
-  }
-  return false;
-}
-
-bool GlobalShortcutListenerMac::RegisterAcceleratorImpl(
-    const ui::Accelerator& accelerator) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(accelerator_ids_.find(accelerator) == accelerator_ids_.end());
-
-  if (IsMediaOrVolumeKey(accelerator)) {
-    if (!IsAnyMediaOrVolumeKeyRegistered()) {
-      // If this is the first media/volume key registered, start the event tap.
-      StartWatchingMediaOrVolumeKeys();
-    }
-  } else {
-    // Register hot_key if they are non-media keyboard shortcuts.
-    if (!RegisterHotKey(accelerator, hot_key_id_))
-      return false;
-
-    if (!IsAnyHotKeyRegistered()) {
-      StartWatchingHotKeys();
-    }
-  }
-
-  // Store the hotkey-ID mappings we will need for lookup later.
-  id_accelerators_[hot_key_id_] = accelerator;
-  accelerator_ids_[accelerator] = hot_key_id_;
-  ++hot_key_id_;
-  return true;
-}
-
-void GlobalShortcutListenerMac::UnregisterAcceleratorImpl(
-    const ui::Accelerator& accelerator) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(accelerator_ids_.find(accelerator) != accelerator_ids_.end());
-
-  // Unregister the hot_key if it's a keyboard shortcut.
-  if (!IsMediaOrVolumeKey(accelerator))
-    UnregisterHotKey(accelerator);
-
-  // Remove hot_key from the mappings.
-  KeyId key_id = accelerator_ids_[accelerator];
-  id_accelerators_.erase(key_id);
-  accelerator_ids_.erase(accelerator);
-
-  if (IsMediaOrVolumeKey(accelerator)) {
-    // If we unregistered a media/volume key, and now no media/volume keys are
-    // registered, stop the media/volume key tap.
-    if (!IsAnyMediaOrVolumeKeyRegistered())
-      StopWatchingMediaOrVolumeKeys();
-  } else {
-    // If we unregistered a hot key, and no more hot keys are registered, remove
-    // the hot key handler.
-    if (!IsAnyHotKeyRegistered()) {
-      StopWatchingHotKeys();
-    }
-  }
-}
-
-bool GlobalShortcutListenerMac::RegisterHotKey(
-    const ui::Accelerator& accelerator,
-    KeyId hot_key_id) {
-  EventHotKeyID event_hot_key_id;
-
-  // Signature uniquely identifies the application that owns this hot_key.
-  event_hot_key_id.signature = base::mac::CreatorCodeForApplication();
-  event_hot_key_id.id = hot_key_id;
-
-  // Translate ui::Accelerator modifiers to cmdKey, altKey, etc.
-  int modifiers = 0;
-  modifiers |= (accelerator.IsShiftDown() ? shiftKey : 0);
-  modifiers |= (accelerator.IsCtrlDown() ? controlKey : 0);
-  modifiers |= (accelerator.IsAltDown() ? optionKey : 0);
-  modifiers |= (accelerator.IsCmdDown() ? cmdKey : 0);
-
-  int key_code =
-      ui::MacKeyCodeForWindowsKeyCode(accelerator.key_code(), 0, NULL, NULL);
-
-  // Register the event hot key.
-  EventHotKeyRef hot_key_ref;
-  OSStatus status =
-      RegisterEventHotKey(key_code, modifiers, event_hot_key_id,
-                          GetApplicationEventTarget(), 0, &hot_key_ref);
-  if (status != noErr)
-    return false;
-
-  id_hot_key_refs_[hot_key_id] = hot_key_ref;
-  return true;
-}
-
-void GlobalShortcutListenerMac::UnregisterHotKey(
-    const ui::Accelerator& accelerator) {
-  // Ensure this accelerator is already registered.
-  DCHECK(accelerator_ids_.find(accelerator) != accelerator_ids_.end());
-  // Get the ref corresponding to this accelerator.
-  KeyId key_id = accelerator_ids_[accelerator];
-  EventHotKeyRef ref = id_hot_key_refs_[key_id];
-  // Unregister the event hot key.
-  UnregisterEventHotKey(ref);
-
-  // Remove the event from the mapping.
-  id_hot_key_refs_.erase(key_id);
-}
-
-void GlobalShortcutListenerMac::StartWatchingMediaOrVolumeKeys() {
-  // Make sure there's no existing event tap.
-  DCHECK(event_tap_ == NULL);
-  DCHECK(event_tap_source_ == NULL);
-
-  // Add an event tap to intercept the system defined media/volume key events.
-  event_tap_ = CGEventTapCreate(
-      kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault,
-      CGEventMaskBit(NX_SYSDEFINED), EventTapCallback, this);
-  if (event_tap_ == NULL) {
-    LOG(ERROR) << "Error: failed to create event tap.";
-    return;
-  }
-
-  event_tap_source_ =
-      CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, event_tap_, 0);
-  if (event_tap_source_ == NULL) {
-    LOG(ERROR) << "Error: failed to create new run loop source.";
-    return;
-  }
-
-  CFRunLoopAddSource(CFRunLoopGetCurrent(), event_tap_source_,
-                     kCFRunLoopCommonModes);
-}
-
-void GlobalShortcutListenerMac::StopWatchingMediaOrVolumeKeys() {
-  CFRunLoopRemoveSource(CFRunLoopGetCurrent(), event_tap_source_,
-                        kCFRunLoopCommonModes);
-  // Ensure both event tap and source are initialized.
-  DCHECK(event_tap_ != NULL);
-  DCHECK(event_tap_source_ != NULL);
-
-  // Invalidate the event tap.
-  CFMachPortInvalidate(event_tap_);
-  CFRelease(event_tap_);
-  event_tap_ = NULL;
-
-  // Release the event tap source.
-  CFRelease(event_tap_source_);
-  event_tap_source_ = NULL;
-}
-
-void GlobalShortcutListenerMac::StartWatchingHotKeys() {
-  DCHECK(!event_handler_);
-  EventHandlerUPP hot_key_function = NewEventHandlerUPP(HotKeyHandler);
-  EventTypeSpec event_type;
-  event_type.eventClass = kEventClassKeyboard;
-  event_type.eventKind = kEventHotKeyPressed;
-  InstallApplicationEventHandler(hot_key_function, 1, &event_type, this,
-                                 &event_handler_);
-}
-
-void GlobalShortcutListenerMac::StopWatchingHotKeys() {
-  DCHECK(event_handler_);
-  RemoveEventHandler(event_handler_);
-  event_handler_ = NULL;
-}
-
-bool GlobalShortcutListenerMac::IsAnyMediaOrVolumeKeyRegistered() {
-  // Iterate through registered accelerators, looking for media/volume keys.
-  AcceleratorIdMap::iterator it;
-  for (it = accelerator_ids_.begin(); it != accelerator_ids_.end(); ++it) {
-    if (IsMediaOrVolumeKey(it->first))
-      return true;
-  }
-  return false;
-}
-
-bool GlobalShortcutListenerMac::IsAnyHotKeyRegistered() {
-  AcceleratorIdMap::iterator it;
-  for (it = accelerator_ids_.begin(); it != accelerator_ids_.end(); ++it) {
-    if (!IsMediaOrVolumeKey(it->first))
-      return true;
-  }
-  return false;
-}
-
-// Processed events should propagate if they aren't handled by any listeners.
-// For events that don't matter, this handler should return as quickly as
-// possible.
-// Returning event causes the event to propagate to other applications.
-// Returning NULL prevents the event from propagating.
-// static
-CGEventRef GlobalShortcutListenerMac::EventTapCallback(CGEventTapProxy proxy,
-                                                       CGEventType type,
-                                                       CGEventRef event,
-                                                       void* refcon) {
-  GlobalShortcutListenerMac* shortcut_listener =
-      static_cast<GlobalShortcutListenerMac*>(refcon);
-
-  // Handle the timeout case by re-enabling the tap.
-  if (type == kCGEventTapDisabledByTimeout) {
-    CGEventTapEnable(shortcut_listener->event_tap_, TRUE);
-    return event;
-  }
-
-  // Convert the CGEvent to an NSEvent for access to the data1 field.
-  NSEvent* ns_event = [NSEvent eventWithCGEvent:event];
-  if (ns_event == nil) {
-    return event;
-  }
-
-  // Ignore events that are not system defined media/volume keys.
-  if (type != NX_SYSDEFINED || [ns_event type] != NSSystemDefined ||
-      [ns_event subtype] != kSystemDefinedEventMediaAndVolumeKeysSubtype) {
-    return event;
-  }
-
-  NSInteger data1 = [ns_event data1];
-  // Ignore media keys that aren't previous, next and play/pause and
-  // volume keys that aren't up, down and mute.
-  // Magical constants are from http://weblog.rogueamoeba.com/2007/09/29/
-  int key_code = (data1 & 0xFFFF0000) >> 16;
-  if (key_code != NX_KEYTYPE_PLAY && key_code != NX_KEYTYPE_NEXT &&
-      key_code != NX_KEYTYPE_PREVIOUS && key_code != NX_KEYTYPE_FAST &&
-      key_code != NX_KEYTYPE_REWIND && key_code != NX_KEYTYPE_SOUND_UP &&
-      key_code != NX_KEYTYPE_SOUND_DOWN && key_code != NX_KEYTYPE_MUTE) {
-    return event;
-  }
-
-  int key_flags = data1 & 0x0000FFFF;
-  bool is_key_pressed = ((key_flags & 0xFF00) >> 8) == 0xA;
-
-  // If the key wasn't pressed (eg. was released), ignore this event.
-  if (!is_key_pressed)
-    return event;
-
-  // Now we have a media/volume key that we care about. Send it to the caller.
-  bool was_handled = shortcut_listener->OnMediaOrVolumeKeyEvent(key_code);
-
-  // Prevent event from proagating to other apps if handled by Chrome.
-  if (was_handled)
-    return NULL;
-
-  // By default, pass the event through.
-  return event;
-}
-
-// static
-OSStatus GlobalShortcutListenerMac::HotKeyHandler(
-    EventHandlerCallRef next_handler,
-    EventRef event,
-    void* user_data) {
-  // Extract the hotkey from the event.
-  EventHotKeyID hot_key_id;
-  OSStatus result =
-      GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL,
-                        sizeof(hot_key_id), NULL, &hot_key_id);
-  if (result != noErr)
-    return result;
-
-  GlobalShortcutListenerMac* shortcut_listener =
-      static_cast<GlobalShortcutListenerMac*>(user_data);
-  shortcut_listener->OnHotKeyEvent(hot_key_id);
-  return noErr;
-}
-
-}  // namespace extensions

+ 0 - 109
chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc

@@ -1,109 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/global_shortcut_listener_win.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/win/win_util.h"
-#include "content/public/browser/browser_thread.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/events/event_constants.h"
-#include "ui/events/keycodes/keyboard_code_conversion_win.h"
-#include "ui/gfx/win/singleton_hwnd.h"
-
-using content::BrowserThread;
-
-namespace extensions {
-
-// static
-GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  static GlobalShortcutListenerWin* instance = new GlobalShortcutListenerWin();
-  return instance;
-}
-
-GlobalShortcutListenerWin::GlobalShortcutListenerWin() : is_listening_(false) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-GlobalShortcutListenerWin::~GlobalShortcutListenerWin() {
-  if (is_listening_)
-    StopListening();
-}
-
-void GlobalShortcutListenerWin::StartListening() {
-  DCHECK(!is_listening_);        // Don't start twice.
-  DCHECK(!hotkey_ids_.empty());  // Also don't start if no hotkey is registered.
-  singleton_hwnd_observer_.reset(new gfx::SingletonHwndObserver(base::Bind(
-      &GlobalShortcutListenerWin::OnWndProc, base::Unretained(this))));
-
-  is_listening_ = true;
-}
-
-void GlobalShortcutListenerWin::StopListening() {
-  DCHECK(is_listening_);        // No point if we are not already listening.
-  DCHECK(hotkey_ids_.empty());  // Make sure the map is clean before ending.
-  singleton_hwnd_observer_.reset(nullptr);
-  is_listening_ = false;
-}
-
-void GlobalShortcutListenerWin::OnWndProc(HWND hwnd,
-                                          UINT message,
-                                          WPARAM wparam,
-                                          LPARAM lparam) {
-  if (message != WM_HOTKEY)
-    return;
-
-  int key_code = HIWORD(lparam);
-  int modifiers = 0;
-  modifiers |= (LOWORD(lparam) & MOD_SHIFT) ? ui::EF_SHIFT_DOWN : 0;
-  modifiers |= (LOWORD(lparam) & MOD_ALT) ? ui::EF_ALT_DOWN : 0;
-  modifiers |= (LOWORD(lparam) & MOD_CONTROL) ? ui::EF_CONTROL_DOWN : 0;
-  modifiers |= (LOWORD(lparam) & MOD_WIN) ? ui::EF_COMMAND_DOWN : 0;
-
-  ui::Accelerator accelerator(ui::KeyboardCodeForWindowsKeyCode(key_code),
-                              modifiers);
-
-  NotifyKeyPressed(accelerator);
-}
-
-bool GlobalShortcutListenerWin::RegisterAcceleratorImpl(
-    const ui::Accelerator& accelerator) {
-  DCHECK(hotkey_ids_.find(accelerator) == hotkey_ids_.end());
-
-  int modifiers = 0;
-  modifiers |= accelerator.IsShiftDown() ? MOD_SHIFT : 0;
-  modifiers |= accelerator.IsCtrlDown() ? MOD_CONTROL : 0;
-  modifiers |= accelerator.IsAltDown() ? MOD_ALT : 0;
-  modifiers |= accelerator.IsCmdDown() ? MOD_WIN : 0;
-
-  static int hotkey_id = 0;
-  bool success = !!RegisterHotKey(gfx::SingletonHwnd::GetInstance()->hwnd(),
-                                  hotkey_id, modifiers, accelerator.key_code());
-
-  if (!success) {
-    // Most likely error: 1409 (Hotkey already registered).
-    return false;
-  }
-
-  hotkey_ids_[accelerator] = hotkey_id++;
-  return true;
-}
-
-void GlobalShortcutListenerWin::UnregisterAcceleratorImpl(
-    const ui::Accelerator& accelerator) {
-  HotkeyIdMap::iterator it = hotkey_ids_.find(accelerator);
-  DCHECK(it != hotkey_ids_.end());
-
-  bool success =
-      !!UnregisterHotKey(gfx::SingletonHwnd::GetInstance()->hwnd(), it->second);
-  // This call should always succeed, as long as we pass in the right HWND and
-  // an id we've used to register before.
-  DCHECK(success);
-
-  hotkey_ids_.erase(it);
-}
-
-}  // namespace extensions

+ 0 - 50
chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h

@@ -1,50 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_WIN_H_
-#define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_WIN_H_
-
-#include <memory>
-
-#include <windows.h>
-
-#include "chrome/browser/extensions/global_shortcut_listener.h"
-#include "ui/gfx/win/singleton_hwnd.h"
-#include "ui/gfx/win/singleton_hwnd_observer.h"
-
-namespace extensions {
-
-// Windows-specific implementation of the GlobalShortcutListener class that
-// listens for global shortcuts. Handles setting up a keyboard hook and
-// forwarding its output to the base class for processing.
-class GlobalShortcutListenerWin : public GlobalShortcutListener {
- public:
-  GlobalShortcutListenerWin();
-  ~GlobalShortcutListenerWin() override;
-
- private:
-  // The implementation of our Window Proc, called by SingletonHwndObserver.
-  void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
-
-  // GlobalShortcutListener implementation.
-  void StartListening() override;
-  void StopListening() override;
-  bool RegisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
-  void UnregisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
-
-  // Whether this object is listening for global shortcuts.
-  bool is_listening_;
-
-  // A map of registered accelerators and their registration ids.
-  typedef std::map<ui::Accelerator, int> HotkeyIdMap;
-  HotkeyIdMap hotkey_ids_;
-
-  std::unique_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerWin);
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_WIN_H_

+ 0 - 161
chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.cc

@@ -1,161 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/global_shortcut_listener_x11.h"
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "content/public/browser/browser_thread.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/events/keycodes/keyboard_code_conversion_x.h"
-#include "ui/events/platform/platform_event_source.h"
-#include "ui/gfx/x/x11.h"
-#include "ui/gfx/x/x11_error_tracker.h"
-#include "ui/gfx/x/x11_types.h"
-
-using content::BrowserThread;
-
-namespace {
-
-// The modifiers masks used for grabing keys. Due to XGrabKey only working on
-// exact modifiers, we need to grab all key combination including zero or more
-// of the following: Num lock, Caps lock and Scroll lock. So that we can make
-// sure the behavior of global shortcuts is consistent on all platforms.
-const unsigned int kModifiersMasks[] = {0,         // No additional modifier.
-                                        Mod2Mask,  // Num lock
-                                        LockMask,  // Caps lock
-                                        Mod5Mask,  // Scroll lock
-                                        Mod2Mask | LockMask,
-                                        Mod2Mask | Mod5Mask,
-                                        LockMask | Mod5Mask,
-                                        Mod2Mask | LockMask | Mod5Mask};
-
-int GetNativeModifiers(const ui::Accelerator& accelerator) {
-  int modifiers = 0;
-  modifiers |= accelerator.IsShiftDown() ? ShiftMask : 0;
-  modifiers |= accelerator.IsCtrlDown() ? ControlMask : 0;
-  modifiers |= accelerator.IsAltDown() ? Mod1Mask : 0;
-  modifiers |= accelerator.IsCmdDown() ? Mod4Mask : 0;
-
-  return modifiers;
-}
-
-}  // namespace
-
-namespace extensions {
-
-// static
-GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  static GlobalShortcutListenerX11* instance = new GlobalShortcutListenerX11();
-  return instance;
-}
-
-GlobalShortcutListenerX11::GlobalShortcutListenerX11()
-    : is_listening_(false),
-      x_display_(gfx::GetXDisplay()),
-      x_root_window_(DefaultRootWindow(x_display_)) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-GlobalShortcutListenerX11::~GlobalShortcutListenerX11() {
-  if (is_listening_)
-    StopListening();
-}
-
-void GlobalShortcutListenerX11::StartListening() {
-  DCHECK(!is_listening_);                 // Don't start twice.
-  DCHECK(!registered_hot_keys_.empty());  // Also don't start if no hotkey is
-                                          // registered.
-
-  ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
-
-  is_listening_ = true;
-}
-
-void GlobalShortcutListenerX11::StopListening() {
-  DCHECK(is_listening_);  // No point if we are not already listening.
-  DCHECK(registered_hot_keys_.empty());  // Make sure the set is clean before
-                                         // ending.
-
-  ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
-
-  is_listening_ = false;
-}
-
-bool GlobalShortcutListenerX11::CanDispatchEvent(
-    const ui::PlatformEvent& event) {
-  return event->type == KeyPress;
-}
-
-uint32_t GlobalShortcutListenerX11::DispatchEvent(
-    const ui::PlatformEvent& event) {
-  CHECK_EQ(KeyPress, event->type);
-  OnXKeyPressEvent(event);
-
-  return ui::POST_DISPATCH_NONE;
-}
-
-bool GlobalShortcutListenerX11::RegisterAcceleratorImpl(
-    const ui::Accelerator& accelerator) {
-  DCHECK(registered_hot_keys_.find(accelerator) == registered_hot_keys_.end());
-
-  int modifiers = GetNativeModifiers(accelerator);
-  KeyCode keycode = XKeysymToKeycode(
-      x_display_, XKeysymForWindowsKeyCode(accelerator.key_code(), false));
-  gfx::X11ErrorTracker err_tracker;
-
-  // Because XGrabKey only works on the exact modifiers mask, we should register
-  // our hot keys with modifiers that we want to ignore, including Num lock,
-  // Caps lock, Scroll lock. See comment about |kModifiersMasks|.
-  for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) {
-    XGrabKey(x_display_, keycode, modifiers | kModifiersMasks[i],
-             x_root_window_, x11::False, GrabModeAsync, GrabModeAsync);
-  }
-
-  if (err_tracker.FoundNewError()) {
-    // We may have part of the hotkeys registered, clean up.
-    for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) {
-      XUngrabKey(x_display_, keycode, modifiers | kModifiersMasks[i],
-                 x_root_window_);
-    }
-
-    return false;
-  }
-
-  registered_hot_keys_.insert(accelerator);
-  return true;
-}
-
-void GlobalShortcutListenerX11::UnregisterAcceleratorImpl(
-    const ui::Accelerator& accelerator) {
-  DCHECK(registered_hot_keys_.find(accelerator) != registered_hot_keys_.end());
-
-  int modifiers = GetNativeModifiers(accelerator);
-  KeyCode keycode = XKeysymToKeycode(
-      x_display_, XKeysymForWindowsKeyCode(accelerator.key_code(), false));
-
-  for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) {
-    XUngrabKey(x_display_, keycode, modifiers | kModifiersMasks[i],
-               x_root_window_);
-  }
-  registered_hot_keys_.erase(accelerator);
-}
-
-void GlobalShortcutListenerX11::OnXKeyPressEvent(::XEvent* x_event) {
-  DCHECK(x_event->type == KeyPress);
-  int modifiers = 0;
-  modifiers |= (x_event->xkey.state & ShiftMask) ? ui::EF_SHIFT_DOWN : 0;
-  modifiers |= (x_event->xkey.state & ControlMask) ? ui::EF_CONTROL_DOWN : 0;
-  modifiers |= (x_event->xkey.state & Mod1Mask) ? ui::EF_ALT_DOWN : 0;
-  modifiers |= (x_event->xkey.state & Mod4Mask) ? ui::EF_COMMAND_DOWN : 0;
-
-  ui::Accelerator accelerator(ui::KeyboardCodeFromXKeyEvent(x_event),
-                              modifiers);
-  if (registered_hot_keys_.find(accelerator) != registered_hot_keys_.end())
-    NotifyKeyPressed(accelerator);
-}
-
-}  // namespace extensions

+ 0 - 58
chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h

@@ -1,58 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_X11_H_
-#define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_X11_H_
-
-#include <stdint.h>
-
-#include <set>
-
-#include "base/macros.h"
-#include "chrome/browser/extensions/global_shortcut_listener.h"
-#include "ui/events/platform/platform_event_dispatcher.h"
-#include "ui/gfx/x/x11.h"
-
-namespace extensions {
-
-// X11-specific implementation of the GlobalShortcutListener class that
-// listens for global shortcuts. Handles basic keyboard intercepting and
-// forwards its output to the base class for processing.
-class GlobalShortcutListenerX11 : public GlobalShortcutListener,
-                                  public ui::PlatformEventDispatcher {
- public:
-  GlobalShortcutListenerX11();
-  ~GlobalShortcutListenerX11() override;
-
-  // ui::PlatformEventDispatcher implementation.
-  bool CanDispatchEvent(const ui::PlatformEvent& event) override;
-  uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
-
- private:
-  // GlobalShortcutListener implementation.
-  void StartListening() override;
-  void StopListening() override;
-  bool RegisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
-  void UnregisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
-
-  // Invoked when a global shortcut is pressed.
-  void OnXKeyPressEvent(::XEvent* x_event);
-
-  // Whether this object is listening for global shortcuts.
-  bool is_listening_;
-
-  // The x11 default display and the native root window.
-  ::Display* x_display_;
-  ::Window x_root_window_;
-
-  // A set of registered accelerators.
-  typedef std::set<ui::Accelerator> RegisteredHotKeys;
-  RegisteredHotKeys registered_hot_keys_;
-
-  DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerX11);
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_X11_H_

+ 0 - 8
filenames.gni

@@ -582,14 +582,6 @@ filenames = {
     "chromium_src/chrome/browser/chrome_process_finder_win.cc",
     "chromium_src/chrome/browser/chrome_process_finder_win.h",
     "chromium_src/chrome/browser/chrome_notification_types.h",
-    "chromium_src/chrome/browser/extensions/global_shortcut_listener.cc",
-    "chromium_src/chrome/browser/extensions/global_shortcut_listener.h",
-    "chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm",
-    "chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.h",
-    "chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.cc",
-    "chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h",
-    "chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc",
-    "chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h",
     "chromium_src/chrome/browser/printing/print_job.cc",
     "chromium_src/chrome/browser/printing/print_job.h",
     "chromium_src/chrome/browser/printing/print_job_manager.cc",

+ 12 - 0
patches/common/chromium/.patches.yaml

@@ -491,3 +491,15 @@ patches:
     dylib currently fails to resolve Squirrel.framework on OSX, we need to fix
     this but it is not a blocker for releasing Electron.  This patch removes
     the hard fail on dylib resolve failure from dump_syms
+-
+  author: Jeremy Apthorp <[email protected]>
+  file: command-ismediakey.patch
+  description: |
+    define Command::IsMediaKey on mac
+
+    the definition is copied from //chrome/common/extensions/command.cc,
+    which also defines a bunch of other stuff that depends on extensions.
+    since we only need IsMediaKey, and we don't want the extensions stuff
+    (and aren't compiling command.cc), it's safe to duplicate the
+    definition. A candidate for upstreaming would be to move the IsMediaKey
+    function into //ui.

+ 122 - 0
patches/common/chromium/command-ismediakey.patch

@@ -0,0 +1,122 @@
+From 2d028f727b68a0aa7f83cc069e1df4d13a9e173e Mon Sep 17 00:00:00 2001
+From: Jeremy Apthorp <[email protected]>
+Date: Wed, 10 Oct 2018 15:07:34 -0700
+Subject: define Command::IsMediaKey on mac
+
+the definition is copied from //chrome/common/extensions/command.cc,
+which also defines a bunch of other stuff that depends on extensions.
+since we only need IsMediaKey, and we don't want the extensions stuff
+(and aren't compiling command.cc), it's safe to duplicate the
+definition. A candidate for upstreaming would be to move the IsMediaKey
+function into //ui.
+
+Also apply electron/electron@0f67b1866a9f00b852370e721affa4efda623f3a
+and electron/electron@d2368d2d3b3de9eec4cc32b6aaf035cc89921bf1 as
+patches.
+
+diff --git a/chrome/browser/extensions/global_shortcut_listener_mac.mm b/chrome/browser/extensions/global_shortcut_listener_mac.mm
+index f612ba2fb795..77c2c68e6f9b 100644
+--- a/chrome/browser/extensions/global_shortcut_listener_mac.mm
++++ b/chrome/browser/extensions/global_shortcut_listener_mac.mm
+@@ -20,6 +20,26 @@ using extensions::GlobalShortcutListenerMac;
+ 
+ namespace extensions {
+ 
++// NOTE: this is defined in command.cc, but command.cc is full of
++// chrome-extensions-specific logic that we don't want to depend on.
++// Since we don't build command.cc in Electron, it's safe to re-define this
++// function here. Ideally, though, `IsMediaKey` would be the responsibility of
++// `ui::Accelerator`, rather than `extensions::Command`.
++
++// static
++bool Command::IsMediaKey(const ui::Accelerator& accelerator) {
++  if (accelerator.modifiers() != 0)
++    return false;
++
++  return (accelerator.key_code() == ui::VKEY_MEDIA_NEXT_TRACK ||
++          accelerator.key_code() == ui::VKEY_MEDIA_PREV_TRACK ||
++          accelerator.key_code() == ui::VKEY_MEDIA_PLAY_PAUSE ||
++          accelerator.key_code() == ui::VKEY_MEDIA_STOP ||
++          accelerator.key_code() == ui::VKEY_VOLUME_UP ||
++          accelerator.key_code() == ui::VKEY_VOLUME_DOWN ||
++          accelerator.key_code() == ui::VKEY_VOLUME_MUTE);
++}
++
+ // static
+ GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
+   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+diff --git a/chrome/browser/extensions/global_shortcut_listener_win.cc b/chrome/browser/extensions/global_shortcut_listener_win.cc
+index 65b244d55441..a217f0a1ad96 100644
+--- a/chrome/browser/extensions/global_shortcut_listener_win.cc
++++ b/chrome/browser/extensions/global_shortcut_listener_win.cc
+@@ -63,6 +63,8 @@ void GlobalShortcutListenerWin::OnWndProc(HWND hwnd,
+   modifiers |= (LOWORD(lparam) & MOD_SHIFT) ? ui::EF_SHIFT_DOWN : 0;
+   modifiers |= (LOWORD(lparam) & MOD_ALT) ? ui::EF_ALT_DOWN : 0;
+   modifiers |= (LOWORD(lparam) & MOD_CONTROL) ? ui::EF_CONTROL_DOWN : 0;
++  modifiers |= (LOWORD(lparam) & MOD_WIN) ? ui::EF_COMMAND_DOWN : 0;
++
+   ui::Accelerator accelerator(
+       ui::KeyboardCodeForWindowsKeyCode(key_code), modifiers);
+ 
+@@ -77,6 +79,8 @@ bool GlobalShortcutListenerWin::RegisterAcceleratorImpl(
+   modifiers |= accelerator.IsShiftDown() ? MOD_SHIFT : 0;
+   modifiers |= accelerator.IsCtrlDown() ? MOD_CONTROL : 0;
+   modifiers |= accelerator.IsAltDown() ? MOD_ALT : 0;
++  modifiers |= accelerator.IsCmdDown() ? MOD_WIN : 0;
++
+   static int hotkey_id = 0;
+   bool success = !!RegisterHotKey(
+       gfx::SingletonHwnd::GetInstance()->hwnd(),
+diff --git a/chrome/browser/extensions/global_shortcut_listener_x11.cc b/chrome/browser/extensions/global_shortcut_listener_x11.cc
+index 362811063a42..fc407da7047b 100644
+--- a/chrome/browser/extensions/global_shortcut_listener_x11.cc
++++ b/chrome/browser/extensions/global_shortcut_listener_x11.cc
+@@ -38,6 +38,7 @@ int GetNativeModifiers(const ui::Accelerator& accelerator) {
+   modifiers |= accelerator.IsShiftDown() ? ShiftMask : 0;
+   modifiers |= accelerator.IsCtrlDown() ? ControlMask : 0;
+   modifiers |= accelerator.IsAltDown() ? Mod1Mask : 0;
++  modifiers |= accelerator.IsCmdDown() ? Mod4Mask : 0;
+ 
+   return modifiers;
+ }
+@@ -151,6 +152,8 @@ void GlobalShortcutListenerX11::OnXKeyPressEvent(::XEvent* x_event) {
+   modifiers |= (x_event->xkey.state & ShiftMask) ? ui::EF_SHIFT_DOWN : 0;
+   modifiers |= (x_event->xkey.state & ControlMask) ? ui::EF_CONTROL_DOWN : 0;
+   modifiers |= (x_event->xkey.state & Mod1Mask) ? ui::EF_ALT_DOWN : 0;
++  // For Windows key
++  modifiers |= (x_event->xkey.state & Mod4Mask) ? ui::EF_COMMAND_DOWN: 0;
+ 
+   ui::Accelerator accelerator(
+       ui::KeyboardCodeFromXKeyEvent(x_event), modifiers);
+diff --git a/ui/base/accelerators/media_keys_listener_mac.mm b/ui/base/accelerators/media_keys_listener_mac.mm
+index cd595b0c017d..941c1a76a1c3 100644
+--- a/ui/base/accelerators/media_keys_listener_mac.mm
++++ b/ui/base/accelerators/media_keys_listener_mac.mm
+@@ -30,6 +30,12 @@ ui::KeyboardCode MediaKeyCodeToKeyboardCode(int key_code) {
+     case NX_KEYTYPE_NEXT:
+     case NX_KEYTYPE_FAST:
+       return ui::VKEY_MEDIA_NEXT_TRACK;
++    case NX_KEYTYPE_SOUND_UP:
++      return ui::VKEY_VOLUME_UP;
++    case NX_KEYTYPE_SOUND_DOWN:
++      return ui::VKEY_VOLUME_DOWN;
++    case NX_KEYTYPE_MUTE:
++      return ui::VKEY_VOLUME_MUTE;
+   }
+   return ui::VKEY_UNKNOWN;
+ }
+@@ -180,7 +186,10 @@ CGEventRef MediaKeysListenerImpl::EventTapCallback(CGEventTapProxy proxy,
+   int key_code = (data1 & 0xFFFF0000) >> 16;
+   if (key_code != NX_KEYTYPE_PLAY && key_code != NX_KEYTYPE_NEXT &&
+       key_code != NX_KEYTYPE_PREVIOUS && key_code != NX_KEYTYPE_FAST &&
+-      key_code != NX_KEYTYPE_REWIND) {
++      key_code != NX_KEYTYPE_REWIND &&
++      key_code != NX_KEYTYPE_SOUND_UP &&
++      key_code != NX_KEYTYPE_SOUND_DOWN &&
++      key_code != NX_KEYTYPE_MUTE) {
+     return event;
+   }
+ 
+-- 
+2.17.0
+