Просмотр исходного кода

main: If SDL_MAIN_CALLBACK_RATE="waitevent", have at least one iteration run.

This way apps can at least draw an initial image to their windows before going
into a deep, blocking wait for user interaction.

Fixes #15027.
Ryan C. Gordon 2 дней назад
Родитель
Сommit
3a1cfbc147

+ 5 - 1
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

+ 6 - 2
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);

+ 16 - 2
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)