sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_quit.c (5132B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
      4 
      5   This software is provided 'as-is', without any express or implied
      6   warranty.  In no event will the authors be held liable for any damages
      7   arising from the use of this software.
      8 
      9   Permission is granted to anyone to use this software for any purpose,
     10   including commercial applications, and to alter it and redistribute it
     11   freely, subject to the following restrictions:
     12 
     13   1. The origin of this software must not be misrepresented; you must not
     14      claim that you wrote the original software. If you use this software
     15      in a product, an acknowledgment in the product documentation would be
     16      appreciated but is not required.
     17   2. Altered source versions must be plainly marked as such, and must not be
     18      misrepresented as being the original software.
     19   3. This notice may not be removed or altered from any source distribution.
     20 */
     21 #include "../SDL_internal.h"
     22 
     23 #include "SDL_hints.h"
     24 
     25 /* General quit handling code for SDL */
     26 
     27 #ifdef HAVE_SIGNAL_H
     28 #include <signal.h>
     29 #endif
     30 
     31 #include "SDL_events.h"
     32 #include "SDL_events_c.h"
     33 
     34 #if defined(HAVE_SIGNAL_H) || defined(HAVE_SIGACTION)
     35 #define HAVE_SIGNAL_SUPPORT 1
     36 #endif
     37 
     38 #ifdef HAVE_SIGNAL_SUPPORT
     39 static SDL_bool disable_signals = SDL_FALSE;
     40 static SDL_bool send_quit_pending = SDL_FALSE;
     41 
     42 #ifdef SDL_BACKGROUNDING_SIGNAL
     43 static SDL_bool send_backgrounding_pending = SDL_FALSE;
     44 #endif
     45 
     46 #ifdef SDL_FOREGROUNDING_SIGNAL
     47 static SDL_bool send_foregrounding_pending = SDL_FALSE;
     48 #endif
     49 
     50 static void
     51 SDL_HandleSIG(int sig)
     52 {
     53     /* Reset the signal handler */
     54     signal(sig, SDL_HandleSIG);
     55 
     56     /* Send a quit event next time the event loop pumps. */
     57     /* We can't send it in signal handler; malloc() might be interrupted! */
     58     if ((sig == SIGINT) || (sig == SIGTERM)) {
     59         send_quit_pending = SDL_TRUE;
     60     }
     61 
     62     #ifdef SDL_BACKGROUNDING_SIGNAL
     63     else if (sig == SDL_BACKGROUNDING_SIGNAL) {
     64         send_backgrounding_pending = SDL_TRUE;
     65     }
     66     #endif
     67 
     68     #ifdef SDL_FOREGROUNDING_SIGNAL
     69     else if (sig == SDL_FOREGROUNDING_SIGNAL) {
     70         send_foregrounding_pending = SDL_TRUE;
     71     }
     72     #endif
     73 }
     74 
     75 static void
     76 SDL_EventSignal_Init(const int sig)
     77 {
     78 #ifdef HAVE_SIGACTION
     79     struct sigaction action;
     80 
     81     sigaction(sig, NULL, &action);
     82 #ifdef HAVE_SA_SIGACTION
     83     if ( action.sa_handler == SIG_DFL && (void (*)(int))action.sa_sigaction == SIG_DFL ) {
     84 #else
     85     if ( action.sa_handler == SIG_DFL ) {
     86 #endif
     87         action.sa_handler = SDL_HandleSIG;
     88         sigaction(sig, &action, NULL);
     89     }
     90 #elif HAVE_SIGNAL_H
     91     void (*ohandler) (int) = signal(sig, SDL_HandleSIG);
     92     if (ohandler != SIG_DFL) {
     93         signal(sig, ohandler);
     94     }
     95 #endif
     96 }
     97 
     98 static void
     99 SDL_EventSignal_Quit(const int sig)
    100 {
    101 #ifdef HAVE_SIGACTION
    102     struct sigaction action;
    103     sigaction(sig, NULL, &action);
    104     if ( action.sa_handler == SDL_HandleSIG ) {
    105         action.sa_handler = SIG_DFL;
    106         sigaction(sig, &action, NULL);
    107     }
    108 #elif HAVE_SIGNAL_H
    109     void (*ohandler) (int) = signal(sig, SIG_DFL);
    110     if (ohandler != SDL_HandleSIG) {
    111         signal(sig, ohandler);
    112     }
    113 #endif /* HAVE_SIGNAL_H */
    114 }
    115 
    116 /* Public functions */
    117 static int
    118 SDL_QuitInit_Internal(void)
    119 {
    120     /* Both SIGINT and SIGTERM are translated into quit interrupts */
    121     /* and SDL can be built to simulate iOS/Android semantics with arbitrary signals. */
    122     SDL_EventSignal_Init(SIGINT);
    123     SDL_EventSignal_Init(SIGTERM);
    124 
    125     #ifdef SDL_BACKGROUNDING_SIGNAL
    126     SDL_EventSignal_Init(SDL_BACKGROUNDING_SIGNAL);
    127     #endif
    128 
    129     #ifdef SDL_FOREGROUNDING_SIGNAL
    130     SDL_EventSignal_Init(SDL_FOREGROUNDING_SIGNAL);
    131     #endif
    132 
    133     /* That's it! */
    134     return 0;
    135 }
    136 
    137 static void
    138 SDL_QuitQuit_Internal(void)
    139 {
    140     SDL_EventSignal_Quit(SIGINT);
    141     SDL_EventSignal_Quit(SIGTERM);
    142 
    143     #ifdef SDL_BACKGROUNDING_SIGNAL
    144     SDL_EventSignal_Quit(SDL_BACKGROUNDING_SIGNAL);
    145     #endif
    146 
    147     #ifdef SDL_FOREGROUNDING_SIGNAL
    148     SDL_EventSignal_Quit(SDL_FOREGROUNDING_SIGNAL);
    149     #endif
    150 }
    151 #endif
    152 
    153 int
    154 SDL_QuitInit(void)
    155 {
    156 #ifdef HAVE_SIGNAL_SUPPORT
    157     if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) {
    158         return SDL_QuitInit_Internal();
    159     }
    160 #endif
    161     return 0;
    162 }
    163 
    164 void
    165 SDL_QuitQuit(void)
    166 {
    167 #ifdef HAVE_SIGNAL_SUPPORT
    168     if (!disable_signals) {
    169         SDL_QuitQuit_Internal();
    170     }
    171 #endif
    172 }
    173 
    174 void
    175 SDL_SendPendingSignalEvents(void)
    176 {
    177 #ifdef HAVE_SIGNAL_SUPPORT
    178     if (send_quit_pending) {
    179         SDL_SendQuit();
    180         SDL_assert(!send_quit_pending);
    181     }
    182 
    183     #ifdef SDL_BACKGROUNDING_SIGNAL
    184     if (send_backgrounding_pending) {
    185         send_backgrounding_pending = SDL_FALSE;
    186         SDL_OnApplicationWillResignActive();
    187     }
    188     #endif
    189 
    190     #ifdef SDL_FOREGROUNDING_SIGNAL
    191     if (send_foregrounding_pending) {
    192         send_foregrounding_pending = SDL_FALSE;
    193         SDL_OnApplicationDidBecomeActive();
    194     }
    195     #endif
    196 #endif
    197 }
    198 
    199 /* This function returns 1 if it's okay to close the application window */
    200 int
    201 SDL_SendQuit(void)
    202 {
    203 #ifdef HAVE_SIGNAL_SUPPORT
    204     send_quit_pending = SDL_FALSE;
    205 #endif
    206     return SDL_SendAppEvent(SDL_QUIT);
    207 }
    208 
    209 /* vi: set ts=4 sw=4 expandtab: */