Fixed Nintendo controller face button layout under Steam

(cherry picked from commit 2ce3dfdf1d)
This commit is contained in:
Sam Lantinga
2025-03-10 17:25:01 -07:00
parent 776f0a685c
commit 21e6c5814c
2 changed files with 44 additions and 0 deletions

View File

@@ -1043,6 +1043,27 @@ static void CleanupSensorFusion(SDL_Joystick *joystick)
}
}
static bool ShouldSwapFaceButtons(const SDL_SteamVirtualGamepadInfo *info)
{
// When "Use Nintendo Button Layout" is enabled under Steam (the default)
// it will send button 0 for the A (east) button and button 1 for the
// B (south) button. This is done so that games that interpret the
// buttons as Xbox input will get button 0 for "A" as they expect.
//
// However, SDL reports positional buttons, so we need to swap
// the buttons so they show up in the correct position. This provides
// consistent behavior regardless of whether we're running under Steam,
// under the default settings.
if (info &&
(info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO ||
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT ||
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT ||
info->type == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR)) {
return true;
}
return false;
}
/*
* Open a joystick for use - the index passed as an argument refers to
* the N'th joystick on the system. This index is the value which will
@@ -1148,6 +1169,7 @@ SDL_Joystick *SDL_OpenJoystick(SDL_JoystickID instance_id)
info = SDL_GetJoystickVirtualGamepadInfoForID(instance_id);
if (info) {
joystick->steam_handle = info->handle;
joystick->swap_face_buttons = ShouldSwapFaceButtons(info);
}
// Use system gyro and accelerometer if the gamepad doesn't have built-in sensors
@@ -2305,6 +2327,25 @@ void SDL_SendJoystickButton(Uint64 timestamp, SDL_Joystick *joystick, Uint8 butt
event.type = SDL_EVENT_JOYSTICK_BUTTON_UP;
}
if (joystick->swap_face_buttons) {
switch (button) {
case 0:
button = 1;
break;
case 1:
button = 0;
break;
case 2:
button = 3;
break;
case 3:
button = 2;
break;
default:
break;
}
}
// Make sure we're not getting garbage or duplicate events
if (button >= joystick->nbuttons) {
return;
@@ -2353,11 +2394,13 @@ static void SendSteamHandleUpdateEvents(void)
if (info) {
if (joystick->steam_handle != info->handle) {
joystick->steam_handle = info->handle;
joystick->swap_face_buttons = ShouldSwapFaceButtons(info);
changed = true;
}
} else {
if (joystick->steam_handle != 0) {
joystick->steam_handle = 0;
joystick->swap_face_buttons = false;
changed = true;
}
}

View File

@@ -83,6 +83,7 @@ struct SDL_Joystick
SDL_GUID guid _guarded; // Joystick guid
Uint16 firmware_version _guarded; // Firmware version, if available
Uint64 steam_handle _guarded; // Steam controller API handle
bool swap_face_buttons _guarded; // Whether we should swap face buttons
int naxes _guarded; // Number of axis controls on the joystick
SDL_JoystickAxisInfo *axes _guarded;