2
0
Эх сурвалжийг харах

events: Let arbitrary signals to simulate iOS/Android backgrounding events.

This lets you build a custom embedded device that roughly offers the "this
process is going to the background NOW" semantics of SDL on a mobile device.
Ryan C. Gordon 6 жил өмнө
parent
commit
8a5a05c168

+ 10 - 0
CMakeLists.txt

@@ -341,6 +341,8 @@ set_option(VIDEO_VIVANTE       "Use Vivante EGL video driver" ${UNIX_SYS})
 dep_option(VIDEO_VULKAN        "Enable Vulkan support" ON "ANDROID OR APPLE OR LINUX OR WINDOWS" OFF)
 dep_option(VIDEO_VULKAN        "Enable Vulkan support" ON "ANDROID OR APPLE OR LINUX OR WINDOWS" OFF)
 set_option(VIDEO_KMSDRM        "Use KMS DRM video driver" ${UNIX_SYS})
 set_option(VIDEO_KMSDRM        "Use KMS DRM video driver" ${UNIX_SYS})
 dep_option(KMSDRM_SHARED       "Dynamically load KMS DRM support" ON "VIDEO_KMSDRM" OFF)
 dep_option(KMSDRM_SHARED       "Dynamically load KMS DRM support" ON "VIDEO_KMSDRM" OFF)
+option_string(BACKGROUNDING_SIGNAL "number to use for magic backgrounding signal or 'OFF'" "OFF")
+option_string(FOREGROUNDING_SIGNAL "number to use for magic foregrounding signal or 'OFF'" "OFF")
 
 
 # TODO: We should (should we?) respect cmake's ${BUILD_SHARED_LIBS} flag here
 # TODO: We should (should we?) respect cmake's ${BUILD_SHARED_LIBS} flag here
 # The options below are for compatibility to configure's default behaviour.
 # The options below are for compatibility to configure's default behaviour.
@@ -384,6 +386,14 @@ else()
 endif()
 endif()
 set(HAVE_ASSERTIONS ${ASSERTIONS})
 set(HAVE_ASSERTIONS ${ASSERTIONS})
 
 
+if(NOT BACKGROUNDING_SIGNAL STREQUAL "OFF")
+  add_definitions("-DSDL_BACKGROUNDING_SIGNAL=${BACKGROUNDING_SIGNAL}")
+endif()
+
+if(NOT FOREGROUNDING_SIGNAL STREQUAL "OFF")
+  add_definitions("-DSDL_FOREGROUNDING_SIGNAL=${FOREGROUNDING_SIGNAL}")
+endif()
+
 # Compiler option evaluation
 # Compiler option evaluation
 if(USE_GCC OR USE_CLANG)
 if(USE_GCC OR USE_CLANG)
   # Check for -Wall first, so later things can override pieces of it.
   # Check for -Wall first, so later things can override pieces of it.

+ 37 - 0
configure

@@ -870,6 +870,8 @@ enable_sdl_dlopen
 enable_hidapi
 enable_hidapi
 enable_clock_gettime
 enable_clock_gettime
 enable_rpath
 enable_rpath
+enable_backgrounding_signal
+enable_foregrounding_signal
 enable_render_d3d
 enable_render_d3d
 '
 '
       ac_precious_vars='build_alias
       ac_precious_vars='build_alias
@@ -1627,6 +1629,12 @@ Optional Features:
   --enable-clock_gettime  use clock_gettime() instead of gettimeofday() on
   --enable-clock_gettime  use clock_gettime() instead of gettimeofday() on
                           UNIX [[default=yes]]
                           UNIX [[default=yes]]
   --enable-rpath          use an rpath when linking SDL [[default=yes]]
   --enable-rpath          use an rpath when linking SDL [[default=yes]]
+  --enable-backgrounding-signal
+                          number to use for magic backgrounding signal or 'no'
+                          [[default=no]]
+  --enable-foregrounding-signal
+                          number to use for magic foregrounding signal or 'no'
+                          [[default=no]]
   --enable-render-d3d     enable the Direct3D render driver [[default=yes]]
   --enable-render-d3d     enable the Direct3D render driver [[default=yes]]
 
 
 Optional Packages:
 Optional Packages:
@@ -23947,8 +23955,37 @@ fi
 
 
 }
 }
 
 
