A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/winit_app.rs')
-rw-r--r--src/winit_app.rs237
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);
+ }
}