diff --git a/WhatsNew.txt b/WhatsNew.txt index feb4aaca3..8997d0bf8 100644 --- a/WhatsNew.txt +++ b/WhatsNew.txt @@ -20,6 +20,7 @@ General: the SDL 2.24.0 stable release. * Added SDL_bsearch() and SDL_utf8strnlen() to the stdlib routines * Added SDL_size_mul_overflow() and SDL_size_add_overflow() for better size overflow protection +* Added SDL_ResetHint() to reset a hint to the default value * The hint SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS now defaults on * Added support for mini-gamepad mode for Nintendo Joy-Con controllers using the HIDAPI driver * Added the hint SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS to control whether Joy-Con controllers are automatically merged into a unified gamepad when using the HIDAPI driver. This hint defaults on. diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 02d5fc5f8..2c7a33aec 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -2286,6 +2286,23 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name, extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name, const char *value); +/** + * Reset a hint to the default value. + * + * This will reset a hint to the value of the environment variable, or NULL + * if the environment isn't set. Callbacks will be called normally with + * this change. + * + * \param name the hint to set + * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise. + * + * \since This function is available since SDL 2.24.0. + * + * \sa SDL_GetHint + * \sa SDL_SetHint + */ +extern DECLSPEC SDL_bool SDLCALL SDL_ResetHint(const char *name); + /** * Get the value of a hint. * diff --git a/src/SDL_hints.c b/src/SDL_hints.c index 423851a83..93bcc47ca 100644 --- a/src/SDL_hints.c +++ b/src/SDL_hints.c @@ -96,6 +96,43 @@ SDL_SetHintWithPriority(const char *name, const char *value, return SDL_TRUE; } +SDL_bool +SDL_ResetHint(const char *name) +{ + const char *env; + SDL_Hint *hint, *prev; + SDL_HintWatch *entry; + + if (!name) { + return SDL_FALSE; + } + + env = SDL_getenv(name); + for (prev = NULL, hint = SDL_hints; hint; prev = hint, hint = hint->next) { + if (SDL_strcmp(name, hint->name) == 0) { + if ((env == NULL && hint->value != NULL) || + (env != NULL && hint->value == NULL) || + (env && SDL_strcmp(env, hint->value) != 0)) { + for (entry = hint->callbacks; entry; ) { + /* Save the next entry in case this one is deleted */ + SDL_HintWatch *next = entry->next; + entry->callback(entry->userdata, name, hint->value, env); + entry = next; + } + } + if (prev) { + prev->next = hint->next; + } else { + SDL_hints = hint->next; + } + SDL_free(hint->value); + SDL_free(hint); + return SDL_TRUE; + } + } + return SDL_FALSE; +} + SDL_bool SDL_SetHint(const char *name, const char *value) { diff --git a/src/dynapi/SDL2.exports b/src/dynapi/SDL2.exports index 80d15ee5a..c790e2582 100644 --- a/src/dynapi/SDL2.exports +++ b/src/dynapi/SDL2.exports @@ -856,3 +856,4 @@ ++'_SDL_GetDefaultAudioInfo'.'SDL2.dll'.'SDL_GetDefaultAudioInfo' ++'_SDL_GetPointDisplayIndex'.'SDL2.dll'.'SDL_GetPointDisplayIndex' ++'_SDL_GetRectDisplayIndex'.'SDL2.dll'.'SDL_GetRectDisplayIndex' +++'_SDL_ResetHint'.'SDL2.dll'.'SDL_ResetHint' diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 91f13c3e3..48c599bbb 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -882,3 +882,4 @@ #define SDL_GetDefaultAudioInfo SDL_GetDefaultAudioInfo_REAL #define SDL_GetPointDisplayIndex SDL_GetPointDisplayIndex_REAL #define SDL_GetRectDisplayIndex SDL_GetRectDisplayIndex_REAL +#define SDL_ResetHint SDL_ResetHint_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index f23cdf7c9..1d2cbfe23 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -965,3 +965,4 @@ SDL_DYNAPI_PROC(void,SDL_ResetKeyboard,(void),(),) SDL_DYNAPI_PROC(int,SDL_GetDefaultAudioInfo,(char **a, SDL_AudioSpec *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetPointDisplayIndex,(const SDL_Point *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetRectDisplayIndex,(const SDL_Rect *a),(a),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_ResetHint,(const char *a),(a),return) diff --git a/test/testautomation_hints.c b/test/testautomation_hints.c index 91b8c02ab..bbcc9fd21 100644 --- a/test/testautomation_hints.c +++ b/test/testautomation_hints.c @@ -98,8 +98,9 @@ hints_getHint(void *arg) int hints_setHint(void *arg) { + const char *testHint = "SDL_AUTOMATED_TEST_HINT"; const char *originalValue; - const char *value; + char *value; const char *testValue; SDL_bool result; int i, j; @@ -142,7 +143,54 @@ hints_setHint(void *arg) SDL_free((void *)originalValue); } - SDL_free((void *)value); + SDL_free(value); + + /* Set default value in environment */ + SDL_setenv(testHint, "original", 1); + + SDLTest_AssertPass("Call to SDL_GetHint() after saving and restoring hint"); + originalValue = SDL_GetHint(testHint); + value = (originalValue == NULL) ? NULL : SDL_strdup(originalValue); + SDL_SetHint(testHint, "temp"); + SDL_SetHint(testHint, value); + SDL_free(value); + testValue = SDL_GetHint(testHint); + SDLTest_AssertCheck( + testValue && SDL_strcmp(testValue, "original") == 0, + "testValue = %s, expected \"original\"", + testValue); + + SDLTest_AssertPass("Call to SDL_SetHintWithPriority(NULL, SDL_HINT_DEFAULT)"); + SDL_SetHintWithPriority(testHint, NULL, SDL_HINT_DEFAULT); + testValue = SDL_GetHint(testHint); + SDLTest_AssertCheck( + testValue && SDL_strcmp(testValue, "original") == 0, + "testValue = %s, expected \"original\"", + testValue); + + SDLTest_AssertPass("Call to SDL_SetHintWithPriority(\"temp\", SDL_HINT_OVERRIDE)"); + SDL_SetHintWithPriority(testHint, "temp", SDL_HINT_OVERRIDE); + testValue = SDL_GetHint(testHint); + SDLTest_AssertCheck( + testValue && SDL_strcmp(testValue, "temp") == 0, + "testValue = %s, expected \"temp\"", + testValue); + + SDLTest_AssertPass("Call to SDL_SetHintWithPriority(NULL, SDL_HINT_OVERRIDE)"); + SDL_SetHintWithPriority(testHint, NULL, SDL_HINT_OVERRIDE); + testValue = SDL_GetHint(testHint); + SDLTest_AssertCheck( + testValue == NULL, + "testValue = %s, expected NULL", + testValue); + + SDLTest_AssertPass("Call to SDL_ResetHint()"); + SDL_ResetHint(testHint); + testValue = SDL_GetHint(testHint); + SDLTest_AssertCheck( + testValue && SDL_strcmp(testValue, "original") == 0, + "testValue = %s, expected \"original\"", + testValue); return TEST_COMPLETED; }