Allowing mouse events
This commit is contained in:
parent
222b43f1d0
commit
f2a7c39abe
@ -11,7 +11,8 @@
|
|||||||
#endif
|
#endif
|
||||||
class KeyboardHook {
|
class KeyboardHook {
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
friend LRESULT CALLBACK keyboard_hook_callback(int, WPARAM, LPARAM);
|
friend LRESULT CALLBACK _keyboard_hook_callback(int, WPARAM, LPARAM);
|
||||||
|
friend LRESULT CALLBACK _mouse_hook_callback(int, WPARAM, LPARAM);
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
struct KeyType {
|
struct KeyType {
|
||||||
@ -63,9 +64,14 @@ class KeyboardHook {
|
|||||||
long end_id = 0;
|
long end_id = 0;
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
typedef UINT KeyID;
|
typedef UINT KeyID;
|
||||||
HHOOK hook_id = nullptr;
|
HHOOK keyboad_hook_id{nullptr};
|
||||||
bool _hook_callback(int, WPARAM, LPARAM);
|
HHOOK mouse_hook_id{nullptr};
|
||||||
#endif
|
|
||||||
|
bool keyboard_hook_callback(int, WPARAM, LPARAM);
|
||||||
|
bool mouse_hook_callback(int, WPARAM, LPARAM);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void trigger_key_event(const enum KeyEvent::type&, const std::string& /* key */);
|
||||||
|
|
||||||
std::map<KeyID, bool> map_key;
|
std::map<KeyID, bool> map_key;
|
||||||
std::map<KeyID, KeyID> map_special;
|
std::map<KeyID, KeyID> map_special;
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <string>
|
||||||
#include "KeyboardHook.h"
|
#include "KeyboardHook.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
typedef KBDLLHOOKSTRUCT KeyboardHookStruct;
|
typedef KBDLLHOOKSTRUCT KeyboardHookStruct;
|
||||||
LRESULT CALLBACK keyboard_hook_callback(int, WPARAM, LPARAM);
|
typedef MSLLHOOKSTRUCT MouseHookStruct;
|
||||||
std::map<thread::id, KeyboardHook*> hook_handles;
|
std::map<thread::id, KeyboardHook*> hook_handles;
|
||||||
|
|
||||||
KeyboardHook::KeyboardHook() {}
|
KeyboardHook::KeyboardHook() {}
|
||||||
@ -14,6 +15,21 @@ KeyboardHook::~KeyboardHook() {
|
|||||||
this->detach();
|
this->detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyboardHook::trigger_key_event(const enum KeyEvent::type& type, const std::string &key) {
|
||||||
|
if(!this->callback_event) return;
|
||||||
|
|
||||||
|
auto event = make_shared<KeyboardHook::KeyEvent>();
|
||||||
|
event->type = type;
|
||||||
|
event->code = key;
|
||||||
|
|
||||||
|
event->key_alt = this->map_special[KeyType::KEY_ALT];
|
||||||
|
event->key_ctrl = this->map_special[KeyType::KEY_CTRL];
|
||||||
|
event->key_windows = this->map_special[KeyType::KEY_WIN];
|
||||||
|
event->key_shift = this->map_special[KeyType::KEY_SHIFT];
|
||||||
|
|
||||||
|
this->callback_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
bool KeyboardHook::attach() {
|
bool KeyboardHook::attach() {
|
||||||
assert(!this->_attached);
|
assert(!this->_attached);
|
||||||
this->active = true;
|
this->active = true;
|
||||||
@ -36,13 +52,38 @@ void KeyboardHook::detach() {
|
|||||||
this->_attached = false;
|
this->_attached = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LRESULT _keyboard_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) {
|
||||||
|
auto handle = hook_handles[this_thread::get_id()];
|
||||||
|
assert(handle);
|
||||||
|
auto consume = handle->keyboard_hook_callback(nCode, event, ptr_keyboard);
|
||||||
|
if(consume)
|
||||||
|
return 1;
|
||||||
|
return CallNextHookEx(nullptr, nCode, event, ptr_keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT _mouse_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) {
|
||||||
|
auto handle = hook_handles[this_thread::get_id()];
|
||||||
|
assert(handle);
|
||||||
|
auto consume = handle->mouse_hook_callback(nCode, event, ptr_keyboard);
|
||||||
|
if(consume)
|
||||||
|
return 1;
|
||||||
|
return CallNextHookEx(nullptr, nCode, event, ptr_keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
void KeyboardHook::poll_events() {
|
void KeyboardHook::poll_events() {
|
||||||
hook_handles[this_thread::get_id()] = this;
|
hook_handles[this_thread::get_id()] = this;
|
||||||
this->hook_id = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_callback, GetModuleHandle(nullptr), 0);
|
this->keyboad_hook_id = SetWindowsHookEx(WH_KEYBOARD_LL, _keyboard_hook_callback, GetModuleHandle(nullptr), 0);
|
||||||
if(!this->hook_id) {
|
if(!this->keyboad_hook_id) {
|
||||||
cerr << "Failed to register hook!" << endl;
|
cerr << "Failed to register keyboard hook" << endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->mouse_hook_id = SetWindowsHookEx(WH_MOUSE_LL, _mouse_hook_callback, GetModuleHandle(nullptr), 0);
|
||||||
|
if(!this->keyboad_hook_id) {
|
||||||
|
UnhookWindowsHookEx(this->keyboad_hook_id);
|
||||||
|
cerr << "Failed to register mouse hook" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MSG msg;
|
MSG msg;
|
||||||
while(!GetMessage(&msg, nullptr, 0, 0) && this->active) {
|
while(!GetMessage(&msg, nullptr, 0, 0) && this->active) {
|
||||||
@ -50,19 +91,10 @@ void KeyboardHook::poll_events() {
|
|||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnhookWindowsHookEx(this->hook_id);
|
UnhookWindowsHookEx(this->keyboad_hook_id);
|
||||||
hook_handles[this_thread::get_id()] = nullptr;
|
hook_handles[this_thread::get_id()] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT keyboard_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) {
|
|
||||||
auto handle = hook_handles[this_thread::get_id()];
|
|
||||||
assert(handle);
|
|
||||||
auto consume = handle->_hook_callback(nCode, event, ptr_keyboard);
|
|
||||||
if(consume)
|
|
||||||
return 1;
|
|
||||||
return CallNextHookEx(nullptr, nCode, event, ptr_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string key_code(DWORD code, bool extended = false) {
|
inline std::string key_code(DWORD code, bool extended = false) {
|
||||||
auto scan_code = MapVirtualKey(code, MAPVK_VK_TO_VSC);
|
auto scan_code = MapVirtualKey(code, MAPVK_VK_TO_VSC);
|
||||||
if(extended)
|
if(extended)
|
||||||
@ -78,7 +110,7 @@ inline std::string key_code(DWORD code, bool extended = false) {
|
|||||||
|
|
||||||
inline std::string key_code(KeyboardHookStruct* keyboard) {
|
inline std::string key_code(KeyboardHookStruct* keyboard) {
|
||||||
return key_code(keyboard->vkCode, (keyboard->flags & LLKHF_EXTENDED) > 0);
|
return key_code(keyboard->vkCode, (keyboard->flags & LLKHF_EXTENDED) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
using KeyType = KeyboardHook::KeyType;
|
using KeyType = KeyboardHook::KeyType;
|
||||||
//https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes
|
//https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes
|
||||||
@ -104,7 +136,7 @@ inline KeyType::value key_type(DWORD vk_code) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardHook::_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) {
|
bool KeyboardHook::keyboard_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) {
|
||||||
auto keyboard = (KeyboardHookStruct*) ptr_keyboard;
|
auto keyboard = (KeyboardHookStruct*) ptr_keyboard;
|
||||||
if(event == WM_KEYDOWN || event == WM_SYSKEYDOWN) {
|
if(event == WM_KEYDOWN || event == WM_SYSKEYDOWN) {
|
||||||
auto& state = this->map_key[keyboard->vkCode];
|
auto& state = this->map_key[keyboard->vkCode];
|
||||||
@ -112,45 +144,14 @@ bool KeyboardHook::_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard)
|
|||||||
state = true;
|
state = true;
|
||||||
|
|
||||||
auto type = key_type(keyboard->vkCode);
|
auto type = key_type(keyboard->vkCode);
|
||||||
if(type != KeyType::KEY_NORMAL)
|
if(type != KeyType::KEY_NORMAL)
|
||||||
this->map_special[type] = true;
|
this->map_special[type] = true;
|
||||||
else
|
else
|
||||||
this->map_special[type] = keyboard->vkCode;
|
this->map_special[type] = keyboard->vkCode;
|
||||||
|
|
||||||
if (this->callback_event) {
|
if(!typed)
|
||||||
if(!typed) {
|
this->trigger_key_event(KeyEvent::PRESS, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_code(this->map_special[KeyType::KEY_NORMAL], false));
|
||||||
auto e = make_shared<KeyboardHook::KeyEvent>();
|
this->trigger_key_event(KeyEvent::TYPE, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_code(this->map_special[KeyType::KEY_NORMAL], false));
|
||||||
e->type = KeyboardHook::KeyEvent::PRESS;
|
|
||||||
if(type == KeyType::KEY_NORMAL) {
|
|
||||||
e->code = key_code(keyboard);
|
|
||||||
} else {
|
|
||||||
e->code = key_code(this->map_special[KeyType::KEY_NORMAL], false);
|
|
||||||
}
|
|
||||||
|
|
||||||
e->key_alt = this->map_special[KeyType::KEY_ALT];
|
|
||||||
e->key_ctrl = this->map_special[KeyType::KEY_CTRL];
|
|
||||||
e->key_windows = this->map_special[KeyType::KEY_WIN];
|
|
||||||
e->key_shift = this->map_special[KeyType::KEY_SHIFT];
|
|
||||||
|
|
||||||
this->callback_event(e);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto e = make_shared<KeyboardHook::KeyEvent>();
|
|
||||||
e->type = KeyboardHook::KeyEvent::TYPE;
|
|
||||||
if(type == KeyType::KEY_NORMAL) {
|
|
||||||
e->code = key_code(keyboard);
|
|
||||||
} else {
|
|
||||||
e->code = key_code(this->map_special[KeyType::KEY_NORMAL], false);
|
|
||||||
}
|
|
||||||
|
|
||||||
e->key_alt = this->map_special[KeyType::KEY_ALT];
|
|
||||||
e->key_ctrl = this->map_special[KeyType::KEY_CTRL];
|
|
||||||
e->key_windows = this->map_special[KeyType::KEY_WIN];
|
|
||||||
e->key_shift = this->map_special[KeyType::KEY_SHIFT];
|
|
||||||
|
|
||||||
this->callback_event(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(event == WM_KEYUP || event == WM_SYSKEYUP) {
|
} else if(event == WM_KEYUP || event == WM_SYSKEYUP) {
|
||||||
auto& state = this->map_key[keyboard->vkCode];
|
auto& state = this->map_key[keyboard->vkCode];
|
||||||
if(!state) return false; //Duplicate
|
if(!state) return false; //Duplicate
|
||||||
@ -160,26 +161,36 @@ bool KeyboardHook::_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard)
|
|||||||
if(type != KeyType::KEY_NORMAL)
|
if(type != KeyType::KEY_NORMAL)
|
||||||
this->map_special[type] = false;
|
this->map_special[type] = false;
|
||||||
else if(this->map_special[KeyType::KEY_NORMAL] == keyboard->vkCode)
|
else if(this->map_special[KeyType::KEY_NORMAL] == keyboard->vkCode)
|
||||||
this->map_special[KeyType::KEY_NORMAL] = 0xFF;
|
this->map_special[KeyType::KEY_NORMAL] = 0;
|
||||||
|
|
||||||
if (this->callback_event) {
|
this->trigger_key_event(KeyEvent::RELEASE, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_code(this->map_special[KeyType::KEY_NORMAL], false));
|
||||||
auto e = make_shared<KeyboardHook::KeyEvent>();
|
|
||||||
e->type = KeyboardHook::KeyEvent::RELEASE;
|
|
||||||
if(type == KeyType::KEY_NORMAL) {
|
|
||||||
e->code = key_code(keyboard);
|
|
||||||
} else {
|
|
||||||
e->code = key_code(this->map_special[KeyType::KEY_NORMAL], false);
|
|
||||||
}
|
|
||||||
|
|
||||||
e->key_alt = this->map_special[KeyType::KEY_ALT];
|
|
||||||
e->key_ctrl = this->map_special[KeyType::KEY_CTRL];
|
|
||||||
e->key_windows = this->map_special[KeyType::KEY_WIN];
|
|
||||||
e->key_shift = this->map_special[KeyType::KEY_SHIFT];
|
|
||||||
|
|
||||||
this->callback_event(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Consume the event: return 1
|
//Consume the event: return 1
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyboardHook::mouse_hook_callback(int nCode, WPARAM event, LPARAM ptr_mouse) {
|
||||||
|
auto mouse = (MouseHookStruct*) ptr_mouse;
|
||||||
|
if(event == WM_RBUTTONDOWN)
|
||||||
|
this->trigger_key_event(KeyEvent::PRESS, "MOUSE1");
|
||||||
|
else if(event == WM_RBUTTONUP)
|
||||||
|
this->trigger_key_event(KeyEvent::RELEASE, "MOUSE1");
|
||||||
|
if(event == WM_LBUTTONDOWN)
|
||||||
|
this->trigger_key_event(KeyEvent::PRESS, "MOUSE2");
|
||||||
|
else if(event == WM_LBUTTONUP)
|
||||||
|
this->trigger_key_event(KeyEvent::RELEASE, "MOUSE2");
|
||||||
|
if(event == WM_MBUTTONDOWN)
|
||||||
|
this->trigger_key_event(KeyEvent::PRESS, "MOUSE3");
|
||||||
|
else if(event == WM_MBUTTONUP)
|
||||||
|
this->trigger_key_event(KeyEvent::RELEASE, "MOUSE3");
|
||||||
|
else if(event == WM_XBUTTONDOWN || event == WM_XBUTTONUP) {
|
||||||
|
auto x_index = GET_XBUTTON_WPARAM(mouse->mouseData);
|
||||||
|
this->trigger_key_event(event == WM_XBUTTONDOWN ? KeyEvent::PRESS : KeyEvent::RELEASE, "MOUSEX" + std::to_string(x_index));
|
||||||
|
}
|
||||||
|
else if(event == WM_MOUSEMOVE)
|
||||||
|
;
|
||||||
|
else
|
||||||
|
cout << "Unknown event: " << event << endl;
|
||||||
|
return false;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user