1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_
6 #define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_
8 #include "chrome/browser/extensions/global_shortcut_listener.h"
10 #include <Carbon/Carbon.h>
11 #include <CoreFoundation/CoreFoundation.h>
15 #include "base/mac/scoped_nsobject.h"
17 namespace extensions {
19 // Mac-specific implementation of the GlobalShortcutListener class that
20 // listens for global shortcuts. Handles basic keyboard intercepting and
21 // forwards its output to the base class for processing.
23 // This class does two things:
24 // 1. Intercepts media keys. Uses an event tap for intercepting media keys
25 // (PlayPause, NextTrack, PreviousTrack).
26 // 2. Binds keyboard shortcuts (hot keys). Carbon RegisterEventHotKey API for
27 // binding to non-media key global hot keys (eg. Command-Shift-1).
28 class GlobalShortcutListenerMac : public GlobalShortcutListener {
30 GlobalShortcutListenerMac();
31 ~GlobalShortcutListenerMac() override;
35 typedef std::map<ui::Accelerator, KeyId> AcceleratorIdMap;
36 typedef std::map<KeyId, ui::Accelerator> IdAcceleratorMap;
37 typedef std::map<KeyId, EventHotKeyRef> IdHotKeyRefMap;
39 // Keyboard event callbacks.
40 void OnHotKeyEvent(EventHotKeyID hot_key_id);
41 bool OnMediaKeyEvent(int key_code);
43 // GlobalShortcutListener implementation.
44 void StartListening() override;
45 void StopListening() override;
46 bool RegisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
47 void UnregisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
49 // Mac-specific functions for registering hot keys with modifiers.
50 bool RegisterHotKey(const ui::Accelerator& accelerator, KeyId hot_key_id);
51 void UnregisterHotKey(const ui::Accelerator& accelerator);
53 // Enable and disable the media key event tap.
54 void StartWatchingMediaKeys();
55 void StopWatchingMediaKeys();
57 // Enable and disable the hot key event handler.
58 void StartWatchingHotKeys();
59 void StopWatchingHotKeys();
61 // Whether or not any media keys are currently registered.
62 bool IsAnyMediaKeyRegistered();
64 // Whether or not any hot keys are currently registered.
65 bool IsAnyHotKeyRegistered();
67 // The callback for when an event tap happens.
68 static CGEventRef EventTapCallback(
69 CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon);
71 // The callback for when a hot key event happens.
72 static OSStatus HotKeyHandler(
73 EventHandlerCallRef next_handler, EventRef event, void* user_data);
75 // Whether this object is listening for global shortcuts.
78 // The hotkey identifier for the next global shortcut that is added.
81 // A map of all hotkeys (media keys and shortcuts) mapping to their
82 // corresponding hotkey IDs. For quickly finding if an accelerator is
84 AcceleratorIdMap accelerator_ids_;
86 // The inverse map for quickly looking up accelerators by hotkey id.
87 IdAcceleratorMap id_accelerators_;
89 // Keyboard shortcut IDs to hotkeys map for unregistration.
90 IdHotKeyRefMap id_hot_key_refs_;
92 // Event tap for intercepting mac media keys.
93 CFMachPortRef event_tap_;
94 CFRunLoopSourceRef event_tap_source_;
96 // Event handler for keyboard shortcut hot keys.
97 EventHandlerRef event_handler_;
99 DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerMac);
102 } // namespace extensions
104 #endif // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_