SDLGamepad: Support multiple touchpads

This commit is contained in:
Joshua Vandaële 2026-06-15 16:42:16 +02:00
parent 144d19433a
commit bb6551e5dc
No known key found for this signature in database
GPG Key ID: 6BB95AF71EB0F406
2 changed files with 38 additions and 27 deletions

View File

@ -104,15 +104,21 @@ Gamepad::Gamepad(SDL_Gamepad* const gamepad, SDL_Joystick* const joystick)
}
// Touchpad
if (SDL_GetNumGamepadTouchpads(m_gamepad) > 0)
const int num_touchpads = SDL_GetNumGamepadTouchpads(m_gamepad);
if (num_touchpads > 0)
{
const char* const name_x = "Touchpad X";
AddInput(new NonDetectableDirectionalInput<-1>(name_x, &m_touchpad_x));
AddInput(new NonDetectableDirectionalInput<+1>(name_x, &m_touchpad_x));
const char* const name_y = "Touchpad Y";
AddInput(new NonDetectableDirectionalInput<-1>(name_y, &m_touchpad_y));
AddInput(new NonDetectableDirectionalInput<+1>(name_y, &m_touchpad_y));
AddInput(new NormalizedInput("Touchpad Pressure", &m_touchpad_pressure));
m_touchpads.resize(num_touchpads);
for (int t = 0; t < num_touchpads; ++t)
{
// We do not number the first touchpad to keep backwards compatibility with existing configs
// that use "Touchpad X" and "Touchpad Y" as input names.
const std::string prefix = t > 0 ? fmt::format("Touchpad {} ", t + 1) : "Touchpad ";
AddInput(new NonDetectableDirectionalInput<-1>(prefix + "X", &m_touchpads[t].x));
AddInput(new NonDetectableDirectionalInput<+1>(prefix + "X", &m_touchpads[t].x));
AddInput(new NonDetectableDirectionalInput<-1>(prefix + "Y", &m_touchpads[t].y));
AddInput(new NonDetectableDirectionalInput<+1>(prefix + "Y", &m_touchpads[t].y));
AddInput(new NormalizedInput(prefix + "Pressure", &m_touchpads[t].pressure));
}
}
// Motion

View File

@ -42,6 +42,13 @@ static_assert(GetDirectionFromHatMask(SDL_HAT_LEFT) == 3);
namespace ciface::SDL
{
struct TouchpadState
{
float x = 0.f;
float y = 0.f;
float pressure = 0.f;
};
class Gamepad : public Core::Device
{
private:
@ -262,15 +269,15 @@ private:
class NormalizedInput : public Input
{
public:
NormalizedInput(const char* name, const float* state) : m_name{std::move(name)}, m_state{*state}
NormalizedInput(std::string name, const float* state) : m_name{std::move(name)}, m_state{*state}
{
}
std::string GetName() const override { return std::string{m_name}; }
std::string GetName() const override { return m_name; }
ControlState GetState() const override { return m_state; }
private:
const char* const m_name;
const std::string m_name;
const float& m_state;
};
@ -278,17 +285,17 @@ private:
class NonDetectableDirectionalInput : public Input
{
public:
NonDetectableDirectionalInput(const char* name, const float* state)
NonDetectableDirectionalInput(std::string name, const float* state)
: m_name{std::move(name)}, m_state{*state}
{
}
std::string GetName() const override { return std::string{m_name} + (Scale > 0 ? '+' : '-'); }
std::string GetName() const override { return m_name + (Scale > 0 ? '+' : '-'); }
bool IsDetectable() const override { return false; }
ControlState GetState() const override { return m_state * Scale; }
private:
const char* const m_name;
const std::string m_name;
const float& m_state;
};
@ -326,17 +333,17 @@ public:
{
UpdateBatteryLevel();
// We only support one touchpad and one finger.
const int touchpad_index = 0;
const int finger_index = 0;
if (SDL_GetNumGamepadTouchpads(m_gamepad) > touchpad_index &&
SDL_GetNumGamepadTouchpadFingers(m_gamepad, touchpad_index) > finger_index)
// We only support one finger per touchpad
static constexpr int finger_index = 0;
for (int t = 0; t < static_cast<int>(m_touchpads.size()); ++t)
{
SDL_GetGamepadTouchpadFinger(m_gamepad, touchpad_index, finger_index, nullptr, &m_touchpad_x,
&m_touchpad_y, &m_touchpad_pressure);
m_touchpad_x = m_touchpad_x * 2 - 1;
m_touchpad_y = m_touchpad_y * 2 - 1;
if (SDL_GetNumGamepadTouchpadFingers(m_gamepad, t) <= finger_index)
continue;
SDL_GetGamepadTouchpadFinger(m_gamepad, t, finger_index, nullptr, &m_touchpads[t].x,
&m_touchpads[t].y, &m_touchpads[t].pressure);
m_touchpads[t].x = m_touchpads[t].x * 2 - 1;
m_touchpads[t].y = m_touchpads[t].y * 2 - 1;
}
return Core::DeviceRemoval::Keep;
@ -366,9 +373,7 @@ private:
SDL_Joystick* const m_joystick;
SDL_Haptic* m_haptic = nullptr;
ControlState m_battery_value;
float m_touchpad_x = 0.f;
float m_touchpad_y = 0.f;
float m_touchpad_pressure = 0.f;
std::vector<TouchpadState> m_touchpads;
};
struct SDLMotionAxis