Change run_app(app: &mut A) to run_app(app: A) (#3721)

This allows the user more control over how they pass their application state
to Winit, and will hopefully allow `Drop` implementations on the application
handler to work in the future on all platforms.
This commit is contained in:
Mads Marquart 2024-07-11 15:38:09 +02:00 committed by GitHub
parent d5fd8682eb
commit bf97def398
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 53 additions and 59 deletions

View file

@ -86,8 +86,7 @@ fn main() -> Result<(), impl std::error::Error> {
} }
let event_loop = EventLoop::new().unwrap(); let event_loop = EventLoop::new().unwrap();
let mut app = Application::default(); event_loop.run_app(Application::default())
event_loop.run_app(&mut app)
} }
#[cfg(all(feature = "rwh_06", not(any(x11_platform, macos_platform, windows_platform))))] #[cfg(all(feature = "rwh_06", not(any(x11_platform, macos_platform, windows_platform))))]

View file

@ -43,8 +43,7 @@ fn main() -> Result<(), impl std::error::Error> {
let event_loop = EventLoop::new().unwrap(); let event_loop = EventLoop::new().unwrap();
let mut app = ControlFlowDemo::default(); event_loop.run_app(ControlFlowDemo::default())
event_loop.run_app(&mut app)
} }
#[derive(Default)] #[derive(Default)]

View file

@ -57,9 +57,8 @@ fn main() -> Result<(), Box<dyn Error>> {
} }
}); });
let mut state = Application::new(&event_loop); let app = Application::new(&event_loop);
Ok(event_loop.run_app(app)?)
event_loop.run_app(&mut state).map_err(Into::into)
} }
/// Application state and event handling. /// Application state and event handling.

View file

@ -58,8 +58,7 @@ fn main() -> Result<(), Box<dyn Error>> {
tracing_subscriber::fmt::init(); tracing_subscriber::fmt::init();
let event_loop = EventLoop::new()?; let event_loop = EventLoop::new()?;
let mut app = XEmbedDemo { parent_window_id, window: None }; Ok(event_loop.run_app(XEmbedDemo { parent_window_id, window: None })?)
event_loop.run_app(&mut app).map_err(Into::into)
} }
#[cfg(not(x11_platform))] #[cfg(not(x11_platform))]

View file

@ -65,6 +65,9 @@ changelog entry.
`ApplicationHandler::resumed/suspended()` are now only emitted by iOS and Web `ApplicationHandler::resumed/suspended()` are now only emitted by iOS and Web
and now signify actually resuming/suspending the application. and now signify actually resuming/suspending the application.
- Rename `platform::web::*ExtWebSys` to `*ExtWeb`. - Rename `platform::web::*ExtWebSys` to `*ExtWeb`.
- Change signature of `EventLoop::run_app`, `EventLoopExtPumpEvents::pump_app_events` and
`EventLoopExtRunOnDemand::run_app_on_demand` to accept a `impl ApplicationHandler` directly,
instead of requiring a `&mut` reference to it.
### Removed ### Removed

View file

