diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2015-11-22 15:06:30 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2015-11-22 15:55:39 +0100 |
commit | a9860e951757bf454b83b13ce7eff865f0b6644e (patch) | |
tree | 88d13f20a8066e0a2aaf0f94944a03733279db66 /opentrack | |
parent | 763da906a83b80eadb736008dbb558b809552505 (diff) |
api/keyboard: implement a central worker
DirectInput dies when two LPDIRECTINPUT8 handles are obtained. Implement
a singleton worker providing keypress events.
Diffstat (limited to 'opentrack')
-rw-r--r-- | opentrack/keybinding-worker.cpp | 153 | ||||
-rw-r--r-- | opentrack/keybinding-worker.hpp | 48 |
2 files changed, 137 insertions, 64 deletions
diff --git a/opentrack/keybinding-worker.cpp b/opentrack/keybinding-worker.cpp index 31eb9e80..d876d5a1 100644 --- a/opentrack/keybinding-worker.cpp +++ b/opentrack/keybinding-worker.cpp @@ -9,11 +9,14 @@ #include "keybinding-worker.hpp" #if defined(_WIN32) -# include <functional> -# include <windows.h> -# include <QDebug> + +#include <functional> +#include <windows.h> +#include <QDebug> +#include <QMutexLocker> KeybindingWorker::~KeybindingWorker() { + qDebug() << "keybinding worker stop"; should_quit = true; wait(); if (dinkeyboard) { @@ -24,11 +27,8 @@ KeybindingWorker::~KeybindingWorker() { din->Release(); } -KeybindingWorker::KeybindingWorker(std::function<void(Key&)> receiver, WId h) : - should_quit(true), receiver(receiver) +KeybindingWorker::KeybindingWorker() : should_quit(true) { - HWND handle = reinterpret_cast<HWND>(h); - if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); return; @@ -47,7 +47,7 @@ KeybindingWorker::KeybindingWorker(std::function<void(Key&)> receiver, WId h) : din = 0; return; } - if (dinkeyboard->SetCooperativeLevel((HWND) handle, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + if (dinkeyboard->SetCooperativeLevel(GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { dinkeyboard->Release(); din->Release(); din = 0; @@ -65,6 +65,13 @@ KeybindingWorker::KeybindingWorker(std::function<void(Key&)> receiver, WId h) : return; } should_quit = false; + start(); +} + +KeybindingWorker& KeybindingWorker::make() +{ + static KeybindingWorker k; + return k; } void KeybindingWorker::run() { @@ -73,59 +80,99 @@ void KeybindingWorker::run() { while (!should_quit) { { - const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); - - if (hr != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); - Sleep(25); - continue; - } - } - - { - using joy_fn = std::function<void(const QString& guid, int idx, bool held)>; - - joy_fn f = [&](const QString& guid, int idx, bool held) -> void { - Key k; - k.keycode = idx; - k.shift = !!(keystate[DIK_LSHIFT] & 0x80 || keystate[DIK_RSHIFT] & 0x80); - k.alt = !!(keystate[DIK_LALT] & 0x80 || keystate[DIK_RALT] & 0x80); - k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); - k.guid = guid; - k.held = held; - receiver(k); - }; + QMutexLocker l(&mtx); - joy_ctx.poll(f); - } - - for (int i = 0; i < 256; i++) - { - Key k; - if (keystate[i] & 0x80) + if (receivers.size()) { - switch (i) { - case DIK_LCONTROL: - case DIK_LSHIFT: - case DIK_LALT: - case DIK_RCONTROL: - case DIK_RSHIFT: - case DIK_RALT: - break; - default: - k.shift = !!(keystate[DIK_LSHIFT] & 0x80) || !!(keystate[DIK_RSHIFT] & 0x80); - k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); - k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); - k.keycode = i; - receiver(k); - break; + const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); + + if (hr != DI_OK) { + qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); + Sleep(25); + continue; + } + } + + { + using joy_fn = std::function<void(const QString& guid, int idx, bool held)>; + + joy_fn f = [&](const QString& guid, int idx, bool held) -> void { + Key k; + k.keycode = idx; + k.shift = !!(keystate[DIK_LSHIFT] & 0x80 || keystate[DIK_RSHIFT] & 0x80); + k.alt = !!(keystate[DIK_LALT] & 0x80 || keystate[DIK_RALT] & 0x80); + k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80 || keystate[DIK_RCONTROL] & 0x80); + k.guid = guid; + k.held = held; + + for (auto& r : receivers) + r(k); + }; + + joy_ctx.poll(f); + } + + for (int i = 0; i < 256; i++) + { + Key k; + if (keystate[i] & 0x80) + { + switch (i) + { + case DIK_LCONTROL: + case DIK_LSHIFT: + case DIK_LALT: + case DIK_RCONTROL: + case DIK_RSHIFT: + case DIK_RALT: + break; + default: + k.shift = !!(keystate[DIK_LSHIFT] & 0x80) || !!(keystate[DIK_RSHIFT] & 0x80); + k.alt = !!(keystate[DIK_LALT] & 0x80) || !!(keystate[DIK_RALT] & 0x80); + k.ctrl = !!(keystate[DIK_LCONTROL] & 0x80) || !!(keystate[DIK_RCONTROL] & 0x80); + k.keycode = i; + + for (auto& r : receivers) + r(k); + break; + } + } } } } - + // keypresses get dropped with high values Sleep(4); } } + +KeybindingWorker::fun* KeybindingWorker::_add_receiver(KeybindingWorker::fun receiver) +{ + QMutexLocker l(&mtx); + receivers.push_back(receiver); + qDebug() << "add receiver" << (long) &receivers[receivers.size()-1]; + return &receivers[receivers.size()-1]; +} + +void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos) +{ + QMutexLocker l(&mtx); + bool ok = false; + + for (int i = receivers.size() - 1; i >= 0; i--) + { + if (&receivers[i] == pos) + { + ok = true; + qDebug() << "remove receiver" << (long) pos; + receivers.erase(receivers.begin() + i); + } + } + if (!ok) + { + qDebug() << "bad remove receiver" << (long) pos; + } +} + #endif
\ No newline at end of file diff --git a/opentrack/keybinding-worker.hpp b/opentrack/keybinding-worker.hpp index b5d63fac..5a73b1b1 100644 --- a/opentrack/keybinding-worker.hpp +++ b/opentrack/keybinding-worker.hpp @@ -20,6 +20,7 @@ #include <QMutex> #include <QWidget> #include <functional> +#include <vector> #ifdef _WIN32 # undef DIRECTINPUT_VERSION @@ -53,21 +54,46 @@ typedef unsigned char BYTE; struct Key { int foo; }; #endif -struct OPENTRACK_EXPORT KeybindingWorker : public QThread { -#ifdef _WIN32 +struct OPENTRACK_EXPORT KeybindingWorker : private QThread +{ private: LPDIRECTINPUT8 din; LPDIRECTINPUTDEVICE8 dinkeyboard; win32_joy_ctx joy_ctx; -public: volatile bool should_quit; - std::function<void(Key&)> receiver; + using fun = std::function<void(Key&)>; + std::vector<fun> receivers; + QMutex mtx; + + void run() override; + KeybindingWorker(); + + KeybindingWorker(const KeybindingWorker&) = delete; + KeybindingWorker& operator=(KeybindingWorker&) = delete; + static KeybindingWorker& make(); + fun* _add_receiver(fun receiver); + void remove_receiver(fun* pos); ~KeybindingWorker(); - KeybindingWorker(std::function<void(Key&)> receiver, WId h); - void run(); -#else public: - KeybindingWorker(Key, Key, Key, WId) {} - void run() {} -#endif -};
\ No newline at end of file + class Token + { + friend class KeybindingWorker; + fun* pos; + //Token(const Token&) = delete; + Token& operator=(Token&) = delete; + public: + Token(fun receiver) + { + pos = make()._add_receiver(receiver); + } + ~Token() + { + make().remove_receiver(pos); + } + }; + friend class Token; + static Token add_receiver(fun receiver) + { + return Token(receiver); + } +}; |