From 4922364c461e101deb206adae10848dba6879df8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 16 Jun 2020 16:26:52 +0200 Subject: [PATCH] Cleanup: move the event loop code into a separate module --- sixtyfps_runtime/corelib/eventloop.rs | 94 ++++++++++++++++++++ sixtyfps_runtime/corelib/lib.rs | 119 ++++---------------------- 2 files changed, 111 insertions(+), 102 deletions(-) create mode 100644 sixtyfps_runtime/corelib/eventloop.rs diff --git a/sixtyfps_runtime/corelib/eventloop.rs b/sixtyfps_runtime/corelib/eventloop.rs new file mode 100644 index 000000000..1969590b6 --- /dev/null +++ b/sixtyfps_runtime/corelib/eventloop.rs @@ -0,0 +1,94 @@ +use std::cell::RefCell; +use std::rc::{Rc, Weak}; + +#[cfg(not(target_arch = "wasm32"))] +use winit::platform::desktop::EventLoopExtDesktop; + +pub trait GenericWindow { + fn draw(&self, component: vtable::VRef); + fn process_mouse_input( + &self, + pos: winit::dpi::PhysicalPosition, + state: winit::event::ElementState, + component: vtable::VRef, + ); + fn window_handle(&self) -> std::cell::Ref<'_, winit::window::Window>; + fn map_window(self: Rc, event_loop: &winit::event_loop::EventLoop<()>); +} + +thread_local! { + pub(crate) static ALL_WINDOWS: RefCell>> = RefCell::new(std::collections::HashMap::new()); +} + +#[allow(unused_mut)] // mut need changes for wasm +pub fn run( + mut event_loop: winit::event_loop::EventLoop<()>, + component: vtable::VRef, +) { + use winit::event::Event; + use winit::event_loop::{ControlFlow, EventLoopWindowTarget}; + + let mut cursor_pos = winit::dpi::PhysicalPosition::new(0., 0.); + let mut run_fn = + move |event: Event<()>, _: &EventLoopWindowTarget<()>, control_flow: &mut ControlFlow| { + *control_flow = ControlFlow::Wait; + + match event { + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::CloseRequested, + .. + } => *control_flow = winit::event_loop::ControlFlow::Exit, + winit::event::Event::RedrawRequested(id) => { + ALL_WINDOWS.with(|windows| { + if let Some(Some(window)) = + windows.borrow().get(&id).map(|weakref| weakref.upgrade()) + { + window.draw(component); + } + }); + } + winit::event::Event::WindowEvent { + event: winit::event::WindowEvent::CursorMoved { position, .. }, + .. + } => { + cursor_pos = position; + // TODO: propagate mouse move? + } + + winit::event::Event::WindowEvent { + ref window_id, + event: winit::event::WindowEvent::MouseInput { state, .. }, + .. + } => { + ALL_WINDOWS.with(|windows| { + if let Some(Some(window)) = + windows.borrow().get(&window_id).map(|weakref| weakref.upgrade()) + { + window.process_mouse_input(cursor_pos, state, component); + let window = window.window_handle(); + // FIXME: remove this, it should be based on actual changes rather than this + window.request_redraw(); + } + }); + } + + _ => (), + } + }; + + #[cfg(not(target_arch = "wasm32"))] + event_loop.run_return(run_fn); + #[cfg(target_arch = "wasm32")] + { + // Since wasm does not have a run_return function that takes a non-static closure, + // we use this hack to work that around + scoped_tls_hkt::scoped_thread_local!(static mut RUN_FN_TLS: for <'a> &'a mut dyn FnMut( + Event<'_, ()>, + &EventLoopWindowTarget<()>, + &mut ControlFlow, + )); + RUN_FN_TLS.set(&mut run_fn, move || { + event_loop.run(|e, t, cf| RUN_FN_TLS.with(|mut run_fn| run_fn(e, t, cf))) + }); + } +} diff --git a/sixtyfps_runtime/corelib/lib.rs b/sixtyfps_runtime/corelib/lib.rs index da74d430c..c34c10ca7 100644 --- a/sixtyfps_runtime/corelib/lib.rs +++ b/sixtyfps_runtime/corelib/lib.rs @@ -45,32 +45,15 @@ pub use abi::properties::{EvaluationContext, Property}; #[doc(inline)] pub use abi::signals::Signal; +mod eventloop; mod item_rendering; use abi::datastructures::Color; -#[cfg(not(target_arch = "wasm32"))] -use winit::platform::desktop::EventLoopExtDesktop; use std::cell::RefCell; -use std::rc::{Rc, Weak}; +use std::rc::Rc; -trait GenericWindow { - fn draw(&self, component: vtable::VRef); - fn process_mouse_input( - &self, - pos: winit::dpi::PhysicalPosition, - state: winit::event::ElementState, - component: vtable::VRef, - ); - fn window_handle(&self) -> std::cell::Ref<'_, winit::window::Window>; - fn map_window(self: Rc, event_loop: &winit::event_loop::EventLoop<()>); -} - -thread_local! { - static ALL_WINDOWS: RefCell>> = RefCell::new(std::collections::HashMap::new()); -} - -pub struct MainWindow { +pub struct GraphicsWindow { graphics_backend_factory: Box< dyn Fn(&winit::event_loop::EventLoop<()>, winit::window::WindowBuilder) -> GraphicsBackend, >, @@ -78,7 +61,7 @@ pub struct MainWindow { rendering_cache: graphics::RenderingCache, } -impl MainWindow { +impl GraphicsWindow { pub fn new( graphics_backend_factory: impl Fn(&winit::event_loop::EventLoop<()>, winit::window::WindowBuilder) -> GraphicsBackend + 'static, @@ -97,18 +80,18 @@ impl MainWindow Drop for MainWindow { +impl Drop for GraphicsWindow { fn drop(&mut self) { if let Some(backend) = self.graphics_backend.as_ref() { - ALL_WINDOWS.with(|windows| { + eventloop::ALL_WINDOWS.with(|windows| { windows.borrow_mut().remove(&backend.window().id()); }); } } } -impl GenericWindow - for RefCell> +impl eventloop::GenericWindow + for RefCell> { fn draw(&self, component: vtable::VRef) { // FIXME: we should do that only if some property change @@ -200,93 +183,25 @@ impl GenericWindow window_id }; - ALL_WINDOWS.with(|windows| { - windows.borrow_mut().insert(id, Rc::downgrade(&(self.clone() as Rc))) + eventloop::ALL_WINDOWS.with(|windows| { + windows + .borrow_mut() + .insert(id, Rc::downgrade(&(self.clone() as Rc))) }); } } -#[allow(unused_mut)] // mut need changes for wasm -fn run_event_loop( - mut event_loop: winit::event_loop::EventLoop<()>, - component: vtable::VRef, -) { - use winit::event::Event; - use winit::event_loop::{ControlFlow, EventLoopWindowTarget}; - - let mut cursor_pos = winit::dpi::PhysicalPosition::new(0., 0.); - let mut run_fn = - move |event: Event<()>, _: &EventLoopWindowTarget<()>, control_flow: &mut ControlFlow| { - *control_flow = ControlFlow::Wait; - - match event { - winit::event::Event::WindowEvent { - event: winit::event::WindowEvent::CloseRequested, - .. - } => *control_flow = winit::event_loop::ControlFlow::Exit, - winit::event::Event::RedrawRequested(id) => { - ALL_WINDOWS.with(|windows| { - if let Some(Some(window)) = - windows.borrow().get(&id).map(|weakref| weakref.upgrade()) - { - window.draw(component); - } - }); - } - winit::event::Event::WindowEvent { - event: winit::event::WindowEvent::CursorMoved { position, .. }, - .. - } => { - cursor_pos = position; - // TODO: propagate mouse move? - } - - winit::event::Event::WindowEvent { - ref window_id, - event: winit::event::WindowEvent::MouseInput { state, .. }, - .. - } => { - ALL_WINDOWS.with(|windows| { - if let Some(Some(window)) = - windows.borrow().get(&window_id).map(|weakref| weakref.upgrade()) - { - window.process_mouse_input(cursor_pos, state, component); - let window = window.window_handle(); - // FIXME: remove this, it should be based on actual changes rather than this - window.request_redraw(); - } - }); - } - - _ => (), - } - }; - - #[cfg(not(target_arch = "wasm32"))] - event_loop.run_return(run_fn); - #[cfg(target_arch = "wasm32")] - { - // Since wasm does not have a run_return function that takes a non-static closure, - // we use this hack to work that around - scoped_tls_hkt::scoped_thread_local!(static mut RUN_FN_TLS: for <'a> &'a mut dyn FnMut( - Event<'_, ()>, - &EventLoopWindowTarget<()>, - &mut ControlFlow, - )); - RUN_FN_TLS.set(&mut run_fn, move || { - event_loop.run(|e, t, cf| RUN_FN_TLS.with(|mut run_fn| run_fn(e, t, cf))) - }); - } -} pub fn run_component( component: vtable::VRef, graphics_backend_factory: impl Fn(&winit::event_loop::EventLoop<()>, winit::window::WindowBuilder) -> GraphicsBackend + 'static, ) { - let main_window = MainWindow::new(graphics_backend_factory); + use eventloop::GenericWindow; + + let window = GraphicsWindow::new(graphics_backend_factory); let event_loop = winit::event_loop::EventLoop::new(); - main_window.clone().map_window(&event_loop); + window.clone().map_window(&event_loop); - run_event_loop(event_loop, component); + eventloop::run(event_loop, component); }