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.
This commit is contained in:
Ryan C. Gordon 2019-03-15 15:51:05 -04:00
parent 911bf6241b
commit 8a5a05c168
6 changed files with 174 additions and 57 deletions

View File

@ -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)
set_option(VIDEO_KMSDRM "Use KMS DRM video driver" ${UNIX_SYS})
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
# The options below are for compatibility to configure's default behaviour.
@ -384,6 +386,14 @@ else()
endif()
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
if(USE_GCC OR USE_CLANG)
# Check for -Wall first, so later things can override pieces of it.

37
configure vendored
View File

@ -870,6 +870,8 @@ enable_sdl_dlopen
enable_hidapi
enable_clock_gettime
enable_rpath
enable_backgrounding_signal
enable_foregrounding_signal
enable_render_d3d
'
ac_precious_vars='build_alias
@ -1627,6 +1629,12 @@ Optional Features:
--enable-clock_gettime use clock_gettime() instead of gettimeofday() on
UNIX [[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]]
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
CheckEventSignals
case "$host" in
*-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*|*-*-nto*)
case "$host" in

View File

@ -3344,9 +3344,34 @@ AC_HELP_STRING([--enable-rpath], [use an rpath when linking SDL [[default=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).
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!
case "$host" in
*-*-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
CheckInputEvents
CheckPTHREAD
# Set up files for the timer library
if test x$enable_timers = xyes; then
AC_DEFINE(SDL_TIMER_UNIX, 1, [ ])

View File

@ -689,7 +689,7 @@ SDL_PumpEvents(void)
}
#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 */

View File

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

View File

@ -34,6 +34,14 @@
static SDL_bool disable_signals = 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
static void
SDL_HandleSIG(int sig)
@ -43,46 +51,81 @@ SDL_HandleSIG(int sig)
/* Send a quit event next time the event loop pumps. */
/* 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 */
static void
SDL_EventSignal_Init(const int sig)
{
#ifdef HAVE_SIGACTION
struct sigaction action;
sigaction(sig, 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
action.sa_handler = SDL_HandleSIG;
sigaction(sig, &action, NULL);
}
#elif HAVE_SIGNAL_H
void (*ohandler) (int) = signal(sig, SDL_HandleSIG);
if (ohandler != SIG_DFL) {
signal(sig, ohandler);
}
#endif
}
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
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)
{
#ifdef HAVE_SIGACTION
struct sigaction action;
sigaction(SIGINT, 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
action.sa_handler = SDL_HandleSIG;
sigaction(SIGINT, &action, NULL);
}
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
action.sa_handler = SDL_HandleSIG;
sigaction(SIGTERM, &action, NULL);
}
#elif HAVE_SIGNAL_H
void (*ohandler) (int);
/* 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! */
return 0;
@ -100,28 +143,16 @@ SDL_QuitInit(void)
static 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);
SDL_EventSignal_Quit(SIGINT);
SDL_EventSignal_Quit(SIGTERM);
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 */
#ifdef SDL_BACKGROUNDING_SIGNAL
SDL_EventSignal_Quit(SDL_BACKGROUNDING_SIGNAL);
#endif
#ifdef SDL_FOREGROUNDING_SIGNAL
SDL_EventSignal_Quit(SDL_FOREGROUNDING_SIGNAL);
#endif
}
void
@ -141,12 +172,26 @@ SDL_SendQuit(void)
}
void
SDL_SendPendingQuit(void)
SDL_SendPendingSignalEvents(void)
{
if (send_quit_pending) {
SDL_SendQuit();
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: */