Browse Source

fix: media key globalShortcuts on macOS (#30568)

Co-authored-by: Shelley Vohr <[email protected]>
Co-authored-by: John Kleinschmidt <[email protected]>
Co-authored-by: Cheng Zhao <[email protected]>
trop[bot] 3 years ago
parent
commit
75349f58ad

+ 1 - 0
patches/chromium/.patches

@@ -129,6 +129,7 @@ cherry-pick-1230767.patch
 cherry-pick-1231134.patch
 cherry-pick-1233564.patch
 cherry-pick-1234009.patch
+fix_media_key_usage_with_globalshortcuts.patch
 attach_to_correct_frame_in.patch
 merge_m92_speculative_fix_for_crash_in.patch
 cherry-pick-d727013bb543.patch

+ 64 - 0
patches/chromium/fix_media_key_usage_with_globalshortcuts.patch

@@ -0,0 +1,64 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Shelley Vohr <[email protected]>
+Date: Mon, 16 Aug 2021 17:55:32 +0200
+Subject: fix: media key usage with globalShortcuts
+
+This patch enables media keys to work properly with Electron's globalShortcut
+module. Chromium's default usage of RemoteCommandCenterDelegate on macOS falls
+down into MPRemoteCommandCenter, which makes it such that an app will not
+receive remote control events until it begins playing audio. This runs
+counter to the design of globalShortcuts, and so we need to instead
+use `ui::MediaKeysListener`.
+
+diff --git a/content/browser/media/media_keys_listener_manager_impl.cc b/content/browser/media/media_keys_listener_manager_impl.cc
+index 5938f75742b793868638e693a9a8c8dc686dfc46..bf8782c23095a09dec62c68d7d902df24abcb13e 100644
+--- a/content/browser/media/media_keys_listener_manager_impl.cc
++++ b/content/browser/media/media_keys_listener_manager_impl.cc
+@@ -231,7 +231,7 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
+       media::AudioManager::GetGlobalAppName());
+ #endif
+ 
+-  if (system_media_controls_) {
++  if (/* DISABLES CODE */ (0)) {
+     system_media_controls_->AddObserver(this);
+     system_media_controls_notifier_ =
+         std::make_unique<SystemMediaControlsNotifier>(
+@@ -239,8 +239,13 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
+   } else {
+     // If we can't access system media controls, then directly listen for media
+     // key keypresses instead.
++#if defined(OS_MAC)
++  media_keys_listener_ = ui::MediaKeysListener::Create(
++        this, ui::MediaKeysListener::Scope::kGlobalRequiresAccessibility);
++#else
+     media_keys_listener_ = ui::MediaKeysListener::Create(
+         this, ui::MediaKeysListener::Scope::kGlobal);
++#endif
+     DCHECK(media_keys_listener_);
+   }
+ 
+diff --git a/ui/base/accelerators/media_keys_listener.h b/ui/base/accelerators/media_keys_listener.h
+index c2b03328c0e508995bdc135031500783f500ceba..1b6b14dc2999c99445cef6ffc04d49a7c1728a54 100644
+--- a/ui/base/accelerators/media_keys_listener.h
++++ b/ui/base/accelerators/media_keys_listener.h
+@@ -20,6 +20,7 @@ class Accelerator;
+ class COMPONENT_EXPORT(UI_BASE) MediaKeysListener {
+  public:
+   enum class Scope {
++    kGlobalRequiresAccessibility, // Listener works whenever application in focus or not but requires accessibility permissions on macOS
+     kGlobal,   // Listener works whenever application in focus or not.
+     kFocused,  // Listener only works whan application has focus.
+   };
+diff --git a/ui/base/accelerators/media_keys_listener_win.cc b/ui/base/accelerators/media_keys_listener_win.cc
+index 6c63a88cbb13cfcc9a8ba652554839275ae1ee04..1643eafc094dce77e4ba8752cd02e1ae6c488b56 100644
+--- a/ui/base/accelerators/media_keys_listener_win.cc
++++ b/ui/base/accelerators/media_keys_listener_win.cc
+@@ -13,7 +13,7 @@ std::unique_ptr<MediaKeysListener> MediaKeysListener::Create(
+     MediaKeysListener::Scope scope) {
+   DCHECK(delegate);
+ 
+-  if (scope == Scope::kGlobal) {
++  if (scope == Scope::kGlobal || scope == Scope::kGlobalRequiresAccessibility) {
+     // We should never have more than one global media keys listener.
+     if (!GlobalMediaKeysListenerWin::has_instance())
+       return std::make_unique<GlobalMediaKeysListenerWin>(delegate);

+ 17 - 1
spec-main/api-global-shortcut-spec.ts

@@ -1,5 +1,5 @@
 import { expect } from 'chai';
-import { globalShortcut } from 'electron/main';
+import { globalShortcut, BrowserWindow } from 'electron/main';
 import { ifdescribe } from './spec-helpers';
 
 ifdescribe(process.platform !== 'win32')('globalShortcut module', () => {
@@ -55,4 +55,20 @@ ifdescribe(process.platform !== 'win32')('globalShortcut module', () => {
 
     globalShortcut.unregisterAll();
   });
+
+  it('successfully registers and calls the callback for media keys', function (done) {
+    let robotjs;
+    try {
+      robotjs = require('robotjs');
+    } catch (err) {
+      this.skip();
+    }
+
+    globalShortcut.register('MediaPlayPause', () => done());
+
+    const w = new BrowserWindow({ show: false });
+    w.loadURL('about:blank');
+
+    robotjs.keyTap('audio_play');
+  });
 });