Implement request_redraw

This commit is contained in:
Ryan Goldstein 2019-03-16 18:40:35 -04:00
parent d1deba8620
commit a5166baba2
3 changed files with 37 additions and 23 deletions

View file

@ -32,19 +32,19 @@ impl DeviceId {
pub struct EventLoop<T: 'static> { pub struct EventLoop<T: 'static> {
elw: RootELW<T>, elw: RootELW<T>,
runner: EventLoopRunnerShared<T>
} }
pub struct EventLoopWindowTarget<T: 'static> { pub struct EventLoopWindowTarget<T: 'static> {
pub(crate) canvases: RefCell<Vec<CanvasElement>>, pub(crate) runner: EventLoopRunnerShared<T>,
_marker: PhantomData<T>
} }
impl<T> EventLoopWindowTarget<T> { impl<T> EventLoopWindowTarget<T> {
fn new() -> Self { fn new() -> Self {
EventLoopWindowTarget { EventLoopWindowTarget {
canvases: RefCell::new(Vec::new()), runner: Rc::new(ELRShared {
_marker: PhantomData runner: RefCell::new(None),
events: RefCell::new(VecDeque::new())
})
} }
} }
} }
@ -61,9 +61,9 @@ impl<T> EventLoopProxy<T> {
} }
} }
type EventLoopRunnerShared<T> = Rc<ELRShared<T>>; pub type EventLoopRunnerShared<T> = Rc<ELRShared<T>>;
struct ELRShared<T> { pub struct ELRShared<T> {
runner: RefCell<Option<EventLoopRunner<T>>>, runner: RefCell<Option<EventLoopRunner<T>>>,
events: RefCell<VecDeque<Event<T>>>, // TODO: this may not be necessary? events: RefCell<VecDeque<Event<T>>>, // TODO: this may not be necessary?
} }
@ -80,7 +80,6 @@ impl<T> EventLoop<T> {
p: EventLoopWindowTarget::new(), p: EventLoopWindowTarget::new(),
_marker: PhantomData _marker: PhantomData
}, },
runner: Rc::new(ELRShared::blank()),
} }
} }
@ -95,14 +94,11 @@ impl<T> EventLoop<T> {
pub fn run<F>(mut self, mut event_handler: F) -> ! pub fn run<F>(mut self, mut event_handler: F) -> !
where F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow) where F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow)
{ {
// TODO: Create event handlers for the JS events
// TODO: how to handle request redraw? // TODO: how to handle request redraw?
// TODO: onclose (stdweb PR) // TODO: onclose (stdweb PR)
// TODO: file dropping, PathBuf isn't useful for web // TODO: file dropping, PathBuf isn't useful for web
let EventLoop { elw, runner } = self; let runner = self.elw.p.runner;
for canvas in elw.p.canvases.borrow().iter() {
register(&runner, canvas);
}
let relw = RootELW { let relw = RootELW {
p: EventLoopWindowTarget::new(), p: EventLoopWindowTarget::new(),
_marker: PhantomData _marker: PhantomData
@ -156,6 +152,9 @@ impl<T> EventLoop<T> {
}); });
}); });
stdweb::event_loop(); // TODO: this is only necessary for stdweb emscripten, should it be here? 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! { js! {
throw "Using exceptions for control flow, don't mind me"; throw "Using exceptions for control flow, don't mind me";
} }
@ -164,7 +163,7 @@ impl<T> EventLoop<T> {
pub fn create_proxy(&self) -> EventLoopProxy<T> { pub fn create_proxy(&self) -> EventLoopProxy<T> {
EventLoopProxy { EventLoopProxy {
runner: self.runner.clone() runner: self.elw.p.runner.clone()
} }
} }
@ -173,7 +172,7 @@ impl<T> EventLoop<T> {
} }
} }
fn register<T: 'static>(elrs: &EventLoopRunnerShared<T>, canvas: &CanvasElement) { pub fn register<T: 'static>(elrs: &EventLoopRunnerShared<T>, canvas: &CanvasElement) {
add_event(elrs, canvas, |elrs, event: PointerOutEvent| { add_event(elrs, canvas, |elrs, event: PointerOutEvent| {
elrs.send_event(Event::WindowEvent { elrs.send_event(Event::WindowEvent {
window_id: RootWI(WindowId), window_id: RootWI(WindowId),
@ -229,7 +228,7 @@ fn register<T: 'static>(elrs: &EventLoopRunnerShared<T>, canvas: &CanvasElement)
fn add_event<T: 'static, E, F>(elrs: &EventLoopRunnerShared<T>, target: &impl IEventTarget, mut handler: F) fn add_event<T: 'static, E, F>(elrs: &EventLoopRunnerShared<T>, target: &impl IEventTarget, mut handler: F)
where E: ConcreteEvent, F: FnMut(&EventLoopRunnerShared<T>, E) + 'static { where E: ConcreteEvent, F: FnMut(&EventLoopRunnerShared<T>, E) + 'static {
let elrs = elrs.clone(); // TODO: necessary? let elrs = elrs.clone();
target.add_event_listener(move |event: E| { target.add_event_listener(move |event: E| {
event.prevent_default(); event.prevent_default();
@ -257,7 +256,7 @@ impl<T> ELRShared<T> {
// TODO: handle event loop closures // TODO: handle event loop closures
// TODO: handle event buffer // TODO: handle event buffer
fn send_event(&self, event: Event<T>) { pub fn send_event(&self, event: Event<T>) {
match *self.runner.borrow_mut() { match *self.runner.borrow_mut() {
Some(ref mut runner) => { Some(ref mut runner) => {
// TODO: bracket this in control flow events? // TODO: bracket this in control flow events?

View file

@ -2,7 +2,7 @@ mod event_loop;
mod events; mod events;
mod window; 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::window::{MonitorHandle, Window, WindowId, PlatformSpecificWindowBuilderAttributes};
pub use self::events::{button_mapping, mouse_modifiers_state, mouse_button, keyboard_modifiers_state, scancode}; pub use self::events::{button_mapping, mouse_modifiers_state, mouse_button, keyboard_modifiers_state, scancode};

View file

@ -1,8 +1,9 @@
use dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}; use dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize};
use event::{Event, WindowEvent};
use icon::Icon; use icon::Icon;
use monitor::{MonitorHandle as RootMH}; use monitor::{MonitorHandle as RootMH};
use window::{CreationError, MouseCursor, WindowAttributes}; use window::{CreationError, MouseCursor, WindowAttributes, WindowId as RootWI};
use super::EventLoopWindowTarget; use super::{EventLoopWindowTarget, EventLoopRunnerShared, register};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::collections::vec_deque::IntoIter as VecDequeIter; use std::collections::vec_deque::IntoIter as VecDequeIter;
use stdweb::{ use stdweb::{
@ -50,6 +51,7 @@ impl WindowId {
pub struct Window { pub struct Window {
pub(crate) canvas: CanvasElement, pub(crate) canvas: CanvasElement,
pub(crate) redraw: Box<dyn Fn()>
} }
impl Window { impl Window {
@ -63,8 +65,20 @@ impl Window {
document().body() document().body()
.ok_or_else(|| CreationError::OsError("Failed to find body node".to_owned()))? .ok_or_else(|| CreationError::OsError("Failed to find body node".to_owned()))?
.append_child(&canvas); .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 { if let Some(dimensions) = attr.dimensions {
window.set_inner_size(dimensions); window.set_inner_size(dimensions);
} else { } else {
@ -88,6 +102,7 @@ impl Window {
window.set_decorations(attr.decorations); window.set_decorations(attr.decorations);
window.set_always_on_top(attr.always_on_top); window.set_always_on_top(attr.always_on_top);
window.set_window_icon(attr.window_icon); window.set_window_icon(attr.window_icon);
Ok(window) Ok(window)
} }
@ -104,7 +119,7 @@ impl Window {
} }
pub fn request_redraw(&self) { 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<LogicalPosition> { pub fn get_position(&self) -> Option<LogicalPosition> {