Fix web redraw requested (#1181)

* Keep track of what windows have requested redraw

Instead of using request_animation_frame and sending redraw request
events, just keep track of all windows that have asked for a redraw.
This doesn't handle dispatching the events

* Issue redraw events to windows that request it

* Cargo fmt
This commit is contained in:
Ryan G 2019-09-23 09:14:26 -04:00 committed by GitHub
parent 2c47c43f47
commit 28a50817af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 36 deletions

View file

@ -1,9 +1,15 @@
use super::{backend, state::State};
use crate::event::{Event, StartCause};
use crate::event::{Event, StartCause, WindowEvent};
use crate::event_loop as root;
use crate::window::WindowId;
use instant::{Duration, Instant};
use std::{cell::RefCell, clone::Clone, collections::VecDeque, rc::Rc};
use std::{
cell::RefCell,
clone::Clone,
collections::{HashSet, VecDeque},
rc::Rc,
};
pub struct Shared<T>(Rc<Execution<T>>);
@ -17,6 +23,7 @@ pub struct Execution<T> {
runner: RefCell<Option<Runner<T>>>,
events: RefCell<VecDeque<Event<T>>>,
id: RefCell<u32>,
redraw_pending: RefCell<HashSet<WindowId>>,
}
struct Runner<T> {
@ -41,6 +48,7 @@ impl<T: 'static> Shared<T> {
runner: RefCell::new(None),
events: RefCell::new(VecDeque::new()),
id: RefCell::new(0),
redraw_pending: RefCell::new(HashSet::new()),
}))
}
@ -64,6 +72,10 @@ impl<T: 'static> Shared<T> {
*id
}
pub fn request_redraw(&self, id: WindowId) {
self.0.redraw_pending.borrow_mut().insert(id);
}
// Add an event to the event loop runner
//
// It will determine if the event should be immediately sent to the user or buffered for later
@ -115,6 +127,17 @@ impl<T: 'static> Shared<T> {
if !event_is_start {
self.handle_event(event, &mut control);
}
// Collect all of the redraw events to avoid double-locking the RefCell
let redraw_events: Vec<WindowId> = self.0.redraw_pending.borrow_mut().drain().collect();
for window_id in redraw_events {
self.handle_event(
Event::WindowEvent {
window_id,
event: WindowEvent::RedrawRequested,
},
&mut control,
);
}
self.handle_event(Event::EventsCleared, &mut control);
self.apply_control_flow(control);
// If the event loop is closed, it has been closed this iteration and now the closing

View file

@ -4,7 +4,6 @@ use crate::error::OsError as RootOE;
use crate::event::{ModifiersState, MouseButton, MouseScrollDelta, ScanCode, VirtualKeyCode};
use crate::platform_impl::OsError;
use std::rc::Rc;
use stdweb::traits::IPointerEvent;
use stdweb::unstable::TryInto;
use stdweb::web::event::{
@ -13,12 +12,11 @@ use stdweb::web::event::{
};
use stdweb::web::html_element::CanvasElement;
use stdweb::web::{
document, window, EventListenerHandle, IChildNode, IElement, IEventTarget, IHtmlElement,
document, EventListenerHandle, IChildNode, IElement, IEventTarget, IHtmlElement,
};
pub struct Canvas {
raw: CanvasElement,
on_redraw: Rc<dyn Fn()>,
on_focus: Option<EventListenerHandle>,
on_blur: Option<EventListenerHandle>,
on_keyboard_release: Option<EventListenerHandle>,
@ -39,10 +37,7 @@ impl Drop for Canvas {
}
impl Canvas {
pub fn create<F>(on_redraw: F) -> Result<Self, RootOE>
where
F: 'static + Fn(),
{
pub fn create() -> Result<Self, RootOE> {
let canvas: CanvasElement = document()
.create_element("canvas")
.map_err(|_| os_error!(OsError("Failed to create canvas element".to_owned())))?
@ -60,7 +55,6 @@ impl Canvas {
Ok(Canvas {
raw: canvas,
on_redraw: Rc::new(on_redraw),
on_blur: None,
on_focus: None,
on_keyboard_release: None,
@ -104,11 +98,6 @@ impl Canvas {
&self.raw
}
pub fn request_redraw(&self) {
let on_redraw = self.on_redraw.clone();
window().request_animation_frame(move |_| on_redraw());
}
pub fn on_blur<F>(&mut self, mut handler: F)
where
F: 'static + FnMut(),

View file

@ -9,7 +9,6 @@ use web_sys::{FocusEvent, HtmlCanvasElement, KeyboardEvent, PointerEvent, WheelE
pub struct Canvas {
raw: HtmlCanvasElement,
on_redraw: Closure<dyn Fn()>,
on_focus: Option<Closure<dyn FnMut(FocusEvent)>>,
on_blur: Option<Closure<dyn FnMut(FocusEvent)>>,
on_keyboard_release: Option<Closure<dyn FnMut(KeyboardEvent)>>,
@ -30,10 +29,7 @@ impl Drop for Canvas {
}
impl Canvas {
pub fn create<F>(on_redraw: F) -> Result<Self, RootOE>
where
F: 'static + Fn(),
{
pub fn create() -> Result<Self, RootOE> {
let window =
web_sys::window().ok_or(os_error!(OsError("Failed to obtain window".to_owned())))?;
@ -57,7 +53,6 @@ impl Canvas {
Ok(Canvas {
raw: canvas,
on_redraw: Closure::wrap(Box::new(on_redraw) as Box<dyn Fn()>),
on_blur: None,
on_focus: None,
on_keyboard_release: None,
@ -101,13 +96,6 @@ impl Canvas {
&self.raw
}
pub fn request_redraw(&self) {
let window = web_sys::window().expect("Failed to obtain window");
window
.request_animation_frame(&self.on_redraw.as_ref().unchecked_ref())
.expect("Failed to request animation frame");
}
pub fn on_blur<F>(&mut self, mut handler: F)
where
F: 'static + FnMut(),

View file

@ -1,6 +1,5 @@
use crate::dpi::{LogicalPosition, LogicalSize};
use crate::error::{ExternalError, NotSupportedError, OsError as RootOE};
use crate::event::{Event, WindowEvent};
use crate::icon::Icon;
use crate::monitor::MonitorHandle as RootMH;
use crate::window::{CursorIcon, WindowAttributes, WindowId as RootWI};
@ -16,6 +15,7 @@ pub struct Window {
previous_pointer: RefCell<&'static str>,
position: RefCell<LogicalPosition>,
id: Id,
register_redraw_request: Box<dyn Fn()>,
}
impl Window {
@ -28,12 +28,9 @@ impl Window {
let id = target.generate_id();
let mut canvas = backend::Canvas::create(move || {
runner.send_event(Event::WindowEvent {
window_id: RootWI(id),
event: WindowEvent::RedrawRequested,
})
})?;
let mut canvas = backend::Canvas::create()?;
let register_redraw_request = Box::new(move || runner.request_redraw(RootWI(id)));
target.register(&mut canvas, id);
@ -42,6 +39,7 @@ impl Window {
previous_pointer: RefCell::new("auto"),
position: RefCell::new(LogicalPosition { x: 0.0, y: 0.0 }),
id,
register_redraw_request,
};
window.set_inner_size(attr.inner_size.unwrap_or(LogicalSize {
@ -69,7 +67,7 @@ impl Window {
}
pub fn request_redraw(&self) {
self.canvas.request_redraw();
(self.register_redraw_request)();
}
pub fn outer_position(&self) -> Result<LogicalPosition, NotSupportedError> {