mirror of https://github.com/PCSX2/pcsx2.git
InputManager: Add device/motor enumeration, connect callbacks
This commit is contained in:
parent
7555091d56
commit
14b54e554e
|
@ -535,8 +535,7 @@ std::vector<const HotkeyInfo*> InputManager::GetHotkeyList()
|
||||||
for (const HotkeyInfo* hotkey = hotkey_list; hotkey->name != nullptr; hotkey++)
|
for (const HotkeyInfo* hotkey = hotkey_list; hotkey->name != nullptr; hotkey++)
|
||||||
ret.push_back(hotkey);
|
ret.push_back(hotkey);
|
||||||
}
|
}
|
||||||
std::sort(ret.begin(), ret.end(), [](const HotkeyInfo* left, const HotkeyInfo* right)
|
std::sort(ret.begin(), ret.end(), [](const HotkeyInfo* left, const HotkeyInfo* right) {
|
||||||
{
|
|
||||||
// category -> display name
|
// category -> display name
|
||||||
if (const int res = StringUtil::Strcasecmp(left->category, right->category); res != 0)
|
if (const int res = StringUtil::Strcasecmp(left->category, right->category); res != 0)
|
||||||
return (res < 0);
|
return (res < 0);
|
||||||
|
@ -660,7 +659,8 @@ bool InputManager::InvokeEvents(InputBindingKey key, float value)
|
||||||
binding->current_mask = new_mask;
|
binding->current_mask = new_mask;
|
||||||
|
|
||||||
// invert if we're negative, since the handler expects 0..1
|
// invert if we're negative, since the handler expects 0..1
|
||||||
const float value_to_pass = (negative ? ((value < 0.0f) ? -value : 0.0f) : (value > 0.0f) ? value : 0.0f);
|
const float value_to_pass = (negative ? ((value < 0.0f) ? -value : 0.0f) : (value > 0.0f) ? value :
|
||||||
|
0.0f);
|
||||||
|
|
||||||
// axes are fired regardless of a state change, unless they're zero
|
// axes are fired regardless of a state change, unless they're zero
|
||||||
// for buttons, we can use the state of the last chord key, because it'll be 1 on press,
|
// for buttons, we can use the state of the last chord key, because it'll be 1 on press,
|
||||||
|
@ -825,10 +825,7 @@ bool InputManager::DoEventHook(InputBindingKey key, float value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const InputInterceptHook::CallbackResult action = m_event_intercept_callback(key, value);
|
const InputInterceptHook::CallbackResult action = m_event_intercept_callback(key, value);
|
||||||
if (action == InputInterceptHook::CallbackResult::StopMonitoring)
|
return (action == InputInterceptHook::CallbackResult::StopProcessingEvent);
|
||||||
m_event_intercept_callback = {};
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -884,6 +881,48 @@ void InputManager::PollSources()
|
||||||
UpdateContinuedVibration();
|
UpdateContinuedVibration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> InputManager::EnumerateDevices()
|
||||||
|
{
|
||||||
|
std::vector<std::pair<std::string, std::string>> ret;
|
||||||
|
|
||||||
|
ret.emplace_back("Keyboard", "Keyboard");
|
||||||
|
ret.emplace_back("Mouse", "Mouse");
|
||||||
|
|
||||||
|
for (u32 i = FIRST_EXTERNAL_INPUT_SOURCE; i < LAST_EXTERNAL_INPUT_SOURCE; i++)
|
||||||
|
{
|
||||||
|
if (s_input_sources[i])
|
||||||
|
{
|
||||||
|
std::vector<std::pair<std::string, std::string>> devs(s_input_sources[i]->EnumerateDevices());
|
||||||
|
if (ret.empty())
|
||||||
|
ret = std::move(devs);
|
||||||
|
else
|
||||||
|
std::move(devs.begin(), devs.end(), std::back_inserter(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<InputBindingKey> InputManager::EnumerateMotors()
|
||||||
|
{
|
||||||
|
std::vector<InputBindingKey> ret;
|
||||||
|
|
||||||
|
for (u32 i = FIRST_EXTERNAL_INPUT_SOURCE; i < LAST_EXTERNAL_INPUT_SOURCE; i++)
|
||||||
|
{
|
||||||
|
if (s_input_sources[i])
|
||||||
|
{
|
||||||
|
std::vector<InputBindingKey> devs(s_input_sources[i]->EnumerateMotors());
|
||||||
|
if (ret.empty())
|
||||||
|
ret = std::move(devs);
|
||||||
|
else
|
||||||
|
std::move(devs.begin(), devs.end(), std::back_inserter(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void UpdateInputSourceState(SettingsInterface& si, InputSourceType type, bool default_state)
|
static void UpdateInputSourceState(SettingsInterface& si, InputSourceType type, bool default_state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string_view>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -100,8 +101,8 @@ struct InputInterceptHook
|
||||||
{
|
{
|
||||||
enum class CallbackResult
|
enum class CallbackResult
|
||||||
{
|
{
|
||||||
StopMonitoring,
|
StopProcessingEvent,
|
||||||
ContinueMonitoring
|
ContinueProcessingEvent
|
||||||
};
|
};
|
||||||
|
|
||||||
using Callback = std::function<CallbackResult(InputBindingKey key, float value)>;
|
using Callback = std::function<CallbackResult(InputBindingKey key, float value)>;
|
||||||
|
@ -171,6 +172,12 @@ namespace InputManager
|
||||||
/// Returns a list of all hotkeys.
|
/// Returns a list of all hotkeys.
|
||||||
std::vector<const HotkeyInfo*> GetHotkeyList();
|
std::vector<const HotkeyInfo*> GetHotkeyList();
|
||||||
|
|
||||||
|
/// Enumerates available devices. Returns a pair of the prefix (e.g. SDL-0) and the device name.
|
||||||
|
std::vector<std::pair<std::string, std::string>> EnumerateDevices();
|
||||||
|
|
||||||
|
/// Enumerates available vibration motors at the time of call.
|
||||||
|
std::vector<InputBindingKey> EnumerateMotors();
|
||||||
|
|
||||||
/// Re-parses the config and registers all hotkey and pad bindings.
|
/// Re-parses the config and registers all hotkey and pad bindings.
|
||||||
void ReloadBindings(SettingsInterface& si);
|
void ReloadBindings(SettingsInterface& si);
|
||||||
|
|
||||||
|
@ -209,3 +216,12 @@ namespace InputManager
|
||||||
/// The pad vibration state will internally remain, so that when emulation is unpaused, the effect resumes.
|
/// The pad vibration state will internally remain, so that when emulation is unpaused, the effect resumes.
|
||||||
void PauseVibration();
|
void PauseVibration();
|
||||||
} // namespace InputManager
|
} // namespace InputManager
|
||||||
|
|
||||||
|
namespace Host
|
||||||
|
{
|
||||||
|
/// Called when a new input device is connected.
|
||||||
|
void OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name);
|
||||||
|
|
||||||
|
/// Called when an input device is disconnected.
|
||||||
|
void OnInputDeviceDisconnected(const std::string_view& identifier);
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/Pcsx2Defs.h"
|
#include "common/Pcsx2Defs.h"
|
||||||
|
@ -40,6 +41,9 @@ public:
|
||||||
const std::string_view& device, const std::string_view& binding) = 0;
|
const std::string_view& device, const std::string_view& binding) = 0;
|
||||||
virtual std::string ConvertKeyToString(InputBindingKey key) = 0;
|
virtual std::string ConvertKeyToString(InputBindingKey key) = 0;
|
||||||
|
|
||||||
|
/// Enumerates available devices. Returns a pair of the prefix (e.g. SDL-0) and the device name.
|
||||||
|
virtual std::vector<std::pair<std::string, std::string>> EnumerateDevices() = 0;
|
||||||
|
|
||||||
/// Enumerates available vibration motors at the time of call.
|
/// Enumerates available vibration motors at the time of call.
|
||||||
virtual std::vector<InputBindingKey> EnumerateMotors() = 0;
|
virtual std::vector<InputBindingKey> EnumerateMotors() = 0;
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,11 @@ void SDLInputSource::UpdateSettings(SettingsInterface& si)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDLInputSource::Shutdown()
|
||||||
|
{
|
||||||
|
ShutdownSubsystem();
|
||||||
|
}
|
||||||
|
|
||||||
void SDLInputSource::LoadSettings(SettingsInterface& si)
|
void SDLInputSource::LoadSettings(SettingsInterface& si)
|
||||||
{
|
{
|
||||||
m_controller_enhanced_mode = si.GetBoolValue("InputSources", "SDLControllerEnhancedMode", false);
|
m_controller_enhanced_mode = si.GetBoolValue("InputSources", "SDLControllerEnhancedMode", false);
|
||||||
|
@ -145,6 +150,24 @@ void SDLInputSource::PollEvents()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> SDLInputSource::EnumerateDevices()
|
||||||
|
{
|
||||||
|
std::vector<std::pair<std::string, std::string>> ret;
|
||||||
|
|
||||||
|
for (const ControllerData& cd : m_controllers)
|
||||||
|
{
|
||||||
|
std::string id(StringUtil::StdStringFromFormat("SDL-%d", cd.player_id));
|
||||||
|
|
||||||
|
const char* name = SDL_GameControllerName(cd.game_controller);
|
||||||
|
if (name)
|
||||||
|
ret.emplace_back(std::move(id), name);
|
||||||
|
else
|
||||||
|
ret.emplace_back(std::move(id), "Unknown Device");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<InputBindingKey> SDLInputSource::ParseKeyString(
|
std::optional<InputBindingKey> SDLInputSource::ParseKeyString(
|
||||||
const std::string_view& device, const std::string_view& binding)
|
const std::string_view& device, const std::string_view& binding)
|
||||||
{
|
{
|
||||||
|
@ -391,6 +414,9 @@ bool SDLInputSource::OpenGameController(int index)
|
||||||
Console.Warning("(SDLInputSource) Rumble is not supported on '%s'", SDL_GameControllerName(gcontroller));
|
Console.Warning("(SDLInputSource) Rumble is not supported on '%s'", SDL_GameControllerName(gcontroller));
|
||||||
|
|
||||||
m_controllers.push_back(std::move(cd));
|
m_controllers.push_back(std::move(cd));
|
||||||
|
|
||||||
|
const char* name = SDL_GameControllerName(cd.game_controller);
|
||||||
|
Host::OnInputDeviceConnected(StringUtil::StdStringFromFormat("SDL-%d", player_id), name ? name : "Unknown Device");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,7 +430,11 @@ bool SDLInputSource::CloseGameController(int joystick_index)
|
||||||
SDL_HapticClose(static_cast<SDL_Haptic*>(it->haptic));
|
SDL_HapticClose(static_cast<SDL_Haptic*>(it->haptic));
|
||||||
|
|
||||||
SDL_GameControllerClose(static_cast<SDL_GameController*>(it->game_controller));
|
SDL_GameControllerClose(static_cast<SDL_GameController*>(it->game_controller));
|
||||||
|
|
||||||
|
const int player_id = it->player_id;
|
||||||
m_controllers.erase(it);
|
m_controllers.erase(it);
|
||||||
|
|
||||||
|
Host::OnInputDeviceDisconnected(StringUtil::StdStringFromFormat("SDL-%d", player_id));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
||||||
void PollEvents() override;
|
void PollEvents() override;
|
||||||
|
std::vector<std::pair<std::string, std::string>> EnumerateDevices() override;
|
||||||
std::vector<InputBindingKey> EnumerateMotors() override;
|
std::vector<InputBindingKey> EnumerateMotors() override;
|
||||||
void UpdateMotorState(InputBindingKey key, float intensity) override;
|
void UpdateMotorState(InputBindingKey key, float intensity) override;
|
||||||
void UpdateMotorState(InputBindingKey large_key, InputBindingKey small_key, float large_intensity, float small_intensity) override;
|
void UpdateMotorState(InputBindingKey large_key, InputBindingKey small_key, float large_intensity, float small_intensity) override;
|
||||||
|
|
|
@ -116,6 +116,12 @@ void XInputSource::UpdateSettings(SettingsInterface& si)
|
||||||
|
|
||||||
void XInputSource::Shutdown()
|
void XInputSource::Shutdown()
|
||||||
{
|
{
|
||||||
|
for (u32 i = 0; i < NUM_CONTROLLERS; i++)
|
||||||
|
{
|
||||||
|
if (m_controllers[i].connected)
|
||||||
|
HandleControllerDisconnection(i);
|
||||||
|
}
|
||||||
|
|
||||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||||
if (m_xinput_module)
|
if (m_xinput_module)
|
||||||
{
|
{
|
||||||
|
@ -154,6 +160,22 @@ void XInputSource::PollEvents()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> XInputSource::EnumerateDevices()
|
||||||
|
{
|
||||||
|
std::vector<std::pair<std::string, std::string>> ret;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < NUM_CONTROLLERS; i++)
|
||||||
|
{
|
||||||
|
if (!m_controllers[i].connected)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret.emplace_back(StringUtil::StdStringFromFormat("XInput-%u", i),
|
||||||
|
StringUtil::StdStringFromFormat("XInput Controller %u", i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<InputBindingKey> XInputSource::ParseKeyString(
|
std::optional<InputBindingKey> XInputSource::ParseKeyString(
|
||||||
const std::string_view& device, const std::string_view& binding)
|
const std::string_view& device, const std::string_view& binding)
|
||||||
{
|
{
|
||||||
|
@ -276,12 +298,17 @@ void XInputSource::HandleControllerConnection(u32 index)
|
||||||
cd.connected = true;
|
cd.connected = true;
|
||||||
cd.has_large_motor = caps.Vibration.wLeftMotorSpeed != 0;
|
cd.has_large_motor = caps.Vibration.wLeftMotorSpeed != 0;
|
||||||
cd.has_small_motor = caps.Vibration.wRightMotorSpeed != 0;
|
cd.has_small_motor = caps.Vibration.wRightMotorSpeed != 0;
|
||||||
|
|
||||||
|
Host::OnInputDeviceConnected(StringUtil::StdStringFromFormat("XInput-%u", index),
|
||||||
|
StringUtil::StdStringFromFormat("XInput Controller %u", index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void XInputSource::HandleControllerDisconnection(u32 index)
|
void XInputSource::HandleControllerDisconnection(u32 index)
|
||||||
{
|
{
|
||||||
Console.WriteLn("XInput controller %u disconnected.", index);
|
Console.WriteLn("XInput controller %u disconnected.", index);
|
||||||
m_controllers[index] = {};
|
m_controllers[index] = {};
|
||||||
|
|
||||||
|
Host::OnInputDeviceDisconnected(StringUtil::StdStringFromFormat("XInput-%u", index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void XInputSource::CheckForStateChanges(u32 index, const XINPUT_STATE& new_state)
|
void XInputSource::CheckForStateChanges(u32 index, const XINPUT_STATE& new_state)
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
||||||
void PollEvents() override;
|
void PollEvents() override;
|
||||||
|
std::vector<std::pair<std::string, std::string>> EnumerateDevices() override;
|
||||||
std::vector<InputBindingKey> EnumerateMotors() override;
|
std::vector<InputBindingKey> EnumerateMotors() override;
|
||||||
void UpdateMotorState(InputBindingKey key, float intensity) override;
|
void UpdateMotorState(InputBindingKey key, float intensity) override;
|
||||||
void UpdateMotorState(InputBindingKey large_key, InputBindingKey small_key, float large_intensity, float small_intensity) override;
|
void UpdateMotorState(InputBindingKey large_key, InputBindingKey small_key, float large_intensity, float small_intensity) override;
|
||||||
|
|
Loading…
Reference in New Issue