[Input] Dynamically link to XInput.

This commit is contained in:
gibbed 2018-11-22 10:46:48 -06:00
parent 86d2c9ae1e
commit 086d7e9da7
4 changed files with 76 additions and 19 deletions

View File

@ -119,11 +119,18 @@ std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
drivers.emplace_back(std::move(winkey_driver)); drivers.emplace_back(std::move(winkey_driver));
} }
#endif // XE_PLATFORM_WIN32 #endif // XE_PLATFORM_WIN32
if (drivers.empty()) { }
// Fallback to nop if none created. for (auto it = drivers.begin(); it != drivers.end();) {
drivers.emplace_back(xe::hid::nop::Create(window)); if (XFAILED((*it)->Setup())) {
it = drivers.erase(it);
} else {
++it;
} }
} }
if (drivers.empty()) {
// Fallback to nop if none created.
drivers.emplace_back(xe::hid::nop::Create(window));
}
return drivers; return drivers;
} }

View File

@ -21,26 +21,64 @@ namespace hid {
namespace xinput { namespace xinput {
XInputInputDriver::XInputInputDriver(xe::ui::Window* window) XInputInputDriver::XInputInputDriver(xe::ui::Window* window)
: InputDriver(window) { : InputDriver(window),
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8 && _WIN32_WINNT < _WIN32_WINNT_WIN10) module_(nullptr),
// TODO(gibbed): Is this necessary? XInputGetCapabilities_(nullptr),
XInputEnable(TRUE); XInputGetState_(nullptr),
#endif XInputGetKeystroke_(nullptr),
} XInputSetState_(nullptr),
XInputEnable_(nullptr) {}
XInputInputDriver::~XInputInputDriver() { XInputInputDriver::~XInputInputDriver() {
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8 && _WIN32_WINNT < _WIN32_WINNT_WIN10) if (module_) {
// TODO(gibbed): Is this necessary? FreeLibrary((HMODULE)module_);
XInputEnable(FALSE); module_ = nullptr;
#endif XInputGetCapabilities_ = nullptr;
XInputGetState_ = nullptr;
XInputGetKeystroke_ = nullptr;
XInputSetState_ = nullptr;
XInputEnable_ = nullptr;
}
} }
X_STATUS XInputInputDriver::Setup() { return X_STATUS_SUCCESS; } X_STATUS XInputInputDriver::Setup() {
HMODULE module = LoadLibraryW(L"xinput1_4.dll");
if (!module) {
module = LoadLibraryW(L"xinput1_3.dll");
}
if (!module) {
return X_STATUS_DLL_NOT_FOUND;
}
// Required.
auto xigc = GetProcAddress(module, "XInputGetCapabilities");
auto xigs = GetProcAddress(module, "XInputGetState");
auto xigk = GetProcAddress(module, "XInputGetKeystroke");
auto xiss = GetProcAddress(module, "XInputSetState");
// Not required.
auto xie = GetProcAddress(module, "XInputEnable");
// Only fail when we don't have the bare essentials;
if (!xigc || !xigs || !xigk || !xiss) {
FreeLibrary(module);
return X_STATUS_PROCEDURE_NOT_FOUND;
}
module_ = module;
XInputGetCapabilities_ = xigc;
XInputGetState_ = xigs;
XInputGetKeystroke_ = xigk;
XInputSetState_ = xiss;
XInputEnable_ = xie;
return X_STATUS_SUCCESS;
}
X_RESULT XInputInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags, X_RESULT XInputInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
X_INPUT_CAPABILITIES* out_caps) { X_INPUT_CAPABILITIES* out_caps) {
XINPUT_CAPABILITIES native_caps; XINPUT_CAPABILITIES native_caps;
DWORD result = XInputGetCapabilities(user_index, flags, &native_caps); auto xigc = (decltype(&XInputGetCapabilities))XInputGetCapabilities_;
DWORD result = xigc(user_index, flags, &native_caps);
if (result) { if (result) {
return result; return result;
} }
@ -65,7 +103,8 @@ X_RESULT XInputInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
X_RESULT XInputInputDriver::GetState(uint32_t user_index, X_RESULT XInputInputDriver::GetState(uint32_t user_index,
X_INPUT_STATE* out_state) { X_INPUT_STATE* out_state) {
XINPUT_STATE native_state; XINPUT_STATE native_state;
DWORD result = XInputGetState(user_index, &native_state); auto xigs = (decltype(&XInputGetState))XInputGetState_;
DWORD result = xigs(user_index, &native_state);
if (result) { if (result) {
return result; return result;
} }
@ -87,7 +126,8 @@ X_RESULT XInputInputDriver::SetState(uint32_t user_index,
XINPUT_VIBRATION native_vibration; XINPUT_VIBRATION native_vibration;
native_vibration.wLeftMotorSpeed = vibration->left_motor_speed; native_vibration.wLeftMotorSpeed = vibration->left_motor_speed;
native_vibration.wRightMotorSpeed = vibration->right_motor_speed; native_vibration.wRightMotorSpeed = vibration->right_motor_speed;
DWORD result = XInputSetState(user_index, &native_vibration); auto xiss = (decltype(&XInputSetState))XInputSetState_;
DWORD result = xiss(user_index, &native_vibration);
return result; return result;
} }
@ -104,13 +144,15 @@ X_RESULT XInputInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
// So we first check if the device is connected via XInputGetCapabilities, so // So we first check if the device is connected via XInputGetCapabilities, so
// we are not passing back an uninitialized X_INPUT_KEYSTROKE structure: // we are not passing back an uninitialized X_INPUT_KEYSTROKE structure:
XINPUT_CAPABILITIES caps; XINPUT_CAPABILITIES caps;
result = XInputGetCapabilities(user_index, 0, &caps); auto xigc = (decltype(&XInputGetCapabilities))XInputGetCapabilities_;
result = xigc(user_index, 0, &caps);
if (result) { if (result) {
return result; return result;
} }
XINPUT_KEYSTROKE native_keystroke; XINPUT_KEYSTROKE native_keystroke;
result = XInputGetKeystroke(user_index, 0, &native_keystroke); auto xigk = (decltype(&XInputGetKeystroke))XInputGetKeystroke_;
result = xigk(user_index, 0, &native_keystroke);
if (result) { if (result) {
return result; return result;
} }

View File

@ -31,6 +31,12 @@ class XInputInputDriver : public InputDriver {
X_INPUT_KEYSTROKE* out_keystroke) override; X_INPUT_KEYSTROKE* out_keystroke) override;
protected: protected:
void* module_;
void* XInputGetCapabilities_;
void* XInputGetState_;
void* XInputGetKeystroke_;
void* XInputSetState_;
void* XInputEnable_;
}; };
} // namespace xinput } // namespace xinput

