diff options
-rw-r--r-- | opentrack/win32-joystick-shortcuts.hpp | 86 |
1 files changed, 45 insertions, 41 deletions
diff --git a/opentrack/win32-joystick-shortcuts.hpp b/opentrack/win32-joystick-shortcuts.hpp index 530545dc..3e384da5 100644 --- a/opentrack/win32-joystick-shortcuts.hpp +++ b/opentrack/win32-joystick-shortcuts.hpp @@ -1,5 +1,7 @@ #pragma once +#ifdef _WIN32 + #include <cstring> #include <memory> #include <vector> @@ -17,7 +19,7 @@ struct win32_joy_ctx { using fn = std::function<void(const QString& guid, int btn, bool held)>; - + void poll(fn f) { refresh(false); @@ -27,13 +29,13 @@ struct win32_joy_ctx joys.erase(joys.begin() + i); } } - + struct joy { LPDIRECTINPUTDEVICE8 joy_handle; QString guid; bool pressed[128]; - + joy(LPDIRECTINPUTDEVICE8 handle, const QString& guid) : joy_handle(handle), guid(guid) { qDebug() << "got joy" << guid; @@ -41,13 +43,13 @@ struct win32_joy_ctx pressed[i] = false; poll([&](const QString&, int idx, bool held) -> void { pressed[idx] = held; }); } - + ~joy() { qDebug() << "nix joy" << guid; release(); } - + void release() { if (joy_handle) @@ -57,12 +59,12 @@ struct win32_joy_ctx joy_handle = nullptr; } } - + bool poll(fn f) { HRESULT hr; bool ok = false; - + for (int i = 0; i < 5; i++) { if (!FAILED(joy_handle->Poll())) @@ -76,22 +78,22 @@ struct win32_joy_ctx ok = true; break; } - + if (!ok) { qDebug() << "joy acquire failed" << guid << hr; return false; } - + DIJOYSTATE2 js; memset(&js, 0, sizeof(js)); - + if (FAILED(hr = joy_handle->GetDeviceState(sizeof(js), &js))) { qDebug() << "joy get state failed" << guid << hr; return false; } - + for (int i = 0; i < 128; i++) { const bool state = !!(js.rgbButtons[i] & 0x80); @@ -102,49 +104,49 @@ struct win32_joy_ctx } pressed[i] = state; } - + return true; } }; - + static QString guid_to_string(const GUID guid) { char buf[40] = {0}; wchar_t szGuidW[40] = {0}; - + StringFromGUID2(guid, szGuidW, 40); WideCharToMultiByte(0, 0, szGuidW, -1, buf, 40, NULL, NULL); - + return QString(buf); } - + win32_joy_ctx() : dinput_handle(nullptr) { (void) CoInitialize(nullptr); - + HRESULT hr; - + if (FAILED(hr = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**) &dinput_handle, nullptr))) goto fail; - + refresh(true); - + return; fail: qDebug() << "dinput8 failed for shortcuts" << hr; - + release(); } - + ~win32_joy_ctx() { release(); } - + void release() { joys = std::vector<std::shared_ptr<joy>>(); @@ -154,32 +156,32 @@ fail: dinput_handle = nullptr; } } - + void refresh(bool first) { if (!dinput_handle) return; - + if (!first) { if (timer_joylist.elapsed_ms() < joylist_refresh_ms) return; timer_joylist.start(); } - + enum_state st(dinput_handle, joys); } - + struct enum_state { std::vector<std::shared_ptr<joy>>& joys; std::vector<QString> all; LPDIRECTINPUT8 dinput_handle; - + enum_state(LPDIRECTINPUT8 di, std::vector<std::shared_ptr<joy>>& joys) : joys(joys), dinput_handle(di) { HRESULT hr; - + if(FAILED(hr = dinput_handle->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, @@ -188,7 +190,7 @@ fail: qDebug() << "failed enum joysticks" << hr; return; } - + for (int i = joys.size() - 1; i >= 0; i--) { const auto& guid = joys[i]->guid; @@ -196,7 +198,7 @@ fail: joys.erase(joys.begin() + i); } } - + static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) { enum_state& state = *reinterpret_cast<enum_state*>(pContext); @@ -207,13 +209,13 @@ fail: const int cnt_names = std::count_if(state.joys.begin(), state.joys.end(), [&](const joy& j) -> bool { return j.name == name; }); // this is potentially bad since replugged sticks can change guids (?) #endif - + const bool exists = std::find_if(state.joys.cbegin(), state.joys.cend(), [&](const std::shared_ptr<joy>& j) -> bool { return j->guid == guid; }) != state.joys.cend(); - + state.all.push_back(guid); - + if (!exists) { HRESULT hr; @@ -229,7 +231,7 @@ fail: h->Release(); goto end; } - + if (FAILED(h->SetCooperativeLevel((HWND) GetDesktopWindow(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) { qDebug() << "coop"; @@ -246,10 +248,10 @@ fail: #endif state.joys.push_back(std::make_shared<joy>(h, guid)); } - + end: return DIENUM_CONTINUE; } - + #if 0 static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* ctx) { @@ -263,18 +265,20 @@ end: return DIENUM_CONTINUE; diprg.diph.dwObj = pdidoi->dwType; diprg.lMax = 32; diprg.lMin = -32; - + if (FAILED(reinterpret_cast<LPDIRECTINPUTDEVICE8>(ctx)->SetProperty(DIPROP_RANGE, &diprg.diph))) return DIENUM_STOP; } - + return DIENUM_CONTINUE; } #endif }; - + LPDIRECTINPUT8 dinput_handle; std::vector<std::shared_ptr<joy>> joys; Timer timer_joylist; enum { joylist_refresh_ms = 250 }; -};
\ No newline at end of file +}; + +#endif |