@@ -15,6 +15,8 @@ use bevy_window::{
15
15
use winit:: dpi:: { LogicalPosition , LogicalSize , PhysicalPosition , PhysicalSize } ;
16
16
use winit:: event_loop:: ActiveEventLoop ;
17
17
18
+ use bevy_app:: AppExit ;
19
+ use bevy_ecs:: prelude:: EventReader ;
18
20
use bevy_ecs:: query:: With ;
19
21
#[ cfg( target_os = "ios" ) ]
20
22
use winit:: platform:: ios:: WindowExtIOS ;
@@ -116,14 +118,16 @@ pub fn create_windows<F: QueryFilter + 'static>(
116
118
}
117
119
}
118
120
121
+ #[ allow( clippy:: too_many_arguments) ]
119
122
pub ( crate ) fn despawn_windows (
120
123
closing : Query < Entity , With < ClosingWindow > > ,
121
124
mut closed : RemovedComponents < Window > ,
122
- window_entities : Query < & Window > ,
125
+ window_entities : Query < Entity , With < Window > > ,
123
126
mut closing_events : EventWriter < WindowClosing > ,
124
127
mut closed_events : EventWriter < WindowClosed > ,
125
128
mut winit_windows : NonSendMut < WinitWindows > ,
126
129
mut windows_to_drop : Local < Vec < WindowWrapper < winit:: window:: Window > > > ,
130
+ mut exit_events : EventReader < AppExit > ,
127
131
) {
128
132
// Drop all the windows that are waiting to be closed
129
133
windows_to_drop. clear ( ) ;
@@ -146,6 +150,15 @@ pub(crate) fn despawn_windows(
146
150
closed_events. send ( WindowClosed { window } ) ;
147
151
}
148
152
}
153
+
154
+ // On macOS, when exiting, we need to tell the rendering thread the windows are about to
155
+ // close to ensure that they are dropped on the main thread. Otherwise, the app will hang.
156
+ if !exit_events. is_empty ( ) {
157
+ exit_events. clear ( ) ;
158
+ for window in window_entities. iter ( ) {
159
+ closing_events. send ( WindowClosing { window } ) ;
160
+ }
161
+ }
149
162
}
150
163
151
164
/// The cached state of the window so we can check which properties were changed from within the app.
0 commit comments