Drop application handler on run loop exit (#4149)

Calling the `Drop` impl of the user's `ApplicationHandler` is important on
iOS and Web, since they don't return from `EventLoop::run_app`.

And now that we reliably call `Drop`, the `ApplicationHandler::exited`
event/callback is unnecessary; using `Drop` composes much better (open files
etc. stored in the app state will be automatically flushed), and prevents
weirdness like attempting to create a new window while exiting.
This commit is contained in:
Mads Marquart 2025-03-17 10:56:00 +01:00 committed by GitHub
parent ef37b1d5dd
commit afb731bb52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 170 additions and 137 deletions

View file

@ -157,6 +157,7 @@ impl AppState {
pub fn will_terminate(self: &Rc<Self>, _notification: &NSNotification) {
trace_scope!("NSApplicationWillTerminateNotification");
// TODO: Notify every window that it will be destroyed, like done in iOS?
self.event_handler.terminate();
self.internal_exit();
}
@ -164,10 +165,10 @@ impl AppState {
/// of the given closure.
pub fn set_event_handler<R>(
&self,
handler: &mut dyn ApplicationHandler,
handler: impl ApplicationHandler,
closure: impl FnOnce() -> R,
) -> R {
self.event_handler.set(handler, closure)
self.event_handler.set(Box::new(handler), closure)
}
pub fn event_loop_proxy(&self) -> &Arc<EventLoopProxy> {
@ -202,10 +203,6 @@ impl AppState {
/// NOTE: that if the `NSApplication` has been launched then that state is preserved,
/// and we won't need to re-launch the app if subsequent EventLoops are run.
pub fn internal_exit(self: &Rc<Self>) {
self.with_handler(|app, event_loop| {
app.exiting(event_loop);
});
self.set_is_running(false);
self.set_stop_on_redraw(false);
self.set_stop_before_wait(false);

View file

@ -285,10 +285,10 @@ impl EventLoop {
// redundant wake ups.
pub fn run_app_on_demand<A: ApplicationHandler>(
&mut self,
mut app: A,
app: A,
) -> Result<(), EventLoopError> {
self.app_state.clear_exit();
self.app_state.set_event_handler(&mut app, || {
self.app_state.set_event_handler(app, || {
autoreleasepool(|_| {
// clear / normalize pump_events state
self.app_state.set_wait_timeout(None);
@ -324,9 +324,9 @@ impl EventLoop {
pub fn pump_app_events<A: ApplicationHandler>(
&mut self,
timeout: Option<Duration>,
mut app: A,
app: A,
) -> PumpStatus {
self.app_state.set_event_handler(&mut app, || {
self.app_state.set_event_handler(app, || {
autoreleasepool(|_| {
// As a special case, if the application hasn't been launched yet then we at least
// run the loop until it has fully launched.