[HID] Allow winkey driver to use the first unused user index
This removes the user_index == 0 requirement from the InputSystem code, and updates WinKeyInputDriver to use the first non-connected user index if it can. Eg. if you had 2 XInput controllers plugged in, those two will take up user index 0 and 1, and keyboard will take user index 2. If all four indexes are taken up already, the WinKey driver will be disabled. (This is done by passing already-setup drivers to each drivers Setup function: since WinKey is the last to be setup, this'll let it query the XInput driver and find which user_index it should handle)
This commit is contained in:
parent
0a2489d44c
commit
4079a7bb8a
|
@ -195,7 +195,7 @@ std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
|
||||||
#endif // XE_PLATFORM_WIN32
|
#endif // XE_PLATFORM_WIN32
|
||||||
factory.Add("sdl", xe::hid::sdl::Create);
|
factory.Add("sdl", xe::hid::sdl::Create);
|
||||||
for (auto& driver : factory.CreateAll(cvars::hid, window)) {
|
for (auto& driver : factory.CreateAll(cvars::hid, window)) {
|
||||||
if (XSUCCEEDED(driver->Setup())) {
|
if (XSUCCEEDED(driver->Setup(drivers))) {
|
||||||
drivers.emplace_back(std::move(driver));
|
drivers.emplace_back(std::move(driver));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
#ifndef XENIA_HID_INPUT_DRIVER_H_
|
#ifndef XENIA_HID_INPUT_DRIVER_H_
|
||||||
#define XENIA_HID_INPUT_DRIVER_H_
|
#define XENIA_HID_INPUT_DRIVER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/hid/input.h"
|
#include "xenia/hid/input.h"
|
||||||
#include "xenia/xbox.h"
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
|
@ -28,7 +31,8 @@ class InputDriver {
|
||||||
public:
|
public:
|
||||||
virtual ~InputDriver();
|
virtual ~InputDriver();
|
||||||
|
|
||||||
virtual X_STATUS Setup() = 0;
|
virtual X_STATUS Setup(
|
||||||
|
std::vector<std::unique_ptr<hid::InputDriver>>& drivers) = 0;
|
||||||
|
|
||||||
virtual X_RESULT GetCapabilities(uint32_t user_index, uint32_t flags,
|
virtual X_RESULT GetCapabilities(uint32_t user_index, uint32_t flags,
|
||||||
X_INPUT_CAPABILITIES* out_caps) = 0;
|
X_INPUT_CAPABILITIES* out_caps) = 0;
|
||||||
|
|
|
@ -19,7 +19,10 @@ NopInputDriver::NopInputDriver(xe::ui::Window* window) : InputDriver(window) {}
|
||||||
|
|
||||||
NopInputDriver::~NopInputDriver() = default;
|
NopInputDriver::~NopInputDriver() = default;
|
||||||
|
|
||||||
X_STATUS NopInputDriver::Setup() { return X_STATUS_SUCCESS; }
|
X_STATUS NopInputDriver::Setup(
|
||||||
|
std::vector<std::unique_ptr<InputDriver>>& drivers) {
|
||||||
|
return X_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(benvanik): spoof a device so that games don't stop waiting for
|
// TODO(benvanik): spoof a device so that games don't stop waiting for
|
||||||
// a controller to be plugged in.
|
// a controller to be plugged in.
|
||||||
|
|
|
@ -21,7 +21,8 @@ class NopInputDriver : public InputDriver {
|
||||||
explicit NopInputDriver(xe::ui::Window* window);
|
explicit NopInputDriver(xe::ui::Window* window);
|
||||||
~NopInputDriver() override;
|
~NopInputDriver() override;
|
||||||
|
|
||||||
X_STATUS Setup() override;
|
X_STATUS Setup(
|
||||||
|
std::vector<std::unique_ptr<hid::InputDriver>>& drivers) override;
|
||||||
|
|
||||||
X_RESULT GetCapabilities(uint32_t user_index, uint32_t flags,
|
X_RESULT GetCapabilities(uint32_t user_index, uint32_t flags,
|
||||||
X_INPUT_CAPABILITIES* out_caps) override;
|
X_INPUT_CAPABILITIES* out_caps) override;
|
||||||
|
|
|
@ -45,11 +45,40 @@ WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window)
|
||||||
|
|
||||||
WinKeyInputDriver::~WinKeyInputDriver() = default;
|
WinKeyInputDriver::~WinKeyInputDriver() = default;
|
||||||
|
|
||||||
X_STATUS WinKeyInputDriver::Setup() { return X_STATUS_SUCCESS; }
|
X_STATUS WinKeyInputDriver::Setup(
|
||||||
|
std::vector<std::unique_ptr<hid::InputDriver>>& drivers) {
|
||||||
|
int index = 0;
|
||||||
|
X_INPUT_STATE state;
|
||||||
|
|
||||||
|
// Search already added drivers for an index that none of them can use
|
||||||
|
while (index < 4) {
|
||||||
|
bool not_connected = false;
|
||||||
|
|
||||||
|
for (auto& driver : drivers) {
|
||||||
|
if (driver.get()->GetState(index, &state) !=
|
||||||
|
X_ERROR_DEVICE_NOT_CONNECTED) {
|
||||||
|
not_connected = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
not_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not_connected) {
|
||||||
|
user_index_ = index;
|
||||||
|
return X_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All indexes are in use...
|
||||||
|
user_index_ = -1;
|
||||||
|
// Return error so this driver won't get used
|
||||||
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
X_RESULT WinKeyInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
|
X_RESULT WinKeyInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
|
||||||
X_INPUT_CAPABILITIES* out_caps) {
|
X_INPUT_CAPABILITIES* out_caps) {
|
||||||
if (user_index != 0) {
|
if (user_index != user_index_) {
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +103,7 @@ X_RESULT WinKeyInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
|
||||||
|
|
||||||
X_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
|
X_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
|
||||||
X_INPUT_STATE* out_state) {
|
X_INPUT_STATE* out_state) {
|
||||||
if (user_index != 0) {
|
if (user_index != user_index_) {
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +243,7 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
|
||||||
|
|
||||||
X_RESULT WinKeyInputDriver::SetState(uint32_t user_index,
|
X_RESULT WinKeyInputDriver::SetState(uint32_t user_index,
|
||||||
X_INPUT_VIBRATION* vibration) {
|
X_INPUT_VIBRATION* vibration) {
|
||||||
if (user_index != 0) {
|
if (user_index != user_index_) {
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +252,7 @@ X_RESULT WinKeyInputDriver::SetState(uint32_t user_index,
|
||||||
|
|
||||||
X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
|
X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
|
||||||
X_INPUT_KEYSTROKE* out_keystroke) {
|
X_INPUT_KEYSTROKE* out_keystroke) {
|
||||||
if (user_index != 0) {
|
if (user_index != user_index_) {
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +385,7 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
|
||||||
out_keystroke->virtual_key = virtual_key;
|
out_keystroke->virtual_key = virtual_key;
|
||||||
out_keystroke->unicode = unicode;
|
out_keystroke->unicode = unicode;
|
||||||
out_keystroke->flags = keystroke_flags;
|
out_keystroke->flags = keystroke_flags;
|
||||||
out_keystroke->user_index = 0;
|
out_keystroke->user_index = user_index_;
|
||||||
out_keystroke->hid_code = hid_code;
|
out_keystroke->hid_code = hid_code;
|
||||||
|
|
||||||
// X_ERROR_EMPTY if no new keys
|
// X_ERROR_EMPTY if no new keys
|
||||||
|
|
|
@ -24,7 +24,8 @@ class WinKeyInputDriver : public InputDriver {
|
||||||
explicit WinKeyInputDriver(xe::ui::Window* window);
|
explicit WinKeyInputDriver(xe::ui::Window* window);
|
||||||
~WinKeyInputDriver() override;
|
~WinKeyInputDriver() override;
|
||||||
|
|
||||||
X_STATUS Setup() override;
|
X_STATUS Setup(
|
||||||
|
std::vector<std::unique_ptr<hid::InputDriver>>& drivers) override;
|
||||||
|
|
||||||
X_RESULT GetCapabilities(uint32_t user_index, uint32_t flags,
|
X_RESULT GetCapabilities(uint32_t user_index, uint32_t flags,
|
||||||
X_INPUT_CAPABILITIES* out_caps) override;
|
X_INPUT_CAPABILITIES* out_caps) override;
|
||||||
|
@ -33,6 +34,8 @@ class WinKeyInputDriver : public InputDriver {
|
||||||
X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags,
|
X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags,
|
||||||
X_INPUT_KEYSTROKE* out_keystroke) override;
|
X_INPUT_KEYSTROKE* out_keystroke) override;
|
||||||
|
|
||||||
|
void user_index(uint32_t index) { user_index_ = index; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct KeyEvent {
|
struct KeyEvent {
|
||||||
int vkey = 0;
|
int vkey = 0;
|
||||||
|
@ -45,6 +48,8 @@ class WinKeyInputDriver : public InputDriver {
|
||||||
std::queue<KeyEvent> key_events_;
|
std::queue<KeyEvent> key_events_;
|
||||||
|
|
||||||
uint32_t packet_number_;
|
uint32_t packet_number_;
|
||||||
|
|
||||||
|
uint32_t user_index_ = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace winkey
|
} // namespace winkey
|
||||||
|
|
|
@ -42,7 +42,8 @@ XInputInputDriver::~XInputInputDriver() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
X_STATUS XInputInputDriver::Setup() {
|
X_STATUS XInputInputDriver::Setup(
|
||||||
|
std::vector<std::unique_ptr<InputDriver>>& drivers) {
|
||||||
HMODULE module = LoadLibraryW(L"xinput1_4.dll");
|
HMODULE module = LoadLibraryW(L"xinput1_4.dll");
|
||||||
if (!module) {
|
if (!module) {
|
||||||
module = LoadLibraryW(L"xinput1_3.dll");
|
module = LoadLibraryW(L"xinput1_3.dll");
|
||||||
|
|
|
@ -21,7 +21,8 @@ class XInputInputDriver : public InputDriver {
|
||||||
explicit XInputInputDriver(xe::ui::Window* window);
|
explicit XInputInputDriver(xe::ui::Window* window);
|
||||||
~XInputInputDriver() override;
|
~XInputInputDriver() override;
|
||||||
|
|
||||||
X_STATUS Setup() override;
|
X_STATUS Setup(
|
||||||
|
std::vector<std::unique_ptr<hid::InputDriver>>& drivers) override;
|
||||||
|
|
||||||
X_RESULT GetCapabilities(uint32_t user_index, uint32_t flags,
|
X_RESULT GetCapabilities(uint32_t user_index, uint32_t flags,
|
||||||
X_INPUT_CAPABILITIES* out_caps) override;
|
X_INPUT_CAPABILITIES* out_caps) override;
|
||||||
|
|
|
@ -101,7 +101,7 @@ dword_result_t XamInputGetState(dword_t user_index, dword_t flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
auto input_system = kernel_state()->emulator()->input_system();
|
auto input_system = kernel_state()->emulator()->input_system();
|
||||||
return input_system->GetState(user_index, input_state);
|
return input_system->GetState(actual_user_index, input_state);
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamInputGetState, kInput, kImplemented);
|
DECLARE_XAM_EXPORT1(XamInputGetState, kInput, kImplemented);
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ dword_result_t XamInputSetState(dword_t user_index, dword_t unk,
|
||||||
}
|
}
|
||||||
|
|
||||||
auto input_system = kernel_state()->emulator()->input_system();
|
auto input_system = kernel_state()->emulator()->input_system();
|
||||||
return input_system->SetState(user_index, vibration);
|
return input_system->SetState(actual_user_index, vibration);
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamInputSetState, kInput, kImplemented);
|
DECLARE_XAM_EXPORT1(XamInputSetState, kInput, kImplemented);
|
||||||
|
|
||||||
|
@ -182,12 +182,17 @@ X_HRESULT_result_t XamUserGetDeviceContext(dword_t user_index, dword_t unk,
|
||||||
// Games check the result - usually with some masking.
|
// Games check the result - usually with some masking.
|
||||||
// If this function fails they assume zero, so let's fail AND
|
// If this function fails they assume zero, so let's fail AND
|
||||||
// set zero just to be safe.
|
// set zero just to be safe.
|
||||||
*out_ptr = 0;
|
// *out_ptr = 0;
|
||||||
if (!user_index || (user_index & 0xFF) == 0xFF) {
|
|
||||||
return X_E_SUCCESS;
|
uint32_t actual_user_index = user_index;
|
||||||
} else {
|
if ((user_index & 0xFF) == 0xFF) {
|
||||||
return X_E_DEVICE_NOT_CONNECTED;
|
// Always pin user to 0.
|
||||||
|
actual_user_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto input_system = kernel_state()->emulator()->input_system();
|
||||||
|
X_INPUT_STATE state;
|
||||||
|
return input_system->GetState(actual_user_index, &state);
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamUserGetDeviceContext, kInput, kStub);
|
DECLARE_XAM_EXPORT1(XamUserGetDeviceContext, kInput, kStub);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue