diff options
Diffstat (limited to 'dinput/keybinding-worker.cpp')
-rw-r--r-- | dinput/keybinding-worker.cpp | 116 |
1 files changed, 73 insertions, 43 deletions
diff --git a/dinput/keybinding-worker.cpp b/dinput/keybinding-worker.cpp index e0d09909..468ef477 100644 --- a/dinput/keybinding-worker.cpp +++ b/dinput/keybinding-worker.cpp @@ -8,13 +8,15 @@ #ifdef _WIN32 -#include "keybinding-worker.hpp" +#include "compat/sleep.hpp" #include "compat/util.hpp" -#include <functional> -#include <windows.h> +#include "keybinding-worker.hpp" + #include <QDebug> #include <QMutexLocker> +#include <windows.h> + Key::Key() {} bool Key::should_process() @@ -65,6 +67,22 @@ bool KeybindingWorker::init() return false; } + { + DIPROPDWORD dipdw; + dipdw.dwData = 128; + dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.diph.dwObj = 0; + dipdw.diph.dwSize = sizeof(dipdw); + if ( dinkeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph) != DI_OK) + { + qDebug() << "setup keyboard buffer mode failed!"; + dinkeyboard->Release(); + dinkeyboard = 0; + return false; + } + } + if (dinkeyboard->Acquire() != DI_OK) { dinkeyboard->Release(); @@ -90,9 +108,6 @@ KeybindingWorker& KeybindingWorker::make() void KeybindingWorker::run() { - unsigned char keystate[256] = {0}; - unsigned char old_keystate[256] = {0}; - while (!isInterruptionRequested()) { { @@ -100,21 +115,69 @@ void KeybindingWorker::run() if (receivers.size()) { + /* There are some problems reported on various forums + * with regard to key-up events. But that's what I dug up: + * + * https://www.gamedev.net/forums/topic/633011-keyboard-getdevicedata-buffered-never-releases-keys/ + * + * "Over in the xna forums (http://xboxforums.create.msdn.com/forums/p/108722/642144.aspx#642144) + * we discovered this behavior is caused by calling Unacquire in your event processing loop. + * Funnily enough only the keyboard seems to be affected." + * + * Key-up events work on my end. + */ + { - const HRESULT hr = dinkeyboard->GetDeviceState(256, (LPVOID)keystate); + DWORD sz = num_keyboard_states; + const HRESULT hr = dinkeyboard->GetDeviceData(sizeof(*keyboard_states), keyboard_states, &sz, 0); if (hr != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); + qDebug() << "Tracker::run GetDeviceData function failed!" << hr; Sleep(25); continue; } + else + { + for (unsigned k = 0; k < sz; k++) + { + const unsigned idx = keyboard_states[k].dwOfs & 0xff; // defensive programming + const bool held = !!(keyboard_states[k].dwData & 0x80); + + switch (idx) + { + case DIK_LCONTROL: + case DIK_LSHIFT: + case DIK_LALT: + case DIK_RCONTROL: + case DIK_RSHIFT: + case DIK_RALT: + case DIK_LWIN: + case DIK_RWIN: + break; + default: + { + Key k; + 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 = idx; + k.held = held; + + for (auto& r : receivers) + (*r)(k); + break; + } + } + keystate[idx] = held; + } + } } { using joy_fn = std::function<void(const QString& guid, int idx, bool held)>; - joy_fn f = [&](const QString& guid, int idx, bool held) -> void { + joy_fn f = [&](const QString& guid, int idx, bool held) { Key k; k.keycode = idx; k.shift = !!(keystate[DIK_LSHIFT] & 0x80 || keystate[DIK_RSHIFT] & 0x80); @@ -129,43 +192,10 @@ void KeybindingWorker::run() joy_ctx.poll(f); } - - for (int i = 0; i < 256; i++) - { - Key k; - if (old_keystate[i] != keystate[i]) - { - const bool held = !!(keystate[i] & 0x80); - switch (i) - { - case DIK_LCONTROL: - case DIK_LSHIFT: - case DIK_LALT: - case DIK_RCONTROL: - case DIK_RSHIFT: - case DIK_RALT: - case DIK_LWIN: - case DIK_RWIN: - 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; - k.held = held; - - for (auto& r : receivers) - (*r)(k); - break; - } - } - old_keystate[i] = keystate[i]; - } } } - // keypresses get dropped with high values - Sleep(4); + portable::sleep(100); } } |