From b7e65a81f1b0638c084d3c4195a7b88fb7175b6c Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 11 Nov 2022 08:57:07 -0800
Subject: [PATCH] Fixed incorrect WGI controller state when the application
loses focus
Recenter the controller elements when WGI stops reporting valid state
Fixes https://github.com/libsdl-org/SDL/issues/5261
---
src/joystick/SDL_joystick.c | 2 +-
src/joystick/SDL_joystick_c.h | 1 +
.../windows/SDL_windows_gaming_input.c | 26 ++++++++++++++-----
3 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index c1e47beb0800..c6d2bf393002 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -1432,7 +1432,7 @@ static void UpdateEventsForDeviceRemoval(int device_index, Uint32 type)
SDL_small_free(events, isstack);
}
-static void
+void
SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick)
{
int i, j;
diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h
index 3ded9763e5c8..0f2093cafb80 100644
--- a/src/joystick/SDL_joystick_c.h
+++ b/src/joystick/SDL_joystick_c.h
@@ -152,6 +152,7 @@ extern void SDL_PrivateJoystickAddTouchpad(SDL_Joystick *joystick, int nfingers)
extern void SDL_PrivateJoystickAddSensor(SDL_Joystick *joystick, SDL_SensorType type, float rate);
extern void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance);
extern void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance);
+extern void SDL_PrivateJoystickForceRecentering(SDL_Joystick *joystick);
extern int SDL_PrivateJoystickAxis(SDL_Joystick *joystick,
Uint8 axis, Sint16 value);
extern int SDL_PrivateJoystickBall(SDL_Joystick *joystick,
diff --git a/src/joystick/windows/SDL_windows_gaming_input.c b/src/joystick/windows/SDL_windows_gaming_input.c
index deec84bf5738..3a89d1154a26 100644
--- a/src/joystick/windows/SDL_windows_gaming_input.c
+++ b/src/joystick/windows/SDL_windows_gaming_input.c
@@ -852,15 +852,27 @@ WGI_JoystickUpdate(SDL_Joystick *joystick)
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_GetCurrentReading(hwdata->controller, nbuttons, buttons, nhats, hats, naxes, axes, ×tamp);
if (SUCCEEDED(hr) && timestamp != hwdata->timestamp) {
UINT32 i;
+ SDL_bool all_zero = SDL_TRUE;
- for (i = 0; i < nbuttons; ++i) {
- SDL_PrivateJoystickButton(joystick, (Uint8)i, buttons[i]);
- }
- for (i = 0; i < nhats; ++i) {
- SDL_PrivateJoystickHat(joystick, (Uint8)i, ConvertHatValue(hats[i]));
- }
+ /* The axes are all zero when the application loses focus */
for (i = 0; i < naxes; ++i) {
- SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)((int) (axes[i] * 65535) - 32768));
+ if (axes[i] != 0.0f) {
+ all_zero = SDL_FALSE;
+ break;
+ }
+ }
+ if (all_zero) {
+ SDL_PrivateJoystickForceRecentering(joystick);
+ } else {
+ for (i = 0; i < nbuttons; ++i) {
+ SDL_PrivateJoystickButton(joystick, (Uint8) i, buttons[i]);
+ }
+ for (i = 0; i < nhats; ++i) {
+ SDL_PrivateJoystickHat(joystick, (Uint8) i, ConvertHatValue(hats[i]));
+ }
+ for (i = 0; i < naxes; ++i) {
+ SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)((int) (axes[i] * 65535) - 32768));
+ }
}
hwdata->timestamp = timestamp;
}