#include "SDL_internal.h"
#include "SDL_main_callbacks.h"
static SDL_AppEvent_func SDL_main_event_callback;
static SDL_AppIterate_func SDL_main_iteration_callback;
static SDL_AppQuit_func SDL_main_quit_callback;
static SDL_AtomicInt apprc; static void *SDL_main_appstate = NULL;
static bool ShouldDispatchImmediately(SDL_Event *event)
{
switch (event->type) {
case SDL_EVENT_TERMINATING:
case SDL_EVENT_LOW_MEMORY:
case SDL_EVENT_WILL_ENTER_BACKGROUND:
case SDL_EVENT_DID_ENTER_BACKGROUND:
case SDL_EVENT_WILL_ENTER_FOREGROUND:
case SDL_EVENT_DID_ENTER_FOREGROUND:
return true;
default:
return false;
}
}
static void SDL_DispatchMainCallbackEvent(SDL_Event *event)
{
if (SDL_GetAtomicInt(&apprc) == SDL_APP_CONTINUE) { SDL_CompareAndSwapAtomicInt(&apprc, SDL_APP_CONTINUE, SDL_main_event_callback(SDL_main_appstate, event));
}
}
static void SDL_DispatchMainCallbackEvents(void)
{
SDL_Event events[16];
for (;;) {
int count = SDL_PeepEvents(events, SDL_arraysize(events), SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST);
if (count <= 0) {
break;
}
for (int i = 0; i < count; ++i) {
SDL_Event *event = &events[i];
if (!ShouldDispatchImmediately(event)) {
SDL_DispatchMainCallbackEvent(event);
}
}
}
}
static bool SDLCALL SDL_MainCallbackEventWatcher(void *userdata, SDL_Event *event)
{
if (ShouldDispatchImmediately(event)) {
SDL_DispatchMainCallbackEvents();
SDL_DispatchMainCallbackEvent(event);
if (event->type == SDL_EVENT_TERMINATING) {
SDL_CompareAndSwapAtomicInt(&apprc, SDL_APP_CONTINUE, SDL_APP_SUCCESS);
}
} else {
}
return true;
}
bool SDL_HasMainCallbacks(void)
{
if (SDL_main_iteration_callback) {
return true;
}
return false;
}
SDL_AppResult SDL_InitMainCallbacks(int argc, char *argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit)
{
SDL_main_iteration_callback = appiter;
SDL_main_event_callback = appevent;
SDL_main_quit_callback = appquit;
SDL_SetAtomicInt(&apprc, SDL_APP_CONTINUE);
const SDL_AppResult rc = appinit(&SDL_main_appstate, argc, argv);
if (SDL_CompareAndSwapAtomicInt(&apprc, SDL_APP_CONTINUE, rc) && (rc == SDL_APP_CONTINUE)) { if (!SDL_InitSubSystem(SDL_INIT_EVENTS)) {
SDL_SetAtomicInt(&apprc, SDL_APP_FAILURE);
return SDL_APP_FAILURE;
}
if (!SDL_AddEventWatch(SDL_MainCallbackEventWatcher, NULL)) {
SDL_SetAtomicInt(&apprc, SDL_APP_FAILURE);
return SDL_APP_FAILURE;
}
}
return (SDL_AppResult)SDL_GetAtomicInt(&apprc);
}
SDL_AppResult SDL_IterateMainCallbacks(bool pump_events)
{
if (pump_events) {
SDL_PumpEvents();
}
SDL_DispatchMainCallbackEvents();
SDL_AppResult rc = (SDL_AppResult)SDL_GetAtomicInt(&apprc);
if (rc == SDL_APP_CONTINUE) {
rc = SDL_main_iteration_callback(SDL_main_appstate);
if (!SDL_CompareAndSwapAtomicInt(&apprc, SDL_APP_CONTINUE, rc)) {
rc = (SDL_AppResult)SDL_GetAtomicInt(&apprc); }
}
return rc;
}
void SDL_QuitMainCallbacks(SDL_AppResult result)
{
SDL_RemoveEventWatch(SDL_MainCallbackEventWatcher, NULL);
SDL_main_quit_callback(SDL_main_appstate, result);
SDL_main_appstate = NULL;
SDL_Quit();
}
static void SDL_CheckDefaultArgcArgv(int *argc, char ***argv)
{
if (!*argv) {
static char dummyargv0[] = { 'S', 'D', 'L', '_', 'a', 'p', 'p', '\0' };
static char *argvdummy[2] = { dummyargv0, NULL };
*argc = 1;
*argv = argvdummy;
}
}
int SDL_CallMainFunction(int argc, char *argv[], SDL_main_func mainFunction)
{
SDL_CheckDefaultArgcArgv(&argc, &argv);
SDL_SetMainReady();
return mainFunction(argc, argv);
}