win: Implement global keyboard shortcut API.
This commit is contained in:
parent
4b3bd9c3cc
commit
c2c5111d75
3 changed files with 177 additions and 0 deletions
2
atom.gyp
2
atom.gyp
|
@ -238,6 +238,8 @@
|
|||
'chromium_src/chrome/browser/ui/shortcut/global_shortcut_listener.h',
|
||||
'chromium_src/chrome/browser/ui/shortcut/global_shortcut_listener_mac.mm',
|
||||
'chromium_src/chrome/browser/ui/shortcut/global_shortcut_listener_mac.h',
|
||||
'chromium_src/chrome/browser/ui/shortcut/global_shortcut_listener_win.cc',
|
||||
'chromium_src/chrome/browser/ui/shortcut/global_shortcut_listener_win.h',
|
||||
'<@(native_mate_files)',
|
||||
],
|
||||
'framework_sources': [
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
// Copyright (c) 2014 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/ui/shortcut/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 atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
// static
|
||||
GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
|
||||
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
static GlobalShortcutListenerWin* instance =
|
||||
new GlobalShortcutListenerWin();
|
||||
return instance;
|
||||
}
|
||||
|
||||
GlobalShortcutListenerWin::GlobalShortcutListenerWin()
|
||||
: is_listening_(false) {
|
||||
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
}
|
||||
|
||||
GlobalShortcutListenerWin::~GlobalShortcutListenerWin() {
|
||||
if (is_listening_)
|
||||
StopListening();
|
||||
}
|
||||
|
||||
bool GlobalShortcutListenerWin::IsAcceleratorRegistered(
|
||||
const ui::Accelerator& accelerator) {
|
||||
return hotkey_ids_.find(accelerator) != hotkey_ids_.end();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
NotifyKeyPressed(accelerator);
|
||||
}
|
||||
|
||||
bool GlobalShortcutListenerWin::RegisterAcceleratorImpl(
|
||||
const ui::Accelerator& accelerator) {
|
||||
DCHECK(hotkey_ids_.find(accelerator) == hotkey_ids_.end());
|
||||
|
||||
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 = false;
|
||||
bool success = !!RegisterHotKey(
|
||||
gfx::SingletonHwnd::GetInstance()->hwnd(),
|
||||
hotkey_id,
|
||||
modifiers,
|
||||
accelerator.key_code());
|
||||
|
||||
if (!success) {
|
||||
// Most likely error: 1409 (Hotkey already registered).
|
||||
return false;
|
||||
}
|
||||
|
||||
hotkey_ids_[accelerator] = hotkey_id++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GlobalShortcutListenerWin::UnregisterAcceleratorImpl(
|
||||
const ui::Accelerator& accelerator) {
|
||||
HotkeyIdMap::iterator it = hotkey_ids_.find(accelerator);
|
||||
DCHECK(it != hotkey_ids_.end());
|
||||
|
||||
//bool success = false;
|
||||
gfx::SingletonHwnd::GetInstance();
|
||||
bool success = !!UnregisterHotKey(
|
||||
gfx::SingletonHwnd::GetInstance()->hwnd(), it->second);
|
||||
// This call should always succeed, as long as we pass in the right HWND and
|
||||
// an id we've used to register before.
|
||||
DCHECK(success);
|
||||
|
||||
hotkey_ids_.erase(it);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) 2014 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.
|
||||
|
||||
#ifndef CHROME_BROWSER_UI_SHORTCUT_GLOBAL_SHORTCUT_LISTENER_WIN_H_
|
||||
#define CHROME_BROWSER_UI_SHORTCUT_GLOBAL_SHORTCUT_LISTENER_WIN_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "chrome/browser/ui/shortcut/global_shortcut_listener.h"
|
||||
#include "ui/gfx/win/singleton_hwnd.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
// Windows-specific implementation of the GlobalShortcutListener class that
|
||||
// listens for global shortcuts. Handles setting up a keyboard hook and
|
||||
// forwarding its output to the base class for processing.
|
||||
class GlobalShortcutListenerWin : public GlobalShortcutListener,
|
||||
public gfx::SingletonHwnd::Observer {
|
||||
public:
|
||||
GlobalShortcutListenerWin();
|
||||
virtual ~GlobalShortcutListenerWin();
|
||||
|
||||
virtual bool IsAcceleratorRegistered(
|
||||
const ui::Accelerator& accelerator) OVERRIDE;
|
||||
|
||||
private:
|
||||
// The implementation of our Window Proc, called by SingletonHwnd.
|
||||
virtual void OnWndProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) OVERRIDE;
|
||||
|
||||
// GlobalShortcutListener implementation.
|
||||
virtual void StartListening() OVERRIDE;
|
||||
virtual void StopListening() OVERRIDE;
|
||||
virtual bool RegisterAcceleratorImpl(
|
||||
const ui::Accelerator& accelerator) OVERRIDE;
|
||||
virtual void UnregisterAcceleratorImpl(
|
||||
const ui::Accelerator& accelerator) OVERRIDE;
|
||||
|
||||
// Whether this object is listening for global shortcuts.
|
||||
bool is_listening_;
|
||||
|
||||
// A map of registered accelerators and their registration ids.
|
||||
typedef std::map<ui::Accelerator, int> HotkeyIdMap;
|
||||
HotkeyIdMap hotkey_ids_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerWin);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // CHROME_BROWSER_UI_SHORTCUT_GLOBAL_SHORTCUT_LISTENER_WIN_H_
|
Loading…
Reference in a new issue