+CheckEventSignals()
+{
+    # Check whether --enable-backgrounding-signal was given.
+if test "${enable_backgrounding_signal+set}" = set; then :
+  enableval=$enable_backgrounding_signal;
+else
+  enable_backgrounding_signal=no
+fi
+
+    if test x$enable_backgrounding_signal != xno; then
+        EXTRA_CFLAGS="$EXTRA_CFLAGS -DSDL_BACKGROUNDING_SIGNAL=$enable_backgrounding_signal"
+    fi
+
+    # Check whether --enable-foregrounding-signal was given.
+if test "${enable_foregrounding_signal+set}" = set; then :
+  enableval=$enable_foregrounding_signal;
+else
+  enable_foregrounding_signal=no
+fi
+
+    if test x$enable_foregrounding_signal != xno; then
+        EXTRA_CFLAGS="$EXTRA_CFLAGS -DSDL_FOREGROUNDING_SIGNAL=$enable_foregrounding_signal"
+    fi
+}
+
+
+
 CheckWarnAll
 CheckWarnAll
 
 
+CheckEventSignals
+
 case "$host" in
 case "$host" in
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*|*-*-nto*)
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*|*-*-nto*)
         case "$host" in
         case "$host" in

+ 26 - 1
configure.in

@@ -3344,9 +3344,34 @@ AC_HELP_STRING([--enable-rpath], [use an rpath when linking SDL [[default=yes]]]
                   , enable_rpath=yes)
                   , enable_rpath=yes)
 }
 }
 
 
+dnl Check if we want to use custom signals to fake iOS/Android's backgrounding
+dnl  events. These could be useful if you're building a custom embedded
+dnl  environment, etc, but most people don't need this.
+CheckEventSignals()
+{
+    AC_ARG_ENABLE(backgrounding-signal,
+AC_HELP_STRING([--enable-backgrounding-signal], [number to use for magic backgrounding signal or 'no' [[default=no]]]),
+                  , enable_backgrounding_signal=no)
+    if test x$enable_backgrounding_signal != xno; then
+        EXTRA_CFLAGS="$EXTRA_CFLAGS -DSDL_BACKGROUNDING_SIGNAL=$enable_backgrounding_signal"
+    fi
+
+    AC_ARG_ENABLE(foregrounding-signal,
+AC_HELP_STRING([--enable-foregrounding-signal], [number to use for magic foregrounding signal or 'no' [[default=no]]]),
+                  , enable_foregrounding_signal=no)
+    if test x$enable_foregrounding_signal != xno; then
+        EXTRA_CFLAGS="$EXTRA_CFLAGS -DSDL_FOREGROUNDING_SIGNAL=$enable_foregrounding_signal"
+    fi
+}
+
+
+
 dnl Do this on all platforms, before everything else (other things might want to override it).
 dnl Do this on all platforms, before everything else (other things might want to override it).
 CheckWarnAll
 CheckWarnAll
 
 
+dnl Do this for every platform, but for some it doesn't mean anything, but better to catch it here anyhow.
+CheckEventSignals
+
 dnl Set up the configuration based on the host platform!
 dnl Set up the configuration based on the host platform!
 case "$host" in
 case "$host" in
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*|*-*-nto*)
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*|*-*-nto*)
@@ -3923,7 +3948,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         CheckDummyVideo
         CheckDummyVideo
         CheckInputEvents
         CheckInputEvents
         CheckPTHREAD
         CheckPTHREAD
-        
+
         # Set up files for the timer library
         # Set up files for the timer library
         if test x$enable_timers = xyes; then
         if test x$enable_timers = xyes; then
             AC_DEFINE(SDL_TIMER_UNIX, 1, [ ])
             AC_DEFINE(SDL_TIMER_UNIX, 1, [ ])

+ 1 - 1
src/events/SDL_events.c

@@ -689,7 +689,7 @@ SDL_PumpEvents(void)
     }
     }
 #endif
 #endif
 
 
-    SDL_SendPendingQuit();  /* in case we had a signal handler fire, etc. */
+    SDL_SendPendingSignalEvents();  /* in case we had a signal handler fire, etc. */
 }
 }
 
 
 /* Public functions */
 /* Public functions */

+ 1 - 1
src/events/SDL_events_c.h

@@ -52,7 +52,7 @@ extern int SDL_SendQuit(void);
 extern int SDL_EventsInit(void);
 extern int SDL_EventsInit(void);
 extern void SDL_EventsQuit(void);
 extern void SDL_EventsQuit(void);
 
 
