@@ -27,11 +27,57 @@ static SDL_AppIterate_func SDL_main_iteration_callback;
27
27
static SDL_AppQuit_func SDL_main_quit_callback ;
28
28
static SDL_AtomicInt apprc ; // use an atomic, since events might land from any thread and we don't want to wrap this all in a mutex. A CAS makes sure we only move from zero once.
29
29
30
- static int SDLCALL EventWatcher (void * userdata , SDL_Event * event )
30
+ // Return true if this event needs to be processed before returning from the event watcher
31
+ static SDL_bool ShouldDispatchImmediately (SDL_Event * event )
31
32
{
32
- if (SDL_AtomicGet (& apprc ) == 0 ) { // if already quitting, don't send the event to the app.
33
+ switch (event -> type ) {
34
+ case SDL_EVENT_TERMINATING :
35
+ case SDL_EVENT_LOW_MEMORY :
36
+ case SDL_EVENT_WILL_ENTER_BACKGROUND :
37
+ case SDL_EVENT_DID_ENTER_BACKGROUND :
38
+ case SDL_EVENT_WILL_ENTER_FOREGROUND :
39
+ case SDL_EVENT_DID_ENTER_FOREGROUND :
40
+ return SDL_TRUE ;
41
+ default :
42
+ return SDL_FALSE ;
43
+ }
44
+ }
45
+
46
+ static void SDL_DispatchMainCallbackEvent (SDL_Event * event )
47
+ {
48
+ if (SDL_AtomicGet (& apprc ) == 0 ) { // if already quitting, don't send the event to the app.
33
49
SDL_AtomicCAS (& apprc , 0 , SDL_main_event_callback (event ));
34
50
}
51
+ SDL_CleanupEvent (event );
52
+ }
53
+
54
+ static void SDL_DispatchMainCallbackEvents ()
55
+ {
56
+ SDL_Event events [16 ];
57
+
58
+ for (;;) {
59
+ int count = SDL_PeepEvents (events , SDL_arraysize (events ), SDL_GETEVENT , SDL_EVENT_FIRST , SDL_EVENT_LAST );
60
+ if (count <= 0 ) {
61
+ break ;
62
+ }
63
+ for (int i = 0 ; i < count ; ++ i ) {
64
+ SDL_Event * event = & events [i ];
65
+ if (!ShouldDispatchImmediately (event )) {
66
+ SDL_DispatchMainCallbackEvent (event );
67
+ }
68
+ }
69
+ }
70
+ }
71
+
72
+ static int SDLCALL SDL_MainCallbackEventWatcher (void * userdata , SDL_Event * event )
73
+ {
74
+ if (ShouldDispatchImmediately (event )) {
75
+ // Make sure any currently queued events are processed then dispatch this before continuing
76
+ SDL_DispatchMainCallbackEvents ();
77
+ SDL_DispatchMainCallbackEvent (event );
78
+ } else {
79
+ // We'll process this event later from the main event queue
80
+ }
35
81
return 0 ;
36
82
}
37
83
@@ -50,44 +96,19 @@ int SDL_InitMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_
50
96
return -1 ;
51
97
}
52
98
53
- // drain any initial events that might have arrived before we added a watcher.
54
- SDL_Event event ;
55
- SDL_Event * pending_events = NULL ;
56
- int total_pending_events = 0 ;
57
- while (SDL_PollEvent (& event )) {
58
- void * ptr = SDL_realloc (pending_events , sizeof (SDL_Event ) * (total_pending_events + 1 ));
59
- if (!ptr ) {
60
- SDL_OutOfMemory ();
61
- SDL_free (pending_events );
62
- SDL_AtomicSet (& apprc , -1 );
63
- return -1 ;
64
- }
65
- pending_events = (SDL_Event * ) ptr ;
66
- SDL_copyp (& pending_events [total_pending_events ], & event );
67
- total_pending_events ++ ;
68
- }
69
-
70
- if (SDL_AddEventWatch (EventWatcher , NULL ) == -1 ) {
71
- SDL_free (pending_events );
99
+ if (SDL_AddEventWatch (SDL_MainCallbackEventWatcher , NULL ) < 0 ) {
72
100
SDL_AtomicSet (& apprc , -1 );
73
101
return -1 ;
74
102
}
75
-
76
- for (int i = 0 ; i < total_pending_events ; i ++ ) {
77
- SDL_PushEvent (& pending_events [i ]);
78
- }
79
-
80
- SDL_free (pending_events );
81
103
}
82
104
83
105
return SDL_AtomicGet (& apprc );
84
106
}
85
107
86
108
int SDL_IterateMainCallbacks (void )
87
109
{
88
- // Just pump events and empty the queue, EventWatcher sends the events to the app.
89
110
SDL_PumpEvents ();
90
- SDL_FlushEvents ( SDL_EVENT_FIRST , SDL_EVENT_LAST );
111
+ SDL_DispatchMainCallbackEvents ( );
91
112
92
113
int rc = SDL_main_iteration_callback ();
93
114
if (!SDL_AtomicCAS (& apprc , 0 , rc )) {
@@ -99,7 +120,7 @@ int SDL_IterateMainCallbacks(void)
99
120
100
121
void SDL_QuitMainCallbacks (void )
101
122
{
102
- SDL_DelEventWatch (EventWatcher , NULL );
123
+ SDL_DelEventWatch (SDL_MainCallbackEventWatcher , NULL );
103
124
SDL_main_quit_callback ();
104
125
105
126
// for symmetry, you should explicitly Quit what you Init, but we might come through here uninitialized and SDL_Quit() will clear everything anyhow.
0 commit comments