summaryrefslogtreecommitdiffhomepage
path: root/dinput
diff options
context:
space:
mode:
Diffstat (limited to 'dinput')
-rw-r--r--dinput/dinput.cpp5
-rw-r--r--dinput/dinput.hpp16
-rw-r--r--dinput/keybinding-worker.cpp107
-rw-r--r--dinput/keybinding-worker.hpp12
-rw-r--r--dinput/lang/de_DE.ts4
-rw-r--r--dinput/lang/zh_CN.ts2
-rw-r--r--dinput/win32-joystick.cpp21
-rw-r--r--dinput/win32-joystick.hpp17
8 files changed, 130 insertions, 54 deletions
diff --git a/dinput/dinput.cpp b/dinput/dinput.cpp
index 31de40e7..b9713b8a 100644
--- a/dinput/dinput.cpp
+++ b/dinput/dinput.cpp
@@ -1,10 +1,11 @@
#undef NDEBUG
#include "dinput.hpp"
-#include "compat/macros.hpp"
+#include "compat/macros.h"
#include <cassert>
#include <cstdlib>
+#include <dinput.h>
#include <QDebug>
@@ -60,7 +61,7 @@ diptr di_t::init_di_()
di_t::di_t() = default;
-bool di_t::poll_device(LPDIRECTINPUTDEVICE8 dev)
+bool di_t::poll_device(IDirectInputDevice8A* dev)
{
HRESULT hr;
assert(handle);
diff --git a/dinput/dinput.hpp b/dinput/dinput.hpp
index e9908a94..09c9a30b 100644
--- a/dinput/dinput.hpp
+++ b/dinput/dinput.hpp
@@ -15,7 +15,19 @@
#undef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x800
-#include <dinput.h>
+struct IDirectInputDevice8A;
+typedef struct IDirectInputDevice8A IDirectInputDevice8A;
+struct IDirectInput8A;
+typedef struct IDirectInput8A IDirectInput8A;
+struct _GUID;
+typedef struct _GUID GUID;
+struct _DIDATAFORMAT;
+typedef struct _DIDATAFORMAT DIDATAFORMAT;
+typedef int BOOL;
+struct DIDEVICEINSTANCEA;
+typedef struct DIDEVICEINSTANCEA DIDEVICEINSTANCEA;
+struct DIDEVICEOBJECTINSTANCEA;
+typedef struct DIDEVICEOBJECTINSTANCEA DIDEVICEOBJECTINSTANCEA;
// XXX TODO -sh 20190209
// keybinding_worker and joystick context are badly named
@@ -39,5 +51,5 @@ public:
operator bool() const;
operator diptr() const;
- static bool poll_device(LPDIRECTINPUTDEVICE8 dev);
+ static bool poll_device(IDirectInputDevice8A* dev);
};
diff --git a/dinput/keybinding-worker.cpp b/dinput/keybinding-worker.cpp
index 0ceca789..7cd8d663 100644
--- a/dinput/keybinding-worker.cpp
+++ b/dinput/keybinding-worker.cpp
@@ -9,13 +9,20 @@
#ifdef _WIN32
#include "keybinding-worker.hpp"
-#include "compat/macros.hpp"
+#include "compat/macros.h"
#include "compat/thread-name.hpp"
#include <QDebug>
#include <QMutexLocker>
-#include <windows.h>
+#include <dinput.h>
+
+static void destroy(IDirectInputDevice8A*& dev)
+{
+ if (dev)
+ dev->Release();
+ dev = nullptr;
+}
Key::Key() = default;
@@ -35,16 +42,13 @@ KeybindingWorker::~KeybindingWorker()
requestInterruption();
wait();
- if (dinkeyboard)
- {
- dinkeyboard->Unacquire();
- dinkeyboard->Release();
- }
+ destroy(dinkeyboard);
+ destroy(dinmouse);
}
-bool KeybindingWorker::init()
+bool KeybindingWorker::init_(IDirectInputDevice8A*& dev, const char* name, const GUID& guid, const DIDATAFORMAT& fmt)
{
- if (dinkeyboard)
+ if (dev)
return true;
if (!din)
@@ -53,24 +57,39 @@ bool KeybindingWorker::init()
goto fail;
}
- if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, nullptr) != DI_OK)
+ if (auto hr = din->CreateDevice(guid, &dev, nullptr); hr != DI_OK)
{
- qDebug() << "dinput: create keyboard failed" << GetLastError();
+ qDebug() << "dinput: create" << name << "failed" << (void*)hr;
goto fail;
}
- if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK)
+ if (auto hr = dev->SetDataFormat(&fmt); hr != DI_OK)
{
- qDebug() << "dinput: keyboard SetDataFormat" << GetLastError();
+ qDebug() << "dinput:" << name << "SetDataFormat" << (void*)hr;
goto fail;
}
- if (dinkeyboard->SetCooperativeLevel((HWND) fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK)
+ if (auto hr = dev->SetCooperativeLevel((HWND) fake_main_window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
+ hr != DI_OK)
{
- qDebug() << "dinput: keyboard SetCooperativeLevel" << GetLastError();
+ qDebug() << "dinput:" << name << "SetCooperativeLevel" << (void*)hr;
goto fail;
}
+ return true;
+fail:
+ destroy(dev);
+ return false;
+}
+
+bool KeybindingWorker::init()
+{
+ bool ret = init_(dinkeyboard, "keyboard", GUID_SysKeyboard, c_dfDIKeyboard) &&
+ init_(dinmouse, "mouse", GUID_SysMouse, c_dfDIMouse2);
+
+ if (!ret)
+ goto fail;
+
{
DIPROPDWORD dipdw;
dipdw.dwData = num_keyboard_states;
@@ -79,9 +98,9 @@ bool KeybindingWorker::init()
dipdw.diph.dwObj = 0;
dipdw.diph.dwSize = sizeof(dipdw);
- if (dinkeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph) != DI_OK)
+ if (auto hr = dinkeyboard->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph); hr != DI_OK)
{
- qDebug() << "dinput: DIPROP_BUFFERSIZE";
+ qDebug() << "dinput: keyboard DIPROP_BUFFERSIZE" << (void*)hr;
goto fail;
}
}
@@ -89,11 +108,8 @@ bool KeybindingWorker::init()
return true;
fail:
- if (dinkeyboard)
- {
- dinkeyboard->Release();
- dinkeyboard = nullptr;
- }
+ destroy(dinkeyboard);
+ destroy(dinmouse);
return false;
}
@@ -125,6 +141,7 @@ void KeybindingWorker::run()
bool ok = true;
ok &= run_keyboard_nolock();
+ ok &= run_mouse_nolock();
ok &= run_joystick_nolock();
if (!ok)
@@ -136,6 +153,38 @@ void KeybindingWorker::run()
}
}
+bool KeybindingWorker::run_mouse_nolock()
+{
+ DIMOUSESTATE2 state;
+
+ if (!di_t::poll_device(dinmouse))
+ eval_once(qDebug() << "dinput: mouse poll failed");
+
+ if (auto hr = dinmouse->GetDeviceState(sizeof(state), &state); hr != DI_OK)
+ {
+ eval_once(qDebug() << "dinput: mouse GetDeviceState failed" << (void*) hr << GetLastError);
+ return false;
+ }
+
+ Key k;
+ k.guid = QStringLiteral("mouse");
+
+ for (int i = first_mouse_button; i < num_mouse_buttons; i++)
+ {
+ const bool new_state = state.rgbButtons[i] & 0x80;
+ k.held = new_state;
+ k.keycode = i;
+ bool& old_state = mouse_state[i - first_mouse_button];
+ if (old_state != new_state)
+ {
+ for (auto& r : receivers)
+ (*r)(k);
+ }
+ old_state = new_state;
+ }
+ return true;
+}
+
bool KeybindingWorker::run_keyboard_nolock()
{
/* There are some problems reported on various forums
@@ -153,6 +202,8 @@ bool KeybindingWorker::run_keyboard_nolock()
if (!di_t::poll_device(dinkeyboard))
eval_once(qDebug() << "dinput: keyboard poll failed");
+ DIDEVICEOBJECTDATA keyboard_states[num_keyboard_states];
+
DWORD sz = num_keyboard_states;
HRESULT hr = dinkeyboard->GetDeviceData(sizeof(*keyboard_states), keyboard_states, &sz, 0);
@@ -164,9 +215,13 @@ bool KeybindingWorker::run_keyboard_nolock()
for (unsigned k = 0; k < sz; k++)
{
- const unsigned idx = keyboard_states[k].dwOfs & 0xff; // defensive programming
+ const int idx = keyboard_states[k].dwOfs & 0xff; // defensive programming
const bool held = !!(keyboard_states[k].dwData & 0x80);
+ if (held == keystate[idx])
+ continue;
+ keystate[idx] = held;
+
switch (idx)
{
case DIK_LCONTROL:
@@ -192,8 +247,6 @@ bool KeybindingWorker::run_keyboard_nolock()
}
break;
}
-
- keystate[idx] = held;
}
return true;
@@ -225,7 +278,7 @@ KeybindingWorker::fun* KeybindingWorker::add_receiver(fun& receiver)
{
QMutexLocker l(&mtx);
receivers.push_back(std::make_unique<fun>(receiver));
- fun* f = receivers[receivers.size() - 1].get();
+ fun* f = &*receivers[receivers.size() - 1];
//qDebug() << "add receiver" << (long) f;
joy_ctx.refresh();
return f;
@@ -241,7 +294,7 @@ void KeybindingWorker::remove_receiver(KeybindingWorker::fun* pos)
for (int i = s(receivers.size()) - 1; i >= 0; i--)
{
using u = unsigned;
- if (receivers[u(i)].get() == pos)
+ if (&*receivers[u(i)] == pos)
{
ok = true;
//qDebug() << "remove receiver" << (long) pos;
diff --git a/dinput/keybinding-worker.hpp b/dinput/keybinding-worker.hpp
index 335a5c11..1c22ca17 100644
--- a/dinput/keybinding-worker.hpp
+++ b/dinput/keybinding-worker.hpp
@@ -45,7 +45,11 @@ struct OTR_DINPUT_EXPORT KeybindingWorker : private QThread
KeybindingWorker& operator=(KeybindingWorker&) = delete;
private:
- IDirectInputDevice8A* dinkeyboard = nullptr;
+ static constexpr int num_keyboard_states = 64;
+ static constexpr int num_mouse_buttons = 8;
+ static constexpr int first_mouse_button = 3;
+
+ IDirectInputDevice8A* dinkeyboard = nullptr, *dinmouse = nullptr;
win32_joy_ctx joy_ctx;
std::vector<std::unique_ptr<fun>> receivers;
QMutex mtx;
@@ -53,21 +57,21 @@ private:
di_t din;
bool keystate[256] {};
+ bool mouse_state[num_mouse_buttons - first_mouse_button] = {};
void run() override;
bool run_keyboard_nolock();
bool run_joystick_nolock();
+ bool run_mouse_nolock();
bool init();
+ bool init_(IDirectInputDevice8A*& dev, const char* name, const GUID& guid, const DIDATAFORMAT& fmt);
KeybindingWorker();
static KeybindingWorker& make();
fun* add_receiver(fun& receiver);
void remove_receiver(fun* pos);
~KeybindingWorker() override;
-
- static constexpr int num_keyboard_states = 64;
- DIDEVICEOBJECTDATA keyboard_states[num_keyboard_states] {};
public:
class Token
{
diff --git a/dinput/lang/de_DE.ts b/dinput/lang/de_DE.ts
new file mode 100644
index 00000000..1552582e
--- /dev/null
+++ b/dinput/lang/de_DE.ts
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="de_DE">
+</TS>
diff --git a/dinput/lang/zh_CN.ts b/dinput/lang/zh_CN.ts
index 6401616d..e5ca8aa9 100644
--- a/dinput/lang/zh_CN.ts
+++ b/dinput/lang/zh_CN.ts
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1">
+<TS version="2.1" language="zh_CN">
</TS>
diff --git a/dinput/win32-joystick.cpp b/dinput/win32-joystick.cpp
index 0f2687fe..06c1f89f 100644
--- a/dinput/win32-joystick.cpp
+++ b/dinput/win32-joystick.cpp
@@ -1,7 +1,7 @@
#ifdef _WIN32
#include "win32-joystick.hpp"
-#include "compat/macros.hpp"
+#include "compat/macros.h"
#include <cstddef>
#include <algorithm>
@@ -11,13 +11,13 @@
#include <QWidget>
#include <QDebug>
+#include <dinput.h>
#include <objbase.h>
namespace win32_joy_impl {
QMutex win32_joy_ctx::enum_state::mtx;
win32_joy_ctx::enum_state win32_joy_ctx::enumerator;
-DIDEVICEOBJECTDATA win32_joy_ctx::joy::keystate_buffers[num_buffers] = {};
void win32_joy_ctx::poll(fn const& f)
{
@@ -48,7 +48,7 @@ bool win32_joy_ctx::poll_axis(const QString &guid, int* axes)
auto& j = iter->second;
auto& joy_handle = j->joy_handle;
- DIJOYSTATE2 js = {};
+ DIJOYSTATE2 js;
if (!di_t::poll_device(joy_handle))
continue;
@@ -142,6 +142,8 @@ bool win32_joy_ctx::joy::poll(fn const& f)
return false;
}
+ DIDEVICEOBJECTDATA keystate_buffers[num_buffers];
+
DWORD sz = num_buffers;
if (FAILED(hr = joy_handle->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), keystate_buffers, &sz, 0)))
{
@@ -226,6 +228,9 @@ win32_joy_ctx::enum_state::~enum_state()
void win32_joy_ctx::enum_state::refresh()
{
all.clear();
+#ifdef __SANITIZE_ADDRESS__
+ return;
+#endif
if (!di)
{
@@ -255,7 +260,7 @@ void win32_joy_ctx::enum_state::refresh()
const win32_joy_ctx::joys_t& win32_joy_ctx::enum_state::get_joys() const { return joys; }
-BOOL CALLBACK win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance, void *pContext)
+BOOL CALLBACK win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINSTANCEA *pdidInstance, void *pContext)
{
enum_state& state = *reinterpret_cast<enum_state*>(pContext);
const QString guid = guid_to_string(pdidInstance->guidInstance);
@@ -270,7 +275,7 @@ BOOL CALLBACK win32_joy_ctx::enum_state::EnumJoysticksCallback(const DIDEVICEINS
{
HRESULT hr;
- LPDIRECTINPUTDEVICE8 h;
+ IDirectInputDevice8A* h;
if (FAILED(hr = state.di->CreateDevice(pdidInstance->guidInstance, &h, nullptr)))
{
qDebug() << "dinput: failed joystick CreateDevice" << guid << (void*)hr;
@@ -322,7 +327,7 @@ end:
return DIENUM_CONTINUE;
}
-BOOL CALLBACK win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE *pdidoi, void *ctx)
+BOOL CALLBACK win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCEA* pdidoi, void *ctx)
{
if (pdidoi->dwType & DIDFT_AXIS)
{
@@ -336,7 +341,7 @@ BOOL CALLBACK win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJEC
HRESULT hr;
- if (FAILED(hr = reinterpret_cast<LPDIRECTINPUTDEVICE8>(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph)))
+ if (FAILED(hr = reinterpret_cast<IDirectInputDevice8A*>(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph)))
{
qDebug() << "dinput: failed joystick DIPROP_RANGE" << (void*)hr;
return DIENUM_STOP;
@@ -346,7 +351,7 @@ BOOL CALLBACK win32_joy_ctx::enum_state::EnumObjectsCallback(const DIDEVICEOBJEC
return DIENUM_CONTINUE;
}
-win32_joy_ctx::joy::joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString &name)
+win32_joy_ctx::joy::joy(IDirectInputDevice8A* handle, const QString& guid, const QString &name)
: joy_handle(handle), guid(guid), name(name)
{
//qDebug() << "make joy" << guid << name << joy_handle;
diff --git a/dinput/win32-joystick.hpp b/dinput/win32-joystick.hpp
index ff52ad1d..8e5344d6 100644
--- a/dinput/win32-joystick.hpp
+++ b/dinput/win32-joystick.hpp
@@ -10,6 +10,7 @@
#include "dinput.hpp"
#include "compat/timer.hpp"
#include "export.hpp"
+#include "compat/qhash.hpp"
#include <memory>
#include <vector>
@@ -17,15 +18,13 @@
#include <unordered_map>
#include <iterator>
-#include "compat/qhash.hpp"
#include <QString>
#include <QMutex>
namespace win32_joy_impl {
-static constexpr unsigned max_buttons = std::size(DIJOYSTATE2().rgbButtons);
-static constexpr unsigned max_pov_hats = std::size(DIJOYSTATE2().rgdwPOV);
-
+static constexpr unsigned max_buttons = 128;
+static constexpr unsigned max_pov_hats = 4;
static constexpr unsigned pov_hat_directions = 8;
// cf. https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee416628(v=vs.85)
@@ -48,13 +47,11 @@ struct OTR_DINPUT_EXPORT win32_joy_ctx final
struct joy final
{
- LPDIRECTINPUTDEVICE8 joy_handle;
+ IDirectInputDevice8A* joy_handle;
QString guid, name;
bool last_state[max_buttons_and_pov_hats] {};
- static DIDEVICEOBJECTDATA keystate_buffers[num_buffers];
-
- joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid, const QString& name);
+ joy(IDirectInputDevice8A* handle, const QString& guid, const QString& name);
~joy();
void release();
@@ -89,8 +86,8 @@ private:
joys_t joys;
di_t di;
- static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext);
- static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx);
+ static BOOL __stdcall EnumJoysticksCallback(const DIDEVICEINSTANCEA* pdidInstance, void* pContext);
+ static BOOL __stdcall EnumObjectsCallback(const DIDEVICEOBJECTINSTANCEA* pdidoi, void* ctx);
public:
static QMutex mtx;