From 81ace1db730a2b4cf5d115427ef8308c8edc37d7 Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Fri, 14 Mar 2025 22:49:49 +0100
Subject: [PATCH] Pass original name through hints callbacks
---
src/sdl2_compat.c | 127 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 125 insertions(+), 2 deletions(-)
diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index ed36995..29a553f 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -224,6 +224,13 @@ do { \
static bool WantDebugLogging = false;
static SDL_InitState InitSDL2CompatGlobals;
+typedef struct HintCallbackInfo
+{
+ char *name;
+ SDL_HintCallback callback;
+ void *userdata;
+} HintCallbackInfo;
+static SDL_PropertiesID hint_callbacks = 0;
static char *
SDL2COMPAT_stpcpy(char *dst, const char *src)
@@ -621,6 +628,7 @@ static const char *SDL2_to_SDL3_hint(const char *name)
return name;
}
+/* This function must be kept in sync with SDL3_to_SDL2_hint_value */
static const char *SDL2_to_SDL3_hint_value(const char *name, const char *value, bool *free_value)
{
*free_value = false;
@@ -648,6 +656,34 @@ static const char *SDL2_to_SDL3_hint_value(const char *name, const char *value,
return value;
}
+/* This function must be kept in sync with SDL2_to_SDL3_hint_value */
+static const char *SDL3_to_SDL2_hint_value(const char *name, const char *value, bool *free_value)
+{
+ *free_value = false;
+
+ if (name && value && *value) {
+ if (SDL3_strcmp(name, SDL_HINT_LOGGING) == 0) {
+ /* Rewrite numeric priorities for SDL3 */
+ char *value2 = SDL3_strdup(value);
+ if (value2) {
+ char *sep;
+ for (sep = SDL3_strchr(value2, '='); sep; sep = SDL3_strchr(sep + 1, '=')) {
+ if (SDL3_isdigit(sep[1]) && sep[1] != '0') {
+ sep[1] = '0' + SDL3_atoi(&sep[1]) - 1;
+ }
+ }
+ }
+ *free_value = true;
+ return value2;
+ } else if (SDL3_strcmp(name, "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4") == 0) {
+ /* Invert the boolean value for SDL2 */
+ return (*value == '0' || SDL3_strcasecmp(value, "false") == 0) ? "1" : "0";
+ }
+ }
+
+ return value;
+}
+
SDL_DECLSPEC SDL2_bool SDLCALL
SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority)
{
@@ -684,10 +720,79 @@ SDL_GetHintBoolean(const char *name, SDL2_bool default_value)
return SDL3_GetHintBoolean(SDL2_to_SDL3_hint(name), default_value) ? SDL2_TRUE : SDL2_FALSE;
}
-/* FIXME: callbacks may need tweaking ... */
+static void SDLCALL
+hint_callback_wrapper(void *userdata, const char *name, const char *oldValue, const char *newValue)
+{
+ HintCallbackInfo *callback_info = (HintCallbackInfo *) userdata;
+ const char *sdl2OldValue, *sdl2NewValue;
+ bool freeSdl2OldValue, freeSdl2NewValue;
+
+ sdl2OldValue = SDL3_to_SDL2_hint_value(callback_info->name, oldValue, &freeSdl2OldValue);
+ sdl2NewValue = SDL3_to_SDL2_hint_value(callback_info->name, newValue, &freeSdl2NewValue);
+ callback_info->callback(callback_info->userdata, callback_info->name, sdl2OldValue, sdl2NewValue);
+ if (freeSdl2OldValue) {
+ SDL3_free((void *)sdl2OldValue);
+ }
+ if (freeSdl2NewValue) {
+ SDL3_free((void *)sdl2NewValue);
+ }
+}
+
+static char *
+CreateHintCallbackPropertyName(const char *name, SDL_HintCallback callback, void *userdata) {
+ size_t len_property_name = SDL_strlen(name) + 1 + 2 * sizeof(callback) + 1 + 2 * sizeof(userdata) + 1;
+ char *property_name = (char *)SDL3_malloc(len_property_name);
+ if (!property_name) {
+ return NULL;
+ }
+ SDL3_snprintf(property_name, len_property_name, "%s_%x_%x", name, (void *)callback, (void *)userdata);
+ return property_name;
+}
+
+static void SDLCALL
+HintCallbackInfoPropertyCleanup(void *userdata, void *value)
+{
+ HintCallbackInfo *callback_info = (HintCallbackInfo *) value;
+ SDL3_free(callback_info->name);
+ SDL3_free(callback_info);
+}
+
SDL_DECLSPEC void SDLCALL
SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
{
+ const char *sdl2_name = SDL2_to_SDL3_hint(name);
+ if (name && callback && sdl2_name != name) {
+ HintCallbackInfo *callback_info;
+ char *property_name;
+
+ if (!hint_callbacks) {
+ hint_callbacks = SDL3_CreateProperties();
+ }
+ property_name = CreateHintCallbackPropertyName(name, callback, userdata);
+ if (!property_name) {
+ return;
+ }
+ callback_info = (HintCallbackInfo *) SDL3_malloc(sizeof(*callback_info));
+ if (!callback_info) {
+ SDL3_free(property_name);
+ return;
+ }
+ callback_info->name = SDL3_strdup(name);
+ if (!callback_info->name) {
+ SDL3_free(property_name);
+ SDL3_free(callback_info);
+ return;
+ }
+ callback_info->callback = callback;
+ callback_info->userdata = userdata;
+ SDL3_SetPointerPropertyWithCleanup(hint_callbacks, property_name, callback_info, HintCallbackInfoPropertyCleanup, NULL);
+
+ callback = hint_callback_wrapper;
+ userdata = callback_info;
+
+ SDL3_free(property_name);
+ }
+
/* this returns an int of 0 or -1 in SDL3, but SDL2 it was void (even if it failed). */
(void) SDL3_AddHintCallback(SDL2_to_SDL3_hint(name), callback, userdata);
}
@@ -695,7 +800,20 @@ SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
SDL_DECLSPEC void SDLCALL
SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
{
- SDL3_RemoveHintCallback(SDL2_to_SDL3_hint(name), callback, userdata);
+ const char *sdl3_name = SDL2_to_SDL3_hint(name);
+ if (name && callback && name != sdl3_name) {
+ char *property_name = CreateHintCallbackPropertyName(name, callback, userdata);
+ HintCallbackInfo *callback_info;
+ if (!property_name) {
+ return;
+ }
+ callback_info = (HintCallbackInfo *) SDL3_GetPointerProperty(hint_callbacks, property_name, NULL);
+ SDL3_RemoveHintCallback(sdl3_name, hint_callback_wrapper, callback_info);
+ SDL3_SetPointerProperty(hint_callbacks, property_name, NULL);
+ SDL3_free(property_name);
+ } else {
+ SDL3_RemoveHintCallback(sdl3_name, callback, userdata);
+ }
}
SDL_DECLSPEC void SDLCALL
@@ -7007,6 +7125,11 @@ SDL_Quit(void)
timers = 0;
}
+ if (hint_callbacks) {
+ SDL3_DestroyProperties(hint_callbacks);
+ hint_callbacks = 0;
+ }
+
for (i = 0; i < SDL_LOG_CATEGORY_CUSTOM; i++) {
priorities[i] = SDL3_GetLogPriority(i);
}