| Index: chrome/browser/extensions/global_shortcut_listener_win.cc
|
| diff --git a/chrome/browser/extensions/global_shortcut_listener_win.cc b/chrome/browser/extensions/global_shortcut_listener_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..462ff673ded60281bbe946c8f4ecaa2ec610ee7a
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/global_shortcut_listener_win.cc
|
| @@ -0,0 +1,112 @@
|
| +// 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/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"
|
| +
|
| +using content::BrowserThread;
|
| +
|
| +namespace {
|
| +
|
| +static base::LazyInstance<extensions::GlobalShortcutListenerWin> instance =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +} // namespace
|
| +
|
| +namespace extensions {
|
| +
|
| +// static
|
| +GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
|
| + CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + return instance.Pointer();
|
| +}
|
| +
|
| +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.
|
| + gfx::SingletonHwnd::GetInstance()->AddObserver(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.
|
| + gfx::SingletonHwnd::GetInstance()->RemoveObserver(this);
|
| + 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;
|
| + ui::Accelerator accelerator(
|
| + ui::KeyboardCodeForWindowsKeyCode(key_code), modifiers);
|
| +
|
| + instance.Get().NotifyKeyPressed(accelerator);
|
| +}
|
| +
|
| +void GlobalShortcutListenerWin::RegisterAccelerator(
|
| + const ui::Accelerator& accelerator,
|
| + GlobalShortcutListener::Observer* observer) {
|
| + int modifiers = 0;
|
| + modifiers |= accelerator.IsShiftDown() ? MOD_SHIFT : 0;
|
| + modifiers |= accelerator.IsCtrlDown() ? MOD_CONTROL : 0;
|
| + modifiers |= accelerator.IsAltDown() ? MOD_ALT : 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).
|
| + LOG(ERROR) << "RegisterHotKey failed, error: " << GetLastError();
|
| + return;
|
| + }
|
| +
|
| + hotkey_ids_[accelerator] = hotkey_id++;
|
| + GlobalShortcutListener::RegisterAccelerator(accelerator, observer);
|
| +}
|
| +
|
| +void GlobalShortcutListenerWin::UnregisterAccelerator(
|
| + const ui::Accelerator& accelerator,
|
| + GlobalShortcutListener::Observer* observer) {
|
| + // We may get asked to unregister something that we couldn't register (for
|
| + // example if the shortcut was already taken by another app), so we
|
| + // need to handle that gracefully.
|
| + HotkeyIdMap::iterator it = hotkey_ids_.find(accelerator);
|
| + if (it == hotkey_ids_.end())
|
| + return;
|
| +
|
| + UnregisterHotKey(gfx::SingletonHwnd::GetInstance()->hwnd(), it->second);
|
| + hotkey_ids_.erase(it);
|
| +
|
| + GlobalShortcutListener::UnregisterAccelerator(accelerator, observer);
|
| +}
|
| +
|
| +} // namespace extensions
|
|
|