@@ -82,11 +82,13 @@ where
82
82
#[ derive( Default ) ]
83
83
struct Handler {
84
84
ready : AtomicBool ,
85
+ in_callback : AtomicBool ,
85
86
control_flow : Mutex < ControlFlow > ,
86
87
control_flow_prev : Mutex < ControlFlow > ,
87
88
start_time : Mutex < Option < Instant > > ,
88
89
callback : Mutex < Option < Box < dyn EventHandler > > > ,
89
90
pending_events : Mutex < VecDeque < Event < Never > > > ,
91
+ deferred_events : Mutex < VecDeque < Event < Never > > > ,
90
92
pending_redraw : Mutex < Vec < WindowId > > ,
91
93
waker : Mutex < EventLoopWaker > ,
92
94
}
@@ -99,6 +101,10 @@ impl Handler {
99
101
self . pending_events . lock ( ) . unwrap ( )
100
102
}
101
103
104
+ fn deferred < ' a > ( & ' a self ) -> MutexGuard < ' a , VecDeque < Event < Never > > > {
105
+ self . deferred_events . lock ( ) . unwrap ( )
106
+ }
107
+
102
108
fn redraw < ' a > ( & ' a self ) -> MutexGuard < ' a , Vec < WindowId > > {
103
109
self . pending_redraw . lock ( ) . unwrap ( )
104
110
}
@@ -143,10 +149,22 @@ impl Handler {
143
149
mem:: replace ( & mut * self . events ( ) , Default :: default ( ) )
144
150
}
145
151
152
+ fn take_deferred ( & self ) -> VecDeque < Event < Never > > {
153
+ mem:: replace ( & mut * self . deferred ( ) , Default :: default ( ) )
154
+ }
155
+
146
156
fn should_redraw ( & self ) -> Vec < WindowId > {
147
157
mem:: replace ( & mut * self . redraw ( ) , Default :: default ( ) )
148
158
}
149
159
160
+ fn get_in_callback ( & self ) -> bool {
161
+ self . in_callback . load ( Ordering :: Acquire )
162
+ }
163
+
164
+ fn set_in_callback ( & self , in_callback : bool ) {
165
+ self . in_callback . store ( in_callback, Ordering :: Release ) ;
166
+ }
167
+
150
168
fn handle_nonuser_event ( & self , event : Event < Never > ) {
151
169
if let Some ( ref mut callback) = * self . callback . lock ( ) . unwrap ( ) {
152
170
callback. handle_nonuser_event (
@@ -181,13 +199,17 @@ impl AppState {
181
199
}
182
200
183
201
pub fn exit ( ) {
202
+ HANDLER . set_in_callback ( true ) ;
184
203
HANDLER . handle_nonuser_event ( Event :: LoopDestroyed ) ;
204
+ HANDLER . set_in_callback ( false ) ;
185
205
}
186
206
187
207
pub fn launched ( ) {
188
208
HANDLER . set_ready ( ) ;
189
209
HANDLER . waker ( ) . start ( ) ;
210
+ HANDLER . set_in_callback ( true ) ;
190
211
HANDLER . handle_nonuser_event ( Event :: NewEvents ( StartCause :: Init ) ) ;
212
+ HANDLER . set_in_callback ( false ) ;
191
213
}
192
214
193
215
pub fn wakeup ( ) {
@@ -214,7 +236,9 @@ impl AppState {
214
236
} ,
215
237
ControlFlow :: Exit => StartCause :: Poll , //panic!("unexpected `ControlFlow::Exit`"),
216
238
} ;
239
+ HANDLER . set_in_callback ( true ) ;
217
240
HANDLER . handle_nonuser_event ( Event :: NewEvents ( cause) ) ;
241
+ HANDLER . set_in_callback ( false ) ;
218
242
}
219
243
220
244
// This is called from multiple threads at present
@@ -227,38 +251,49 @@ impl AppState {
227
251
228
252
pub fn queue_event ( event : Event < Never > ) {
229
253
if !unsafe { msg_send ! [ class!( NSThread ) , isMainThread] } {
230
- panic ! ( "uh-oh" ) ;
254
+ panic ! ( "Event queued from different thread: {:#?}" , event ) ;
231
255
}
232
256
HANDLER . events ( ) . push_back ( event) ;
233
257
}
234
258
235
259
pub fn queue_events ( mut events : VecDeque < Event < Never > > ) {
236
260
if !unsafe { msg_send ! [ class!( NSThread ) , isMainThread] } {
237
- panic ! ( "uh-ohs" ) ;
261
+ panic ! ( "Events queued from different thread: {:#?}" , events ) ;
238
262
}
239
263
HANDLER . events ( ) . append ( & mut events) ;
240
264
}
241
265
242
266
pub fn send_event_immediately ( event : Event < Never > ) {
243
267
if !unsafe { msg_send ! [ class!( NSThread ) , isMainThread] } {
244
- panic ! ( "uh-oh" ) ;
268
+ panic ! ( "Event sent from different thread: {:#?}" , event) ;
269
+ }
270
+ HANDLER . deferred ( ) . push_back ( event) ;
271
+ if !HANDLER . get_in_callback ( ) {
272
+ HANDLER . set_in_callback ( true ) ;
273
+ for event in HANDLER . take_deferred ( ) {
274
+ HANDLER . handle_nonuser_event ( event) ;
275
+ }
276
+ HANDLER . set_in_callback ( false ) ;
245
277
}
246
- HANDLER . handle_nonuser_event ( event) ;
247
278
}
248
279
249
280
pub fn cleared ( ) {
250
281
if !HANDLER . is_ready ( ) { return }
251
- HANDLER . handle_user_events ( ) ;
252
- for event in HANDLER . take_events ( ) {
253
- HANDLER . handle_nonuser_event ( event) ;
254
- }
255
- for window_id in HANDLER . should_redraw ( ) {
256
- HANDLER . handle_nonuser_event ( Event :: WindowEvent {
257
- window_id,
258
- event : WindowEvent :: RedrawRequested ,
259
- } ) ;
282
+ if !HANDLER . get_in_callback ( ) {
283
+ HANDLER . set_in_callback ( true ) ;
284
+ HANDLER . handle_user_events ( ) ;
285
+ for event in HANDLER . take_events ( ) {
286
+ HANDLER . handle_nonuser_event ( event) ;
287
+ }
288
+ for window_id in HANDLER . should_redraw ( ) {
289
+ HANDLER . handle_nonuser_event ( Event :: WindowEvent {
290
+ window_id,
291
+ event : WindowEvent :: RedrawRequested ,
292
+ } ) ;
293
+ }
294
+ HANDLER . handle_nonuser_event ( Event :: EventsCleared ) ;
295
+ HANDLER . set_in_callback ( false ) ;
260
296
}
261
- HANDLER . handle_nonuser_event ( Event :: EventsCleared ) ;
262
297
if HANDLER . should_exit ( ) {
263
298
let _: ( ) = unsafe { msg_send ! [ NSApp ( ) , stop: nil] } ;
264
299
return
0 commit comments