diff options
Diffstat (limited to 'Source/3rdParty/SDL2/src/joystick/SDL_gamecontroller.c')
-rw-r--r-- | Source/3rdParty/SDL2/src/joystick/SDL_gamecontroller.c | 322 |
1 files changed, 263 insertions, 59 deletions
diff --git a/Source/3rdParty/SDL2/src/joystick/SDL_gamecontroller.c b/Source/3rdParty/SDL2/src/joystick/SDL_gamecontroller.c index b0f833a..eb1ef06 100644 --- a/Source/3rdParty/SDL2/src/joystick/SDL_gamecontroller.c +++ b/Source/3rdParty/SDL2/src/joystick/SDL_gamecontroller.c @@ -25,6 +25,7 @@ #include "SDL_events.h" #include "SDL_assert.h" #include "SDL_hints.h" +#include "SDL_timer.h" #include "SDL_sysjoystick.h" #include "SDL_joystick_c.h" #include "SDL_gamecontrollerdb.h" @@ -38,6 +39,9 @@ #endif +/* Many controllers turn the center button into an instantaneous button press */ +#define SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS 250 + #define SDL_CONTROLLER_PLATFORM_FIELD "platform:" /* a list of currently opened game controllers */ @@ -97,8 +101,9 @@ typedef struct _ControllerMapping_t static SDL_JoystickGUID s_zeroGUID; static ControllerMapping_t *s_pSupportedControllers = NULL; +static ControllerMapping_t *s_pDefaultMapping = NULL; +static ControllerMapping_t *s_pHIDAPIMapping = NULL; static ControllerMapping_t *s_pXInputMapping = NULL; -static ControllerMapping_t *s_pEmscriptenMapping = NULL; /* The SDL game controller structure */ struct _SDL_GameController @@ -106,12 +111,12 @@ struct _SDL_GameController SDL_Joystick *joystick; /* underlying joystick device */ int ref_count; - SDL_JoystickGUID guid; const char *name; int num_bindings; SDL_ExtendedGameControllerBind *bindings; SDL_ExtendedGameControllerBind **last_match_axis; Uint8 *last_hat_mask; + Uint32 guide_button_down; struct _SDL_GameController *next; /* pointer to next game controller we have allocated */ }; @@ -416,7 +421,7 @@ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event * ev /* * Helper function to scan the mappings database for a controller with the specified GUID */ -static ControllerMapping_t *SDL_PrivateGetControllerMappingForGUID(SDL_JoystickGUID *guid) +static ControllerMapping_t *SDL_PrivateGetControllerMappingForGUID(SDL_JoystickGUID *guid, SDL_bool exact_match) { ControllerMapping_t *pSupportedController = s_pSupportedControllers; while (pSupportedController) { @@ -425,6 +430,18 @@ static ControllerMapping_t *SDL_PrivateGetControllerMappingForGUID(SDL_JoystickG } pSupportedController = pSupportedController->next; } + if (!exact_match) { + if (SDL_IsJoystickHIDAPI(*guid)) { + /* This is a HIDAPI device */ + return s_pHIDAPIMapping; + } +#if SDL_JOYSTICK_XINPUT + if (SDL_IsJoystickXInput(*guid)) { + /* This is an XInput device */ + return s_pXInputMapping; + } +#endif + } return NULL; } @@ -665,11 +682,10 @@ SDL_PrivateGameControllerParseControllerConfigString(SDL_GameController *gamecon /* * Make a new button mapping struct */ -static void SDL_PrivateLoadButtonMapping(SDL_GameController *gamecontroller, SDL_JoystickGUID guid, const char *pchName, const char *pchMapping) +static void SDL_PrivateLoadButtonMapping(SDL_GameController *gamecontroller, const char *pchName, const char *pchMapping) { int i; - gamecontroller->guid = guid; gamecontroller->name = pchName; gamecontroller->num_bindings = 0; SDL_memset(gamecontroller->last_match_axis, 0, gamecontroller->joystick->naxes * sizeof(*gamecontroller->last_match_axis)); @@ -783,14 +799,16 @@ static void SDL_PrivateGameControllerRefreshMapping(ControllerMapping_t *pContro { SDL_GameController *gamecontrollerlist = SDL_gamecontrollers; while (gamecontrollerlist) { - if (!SDL_memcmp(&gamecontrollerlist->guid, &pControllerMapping->guid, sizeof(pControllerMapping->guid))) { - SDL_Event event; - event.type = SDL_CONTROLLERDEVICEREMAPPED; - event.cdevice.which = gamecontrollerlist->joystick->instance_id; - SDL_PushEvent(&event); - + if (!SDL_memcmp(&gamecontrollerlist->joystick->guid, &pControllerMapping->guid, sizeof(pControllerMapping->guid))) { /* Not really threadsafe. Should this lock access within SDL_GameControllerEventWatcher? */ - SDL_PrivateLoadButtonMapping(gamecontrollerlist, pControllerMapping->guid, pControllerMapping->name, pControllerMapping->mapping); + SDL_PrivateLoadButtonMapping(gamecontrollerlist, pControllerMapping->name, pControllerMapping->mapping); + + { + SDL_Event event; + event.type = SDL_CONTROLLERDEVICEREMAPPED; + event.cdevice.which = gamecontrollerlist->joystick->instance_id; + SDL_PushEvent(&event); + } } gamecontrollerlist = gamecontrollerlist->next; @@ -820,7 +838,7 @@ SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, return NULL; } - pControllerMapping = SDL_PrivateGetControllerMappingForGUID(&jGUID); + pControllerMapping = SDL_PrivateGetControllerMappingForGUID(&jGUID, SDL_TRUE); if (pControllerMapping) { /* Only overwrite the mapping if the priority is the same or higher. */ if (pControllerMapping->priority <= priority) { @@ -869,6 +887,119 @@ SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, const char *mappingString, return pControllerMapping; } +#ifdef __ANDROID__ +/* + * Helper function to guess at a mapping based on the elements reported for this controller + */ +static ControllerMapping_t *SDL_CreateMappingForAndroidController(const char *name, SDL_JoystickGUID guid) +{ + SDL_bool existing; + char name_string[128]; + char mapping_string[1024]; + int button_mask; + int axis_mask; + + button_mask = SDL_SwapLE16(*(Uint16*)(&guid.data[sizeof(guid.data)-4])); + axis_mask = SDL_SwapLE16(*(Uint16*)(&guid.data[sizeof(guid.data)-2])); + if (!button_mask && !axis_mask) { + /* Accelerometer, shouldn't have a game controller mapping */ + return NULL; + } + + /* Remove any commas in the name */ + SDL_strlcpy(name_string, name, sizeof(name_string)); + { + char *spot; + for (spot = name_string; *spot; ++spot) { + if (*spot == ',') { + *spot = ' '; + } + } + } + SDL_snprintf(mapping_string, sizeof(mapping_string), "none,%s,", name_string); + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_A)) { + SDL_strlcat(mapping_string, "a:b0,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_B)) { + SDL_strlcat(mapping_string, "b:b1,", sizeof(mapping_string)); + } else if (button_mask & (1 << SDL_CONTROLLER_BUTTON_BACK)) { + /* Use the back button as "B" for easy UI navigation with TV remotes */ + SDL_strlcat(mapping_string, "b:b4,", sizeof(mapping_string)); + button_mask &= ~(1 << SDL_CONTROLLER_BUTTON_BACK); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_X)) { + SDL_strlcat(mapping_string, "x:b2,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_Y)) { + SDL_strlcat(mapping_string, "y:b3,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_BACK)) { + SDL_strlcat(mapping_string, "back:b4,", sizeof(mapping_string)); + } +#if 0 /* The guide button generally isn't functional (or acts as a home button) on most Android controllers */ + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_GUIDE)) { + SDL_strlcat(mapping_string, "guide:b5,", sizeof(mapping_string)); +#if 0 /* Actually this will be done in Steam */ + } else if (button_mask & (1 << SDL_CONTROLLER_BUTTON_START)) { + /* The guide button doesn't exist, use the start button instead, + so you can do Steam guide button chords and open the Steam overlay. + */ + SDL_strlcat(mapping_string, "guide:b6,", sizeof(mapping_string)); + button_mask &= ~(1 << SDL_CONTROLLER_BUTTON_START); +#endif + } +#endif + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_START)) { + SDL_strlcat(mapping_string, "start:b6,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_LEFTSTICK)) { + SDL_strlcat(mapping_string, "leftstick:b7,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_RIGHTSTICK)) { + SDL_strlcat(mapping_string, "rightstick:b8,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_LEFTSHOULDER)) { + SDL_strlcat(mapping_string, "leftshoulder:b9,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)) { + SDL_strlcat(mapping_string, "rightshoulder:b10,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_DPAD_UP)) { + SDL_strlcat(mapping_string, "dpup:b11,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_DPAD_DOWN)) { + SDL_strlcat(mapping_string, "dpdown:b12,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_DPAD_LEFT)) { + SDL_strlcat(mapping_string, "dpleft:b13,", sizeof(mapping_string)); + } + if (button_mask & (1 << SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) { + SDL_strlcat(mapping_string, "dpright:b14,", sizeof(mapping_string)); + } + if (axis_mask & (1 << SDL_CONTROLLER_AXIS_LEFTX)) { + SDL_strlcat(mapping_string, "leftx:a0,", sizeof(mapping_string)); + } + if (axis_mask & (1 << SDL_CONTROLLER_AXIS_LEFTY)) { + SDL_strlcat(mapping_string, "lefty:a1,", sizeof(mapping_string)); + } + if (axis_mask & (1 << SDL_CONTROLLER_AXIS_RIGHTX)) { + SDL_strlcat(mapping_string, "rightx:a2,", sizeof(mapping_string)); + } + if (axis_mask & (1 << SDL_CONTROLLER_AXIS_RIGHTY)) { + SDL_strlcat(mapping_string, "righty:a3,", sizeof(mapping_string)); + } + if (axis_mask & (1 << SDL_CONTROLLER_AXIS_TRIGGERLEFT)) { + SDL_strlcat(mapping_string, "lefttrigger:a4,", sizeof(mapping_string)); + } + if (axis_mask & (1 << SDL_CONTROLLER_AXIS_TRIGGERRIGHT)) { + SDL_strlcat(mapping_string, "righttrigger:a5,", sizeof(mapping_string)); + } + return SDL_PrivateAddMappingForGUID(guid, mapping_string, + &existing, SDL_CONTROLLER_MAPPING_PRIORITY_DEFAULT); +} +#endif /* __ANDROID__ */ + + /* * Helper function to determine pre-calculated offset to certain joystick mappings */ @@ -876,14 +1007,7 @@ static ControllerMapping_t *SDL_PrivateGetControllerMappingForNameAndGUID(const { ControllerMapping_t *mapping; - mapping = SDL_PrivateGetControllerMappingForGUID(&guid); -#if defined(SDL_JOYSTICK_EMSCRIPTEN) - if (!mapping && s_pEmscriptenMapping) { - mapping = s_pEmscriptenMapping; - } -#else - (void) s_pEmscriptenMapping; /* pacify ARMCC */ -#endif + mapping = SDL_PrivateGetControllerMappingForGUID(&guid, SDL_FALSE); #ifdef __LINUX__ if (!mapping && name) { if (SDL_strstr(name, "Xbox 360 Wireless Receiver")) { @@ -901,6 +1025,14 @@ static ControllerMapping_t *SDL_PrivateGetControllerMappingForNameAndGUID(const mapping = s_pXInputMapping; } } +#ifdef __ANDROID__ + if (!mapping && name && !SDL_IsJoystickHIDAPI(guid)) { + mapping = SDL_CreateMappingForAndroidController(name, guid); + } +#endif + if (!mapping) { + mapping = s_pDefaultMapping; + } return mapping; } @@ -921,20 +1053,6 @@ static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index) name = SDL_JoystickNameForIndex(device_index); guid = SDL_JoystickGetDeviceGUID(device_index); mapping = SDL_PrivateGetControllerMappingForNameAndGUID(name, guid); -#if SDL_JOYSTICK_XINPUT - if (!mapping && SDL_SYS_IsXInputGamepad_DeviceIndex(device_index)) { - mapping = s_pXInputMapping; - } -#endif -#if defined(__ANDROID__) - if (!mapping && SDL_SYS_IsDPAD_DeviceIndex(device_index)) { - SDL_bool existing; - char mapping_string[1024]; - SDL_snprintf(mapping_string, sizeof(mapping_string), "none,%s,a:b0,b:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,", name); - mapping = SDL_PrivateAddMappingForGUID(guid, mapping_string, - &existing, SDL_CONTROLLER_MAPPING_PRIORITY_DEFAULT); - } -#endif /* __ANDROID__ */ SDL_UnlockJoysticks(); return mapping; } @@ -1018,8 +1136,9 @@ SDL_PrivateGameControllerAddMapping(const char *mappingString, SDL_ControllerMap { char *pchGUID; SDL_JoystickGUID jGUID; + SDL_bool is_default_mapping = SDL_FALSE; + SDL_bool is_hidapi_mapping = SDL_FALSE; SDL_bool is_xinput_mapping = SDL_FALSE; - SDL_bool is_emscripten_mapping = SDL_FALSE; SDL_bool existing = SDL_FALSE; ControllerMapping_t *pControllerMapping; @@ -1031,12 +1150,13 @@ SDL_PrivateGameControllerAddMapping(const char *mappingString, SDL_ControllerMap if (!pchGUID) { return SDL_SetError("Couldn't parse GUID from %s", mappingString); } - if (!SDL_strcasecmp(pchGUID, "xinput")) { + if (!SDL_strcasecmp(pchGUID, "default")) { + is_default_mapping = SDL_TRUE; + } else if (!SDL_strcasecmp(pchGUID, "hidapi")) { + is_hidapi_mapping = SDL_TRUE; + } else if (!SDL_strcasecmp(pchGUID, "xinput")) { is_xinput_mapping = SDL_TRUE; } - if (!SDL_strcasecmp(pchGUID, "emscripten")) { - is_emscripten_mapping = SDL_TRUE; - } jGUID = SDL_JoystickGetGUIDFromString(pchGUID); SDL_free(pchGUID); @@ -1048,12 +1168,13 @@ SDL_PrivateGameControllerAddMapping(const char *mappingString, SDL_ControllerMap if (existing) { return 0; } else { - if (is_xinput_mapping) { + if (is_default_mapping) { + s_pDefaultMapping = pControllerMapping; + } else if (is_hidapi_mapping) { + s_pHIDAPIMapping = pControllerMapping; + } else if (is_xinput_mapping) { s_pXInputMapping = pControllerMapping; } - if (is_emscripten_mapping) { - s_pEmscriptenMapping = pControllerMapping; - } return 1; } } @@ -1125,7 +1246,7 @@ char * SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid) { char *pMappingString = NULL; - ControllerMapping_t *mapping = SDL_PrivateGetControllerMappingForGUID(&guid); + ControllerMapping_t *mapping = SDL_PrivateGetControllerMappingForGUID(&guid, SDL_FALSE); if (mapping) { char pchGUID[33]; size_t needed; @@ -1152,7 +1273,7 @@ SDL_GameControllerMapping(SDL_GameController * gamecontroller) return NULL; } - return SDL_GameControllerMappingForGUID(gamecontroller->guid); + return SDL_GameControllerMappingForGUID(gamecontroller->joystick->guid); } static void @@ -1263,12 +1384,50 @@ SDL_GameControllerNameForIndex(int device_index) { ControllerMapping_t *pSupportedController = SDL_PrivateGetControllerMapping(device_index); if (pSupportedController) { - return pSupportedController->name; + if (SDL_strcmp(pSupportedController->name, "*") == 0) { + return SDL_JoystickNameForIndex(device_index); + } else { + return pSupportedController->name; + } } return NULL; } +/** + * Get the mapping of a game controller. + * This can be called before any controllers are opened. + * If no mapping can be found, this function returns NULL. + */ +char * +SDL_GameControllerMappingForDeviceIndex(int joystick_index) +{ + char *pMappingString = NULL; + ControllerMapping_t *mapping; + + SDL_LockJoysticks(); + mapping = SDL_PrivateGetControllerMapping(joystick_index); + if (mapping) { + SDL_JoystickGUID guid; + char pchGUID[33]; + size_t needed; + guid = SDL_JoystickGetDeviceGUID(joystick_index); + SDL_JoystickGetGUIDString(guid, pchGUID, sizeof(pchGUID)); + /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ + needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1; + pMappingString = SDL_malloc(needed); + if (!pMappingString) { + SDL_OutOfMemory(); + SDL_UnlockJoysticks(); + return NULL; + } + SDL_snprintf(pMappingString, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping); + } + SDL_UnlockJoysticks(); + return pMappingString; +} + + /* * Return 1 if the joystick with this name and GUID is a supported controller */ @@ -1303,6 +1462,7 @@ SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid) int i; Uint16 vendor; Uint16 product; + Uint16 version; Uint32 vidpid; if (SDL_allowed_controllers.num_entries == 0 && @@ -1310,8 +1470,7 @@ SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid) return SDL_FALSE; } - SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL); - vidpid = MAKE_VIDPID(vendor, product); + SDL_GetJoystickGUIDInfo(guid, &vendor, &product, &version); if (SDL_GetHintBoolean("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD", SDL_FALSE)) { /* We shouldn't ignore Steam's virtual gamepad since it's using the hints to filter out the real controllers so it can remap input for the virtual controller */ @@ -1319,7 +1478,7 @@ SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid) #if defined(__LINUX__) bSteamVirtualGamepad = (vendor == 0x28DE && product == 0x11FF); #elif defined(__MACOSX__) - bSteamVirtualGamepad = (SDL_strncmp(name, "GamePad-", 8) == 0); + bSteamVirtualGamepad = (vendor == 0x045E && product == 0x028E && version == 1); #elif defined(__WIN32__) /* We can't tell on Windows, but Steam will block others in input hooks */ bSteamVirtualGamepad = SDL_TRUE; @@ -1329,6 +1488,8 @@ SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid) } } + vidpid = MAKE_VIDPID(vendor, product); + if (SDL_allowed_controllers.num_entries > 0) { for (i = 0; i < SDL_allowed_controllers.num_entries; ++i) { if (vidpid == SDL_allowed_controllers.entries[i]) { @@ -1356,22 +1517,18 @@ SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid) SDL_GameController * SDL_GameControllerOpen(int device_index) { + SDL_JoystickID instance_id; SDL_GameController *gamecontroller; SDL_GameController *gamecontrollerlist; ControllerMapping_t *pSupportedController = NULL; SDL_LockJoysticks(); - if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) { - SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); - SDL_UnlockJoysticks(); - return (NULL); - } - gamecontrollerlist = SDL_gamecontrollers; /* If the controller is already open, return it */ + instance_id = SDL_JoystickGetDeviceInstanceID(device_index); while (gamecontrollerlist) { - if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == gamecontrollerlist->joystick->instance_id) { + if (instance_id == gamecontrollerlist->joystick->instance_id) { gamecontroller = gamecontrollerlist; ++gamecontroller->ref_count; SDL_UnlockJoysticks(); @@ -1425,7 +1582,7 @@ SDL_GameControllerOpen(int device_index) } } - SDL_PrivateLoadButtonMapping(gamecontroller, pSupportedController->guid, pSupportedController->name, pSupportedController->mapping); + SDL_PrivateLoadButtonMapping(gamecontroller, pSupportedController->name, pSupportedController->mapping); /* Add the controller to list */ ++gamecontroller->ref_count; @@ -1552,7 +1709,17 @@ SDL_GameControllerName(SDL_GameController * gamecontroller) if (!gamecontroller) return NULL; - return gamecontroller->name; + if (SDL_strcmp(gamecontroller->name, "*") == 0) { + return SDL_JoystickName(SDL_GameControllerGetJoystick(gamecontroller)); + } else { + return gamecontroller->name; + } +} + +int +SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller) +{ + return SDL_JoystickGetPlayerIndex(SDL_GameControllerGetJoystick(gamecontroller)); } Uint16 @@ -1683,6 +1850,12 @@ SDL_GameControllerButtonBind SDL_GameControllerGetBindForButton(SDL_GameControll } +int +SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) +{ + return SDL_JoystickRumble(SDL_GameControllerGetJoystick(gamecontroller), low_frequency_rumble, high_frequency_rumble, duration_ms); +} + void SDL_GameControllerClose(SDL_GameController * gamecontroller) { @@ -1820,6 +1993,24 @@ SDL_PrivateGameControllerButton(SDL_GameController * gamecontroller, SDL_GameCon } #endif /* !SDL_EVENTS_DISABLED */ + if (button == SDL_CONTROLLER_BUTTON_GUIDE) { + Uint32 now = SDL_GetTicks(); + if (state == SDL_PRESSED) { + gamecontroller->guide_button_down = now; + + if (gamecontroller->joystick->delayed_guide_button) { + /* Skip duplicate press */ + return (0); + } + } else { + if (!SDL_TICKS_PASSED(now, gamecontroller->guide_button_down+SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS) && !gamecontroller->joystick->force_recentering) { + gamecontroller->joystick->delayed_guide_button = SDL_TRUE; + return (0); + } + gamecontroller->joystick->delayed_guide_button = SDL_FALSE; + } + } + /* translate the event, if desired */ posted = 0; #if !SDL_EVENTS_DISABLED @@ -1868,4 +2059,17 @@ SDL_GameControllerEventState(int state) #endif /* SDL_EVENTS_DISABLED */ } +void +SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick) +{ + SDL_GameController *controllerlist = SDL_gamecontrollers; + while (controllerlist) { + if (controllerlist->joystick == joystick) { + SDL_PrivateGameControllerButton(controllerlist, SDL_CONTROLLER_BUTTON_GUIDE, SDL_RELEASED); + break; + } + controllerlist = controllerlist->next; + } +} + /* vi: set ts=4 sw=4 expandtab: */ |