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

@ -6,7 +6,17 @@ use crate::event_loop::ActiveEventLoop;
use crate::platform::macos::ApplicationHandlerExtMacOS;
use crate::window::WindowId;
/// The handler of the application events.
/// The handler of application-level events.
///
/// See [the top-level docs] for example usage, and [`EventLoop::run_app`] for an overview of when
/// events are delivered.
///
/// This is [dropped] when the event loop is shut down. Note that this only works if you're passing
/// the entire state to [`EventLoop::run_app`] (passing `&mut app` won't work).
///
/// [the top-level docs]: crate
/// [`EventLoop::run_app`]: crate::event_loop::EventLoop::run_app
/// [dropped]: std::ops::Drop
pub trait ApplicationHandler {
/// Emitted when new events arrive from the OS to be processed.
///
@ -57,7 +67,6 @@ pub trait ApplicationHandler {
///
/// [`resumed()`]: Self::resumed()
/// [`suspended()`]: Self::suspended()
/// [`exiting()`]: Self::exiting()
fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
@ -162,8 +171,6 @@ pub trait ApplicationHandler {
///
/// let (sender, receiver) = mpsc::channel();
///
/// let mut app = MyApp { receiver };
///
/// // Send an event in a loop
/// let proxy = event_loop.create_proxy();
/// let background_thread = thread::spawn(move || {
@ -171,7 +178,7 @@ pub trait ApplicationHandler {
/// loop {
/// println!("sending: {i}");
/// if sender.send(i).is_err() {
/// // Stop sending once `MyApp` is dropped
/// // Stop sending once the receiver is dropped
/// break;
/// }
/// // Trigger the wake-up _after_ we placed the event in the channel.
@ -182,9 +189,8 @@ pub trait ApplicationHandler {
/// }
/// });
///
/// event_loop.run_app(&mut app)?;
/// event_loop.run_app(MyApp { receiver })?;
///
/// drop(app);
/// background_thread.join().unwrap();
///
/// Ok(())
@ -203,6 +209,10 @@ pub trait ApplicationHandler {
);
/// Emitted when the OS sends an event to a device.
///
/// For this to be called, it must be enabled with [`EventLoop::listen_device_events`].
///
/// [`EventLoop::listen_device_events`]: crate::event_loop::EventLoop::listen_device_events
fn device_event(
&mut self,
event_loop: &dyn ActiveEventLoop,
@ -258,7 +268,7 @@ pub trait ApplicationHandler {
/// to the user. This is a good place to stop refreshing UI, running animations and other visual
/// things. It is driven by Android's [`onStop()`] method.
///
/// After this event the application either receives [`resumed()`] again, or [`exiting()`].
/// After this event the application either receives [`resumed()`] again, or will exit.
///
/// [`onStop()`]: https://developer.android.com/reference/android/app/Activity#onStop()
///
@ -268,7 +278,6 @@ pub trait ApplicationHandler {
///
/// [`resumed()`]: Self::resumed()
/// [`suspended()`]: Self::suspended()
/// [`exiting()`]: Self::exiting()
fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
@ -310,14 +319,6 @@ pub trait ApplicationHandler {
let _ = event_loop;
}
/// Emitted when the event loop is being shut down.
///
/// This is irreversible - if this method is called, it is guaranteed that the event loop
/// will exit right after.
fn exiting(&mut self, event_loop: &dyn ActiveEventLoop) {
let _ = event_loop;
}
/// Emitted when the application has received a memory warning.
///
/// ## Platform-specific
@ -413,11 +414,6 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for &mut A {
(**self).destroy_surfaces(event_loop);
}
#[inline]
fn exiting(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).exiting(event_loop);
}
#[inline]
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).memory_warning(event_loop);
@ -487,11 +483,6 @@ impl<A: ?Sized + ApplicationHandler> ApplicationHandler for Box<A> {
(**self).destroy_surfaces(event_loop);
}
#[inline]
fn exiting(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).exiting(event_loop);
}
#[inline]
fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) {
(**self).memory_warning(event_loop);