diff options
Diffstat (limited to 'dinput')
-rw-r--r-- | dinput/dinput.cpp | 5 | ||||
-rw-r--r-- | dinput/dinput.hpp | 16 | ||||
-rw-r--r-- | dinput/keybinding-worker.cpp | 107 | ||||
-rw-r--r-- | dinput/keybinding-worker.hpp | 12 | ||||
-rw-r--r-- | dinput/lang/de_DE.ts | 4 | ||||
-rw-r--r-- | dinput/lang/zh_CN.ts | 2 | ||||
-rw-r--r-- | dinput/win32-joystick.cpp | 21 | ||||
-rw-r--r-- | dinput/win32-joystick.hpp | 17 |
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; |