1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2021 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: */ |
210 | |