From ce26687577b9c09f7746b53bee861248f9d1d073 Mon Sep 17 00:00:00 2001 From: Jeremy Apthorp Date: Wed, 10 Oct 2018 22:02:58 -0700 Subject: [PATCH] refactor: remove global_shortcut_listener from chromium_src/ (#15070) --- chromium_src/BUILD.gn | 10 + .../extensions/global_shortcut_listener.cc | 123 ------ .../extensions/global_shortcut_listener.h | 99 ----- .../extensions/global_shortcut_listener_mac.h | 108 ----- .../global_shortcut_listener_mac.mm | 398 ------------------ .../global_shortcut_listener_win.cc | 109 ----- .../extensions/global_shortcut_listener_win.h | 50 --- .../global_shortcut_listener_x11.cc | 161 ------- .../extensions/global_shortcut_listener_x11.h | 58 --- filenames.gni | 8 - patches/common/chromium/.patches.yaml | 12 + .../common/chromium/command-ismediakey.patch | 122 ++++++ 12 files changed, 144 insertions(+), 1114 deletions(-) delete mode 100644 chromium_src/chrome/browser/extensions/global_shortcut_listener.cc delete mode 100644 chromium_src/chrome/browser/extensions/global_shortcut_listener.h delete mode 100644 chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.h delete mode 100644 chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm delete mode 100644 chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc delete mode 100644 chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h delete mode 100644 chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.cc delete mode 100644 chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h create mode 100644 patches/common/chromium/command-ismediakey.patch diff --git a/chromium_src/BUILD.gn b/chromium_src/BUILD.gn index c2014fa175..b9994788ea 100644 --- a/chromium_src/BUILD.gn +++ b/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) { diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener.cc b/chromium_src/chrome/browser/extensions/global_shortcut_listener.cc deleted file mode 100644 index 7cbcf0b551..0000000000 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener.cc +++ /dev/null @@ -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 diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener.h b/chromium_src/chrome/browser/extensions/global_shortcut_listener.h deleted file mode 100644 index 9aec54a326..0000000000 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener.h +++ /dev/null @@ -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 - -#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 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_ diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.h b/chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.h deleted file mode 100644 index 5ee38d6fa2..0000000000 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.h +++ /dev/null @@ -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 -#include - -#include - -#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 AcceleratorIdMap; - typedef std::map IdAcceleratorMap; - typedef std::map 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_ diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm b/chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm deleted file mode 100644 index 5f66bea001..0000000000 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm +++ /dev/null @@ -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 -#import -#include - -#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(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(user_data); - shortcut_listener->OnHotKeyEvent(hot_key_id); - return noErr; -} - -} // namespace extensions diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc b/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc deleted file mode 100644 index a9e578a566..0000000000 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc +++ /dev/null @@ -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 diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h b/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h deleted file mode 100644 index 1a8b6dddef..0000000000 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h +++ /dev/null @@ -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 - -#include - -#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 HotkeyIdMap; - HotkeyIdMap hotkey_ids_; - - std::unique_ptr singleton_hwnd_observer_; - - DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerWin); -}; - -} // namespace extensions - -#endif // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_WIN_H_ diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.cc b/chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.cc deleted file mode 100644 index 98f1108d56..0000000000 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.cc +++ /dev/null @@ -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 - -#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 diff --git a/chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h b/chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h deleted file mode 100644 index 32953c4e16..0000000000 --- a/chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h +++ /dev/null @@ -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 - -#include - -#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 RegisteredHotKeys; - RegisteredHotKeys registered_hot_keys_; - - DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerX11); -}; - -} // namespace extensions - -#endif // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_X11_H_ diff --git a/filenames.gni b/filenames.gni index 3797aa8ad2..79d4ec8b17 100644 --- a/filenames.gni +++ b/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", diff --git a/patches/common/chromium/.patches.yaml b/patches/common/chromium/.patches.yaml index 1152b3235e..34e0238f22 100644 --- a/patches/common/chromium/.patches.yaml +++ b/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 + 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. diff --git a/patches/common/chromium/command-ismediakey.patch b/patches/common/chromium/command-ismediakey.patch new file mode 100644 index 0000000000..c479d9e911 --- /dev/null +++ b/patches/common/chromium/command-ismediakey.patch @@ -0,0 +1,122 @@ +From 2d028f727b68a0aa7f83cc069e1df4d13a9e173e Mon Sep 17 00:00:00 2001 +From: Jeremy Apthorp +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 +