View File

@ -60,6 +60,7 @@ typedef uint32_t X_STATUS;
#define X_STATUS_OBJECT_NAME_COLLISION ((X_STATUS)0xC0000035L) #define X_STATUS_OBJECT_NAME_COLLISION ((X_STATUS)0xC0000035L)
#define X_STATUS_INVALID_PAGE_PROTECTION ((X_STATUS)0xC0000045L) #define X_STATUS_INVALID_PAGE_PROTECTION ((X_STATUS)0xC0000045L)
#define X_STATUS_MUTANT_NOT_OWNED ((X_STATUS)0xC0000046L) #define X_STATUS_MUTANT_NOT_OWNED ((X_STATUS)0xC0000046L)
#define X_STATUS_PROCEDURE_NOT_FOUND ((X_STATUS)0xC000007AL)
#define X_STATUS_INSUFFICIENT_RESOURCES ((X_STATUS)0xC000009AL) #define X_STATUS_INSUFFICIENT_RESOURCES ((X_STATUS)0xC000009AL)
#define X_STATUS_MEMORY_NOT_ALLOCATED ((X_STATUS)0xC00000A0L) #define X_STATUS_MEMORY_NOT_ALLOCATED ((X_STATUS)0xC00000A0L)
#define X_STATUS_NOT_SUPPORTED ((X_STATUS)0xC00000BBL) #define X_STATUS_NOT_SUPPORTED ((X_STATUS)0xC00000BBL)
@ -67,6 +68,7 @@ typedef uint32_t X_STATUS;
#define X_STATUS_INVALID_PARAMETER_2 ((X_STATUS)0xC00000F0L) #define X_STATUS_INVALID_PARAMETER_2 ((X_STATUS)0xC00000F0L)
#define X_STATUS_INVALID_PARAMETER_3 ((X_STATUS)0xC00000F1L) #define X_STATUS_INVALID_PARAMETER_3 ((X_STATUS)0xC00000F1L)
#define X_STATUS_DLL_NOT_FOUND ((X_STATUS)0xC0000135L) #define X_STATUS_DLL_NOT_FOUND ((X_STATUS)0xC0000135L)
#define X_STATUS_ENTRYPOINT_NOT_FOUND ((X_STATUS)0xC0000139L)
#define X_STATUS_MAPPED_ALIGNMENT ((X_STATUS)0xC0000220L) #define X_STATUS_MAPPED_ALIGNMENT ((X_STATUS)0xC0000220L)
#define X_STATUS_NOT_FOUND ((X_STATUS)0xC0000225L) #define X_STATUS_NOT_FOUND ((X_STATUS)0xC0000225L)
#define X_STATUS_DRIVER_ORDINAL_NOT_FOUND ((X_STATUS)0xC0000262L) #define X_STATUS_DRIVER_ORDINAL_NOT_FOUND ((X_STATUS)0xC0000262L)