From a5166baba21c67a0898db6b7c538f3a0405c324b Mon Sep 17 00:00:00 2001 From: Ryan Goldstein Date: Sat, 16 Mar 2019 18:40:35 -0400 Subject: [PATCH] Implement request_redraw --- src/platform_impl/stdweb/event_loop.rs | 33 +++++++++++++------------- src/platform_impl/stdweb/mod.rs | 2 +- src/platform_impl/stdweb/window.rs | 25 +++++++++++++++---- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/platform_impl/stdweb/event_loop.rs b/src/platform_impl/stdweb/event_loop.rs index 06b8c32b..478aa572 100644 --- a/src/platform_impl/stdweb/event_loop.rs +++ b/src/platform_impl/stdweb/event_loop.rs @@ -32,19 +32,19 @@ impl DeviceId { pub struct EventLoop { elw: RootELW, - runner: EventLoopRunnerShared } pub struct EventLoopWindowTarget { - pub(crate) canvases: RefCell>, - _marker: PhantomData + pub(crate) runner: EventLoopRunnerShared, } impl EventLoopWindowTarget { fn new() -> Self { EventLoopWindowTarget { - canvases: RefCell::new(Vec::new()), - _marker: PhantomData + runner: Rc::new(ELRShared { + runner: RefCell::new(None), + events: RefCell::new(VecDeque::new()) + }) } } } @@ -61,9 +61,9 @@ impl EventLoopProxy { } } -type EventLoopRunnerShared = Rc>; +pub type EventLoopRunnerShared = Rc>; -struct ELRShared { +pub struct ELRShared { runner: RefCell>>, events: RefCell>>, // TODO: this may not be necessary? } @@ -80,7 +80,6 @@ impl EventLoop { p: EventLoopWindowTarget::new(), _marker: PhantomData }, - runner: Rc::new(ELRShared::blank()), } } @@ -95,14 +94,11 @@ impl EventLoop { pub fn run(mut self, mut event_handler: F) -> ! where F: 'static + FnMut(Event, &RootELW, &mut ControlFlow) { - // TODO: Create event handlers for the JS events // TODO: how to handle request redraw? // TODO: onclose (stdweb PR) // TODO: file dropping, PathBuf isn't useful for web - let EventLoop { elw, runner } = self; - for canvas in elw.p.canvases.borrow().iter() { - register(&runner, canvas); - } + let runner = self.elw.p.runner; + let relw = RootELW { p: EventLoopWindowTarget::new(), _marker: PhantomData @@ -156,6 +152,9 @@ impl EventLoop { }); }); stdweb::event_loop(); // TODO: this is only necessary for stdweb emscripten, should it be here? + + // Throw an exception to break out of Rust exceution and use unreachable to tell the + // compiler this function won't return, giving it a return type of '!' js! { throw "Using exceptions for control flow, don't mind me"; } @@ -164,7 +163,7 @@ impl EventLoop { pub fn create_proxy(&self) -> EventLoopProxy { EventLoopProxy { - runner: self.runner.clone() + runner: self.elw.p.runner.clone() } } @@ -173,7 +172,7 @@ impl EventLoop { } } -fn register(elrs: &EventLoopRunnerShared, canvas: &CanvasElement) { +pub fn register(elrs: &EventLoopRunnerShared, canvas: &CanvasElement) { add_event(elrs, canvas, |elrs, event: PointerOutEvent| { elrs.send_event(Event::WindowEvent { window_id: RootWI(WindowId), @@ -229,7 +228,7 @@ fn register(elrs: &EventLoopRunnerShared, canvas: &CanvasElement) fn add_event(elrs: &EventLoopRunnerShared, target: &impl IEventTarget, mut handler: F) where E: ConcreteEvent, F: FnMut(&EventLoopRunnerShared, E) + 'static { - let elrs = elrs.clone(); // TODO: necessary? + let elrs = elrs.clone(); target.add_event_listener(move |event: E| { event.prevent_default(); @@ -257,7 +256,7 @@ impl ELRShared { // TODO: handle event loop closures // TODO: handle event buffer - fn send_event(&self, event: Event) { + pub fn send_event(&self, event: Event) { match *self.runner.borrow_mut() { Some(ref mut runner) => { // TODO: bracket this in control flow events? diff --git a/src/platform_impl/stdweb/mod.rs b/src/platform_impl/stdweb/mod.rs index 9a2aab6b..82d8a189 100644 --- a/src/platform_impl/stdweb/mod.rs +++ b/src/platform_impl/stdweb/mod.rs @@ -2,7 +2,7 @@ mod event_loop; mod events; mod window; -pub use self::event_loop::{DeviceId, EventLoop, EventLoopWindowTarget, EventLoopProxy}; +pub use self::event_loop::{DeviceId, EventLoop, EventLoopRunnerShared, EventLoopWindowTarget, EventLoopProxy, register}; pub use self::window::{MonitorHandle, Window, WindowId, PlatformSpecificWindowBuilderAttributes}; pub use self::events::{button_mapping, mouse_modifiers_state, mouse_button, keyboard_modifiers_state, scancode}; diff --git a/src/platform_impl/stdweb/window.rs b/src/platform_impl/stdweb/window.rs index fd6d6f57..a66bc191 100644 --- a/src/platform_impl/stdweb/window.rs +++ b/src/platform_impl/stdweb/window.rs @@ -1,8 +1,9 @@ use dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}; +use event::{Event, WindowEvent}; use icon::Icon; use monitor::{MonitorHandle as RootMH}; -use window::{CreationError, MouseCursor, WindowAttributes}; -use super::EventLoopWindowTarget; +use window::{CreationError, MouseCursor, WindowAttributes, WindowId as RootWI}; +use super::{EventLoopWindowTarget, EventLoopRunnerShared, register}; use std::collections::VecDeque; use std::collections::vec_deque::IntoIter as VecDequeIter; use stdweb::{ @@ -50,6 +51,7 @@ impl WindowId { pub struct Window { pub(crate) canvas: CanvasElement, + pub(crate) redraw: Box } impl Window { @@ -63,8 +65,20 @@ impl Window { document().body() .ok_or_else(|| CreationError::OsError("Failed to find body node".to_owned()))? .append_child(&canvas); - target.canvases.borrow_mut().push(canvas.clone()); - let window = Window { canvas }; + + register(&target.runner, &canvas); + + let runner = target.runner.clone(); + let redraw = Box::new(move || runner.send_event(Event::WindowEvent { + window_id: RootWI(WindowId), + event: WindowEvent::RedrawRequested + })); + + let window = Window { + canvas, + redraw + }; + if let Some(dimensions) = attr.dimensions { window.set_inner_size(dimensions); } else { @@ -88,6 +102,7 @@ impl Window { window.set_decorations(attr.decorations); window.set_always_on_top(attr.always_on_top); window.set_window_icon(attr.window_icon); + Ok(window) } @@ -104,7 +119,7 @@ impl Window { } pub fn request_redraw(&self) { - // TODO: what does this mean? If it's a 'present'-style call then it's not necessary + (self.redraw)(); } pub fn get_position(&self) -> Option {