From 4f031ea5da370762469f977ee115a4d874d3de63 Mon Sep 17 00:00:00 2001 From: Nintorch <92302738+Nintorch@users.noreply.github.com> Date: Fri, 12 Jun 2026 12:06:32 +0500 Subject: [PATCH] Fix Xbox One controller detection on the web --- src/joystick/emscripten/SDL_sysjoystick.c | 40 ++++++++++++++--------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 2ff71d0785..3c58004fee 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -147,15 +147,18 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep vendor = SDL_GetEmscriptenJoystickVendor(gamepadEvent->index); product = SDL_GetEmscriptenJoystickProduct(gamepadEvent->index); is_xinput = SDL_IsEmscriptenJoystickXInput(gamepadEvent->index); - - // Use a generic VID/PID representing an XInput controller - if (!vendor && !product && is_xinput) { - vendor = USB_VENDOR_MICROSOFT; - product = USB_PRODUCT_XBOX360_XUSB_CONTROLLER; - } os_id = SDL_GetEmscriptenOSID(); + item->trigger_rumble_available = MAIN_THREAD_EM_ASM_INT({ + let gamepad = navigator['getGamepads']()[$0]; + // This effect is not supported in Safari, so it's okay for us to check the vibrationActuator.effects array here for the browsers that do support it + if (!gamepad || !gamepad['vibrationActuator'] || !gamepad['vibrationActuator']['effects'] || !gamepad['vibrationActuator']['effects']['includes']('trigger-rumble')) { + return false; + } + return true; + }, item->index); + if (os_id != 0) { if (os_id == 1 || os_id == 3) { // Android or iOS (mobile) bus = SDL_HARDWARE_BUS_BLUETOOTH; @@ -164,6 +167,21 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep } } + if (!vendor && !product && is_xinput) { + // Use a generic VID/PID representing an XInput controller + vendor = USB_VENDOR_MICROSOFT; + product = USB_PRODUCT_XBOX360_XUSB_CONTROLLER; + + if (item->trigger_rumble_available) { + // Assume Xbox One S Controller + if (bus == SDL_HARDWARE_BUS_BLUETOOTH) { + product = USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH; + } else { + product = USB_PRODUCT_XBOX_ONE_S; + } + } + } + if (SDL_strcmp(gamepadEvent->mapping, "standard") == 0) { // We should differentiate between devices that are mapped or unmapped by the browser. os_id += 0x80; @@ -513,15 +531,7 @@ static bool EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index) SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true); } - item->trigger_rumble_available = MAIN_THREAD_EM_ASM_INT({ - let gamepad = navigator['getGamepads']()[$0]; - // This effect is not supported in Safari, so it's okay for us to check the vibrationActuator.effects array here for the browsers that do support it - if (!gamepad || !gamepad['vibrationActuator'] || !gamepad['vibrationActuator']['effects'] || !gamepad['vibrationActuator']['effects']['includes']('trigger-rumble')) { - return false; - } - return true; - }, item->index); - + // item->trigger_rumble_available is set in Emscripten_JoyStickConnected if (item->trigger_rumble_available) { SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, true); }