diff --git a/src/event_loop.rs b/src/event_loop.rs deleted file mode 100644 index 73f756a..0000000 --- a/src/event_loop.rs +++ /dev/null @@ -1 +0,0 @@ -pub struct App {} diff --git a/src/lib.rs b/src/lib.rs index 26cb17f..926d7e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ mod window; use std::collections::HashMap; use std::ops::Deref; use std::process::exit; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{mpsc, Arc, Mutex, PoisonError}; use std::time::Duration; @@ -18,6 +19,7 @@ pub use window::{Run, RunningWindow, Window, WindowAttributes, WindowBehavior, W pub use winit; use winit::application::ApplicationHandler; use winit::error::{EventLoopError, OsError}; +use winit::event::StartCause; use winit::event_loop::{ ActiveEventLoop, ControlFlow, EventLoop, EventLoopProxy, OwnedDisplayHandle, }; @@ -136,6 +138,7 @@ where event_loop: EventLoop>, message_callback: BoxedEventCallback, running: App, + on_startup: Vec>>, pending_windows: Vec>, } @@ -186,8 +189,10 @@ where running: App { proxy, windows: Windows::default(), + started: Arc::new(AtomicBool::new(false)), }, message_callback: Box::new(event_callback), + on_startup: Vec::new(), pending_windows: Vec::new(), } } @@ -198,11 +203,11 @@ where /// available after the event loop has started. For example, to enter an /// exclusive full screen mode, monitor information must be accessed which /// requires the event loop to have been started. - pub fn on_startup(&self, on_startup: F) + pub fn on_startup(&mut self, on_startup: F) where F: FnOnce(ExecutingApp<'_, AppMessage>) + Send + 'static, { - self.running.push_on_startup(Box::new(on_startup)); + self.on_startup.push(Box::new(on_startup)); } /// Begins running the application. @@ -218,11 +223,13 @@ where event_loop, message_callback, running, + on_startup, pending_windows, } = self; event_loop.run_app(&mut RunningApp:: { message_callback, running, + on_startup, pending_windows, }) } @@ -234,6 +241,7 @@ where { message_callback: BoxedEventCallback, running: App, + on_startup: Vec>>, pending_windows: Vec>, } @@ -241,8 +249,11 @@ impl ApplicationHandler> for RunningApp where AppMessage: Message, { - fn resumed(&mut self, event_loop: &ActiveEventLoop) { - event_loop.set_control_flow(ControlFlow::Wait); + fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { + let StartCause::Init = cause else { + return; + }; + self.running.started.store(true, Ordering::Relaxed); for PendingWindow { window, sender, @@ -257,6 +268,13 @@ where .expect("error spawning initial window"); spawner(window); } + for on_startup in self.on_startup.drain(..) { + on_startup(ExecutingApp::new(&self.running.windows, event_loop)); + } + } + + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + event_loop.set_control_flow(ControlFlow::Wait); } fn window_event( @@ -276,9 +294,6 @@ where fn user_event(&mut self, event_loop: &ActiveEventLoop, message: EventLoopMessage) { match message { - EventLoopMessage::Execute(closure) => { - closure(ExecutingApp::new(&self.running.windows, event_loop)); - } EventLoopMessage::CloseWindow(window_id) => { if self.running.windows.close(window_id) { exit(0) @@ -323,6 +338,7 @@ where { proxy: EventLoopProxy>, windows: Windows, + started: Arc, } impl App @@ -336,6 +352,10 @@ where /// running. Otherwise, this function will block until the result of the /// callback has been received. pub fn send(&self, message: AppMessage) -> Option { + if !self.started.load(Ordering::Relaxed) { + return None; + } + let (response_sender, response_receiver) = mpsc::sync_channel(1); self.proxy .send_event(EventLoopMessage::User { @@ -345,10 +365,6 @@ where .ok()?; response_receiver.recv().ok() } - - fn push_on_startup(&self, on_startup: Box>) { - let _ = self.proxy.send_event(EventLoopMessage::Execute(on_startup)); - } } impl Clone for App @@ -359,6 +375,7 @@ where Self { proxy: self.proxy.clone(), windows: self.windows.clone(), + started: self.started.clone(), } } } diff --git a/src/private.rs b/src/private.rs index 1402d4c..7018d23 100644 --- a/src/private.rs +++ b/src/private.rs @@ -12,7 +12,7 @@ use winit::event_loop::AsyncRequestSerial; use winit::window::{ActivationToken, Theme, WindowId}; use crate::window::WindowAttributes; -use crate::{Message, StartupClosure}; +use crate::Message; pub type WindowSpawner = Box; @@ -48,7 +48,6 @@ pub enum EventLoopMessage where AppMessage: Message, { - Execute(Box>), OpenWindow { attrs: WindowAttributes, sender: Arc>>,