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. 4 5 #ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_ 6 #define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_ 7 8 #include "chrome/browser/extensions/global_shortcut_listener.h" 9 10 #include <Carbon/Carbon.h> 11 #include <CoreFoundation/CoreFoundation.h> 12 13 #include <map> 14 15 #include "base/mac/scoped_nsobject.h" 16 17 namespace extensions { 18 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. 22 // 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 { 29 public: 30 GlobalShortcutListenerMac(); 31 virtual ~GlobalShortcutListenerMac(); 32 33 private: 34 typedef int KeyId; 35 typedef std::map<ui::Accelerator, KeyId> AcceleratorIdMap; 36 typedef std::map<KeyId, ui::Accelerator> IdAcceleratorMap; 37 typedef std::map<KeyId, EventHotKeyRef> IdHotKeyRefMap; 38 39 // Keyboard event callbacks. 40 void OnHotKeyEvent(EventHotKeyID hot_key_id); 41 bool OnMediaKeyEvent(int key_code); 42 43 // GlobalShortcutListener implementation. 44 virtual void StartListening() OVERRIDE; 45 virtual void StopListening() OVERRIDE; 46 virtual bool RegisterAcceleratorImpl( 47 const ui::Accelerator& accelerator) OVERRIDE; 48 virtual void UnregisterAcceleratorImpl( 49 const ui::Accelerator& accelerator) OVERRIDE; 50 51 // Mac-specific functions for registering hot keys with modifiers. 52 bool RegisterHotKey(const ui::Accelerator& accelerator, KeyId hot_key_id); 53 void UnregisterHotKey(const ui::Accelerator& accelerator); 54 55 // Enable and disable the media key event tap. 56 void StartWatchingMediaKeys(); 57 void StopWatchingMediaKeys(); 58 59 // Enable and disable the hot key event handler. 60 void StartWatchingHotKeys(); 61 void StopWatchingHotKeys(); 62 63 // Whether or not any media keys are currently registered. 64 bool IsAnyMediaKeyRegistered(); 65 66 // Whether or not any hot keys are currently registered. 67 bool IsAnyHotKeyRegistered(); 68 69 // The callback for when an event tap happens. 70 static CGEventRef EventTapCallback( 71 CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon); 72 73 // The callback for when a hot key event happens. 74 static OSStatus HotKeyHandler( 75 EventHandlerCallRef next_handler, EventRef event, void* user_data); 76 77 // Whether this object is listening for global shortcuts. 78 bool is_listening_; 79 80 // The hotkey identifier for the next global shortcut that is added. 81 KeyId hot_key_id_; 82 83 // A map of all hotkeys (media keys and shortcuts) mapping to their 84 // corresponding hotkey IDs. For quickly finding if an accelerator is 85 // registered. 86 AcceleratorIdMap accelerator_ids_; 87 88 // The inverse map for quickly looking up accelerators by hotkey id. 89 IdAcceleratorMap id_accelerators_; 90 91 // Keyboard shortcut IDs to hotkeys map for unregistration. 92 IdHotKeyRefMap id_hot_key_refs_; 93 94 // Event tap for intercepting mac media keys. 95 CFMachPortRef event_tap_; 96 CFRunLoopSourceRef event_tap_source_; 97 98 // Event handler for keyboard shortcut hot keys. 99 EventHandlerRef event_handler_; 100 101 DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerMac); 102 }; 103 104 } // namespace extensions 105 106 #endif // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_ 107