@ -241,7 +241,7 @@ impl EventLoop {
/// [`run_app()`]: Self::run_app() /// [`run_app()`]: Self::run_app()
#[inline] #[inline]
#[cfg(not(all(web_platform, target_feature = "exception-handling")))] #[cfg(not(all(web_platform, target_feature = "exception-handling")))]
pub fn run_app<A: ApplicationHandler>(self, app: &mut A) -> Result<(), EventLoopError> { pub fn run_app<A: ApplicationHandler>(self, app: A) -> Result<(), EventLoopError> {
self.event_loop.run_app(app) self.event_loop.run_app(app)
} }

View file

@ -102,7 +102,7 @@ pub trait EventLoopExtPumpEvents {
fn pump_app_events<A: ApplicationHandler>( fn pump_app_events<A: ApplicationHandler>(
&mut self, &mut self,
timeout: Option<Duration>, timeout: Option<Duration>,
app: &mut A, app: A,
) -> PumpStatus; ) -> PumpStatus;
} }
@ -110,7 +110,7 @@ impl EventLoopExtPumpEvents for EventLoop {
fn pump_app_events<A: ApplicationHandler>( fn pump_app_events<A: ApplicationHandler>(
&mut self, &mut self,
timeout: Option<Duration>, timeout: Option<Duration>,
app: &mut A, app: A,
) -> PumpStatus { ) -> PumpStatus {
self.event_loop.pump_app_events(timeout, app) self.event_loop.pump_app_events(timeout, app)
} }

View file

@ -58,17 +58,11 @@ pub trait EventLoopExtRunOnDemand {
/// ///
/// [`exit()`]: ActiveEventLoop::exit() /// [`exit()`]: ActiveEventLoop::exit()
/// [`set_control_flow()`]: ActiveEventLoop::set_control_flow() /// [`set_control_flow()`]: ActiveEventLoop::set_control_flow()
fn run_app_on_demand<A: ApplicationHandler>( fn run_app_on_demand<A: ApplicationHandler>(&mut self, app: A) -> Result<(), EventLoopError>;
&mut self,
app: &mut A,
) -> Result<(), EventLoopError>;
} }
impl EventLoopExtRunOnDemand for EventLoop { impl EventLoopExtRunOnDemand for EventLoop {
fn run_app_on_demand<A: ApplicationHandler>( fn run_app_on_demand<A: ApplicationHandler>(&mut self, app: A) -> Result<(), EventLoopError> {
&mut self,
app: &mut A,
) -> Result<(), EventLoopError> {
self.event_loop.window_target().clear_exit(); self.event_loop.window_target().clear_exit();
self.event_loop.run_app_on_demand(app) self.event_loop.run_app_on_demand(app)
} }

View file

@ -417,16 +417,16 @@ impl EventLoop {
input_status input_status
} }
pub fn run_app<A: ApplicationHandler>(mut self, app: &mut A) -> Result<(), EventLoopError> { pub fn run_app<A: ApplicationHandler>(mut self, app: A) -> Result<(), EventLoopError> {
self.run_app_on_demand(app) self.run_app_on_demand(app)
} }
pub fn run_app_on_demand<A: ApplicationHandler>( pub fn run_app_on_demand<A: ApplicationHandler>(
&mut self, &mut self,
app: &mut A, mut app: A,
) -> Result<(), EventLoopError> { ) -> Result<(), EventLoopError> {
loop { loop {
match self.pump_app_events(None, app) { match self.pump_app_events(None, &mut app) {
PumpStatus::Exit(0) => { PumpStatus::Exit(0) => {
break Ok(()); break Ok(());
}, },
@ -443,7 +443,7 @@ impl EventLoop {
pub fn pump_app_events<A: ApplicationHandler>( pub fn pump_app_events<A: ApplicationHandler>(
&mut self, &mut self,
timeout: Option<Duration>, timeout: Option<Duration>,
app: &mut A, mut app: A,
) -> PumpStatus { ) -> PumpStatus {
if !self.loop_running { if !self.loop_running {
self.loop_running = true; self.loop_running = true;
@ -455,13 +455,13 @@ impl EventLoop {
self.cause = StartCause::Init; self.cause = StartCause::Init;
// run the initial loop iteration // run the initial loop iteration
self.single_iteration(None, app); self.single_iteration(None, &mut app);
} }
// Consider the possibility that the `StartCause::Init` iteration could // Consider the possibility that the `StartCause::Init` iteration could
// request to Exit // request to Exit
if !self.exiting() { if !self.exiting() {
self.poll_events_with_timeout(timeout, app); self.poll_events_with_timeout(timeout, &mut app);
} }
if self.exiting() { if self.exiting() {
self.loop_running = false; self.loop_running = false;

View file

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

View file

@ -109,10 +109,10 @@ impl OwnedDisplayHandle {
} }
} }
fn map_user_event<A: ApplicationHandler>( fn map_user_event<'a, A: ApplicationHandler + 'a>(
app: &mut A, mut app: A,
proxy_wake_up: Arc<AtomicBool>, proxy_wake_up: Arc<AtomicBool>,
) -> impl FnMut(Event, &RootActiveEventLoop) + '_ { ) -> impl FnMut(Event, &RootActiveEventLoop) + 'a {
move |event, window_target| match event { move |event, window_target| match event {
Event::NewEvents(cause) => app.new_events(window_target, cause), Event::NewEvents(cause) => app.new_events(window_target, cause),
Event::WindowEvent { window_id, event } => { Event::WindowEvent { window_id, event } => {
@ -168,7 +168,7 @@ impl EventLoop {
}) })
} }
pub fn run_app<A: ApplicationHandler>(self, app: &mut A) -> ! { pub fn run_app<A: ApplicationHandler>(self, app: A) -> ! {
let application: Option<Retained<UIApplication>> = let application: Option<Retained<UIApplication>> =
unsafe { msg_send_id![UIApplication::class(), sharedApplication] }; unsafe { msg_send_id![UIApplication::class(), sharedApplication] };
assert!( assert!(

View file

@ -788,13 +788,13 @@ impl EventLoop {
} }
} }
pub fn run_app<A: ApplicationHandler>(self, app: &mut A) -> Result<(), EventLoopError> { pub fn run_app<A: ApplicationHandler>(self, app: A) -> Result<(), EventLoopError> {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_app(app)) x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_app(app))
} }
pub fn run_app_on_demand<A: ApplicationHandler>( pub fn run_app_on_demand<A: ApplicationHandler>(
&mut self, &mut self,
app: &mut A, app: A,
) -> Result<(), EventLoopError> { ) -> Result<(), EventLoopError> {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_app_on_demand(app)) x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_app_on_demand(app))
} }
@ -802,7 +802,7 @@ impl EventLoop {
pub fn pump_app_events<A: ApplicationHandler>( pub fn pump_app_events<A: ApplicationHandler>(
&mut self, &mut self,
timeout: Option<Duration>, timeout: Option<Duration>,
app: &mut A, app: A,
) -> PumpStatus { ) -> PumpStatus {
x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_app_events(timeout, app)) x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_app_events(timeout, app))
} }

View file

@ -160,16 +160,16 @@ impl EventLoop {
Ok(event_loop) Ok(event_loop)
} }
pub fn run_app<A: ApplicationHandler>(mut self, app: &mut A) -> Result<(), EventLoopError> { pub fn run_app<A: ApplicationHandler>(mut self, app: A) -> Result<(), EventLoopError> {
self.run_app_on_demand(app) self.run_app_on_demand(app)
} }
pub fn run_app_on_demand<A: ApplicationHandler>( pub fn run_app_on_demand<A: ApplicationHandler>(
&mut self, &mut self,
app: &mut A, mut app: A,
) -> Result<(), EventLoopError> { ) -> Result<(), EventLoopError> {
let exit = loop { let exit = loop {
match self.pump_app_events(None, app) { match self.pump_app_events(None, &mut app) {
PumpStatus::Exit(0) => { PumpStatus::Exit(0) => {
break Ok(()); break Ok(());
}, },
@ -194,19 +194,19 @@ impl EventLoop {
pub fn pump_app_events<A: ApplicationHandler>( pub fn pump_app_events<A: ApplicationHandler>(
&mut self, &mut self,
timeout: Option<Duration>, timeout: Option<Duration>,
app: &mut A, mut app: A,
) -> PumpStatus { ) -> PumpStatus {
if !self.loop_running { if !self.loop_running {
self.loop_running = true; self.loop_running = true;
// Run the initial loop iteration. // Run the initial loop iteration.
self.single_iteration(app, StartCause::Init); self.single_iteration(&mut app, StartCause::Init);
} }
// Consider the possibility that the `StartCause::Init` iteration could // Consider the possibility that the `StartCause::Init` iteration could
// request to Exit. // request to Exit.
if !self.exiting() { if !self.exiting() {
self.poll_events_with_timeout(timeout, app); self.poll_events_with_timeout(timeout, &mut app);
} }
if let Some(code) = self.exit_code() { if let Some(code) = self.exit_code() {
self.loop_running = false; self.loop_running = false;
@ -219,7 +219,7 @@ impl EventLoop {
} }
} }
pub fn poll_events_with_timeout<A: ApplicationHandler>( fn poll_events_with_timeout<A: ApplicationHandler>(
&mut self, &mut self,
mut timeout: Option<Duration>, mut timeout: Option<Duration>,
app: &mut A, app: &mut A,

View file

@ -367,16 +367,16 @@ impl EventLoop {
&self.event_processor.target &self.event_processor.target
} }
pub fn run_app<A: ApplicationHandler>(mut self, app: &mut A) -> Result<(), EventLoopError> { pub fn run_app<A: ApplicationHandler>(mut self, app: A) -> Result<(), EventLoopError> {
self.run_app_on_demand(app) self.run_app_on_demand(app)
} }
pub fn run_app_on_demand<A: ApplicationHandler>( pub fn run_app_on_demand<A: ApplicationHandler>(
&mut self, &mut self,
app: &mut A, mut app: A,
) -> Result<(), EventLoopError> { ) -> Result<(), EventLoopError> {
let exit = loop { let exit = loop {
match self.pump_app_events(None, app) { match self.pump_app_events(None, &mut app) {
PumpStatus::Exit(0) => { PumpStatus::Exit(0) => {
break Ok(()); break Ok(());
}, },
@ -404,19 +404,19 @@ impl EventLoop {
pub fn pump_app_events<A: ApplicationHandler>( pub fn pump_app_events<A: ApplicationHandler>(
&mut self, &mut self,
timeout: Option<Duration>, timeout: Option<Duration>,
app: &mut A, mut app: A,
) -> PumpStatus { ) -> PumpStatus {
if !self.loop_running { if !self.loop_running {
self.loop_running = true; self.loop_running = true;
// run the initial loop iteration // run the initial loop iteration
self.single_iteration(app, StartCause::Init); self.single_iteration(&mut app, StartCause::Init);
} }
// Consider the possibility that the `StartCause::Init` iteration could // Consider the possibility that the `StartCause::Init` iteration could
// request to Exit. // request to Exit.
if !self.exiting() { if !self.exiting() {
self.poll_events_with_timeout(timeout, app); self.poll_events_with_timeout(timeout, &mut app);
} }
if let Some(code) = self.exit_code() { if let Some(code) = self.exit_code() {
self.loop_running = false; self.loop_running = false;
@ -435,7 +435,7 @@ impl EventLoop {
|| self.redraw_receiver.has_incoming() || self.redraw_receiver.has_incoming()
} }
pub fn poll_events_with_timeout<A: ApplicationHandler>( fn poll_events_with_timeout<A: ApplicationHandler>(
&mut self, &mut self,
mut timeout: Option<Duration>, mut timeout: Option<Duration>,
app: &mut A, app: &mut A,

View file

@ -500,7 +500,7 @@ impl EventLoop {
} }
} }
pub fn run_app<A: ApplicationHandler>(mut self, app: &mut A) -> Result<(), EventLoopError> { pub fn run_app<A: ApplicationHandler>(mut self, mut app: A) -> Result<(), EventLoopError> {
let mut start_cause = StartCause::Init; let mut start_cause = StartCause::Init;
loop { loop {
app.new_events(&self.window_target, start_cause); app.new_events(&self.window_target, start_cause);
@ -567,7 +567,7 @@ impl EventLoop {
orbital_event.to_option(), orbital_event.to_option(),
event_state, event_state,
&self.window_target, &self.window_target,
app, &mut app,
); );
} }

View file

@ -28,11 +28,12 @@ impl EventLoop {
Ok(EventLoop { elw }) Ok(EventLoop { elw })
} }
pub fn run_app<A: ApplicationHandler>(self, app: &mut A) -> ! { pub fn run_app<A: ApplicationHandler>(self, mut app: A) -> ! {
let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData }; let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData };
// SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`. // SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`.
let handler: Box<dyn FnMut(Event)> = Box::new(|event| handle_event(app, &target, event)); let handler: Box<dyn FnMut(Event)> =
Box::new(|event| handle_event(&mut app, &target, event));
// SAFETY: The `transmute` is necessary because `run()` requires `'static`. This is safe // SAFETY: The `transmute` is necessary because `run()` requires `'static`. This is safe
// because this function will never return and all resources not cleaned up by the point we // because this function will never return and all resources not cleaned up by the point we

View file

@ -187,13 +187,13 @@ impl EventLoop {
&self.window_target &self.window_target
} }
pub fn run_app<A: ApplicationHandler>(mut self, app: &mut A) -> Result<(), EventLoopError> { pub fn run_app<A: ApplicationHandler>(mut self, app: A) -> Result<(), EventLoopError> {
self.run_app_on_demand(app) self.run_app_on_demand(app)
} }
pub fn run_app_on_demand<A: ApplicationHandler>( pub fn run_app_on_demand<A: ApplicationHandler>(
&mut self, &mut self,
app: &mut A, mut app: A,
) -> Result<(), EventLoopError> { ) -> Result<(), EventLoopError> {
{ {
let runner = &self.window_target.p.runner_shared; let runner = &self.window_target.p.runner_shared;
@ -254,7 +254,7 @@ impl EventLoop {
pub fn pump_app_events<A: ApplicationHandler>( pub fn pump_app_events<A: ApplicationHandler>(
&mut self, &mut self,
timeout: Option<Duration>, timeout: Option<Duration>,
app: &mut A, mut app: A,
) -> PumpStatus { ) -> PumpStatus {
{ {
let runner = &self.window_target.p.runner_shared; let runner = &self.window_target.p.runner_shared;