diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index a8751ede47..bc23b58add 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -2835,7 +2835,11 @@ extern "C" { * There are other strings that have special meaning. If set to "waitevent", * SDL_AppIterate will not be called until new event(s) have arrived (and been * processed by SDL_AppEvent). This can be useful for apps that are completely - * idle except in response to input. + * idle except in response to input. As of SDL 3.6.0, SDL will allow a single + * call to SDL_AppIterate to proceed without an event immediately after this + * hint is set to "waitevent", so apps can have a minimum of activity, perhaps + * to render an initial image to a window before the user has otherwise + * interacted with the app. * * On some platforms, or if you are using SDL_main instead of SDL_AppIterate, * this hint is ignored. When the hint can be used, it is allowed to be diff --git a/src/main/emscripten/SDL_sysmain_callbacks.c b/src/main/emscripten/SDL_sysmain_callbacks.c index fca3488640..138c6ed6d1 100644 --- a/src/main/emscripten/SDL_sysmain_callbacks.c +++ b/src/main/emscripten/SDL_sysmain_callbacks.c @@ -58,6 +58,8 @@ static bool SDLCALL EmscriptenMainCallbackEventWatcher(void *userdata, SDL_Event static void EmscriptenInternalMainloop(void) { + const bool force_iterate = callback_rate_changed && iterate_after_waitevent; + // callback rate changed? Update emscripten's mainloop iteration speed. if (callback_rate_changed) { callback_rate_changed = false; @@ -70,7 +72,7 @@ static void EmscriptenInternalMainloop(void) if (iterate_after_waitevent) { SDL_PumpEvents(); - if (!saw_new_event) { + if (!saw_new_event && !force_iterate) { // do nothing yet. Note that we're still going to iterate here because we can't block, // but we can stop the app's iteration from progressing until there's an event. return; @@ -94,7 +96,9 @@ int SDL_EnterAppMainCallbacks(int argc, char *argv[], SDL_AppInit_func appinit, rc = SDL_APP_FAILURE; } else { SDL_AddHintCallback(SDL_HINT_MAIN_CALLBACK_RATE, MainCallbackRateHintChanged, NULL); - callback_rate_changed = false; + if (!iterate_after_waitevent) { // if we're doing waitevent, we need callback_rate_changed to stay true for the next iteration. + callback_rate_changed = false; + } emscripten_set_main_loop(EmscriptenInternalMainloop, 0, 0); // don't throw an exception since we do an orderly return. if (callback_rate_increment > 0.0) { emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, callback_rate_increment); diff --git a/src/main/generic/SDL_sysmain_callbacks.c b/src/main/generic/SDL_sysmain_callbacks.c index 77aa2f54de..425e79077c 100644 --- a/src/main/generic/SDL_sysmain_callbacks.c +++ b/src/main/generic/SDL_sysmain_callbacks.c @@ -27,9 +27,11 @@ static Uint64 callback_rate_increment = 0; static bool iterate_after_waitevent = false; +static bool callback_rate_changed = false; static void SDLCALL MainCallbackRateHintChanged(void *userdata, const char *name, const char *oldValue, const char *newValue) { + callback_rate_changed = true; iterate_after_waitevent = newValue && (SDL_strcmp(newValue, "waitevent") == 0); if (iterate_after_waitevent) { callback_rate_increment = 0; @@ -45,10 +47,22 @@ static void SDLCALL MainCallbackRateHintChanged(void *userdata, const char *name static SDL_AppResult GenericIterateMainCallbacks(void) { - if (iterate_after_waitevent) { + bool should_wait = iterate_after_waitevent; + + if (callback_rate_changed) { + callback_rate_changed = false; + if (iterate_after_waitevent) { + // just go immediately for one iteration (it will do a PumpEvents), + // and do a full blocking wait for more events next time. + should_wait = false; + } + } + + if (should_wait) { SDL_WaitEvent(NULL); } - return SDL_IterateMainCallbacks(!iterate_after_waitevent); + + return SDL_IterateMainCallbacks(!should_wait); } int SDL_EnterAppMainCallbacks(int argc, char *argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit)