summaryrefslogtreecommitdiffhomepage
path: root/dinput/keybinding-worker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dinput/keybinding-worker.cpp')
-rw-r--r--dinput/keybinding-worker.cpp116
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);
}
}