diff options
-rw-r--r-- | dinput/keybinding-worker.cpp | 166 | ||||
-rw-r--r-- | dinput/keybinding-worker.hpp | 3 |
2 files changed, 92 insertions, 77 deletions
diff --git a/dinput/keybinding-worker.cpp b/dinput/keybinding-worker.cpp index 9c2b06d4..8ef99921 100644 --- a/dinput/keybinding-worker.cpp +++ b/dinput/keybinding-worker.cpp @@ -114,83 +114,13 @@ void KeybindingWorker::run() if (!receivers.empty()) { - /* 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. - */ - - { - DWORD sz = num_keyboard_states; - const HRESULT hr = dinkeyboard->GetDeviceData(sizeof(*keyboard_states), keyboard_states, &sz, 0); - - if (hr != DI_OK) - { - 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] | keystate[DIK_RSHIFT]; - k.alt = keystate[DIK_LALT] | keystate[DIK_RALT]; - k.ctrl = keystate[DIK_LCONTROL] | keystate[DIK_RCONTROL]; - 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) { - Key k; - k.keycode = idx; - k.shift = keystate[DIK_LSHIFT] | keystate[DIK_RSHIFT]; - k.alt = keystate[DIK_LALT] | keystate[DIK_RALT]; - k.ctrl = keystate[DIK_LCONTROL] | keystate[DIK_RCONTROL]; - k.guid = guid; - k.held = held; - - for (auto& r : receivers) - (*r)(k); - }; - - joy_ctx.poll(f); - } + bool ok = true; + + ok &= run_keyboard_nolock(); + ok &= run_joystick_nolock(); + + if (!ok) + Sleep(500); } } @@ -198,6 +128,88 @@ void KeybindingWorker::run() } } +bool KeybindingWorker::run_keyboard_nolock() +{ + /* 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. + */ + + DWORD sz = num_keyboard_states; + const HRESULT hr = dinkeyboard->GetDeviceData(sizeof(*keyboard_states), keyboard_states, &sz, 0); + + if (hr != DI_OK) + { + eval_once(qDebug() << "dinput: keyboard GetDeviceData failed" << hr); + return false; + } + + 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] | keystate[DIK_RSHIFT]; + k.alt = keystate[DIK_LALT] | keystate[DIK_RALT]; + k.ctrl = keystate[DIK_LCONTROL] | keystate[DIK_RCONTROL]; + k.keycode = idx; + k.held = held; + + for (auto& r : receivers) + (*r)(k); + } + break; + } + + keystate[idx] = held; + } + + return true; +} + +bool KeybindingWorker::run_joystick_nolock() +{ + using joy_fn = std::function<void(const QString& guid, int idx, bool held)>; + + joy_fn f = [&](const QString& guid, int idx, bool held) { + Key k; + k.keycode = idx; + k.shift = keystate[DIK_LSHIFT] | keystate[DIK_RSHIFT]; + k.alt = keystate[DIK_LALT] | keystate[DIK_RALT]; + k.ctrl = keystate[DIK_LCONTROL] | keystate[DIK_RCONTROL]; + k.guid = guid; + k.held = held; + + for (auto& r : receivers) + (*r)(k); + }; + + joy_ctx.poll(f); + + return true; +} + KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver) { QMutexLocker l(&mtx); diff --git a/dinput/keybinding-worker.hpp b/dinput/keybinding-worker.hpp index 6b7d6882..9d067c10 100644 --- a/dinput/keybinding-worker.hpp +++ b/dinput/keybinding-worker.hpp @@ -53,6 +53,9 @@ private: bool old_keystate[256] {}; void run() override; + bool run_keyboard_nolock(); + bool run_joystick_nolock(); + bool init(); KeybindingWorker(); |