A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/winit_app.rs')
| -rw-r--r-- | src/winit_app.rs | 237 |
1 files changed, 189 insertions, 48 deletions
diff --git a/src/winit_app.rs b/src/winit_app.rs index 18f7258..adba393 100644 --- a/src/winit_app.rs +++ b/src/winit_app.rs @@ -1,57 +1,72 @@ /// Common boilerplate for setting up a winit application. use std::marker::PhantomData; -use std::sync::Arc; +use std::sync::Arc as Rc; use winit::application::ApplicationHandler; -use winit::event::{Event, WindowEvent}; +use winit::event::{DeviceEvent, DeviceId, WindowEvent}; use winit::event_loop::{ActiveEventLoop, EventLoop}; use winit::window::{Window, WindowAttributes, WindowId}; /// Run a Winit application. #[allow(unused_mut)] pub(crate) fn run_app( - event_loop: EventLoop<()>, - mut app: impl ApplicationHandler<()> + 'static, + event_loop: EventLoop, + mut app: impl ApplicationHandler + 'static, ) { - #[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))] - event_loop.run_app(&mut app).unwrap(); + #[cfg(not(target_family = "wasm"))] + event_loop.run_app(app).unwrap(); - #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))] + #[cfg(target_family = "wasm")] winit::platform::web::EventLoopExtWebSys::spawn_app(event_loop, app); } /// Create a window from a set of window attributes. #[allow(dead_code)] pub(crate) fn make_window( - elwt: &ActiveEventLoop, + elwt: &dyn ActiveEventLoop, f: impl FnOnce(WindowAttributes) -> WindowAttributes, -) -> Arc<Window> { +) -> Rc<dyn Window> { let attributes = f(WindowAttributes::default()); - #[cfg(target_arch = "wasm32")] + #[cfg(target_family = "wasm")] let attributes = winit::platform::web::WindowAttributesExtWebSys::with_append( attributes, true, ); + let window = elwt.create_window(attributes); - Arc::new(window.unwrap()) + window.unwrap().into() } /// Easily constructable winit application. -pub(crate) struct WinitApp<T, S, Init, InitSurface, Handler> { +pub(crate) struct WinitApp< + T, + S, + Init, + InitSurface, + Handler, + DeviceEventHandler, + AboutToWaitHandler, +> { /// Closure to initialize `state`. - pub init: Init, + init: Init, /// Closure to initialize `surface_state`. - pub init_surface: InitSurface, + init_surface: InitSurface, /// Closure to run on window events. - pub event: Handler, + event: Handler, + + /// Closure to run on device events. + device_event: DeviceEventHandler, + + /// Closure to run on about_to_wait events. + about_to_wait: AboutToWaitHandler, /// Contained state. - pub state: Option<T>, + state: Option<T>, /// Contained surface state. - pub surface_state: Option<S>, + surface_state: Option<S>, } /// Builder that makes it so we don't have to name `T`. @@ -68,8 +83,8 @@ pub(crate) struct WinitAppBuilder<T, S, Init, InitSurface> { impl<T, S, Init, InitSurface> WinitAppBuilder<T, S, Init, InitSurface> where - Init: FnMut(&ActiveEventLoop) -> T, - InitSurface: FnMut(&ActiveEventLoop, &mut T) -> S, + Init: FnMut(&dyn ActiveEventLoop) -> T, + InitSurface: FnMut(&dyn ActiveEventLoop, &mut T) -> S, { /// Create with an "init" closure. pub(crate) fn with_init( @@ -80,55 +95,173 @@ where } /// Build a new application. + #[allow(clippy::type_complexity)] pub(crate) fn with_event_handler<F>( self, handler: F, - ) -> WinitApp<T, S, Init, InitSurface, F> + ) -> WinitApp< + T, + S, + Init, + InitSurface, + F, + impl FnMut(&mut T, Option<&mut S>, DeviceEvent, &dyn ActiveEventLoop), + impl FnMut(&mut T, Option<&mut S>, &dyn ActiveEventLoop), + > where - F: FnMut(&mut T, Option<&mut S>, Event<()>, &ActiveEventLoop), + F: FnMut( + &mut T, + Option<&mut S>, + WindowId, + WindowEvent, + &dyn ActiveEventLoop, + ), { - WinitApp::new(self.init, self.init_surface, handler) + WinitApp::new( + self.init, + self.init_surface, + handler, + |_, _, _, _| {}, + |_, _, _| {}, + ) } } -impl<T, S, Init, InitSurface, Handler> - WinitApp<T, S, Init, InitSurface, Handler> +impl< + T, + S, + Init, + InitSurface, + Handler, + DeviceEventHandler, + AboutToWaitHandler, +> + WinitApp< + T, + S, + Init, + InitSurface, + Handler, + DeviceEventHandler, + AboutToWaitHandler, + > where - Init: FnMut(&ActiveEventLoop) -> T, - InitSurface: FnMut(&ActiveEventLoop, &mut T) -> S, - Handler: FnMut(&mut T, Option<&mut S>, Event<()>, &ActiveEventLoop), + Init: FnMut(&dyn ActiveEventLoop) -> T, + InitSurface: FnMut(&dyn ActiveEventLoop, &mut T) -> S, + Handler: FnMut( + &mut T, + Option<&mut S>, + WindowId, + WindowEvent, + &dyn ActiveEventLoop, + ), + DeviceEventHandler: + FnMut(&mut T, Option<&mut S>, DeviceEvent, &dyn ActiveEventLoop), + AboutToWaitHandler: + FnMut(&mut T, Option<&mut S>, &dyn ActiveEventLoop), { /// Create a new application. pub(crate) fn new( init: Init, init_surface: InitSurface, event: Handler, + device_event: DeviceEventHandler, + about_to_wait: AboutToWaitHandler, ) -> Self { Self { init, init_surface, event, + device_event, + about_to_wait, state: None, surface_state: None, } } + + /// Build a new application. + #[allow(dead_code)] + pub(crate) fn with_about_to_wait_handler<F>( + self, + about_to_wait: F, + ) -> WinitApp<T, S, Init, InitSurface, Handler, DeviceEventHandler, F> + where + F: FnMut(&mut T, Option<&mut S>, &dyn ActiveEventLoop), + { + WinitApp::new( + self.init, + self.init_surface, + self.event, + self.device_event, + about_to_wait, + ) + } + + /// Build a new application. + #[allow(dead_code)] + pub(crate) fn with_device_event_handler<F>( + self, + device_event: F, + ) -> WinitApp<T, S, Init, InitSurface, Handler, F, AboutToWaitHandler> + where + F: FnMut( + &mut T, + Option<&mut S>, + DeviceEvent, + &dyn ActiveEventLoop, + ), + { + WinitApp::new( + self.init, + self.init_surface, + self.event, + device_event, + self.about_to_wait, + ) + } } -impl<T, S, Init, InitSurface, Handler> ApplicationHandler - for WinitApp<T, S, Init, InitSurface, Handler> +impl< + T, + S, + Init, + InitSurface, + Handler, + DeviceEventHandler, + AboutToWaitHandler, +> ApplicationHandler + for WinitApp< + T, + S, + Init, + InitSurface, + Handler, + DeviceEventHandler, + AboutToWaitHandler, + > where - Init: FnMut(&ActiveEventLoop) -> T, - InitSurface: FnMut(&ActiveEventLoop, &mut T) -> S, - Handler: FnMut(&mut T, Option<&mut S>, Event<()>, &ActiveEventLoop), + Init: FnMut(&dyn ActiveEventLoop) -> T, + InitSurface: FnMut(&dyn ActiveEventLoop, &mut T) -> S, + Handler: FnMut( + &mut T, + Option<&mut S>, + WindowId, + WindowEvent, + &dyn ActiveEventLoop, + ), + DeviceEventHandler: + FnMut(&mut T, Option<&mut S>, DeviceEvent, &dyn ActiveEventLoop), + AboutToWaitHandler: + FnMut(&mut T, Option<&mut S>, &dyn ActiveEventLoop), { - fn resumed(&mut self, el: &ActiveEventLoop) { + fn resumed(&mut self, el: &dyn ActiveEventLoop) { debug_assert!(self.state.is_none()); let mut state = (self.init)(el); self.surface_state = Some((self.init_surface)(el, &mut state)); self.state = Some(state); } - fn suspended(&mut self, _event_loop: &ActiveEventLoop) { + fn suspended(&mut self, _event_loop: &dyn ActiveEventLoop) { let surface_state = self.surface_state.take(); debug_assert!(surface_state.is_some()); drop(surface_state); @@ -136,28 +269,36 @@ where fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { let state = self.state.as_mut().unwrap(); let surface_state = self.surface_state.as_mut(); - (self.event)( - state, - surface_state, - Event::WindowEvent { window_id, event }, - event_loop, - ); + (self.event)(state, surface_state, window_id, event, event_loop); } - fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) { if let Some(state) = self.state.as_mut() { - (self.event)( - state, - self.surface_state.as_mut(), - Event::AboutToWait, - event_loop, - ); + let surface_state = self.surface_state.as_mut(); + (self.about_to_wait)(state, surface_state, event_loop); } } + + fn device_event( + &mut self, + event_loop: &dyn ActiveEventLoop, + _device_id: Option<DeviceId>, + event: DeviceEvent, + ) { + let state = self.state.as_mut().unwrap(); + let surface_state = self.surface_state.as_mut(); + (self.device_event)(state, surface_state, event, event_loop); + } + + fn can_create_surfaces(&mut self, el: &dyn ActiveEventLoop) { + let mut state = (self.init)(el); + self.surface_state = Some((self.init_surface)(el, &mut state)); + self.state = Some(state); + } } |