-extern void SDL_SendPendingQuit(void);
+extern void SDL_SendPendingSignalEvents(void);
 
 
 #endif /* SDL_events_c_h_ */
 #endif /* SDL_events_c_h_ */
 
 

+ 90 - 45
src/events/SDL_quit.c

@@ -34,6 +34,14 @@
 static SDL_bool disable_signals = SDL_FALSE;
 static SDL_bool disable_signals = SDL_FALSE;
 static SDL_bool send_quit_pending = SDL_FALSE;
 static SDL_bool send_quit_pending = SDL_FALSE;
 
 
+#ifdef SDL_BACKGROUNDING_SIGNAL
+static SDL_bool send_backgrounding_pending = SDL_FALSE;
+#endif
+
+#ifdef SDL_FOREGROUNDING_SIGNAL
+static SDL_bool send_foregrounding_pending = SDL_FALSE;
+#endif
+
 #ifdef HAVE_SIGNAL_H
 #ifdef HAVE_SIGNAL_H
 static void
 static void
 SDL_HandleSIG(int sig)
 SDL_HandleSIG(int sig)
@@ -43,46 +51,81 @@ SDL_HandleSIG(int sig)
 
 
     /* Send a quit event next time the event loop pumps. */
     /* Send a quit event next time the event loop pumps. */
     /* We can't send it in signal handler; malloc() might be interrupted! */
     /* We can't send it in signal handler; malloc() might be interrupted! */
-    send_quit_pending = SDL_TRUE;
+    if ((sig == SIGINT) || (sig == SIGTERM)) {
+        send_quit_pending = SDL_TRUE;
+    }
+
+    #ifdef SDL_BACKGROUNDING_SIGNAL
+    else if (sig == SDL_BACKGROUNDING_SIGNAL) {
+        send_backgrounding_pending = SDL_TRUE;
+    }
+    #endif
+
+    #ifdef SDL_FOREGROUNDING_SIGNAL
+    else if (sig == SDL_FOREGROUNDING_SIGNAL) {
+        send_foregrounding_pending = SDL_TRUE;
+    }
+    #endif
 }
 }
 #endif /* HAVE_SIGNAL_H */
 #endif /* HAVE_SIGNAL_H */
 
 
