blob: af972bb5193296e7af120918d5b07b9c3dbf19d3 [file] [log] [blame]
// 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 <Carbon/Carbon.h>
#include <map>
#include <memory>
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "ui/base/accelerators/media_keys_listener.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 keys. Uses an event tap for intercepting media keys
// (PlayPause, NextTrack, PreviousTrack).
// 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 ui::MediaKeysListener::Delegate {
~GlobalShortcutListenerMac() override;
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);
// GlobalShortcutListener implementation.
void StartListening() override;
void StopListening() override;
bool RegisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
void UnregisterAcceleratorImpl(const ui::Accelerator& accelerator) override;
// ui::MediaKeysListener::Delegate:
void OnMediaKeysAccelerator(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 hot key event handler.
void StartWatchingHotKeys();
void StopWatchingHotKeys();
// Whether or not any hot keys are currently registered.
bool IsAnyHotKeyRegistered();
// 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 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 handler for keyboard shortcut hot keys.
EventHandlerRef event_handler_;
// Media keys listener.
std::unique_ptr<ui::MediaKeysListener> media_keys_listener_;
} // namespace extensions