sdl2-compat: Updated for changes to touch devices and gamepad mappings in SDL3.

From 532d9af63ec1d5fbb2bc11895037a1e1b5f2977c Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Wed, 29 Nov 2023 15:47:38 -0500
Subject: [PATCH] Updated for changes to touch devices and gamepad mappings in
 SDL3.

---
 src/sdl2_compat.c          | 69 ++++++++++++++++++++++++++++++++++++--
 src/sdl3_include_wrapper.h | 31 +++++++----------
 src/sdl3_syms.h            |  8 ++---
 3 files changed, 83 insertions(+), 25 deletions(-)

diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index 5e06426..8498217 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -1184,6 +1184,11 @@ static SDL2_AudioStream *AudioOpenDevices[16];  /* SDL2 had a limit of 16 simult
 static AudioDeviceList AudioSDL3OutputDevices;
 static AudioDeviceList AudioSDL3CaptureDevices;
 
+static char **GamepadMappings = NULL;
+static int NumGamepadMappings = 0;
+
+static SDL_TouchID *TouchDevices = NULL;
+static int NumTouchDevices = 0;
 
 /* Functions! */
 
@@ -2676,6 +2681,31 @@ SDL_SensorGetDataWithTimestamp(SDL_Sensor *sensor, Uint64 *timestamp, float *dat
     return SDL3_Unsupported();  /* !!! FIXME: maybe try to track this from SDL3 events if something needs this? I can't imagine this was widely used. */
 }
 
+DECLSPEC int SDLCALL
+SDL_GetNumTouchDevices(void)
+{
+    SDL3_free(TouchDevices);
+    TouchDevices = SDL3_GetTouchDevices(&NumTouchDevices);
+    return NumTouchDevices;
+}
+
+DECLSPEC SDL_TouchID SDLCALL
+SDL_GetTouchDevice(int idx)
+{
+    if ((idx < 0) || (idx >= NumTouchDevices)) {
+        SDL3_SetError("Unknown touch device index %d", idx);
+        return 0;
+    }
+    return TouchDevices[idx];
+}
+
+DECLSPEC const char* SDLCALL
+SDL_GetTouchName(int idx)
+{
+    SDL_TouchID tid = SDL_GetTouchDevice(idx);
+    return tid ? SDL3_GetTouchDeviceName(tid) : NULL;
+}
+
 
 /* Touch gestures were removed from SDL3, so this is the SDL2 implementation copied in here, and tweaked a little. */
 
@@ -2743,19 +2773,23 @@ GestureGetTouch(const SDL_TouchID touchId)
 DECLSPEC int SDLCALL
 SDL_RecordGesture(SDL_TouchID touchId)
 {
-    const int numtouchdevs = SDL3_GetNumTouchDevices();
+    int numtouchdevs = 0;
+    SDL_TouchID *touchdevs = SDL3_GetTouchDevices(&numtouchdevs);
     int i;
 
     /* make sure we know about all the devices SDL3 knows about, since we aren't connected as tightly as we were in SDL2. */
     for (i = 0; i < numtouchdevs; i++) {
-        const SDL_TouchID thistouch = SDL3_GetTouchDevice(i);
+        const SDL_TouchID thistouch = touchdevs[i];
         if (!GestureGetTouch(thistouch)) {
             if (!GestureAddTouch(thistouch)) {
+                SDL3_free(touchdevs);
                 return 0;  /* uhoh, out of memory */
             }
         }
     }
 
+    SDL3_free(touchdevs);
+
     if (touchId < 0) {
         GestureRecordAll = SDL_TRUE;  /* !!! FIXME: this is never set back to SDL_FALSE anywhere, that's probably a bug. */
         for (i = 0; i < GestureNumTouches; i++) {
@@ -4299,6 +4333,14 @@ SDL_Quit(void)
     }
     num_gamepad_button_swap_list = 0;
 
+    SDL3_free(GamepadMappings);
+    GamepadMappings = NULL;
+    NumGamepadMappings = 0;
+
+    SDL3_free(TouchDevices);
+    TouchDevices = NULL;
+    NumTouchDevices = 0;
+
     SDL3_Quit();
 }
 
@@ -4308,6 +4350,9 @@ SDL_QuitSubSystem(Uint32 flags)
     if (flags & SDL_INIT_VIDEO) {
         GestureQuit();
     }
+
+    // !!! FIXME: there's cleanup in SDL_Quit that probably needs to be done here, too.
+
     SDL3_QuitSubSystem(flags);
 }
 
