diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h index da25244f84..8460609e92 100644 --- a/include/SDL3/SDL_events.h +++ b/include/SDL3/SDL_events.h @@ -1420,10 +1420,32 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents); * * \since This function is available since SDL 3.0.0. * + * \sa SDL_ClaimEventMemory * \sa SDL_FreeEventMemory */ extern SDL_DECLSPEC void * SDLCALL SDL_AllocateEventMemory(size_t size); +/** + * Claim ownership of temporary event memory allocated by SDL. + * + * This function changes ownership of temporary event memory allocated for events and APIs that + * follow the SDL_GetStringRule. If this function succeeds, the memory will no longer be automatically freed by SDL, it must be freed using SDL_free() by the application. + * + * If the memory isn't temporary, or it was allocated on a different thread, this will return NULL, and the application does not have ownership of the memory. + * + * Note that even if a function follows the SDL_GetStringRule it may not be using temporary event memory, and this function will return NULL in that case. + * + * \param mem a pointer allocated with SDL_AllocateEventMemory(). + * \returns a pointer to the memory now owned by the application, which must be freed using SDL_free(), or NULL if the memory is not temporary or was allocated on a different thread. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AllocateEventMemory + */ +extern SDL_DECLSPEC void * SDLCALL SDL_ClaimEventMemory(const void *mem); + /** * Free temporary event memory allocated by SDL. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 8e7734bddb..5c61c2fe86 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -29,6 +29,7 @@ SDL3_0.0.0 { SDL_BlitSurfaceUncheckedScaled; SDL_BroadcastCondition; SDL_CaptureMouse; + SDL_ClaimEventMemory; SDL_CleanupTLS; SDL_ClearAudioStream; SDL_ClearClipboardData; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index cb95d19ef1..bb2669f022 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -54,6 +54,7 @@ #define SDL_BlitSurfaceUncheckedScaled SDL_BlitSurfaceUncheckedScaled_REAL #define SDL_BroadcastCondition SDL_BroadcastCondition_REAL #define SDL_CaptureMouse SDL_CaptureMouse_REAL +#define SDL_ClaimEventMemory SDL_ClaimEventMemory_REAL #define SDL_CleanupTLS SDL_CleanupTLS_REAL #define SDL_ClearAudioStream SDL_ClearAudioStream_REAL #define SDL_ClearClipboardData SDL_ClearClipboardData_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 1a494d81fe..acb5eb19b1 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -74,6 +74,7 @@ SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUnchecked,(SDL_Surface *a, const SDL_Rect *b, SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUncheckedScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_BroadcastCondition,(SDL_Condition *a),(a),return) SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return) +SDL_DYNAPI_PROC(void*,SDL_ClaimEventMemory,(const void *a),(a),return) SDL_DYNAPI_PROC(void,SDL_CleanupTLS,(void),(),) SDL_DYNAPI_PROC(int,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ClearClipboardData,(void),(),return) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 60bf7d6b18..8b5923ad27 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -212,6 +212,33 @@ static void SDL_FlushEventMemory(Uint32 eventID) } } +void *SDL_ClaimEventMemory(const void *mem) +{ + SDL_EventMemoryState *state; + + state = SDL_GetEventMemoryState(SDL_FALSE); + if (state && mem) { + SDL_EventMemory *prev = NULL, *entry; + + for (entry = state->head; entry; prev = entry, entry = entry->next) { + if (mem == entry->memory) { + if (prev) { + prev->next = entry->next; + } + if (entry == state->head) { + state->head = entry->next; + } + if (entry == state->tail) { + state->tail = prev; + } + SDL_free(entry); + return (void *)mem; + } + } + } + return NULL; +} + void SDL_FreeEventMemory(const void *mem) { SDL_EventMemoryState *state;