From 38697dd8129afc42fe646e4f6978471739589b77 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 24 Mar 2025 10:44:54 -0700
Subject: [PATCH] Fixed mixed trigger and body rumble for Xbox controllers on
Windows
Fixes https://github.com/libsdl-org/SDL/issues/12095
(cherry picked from commit b6ca03611f41100caa40b65ec630f97a0dfb9595)
---
src/joystick/windows/SDL_rawinputjoystick.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c
index d135382e5dcd4..3e2b270fa946d 100644
--- a/src/joystick/windows/SDL_rawinputjoystick.c
+++ b/src/joystick/windows/SDL_rawinputjoystick.c
@@ -160,6 +160,8 @@ struct joystick_hwdata
WindowsGamingInputGamepadState *wgi_slot;
#endif
+ bool triggers_rumbling;
+
SDL_RAWINPUT_Device *device;
};
typedef struct joystick_hwdata RAWINPUT_DeviceContext;
@@ -1461,7 +1463,7 @@ static bool RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency
#ifdef SDL_JOYSTICK_RAWINPUT_XINPUT
// Prefer XInput over WGI because it allows rumble in the background
- if (!rumbled && ctx->xinput_correlated) {
+ if (!rumbled && ctx->xinput_correlated && !ctx->triggers_rumbling) {
XINPUT_VIBRATION XVibration;
if (!XINPUTSETSTATE) {
@@ -1479,11 +1481,12 @@ static bool RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency
#endif // SDL_JOYSTICK_RAWINPUT_XINPUT
#ifdef SDL_JOYSTICK_RAWINPUT_WGI
+ // Save off the motor state in case trigger rumble is started
+ WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
+ HRESULT hr;
+ gamepad_state->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
+ gamepad_state->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
if (!rumbled && ctx->wgi_correlated) {
- WindowsGamingInputGamepadState *gamepad_state = ctx->wgi_slot;
- HRESULT hr;
- gamepad_state->vibration.LeftMotor = (DOUBLE)low_frequency_rumble / SDL_MAX_UINT16;
- gamepad_state->vibration.RightMotor = (DOUBLE)high_frequency_rumble / SDL_MAX_UINT16;
hr = __x_ABI_CWindows_CGaming_CInput_CIGamepad_put_Vibration(gamepad_state->gamepad, gamepad_state->vibration);
if (SUCCEEDED(hr)) {
rumbled = true;
@@ -1515,6 +1518,7 @@ static bool RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_
if (!SUCCEEDED(hr)) {
return SDL_SetError("Setting vibration failed: 0x%lx", hr);
}
+ ctx->triggers_rumbling = (left_rumble > 0 || right_rumble > 0);
return true;
} else {
return SDL_SetError("Controller isn't correlated yet, try hitting a button first");