-/* Public functions */
-static int
-SDL_QuitInit_Internal(void)
+static void
+SDL_EventSignal_Init(const int sig)
 {
 {
 #ifdef HAVE_SIGACTION
 #ifdef HAVE_SIGACTION
     struct sigaction action;
     struct sigaction action;
-    sigaction(SIGINT, NULL, &action);
+
+    sigaction(sig, NULL, &action);
 #ifdef HAVE_SA_SIGACTION
 #ifdef HAVE_SA_SIGACTION
     if ( action.sa_handler == SIG_DFL && (void (*)(int))action.sa_sigaction == SIG_DFL ) {
     if ( action.sa_handler == SIG_DFL && (void (*)(int))action.sa_sigaction == SIG_DFL ) {
 #else
 #else
     if ( action.sa_handler == SIG_DFL ) {
     if ( action.sa_handler == SIG_DFL ) {
 #endif
 #endif
         action.sa_handler = SDL_HandleSIG;
         action.sa_handler = SDL_HandleSIG;
-        sigaction(SIGINT, &action, NULL);
+        sigaction(sig, &action, NULL);
+    }
+#elif HAVE_SIGNAL_H
+    void (*ohandler) (int) = signal(sig, SDL_HandleSIG);
+    if (ohandler != SIG_DFL) {
+        signal(sig, ohandler);
     }
     }
-    sigaction(SIGTERM, NULL, &action);
-
-#ifdef HAVE_SA_SIGACTION
-    if ( action.sa_handler == SIG_DFL && (void (*)(int))action.sa_sigaction == SIG_DFL ) {
-#else
-    if ( action.sa_handler == SIG_DFL ) {
 #endif
 #endif
-        action.sa_handler = SDL_HandleSIG;
-        sigaction(SIGTERM, &action, NULL);
+}
+
+static void
+SDL_EventSignal_Quit(const int sig)
+{
+#ifdef HAVE_SIGACTION
+    struct sigaction action;
+    sigaction(sig, NULL, &action);
+    if ( action.sa_handler == SDL_HandleSIG ) {
+        action.sa_handler = SIG_DFL;
+        sigaction(sig, &action, NULL);
     }
     }
 #elif HAVE_SIGNAL_H
 #elif HAVE_SIGNAL_H
-    void (*ohandler) (int);
+    void (*ohandler) (int) = signal(sig, SIG_DFL);
+    if (ohandler != SDL_HandleSIG) {
+        signal(sig, ohandler);
+    }
+#endif /* HAVE_SIGNAL_H */
+}
 
 
+/* Public functions */
+static int
+SDL_QuitInit_Internal(void)
+{
     /* Both SIGINT and SIGTERM are translated into quit interrupts */
     /* Both SIGINT and SIGTERM are translated into quit interrupts */
-    ohandler = signal(SIGINT, SDL_HandleSIG);
-    if (ohandler != SIG_DFL)
-        signal(SIGINT, ohandler);
-    ohandler = signal(SIGTERM, SDL_HandleSIG);
-    if (ohandler != SIG_DFL)
-        signal(SIGTERM, ohandler);
-#endif /* HAVE_SIGNAL_H */
+    /* and SDL can be built to simulate iOS/Android semantics with arbitrary signals. */
+    SDL_EventSignal_Init(SIGINT);
+    SDL_EventSignal_Init(SIGTERM);
+
+    #ifdef SDL_BACKGROUNDING_SIGNAL
+    SDL_EventSignal_Init(SDL_BACKGROUNDING_SIGNAL);
+    #endif
+
+    #ifdef SDL_FOREGROUNDING_SIGNAL
+    SDL_EventSignal_Init(SDL_FOREGROUNDING_SIGNAL);
+    #endif
 
 
     /* That's it! */
     /* That's it! */
     return 0;
     return 0;
@@ -100,28 +143,16 @@ SDL_QuitInit(void)
 static void
 static void
 SDL_QuitQuit_Internal(void)
 SDL_QuitQuit_Internal(void)
 {
 {
-#ifdef HAVE_SIGACTION
-    struct sigaction action;
-    sigaction(SIGINT, NULL, &action);
-    if ( action.sa_handler == SDL_HandleSIG ) {
-        action.sa_handler = SIG_DFL;
-        sigaction(SIGINT, &action, NULL);
-    }
-    sigaction(SIGTERM, NULL, &action);
-    if ( action.sa_handler == SDL_HandleSIG ) {
-        action.sa_handler = SIG_DFL;
-        sigaction(SIGTERM, &action, NULL);
-    }
-#elif HAVE_SIGNAL_H
-    void (*ohandler) (int);
-
-    ohandler = signal(SIGINT, SIG_DFL);
-    if (ohandler != SDL_HandleSIG)
-        signal(SIGINT, ohandler);
-    ohandler = signal(SIGTERM, SIG_DFL);
-    if (ohandler != SDL_HandleSIG)
-        signal(SIGTERM, ohandler);
-#endif /* HAVE_SIGNAL_H */
+    SDL_EventSignal_Quit(SIGINT);
+    SDL_EventSignal_Quit(SIGTERM);
+
+    #ifdef SDL_BACKGROUNDING_SIGNAL
+    SDL_EventSignal_Quit(SDL_BACKGROUNDING_SIGNAL);
+    #endif
+
+    #ifdef SDL_FOREGROUNDING_SIGNAL
+    SDL_EventSignal_Quit(SDL_FOREGROUNDING_SIGNAL);
+    #endif
 }
 }
 
 
 void
 void
@@ -141,12 +172,26 @@ SDL_SendQuit(void)
 }
 }
 
 
 void
 void
-SDL_SendPendingQuit(void)
+SDL_SendPendingSignalEvents(void)
 {
 {
     if (send_quit_pending) {
     if (send_quit_pending) {
         SDL_SendQuit();
         SDL_SendQuit();
         SDL_assert(!send_quit_pending);
         SDL_assert(!send_quit_pending);
     }
     }
+
+    #ifdef SDL_BACKGROUNDING_SIGNAL
+    if (send_backgrounding_pending) {
+        send_backgrounding_pending = SDL_FALSE;
+        SDL_OnApplicationWillResignActive();
+    }
+    #endif
+
+    #ifdef SDL_FOREGROUNDING_SIGNAL
+    if (send_foregrounding_pending) {
+        send_foregrounding_pending = SDL_FALSE;
+        SDL_OnApplicationDidBecomeActive();
+    }
+    #endif
 }
 }
 
 
 /* vi: set ts=4 sw=4 expandtab: */
 /* vi: set ts=4 sw=4 expandtab: */