@@ -6500,6 +6545,26 @@ SDL_GameControllerNameForIndex(int idx)
     return jid ? SDL3_GetGamepadInstanceName(jid) : NULL;
 }
 
+DECLSPEC int SDLCALL
+SDL_GameControllerNumMappings(void)
+{
+    SDL3_free(GamepadMappings);
+    GamepadMappings = SDL3_GetGamepadMappings(&NumGamepadMappings);
+    return NumGamepadMappings;
+}
+
+DECLSPEC char* SDLCALL
+SDL_GameControllerMappingForIndex(int idx)
+{
+    char *retval = NULL;
+    if ((idx < 0) || (idx >= NumGamepadMappings)) {
+        SDL3_SetError("Mapping not available");
+    } else if ((retval = SDL3_strdup(GamepadMappings[idx])) == NULL) {
+        SDL3_OutOfMemory();
+    }
+    return retval;
+}
+
 DECLSPEC SDL_GameController* SDLCALL
 SDL_GameControllerOpen(int idx)
 {
diff --git a/src/sdl3_include_wrapper.h b/src/sdl3_include_wrapper.h
index ae1b4cd..60fd1f9 100644
--- a/src/sdl3_include_wrapper.h
+++ b/src/sdl3_include_wrapper.h
@@ -214,6 +214,7 @@
 #define SDL_GetGamepadInstanceVendor IGNORE_THIS_VERSION_OF_SDL_GetGamepadInstanceVendor
 #define SDL_GetGamepadJoystick IGNORE_THIS_VERSION_OF_SDL_GetGamepadJoystick
 #define SDL_GetGamepadMapping IGNORE_THIS_VERSION_OF_SDL_GetGamepadMapping
+#define SDL_GetGamepadMappings IGNORE_THIS_VERSION_OF_SDL_GetGamepadMappings
 #define SDL_GetGamepadMappingForGUID IGNORE_THIS_VERSION_OF_SDL_GetGamepadMappingForGUID
 #define SDL_GetGamepadMappingForIndex IGNORE_THIS_VERSION_OF_SDL_GetGamepadMappingForIndex
 #define SDL_GetGamepadName IGNORE_THIS_VERSION_OF_SDL_GetGamepadName
@@ -276,14 +277,12 @@
 #define SDL_GetMouseState IGNORE_THIS_VERSION_OF_SDL_GetMouseState
 #define SDL_GetNaturalDisplayOrientation IGNORE_THIS_VERSION_OF_SDL_GetNaturalDisplayOrientation
 #define SDL_GetNumAllocations IGNORE_THIS_VERSION_OF_SDL_GetNumAllocations
-#define SDL_GetNumGamepadMappings IGNORE_THIS_VERSION_OF_SDL_GetNumGamepadMappings
 #define SDL_GetNumGamepadTouchpadFingers IGNORE_THIS_VERSION_OF_SDL_GetNumGamepadTouchpadFingers
 #define SDL_GetNumGamepadTouchpads IGNORE_THIS_VERSION_OF_SDL_GetNumGamepadTouchpads
 #define SDL_GetNumJoystickAxes IGNORE_THIS_VERSION_OF_SDL_GetNumJoystickAxes
 #define SDL_GetNumJoystickButtons IGNORE_THIS_VERSION_OF_SDL_GetNumJoystickButtons
 #define SDL_GetNumJoystickHats IGNORE_THIS_VERSION_OF_SDL_GetNumJoystickHats
 #define SDL_GetNumRenderDrivers IGNORE_THIS_VERSION_OF_SDL_GetNumRenderDrivers
-#define SDL_GetNumTouchDevices IGNORE_THIS_VERSION_OF_SDL_GetNumTouchDevices
 #define SDL_GetNumTouchFingers IGNORE_THIS_VERSION_OF_SDL_GetNumTouchFingers
 #define SDL_GetNumVideoDrivers IGNORE_THIS_VERSION_OF_SDL_GetNumVideoDrivers
 #define SDL_GetOriginalMemoryFunctions IGNORE_THIS_VERSION_OF_SDL_GetOriginalMemoryFunctions
@@ -356,10 +355,10 @@
 #define SDL_GetThreadName IGNORE_THIS_VERSION_OF_SDL_GetThreadName
 #define SDL_GetTicks IGNORE_THIS_VERSION_OF_SDL_GetTicks
 #define SDL_GetTicksNS IGNORE_THIS_VERSION_OF_SDL_GetTicksNS
-#define SDL_GetTouchDevice IGNORE_THIS_VERSION_OF_SDL_GetTouchDevice
+#define SDL_GetTouchDevices IGNORE_THIS_VERSION_OF_SDL_GetTouchDevices
+#define SDL_GetTouchDeviceName IGNORE_THIS_VERSION_OF_SDL_GetTouchDeviceName
 #define SDL_GetTouchDeviceType IGNORE_THIS_VERSION_OF_SDL_GetTouchDeviceType
 #define SDL_GetTouchFinger IGNORE_THIS_VERSION_OF_SDL_GetTouchFinger
-#define SDL_GetTouchName IGNORE_THIS_VERSION_OF_SDL_GetTouchName
 #define SDL_GetVersion IGNORE_THIS_VERSION_OF_SDL_GetVersion
 #define SDL_GetVideoDriver IGNORE_THIS_VERSION_OF_SDL_GetVideoDriver
 #define SDL_GetWindowBordersSize IGNORE_THIS_VERSION_OF_SDL_GetWindowBordersSize
@@ -1760,6 +1759,10 @@
 #undef SDL_GetGamepadMapping
 #endif
 
+#ifdef SDL_GetGamepadMappings
+#undef SDL_GetGamepadMappings
+#endif
+
 #ifdef SDL_GetGamepadMappingForGUID
 #undef SDL_GetGamepadMappingForGUID
 #endif
@@ -2008,10 +2011,6 @@
 #undef SDL_GetNumAllocations
 #endif
 
-#ifdef SDL_GetNumGamepadMappings
-#undef SDL_GetNumGamepadMappings
-#endif
-
 #ifdef SDL_GetNumGamepadTouchpadFingers
 #undef SDL_GetNumGamepadTouchpadFingers
 #endif
@@ -2036,10 +2035,6 @@
 #undef SDL_GetNumRenderDrivers
 #endif
 
-#ifdef SDL_GetNumTouchDevices
-#undef SDL_GetNumTouchDevices
-#endif
-
 #ifdef SDL_GetNumTouchFingers
 #undef SDL_GetNumTouchFingers
 #endif
@@ -2328,8 +2323,12 @@
 #undef SDL_GetTicksNS
 #endif
 
-#ifdef SDL_GetTouchDevice
-#undef SDL_GetTouchDevice
+#ifdef SDL_GetTouchDevices
+#undef SDL_GetTouchDevices
+#endif
+
+#ifdef SDL_GetTouchDeviceName
+#undef SDL_GetTouchDeviceName
 #endif
 
 #ifdef SDL_GetTouchDeviceType
@@ -2340,10 +2339,6 @@
 #undef SDL_GetTouchFinger
 #endif
 
-#ifdef SDL_GetTouchName
-#undef SDL_GetTouchName
-#endif
-
 #ifdef SDL_GetVersion
 #undef SDL_GetVersion
 #endif
diff --git a/src/sdl3_syms.h b/src/sdl3_syms.h
index 855dcb4..7ca7583 100644
--- a/src/sdl3_syms.h
+++ b/src/sdl3_syms.h
@@ -464,8 +464,7 @@ SDL3_SYM_PASSTHROUGH(Uint64,GetPerformanceFrequency,(void),(),return)
 SDL3_SYM_PASSTHROUGH(void,Delay,(Uint32 a),(a),)
 SDL3_SYM_PASSTHROUGH(SDL_TimerID,AddTimer,(Uint32 a, SDL_TimerCallback b, void *c),(a,b,c),return)
 SDL3_SYM_PASSTHROUGH(SDL_bool,RemoveTimer,(SDL_TimerID a),(a),return)
-SDL3_SYM_PASSTHROUGH(int,GetNumTouchDevices,(void),(),return)
-SDL3_SYM_PASSTHROUGH(SDL_TouchID,GetTouchDevice,(int a),(a),return)
+SDL3_SYM(SDL_TouchID*,GetTouchDevices,(int *a),(a),return)
 SDL3_SYM_PASSTHROUGH(int,GetNumTouchFingers,(SDL_TouchID a),(a),return)
 SDL3_SYM_PASSTHROUGH(SDL_Finger*,GetTouchFinger,(SDL_TouchID a, int b),(a,b),return)
 SDL3_SYM(int,GetVersion,(SDL_version *a),(a),return)
@@ -558,8 +557,6 @@ SDL3_SYM_RENAMED(Uint16,JoystickGetProductVersion,GetJoystickProductVersion,(SDL
 SDL3_SYM_RENAMED(Uint16,GameControllerGetVendor,GetGamepadVendor,(SDL_GameController *a),(a),return)
 SDL3_SYM_RENAMED(Uint16,GameControllerGetProduct,GetGamepadProduct,(SDL_GameController *a),(a),return)
 SDL3_SYM_RENAMED(Uint16,GameControllerGetProductVersion,GetGamepadProductVersion,(SDL_GameController *a),(a),return)
-SDL3_SYM_RENAMED(int,GameControllerNumMappings,GetNumGamepadMappings,(void),(),return)
-SDL3_SYM_RENAMED(char*,GameControllerMappingForIndex,GetGamepadMappingForIndex,(int a),(a),return)
 SDL3_SYM_RENAMED(SDL_bool,JoystickGetAxisInitialState,GetJoystickAxisInitialState,(SDL_Joystick *a, int b, Sint16 *c),(a,b,c),return)
 SDL3_SYM_RENAMED(SDL_JoystickType,JoystickGetType,GetJoystickType,(SDL_Joystick *a),(a),return)
 SDL3_SYM_PASSTHROUGH(void,MemoryBarrierReleaseFunction,(void),(),)
@@ -752,7 +749,7 @@ SDL3_SYM_RENAMED(SDL_bool,GameControllerHasRumble,GamepadHasRumble,(SDL_GameCont
 SDL3_SYM_RENAMED(SDL_bool,GameControllerHasRumbleTriggers,GamepadHasRumbleTriggers,(SDL_GameController *a),(a),return)
 SDL3_SYM_PASSTHROUGH(void,hid_ble_scan,(SDL_bool a),(a),)
 SDL3_SYM_PASSTHROUGH(int,PremultiplyAlpha,(int a, int b, Uint32 c, const void *d, int e, Uint32 f, void *g, int h),(a,b,c,d,e,f,g,h),return)
-SDL3_SYM_PASSTHROUGH(const char*,GetTouchName,(int a),(a),return)
+SDL3_SYM(const char*,GetTouchDeviceName,(SDL_TouchID a),(a),return)
 SDL3_SYM_PASSTHROUGH(void,ClearComposition,(void),(),)
 SDL3_SYM_RENAMED(SDL_bool,IsTextInputShown,TextInputShown,(void),(),return)
 SDL3_SYM_RENAMED(SDL_bool,HasIntersectionF,HasRectIntersectionFloat,(const SDL_FRect *a, const SDL_FRect *b),(a,b),return)
@@ -867,6 +864,7 @@ SDL3_SYM(SDL_PropertiesID,CreateProperties,(void),(),return)
 SDL3_SYM(int,SetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return)
 SDL3_SYM(void,DestroyProperties,(SDL_PropertiesID a),(a),)
 SDL3_SYM(SDL_Window*,CreateWindowWithProperties,(SDL_PropertiesID a),(a),return)
+SDL3_SYM(char **,GetGamepadMappings,(int *a),(a),return)
 
 #undef SDL3_SYM
 #undef SDL3_SYM_PASSTHROUGH