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 super::{backend, state::State};
use crate::event::{Event, StartCause}; use crate::event::{Event, StartCause, WindowEvent};
use crate::event_loop as root; use crate::event_loop as root;
use crate::window::WindowId;
use instant::{Duration, Instant}; 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>>); pub struct Shared<T>(Rc<Execution<T>>);
@ -17,6 +23,7 @@ pub struct Execution<T> {
runner: RefCell<Option<Runner<T>>>, runner: RefCell<Option<Runner<T>>>,
events: RefCell<VecDeque<Event<T>>>, events: RefCell<VecDeque<Event<T>>>,
id: RefCell<u32>, id: RefCell<u32>,
redraw_pending: RefCell<HashSet<WindowId>>,
} }
struct Runner<T> { struct Runner<T> {
@ -41,6 +48,7 @@ impl<T: 'static> Shared<T> {
runner: RefCell::new(None), runner: RefCell::new(None),
events: RefCell::new(VecDeque::new()), events: RefCell::new(VecDeque::new()),
id: RefCell::new(0), id: RefCell::new(0),
redraw_pending: RefCell::new(HashSet::new()),
})) }))
} }
@ -64,6 +72,10 @@ impl<T: 'static> Shared<T> {
*id *id
} }
pub fn request_redraw(&self, id: WindowId) {
self.0.redraw_pending.borrow_mut().insert(id);
}
// Add an event to the event loop runner // 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 // 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 { if !event_is_start {
self.handle_event(event, &mut control); 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.handle_event(Event::EventsCleared, &mut control);
self.apply_control_flow(control); self.apply_control_flow(control);
// If the event loop is closed, it has been closed this iteration and now the closing // 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::event::{ModifiersState, MouseButton, MouseScrollDelta, ScanCode, VirtualKeyCode};
use crate::platform_impl::OsError; use crate::platform_impl::OsError;
use std::rc::Rc;
use stdweb::traits::IPointerEvent; use stdweb::traits::IPointerEvent;
use stdweb::unstable::TryInto; use stdweb::unstable::TryInto;
use stdweb::web::event::{ use stdweb::web::event::{
@ -13,12 +12,11 @@ use stdweb::web::event::{
}; };
use stdweb::web::html_element::CanvasElement; use stdweb::web::html_element::CanvasElement;
use stdweb::web::{ use stdweb::web::{
document, window, EventListenerHandle, IChildNode, IElement, IEventTarget, IHtmlElement, document, EventListenerHandle, IChildNode, IElement, IEventTarget, IHtmlElement,
}; };
pub struct Canvas { pub struct Canvas {
raw: CanvasElement, raw: CanvasElement,
on_redraw: Rc<dyn Fn()>,
on_focus: Option<EventListenerHandle>, on_focus: Option<EventListenerHandle>,
on_blur: Option<EventListenerHandle>, on_blur: Option<EventListenerHandle>,
on_keyboard_release: Option<EventListenerHandle>, on_keyboard_release: Option<EventListenerHandle>,
@ -39,10 +37,7 @@ impl Drop for Canvas {
} }
impl Canvas { impl Canvas {
pub fn create<F>(on_redraw: F) -> Result<Self, RootOE> pub fn create() -> Result<Self, RootOE> {
where
F: 'static + Fn(),
{
let canvas: CanvasElement = document() let canvas: CanvasElement = document()
.create_element("canvas") .create_element("canvas")
.map_err(|_| os_error!(OsError("Failed to create canvas element".to_owned())))? .map_err(|_| os_error!(OsError("Failed to create canvas element".to_owned())))?
@ -60,7 +55,6 @@ impl Canvas {
Ok(Canvas { Ok(Canvas {
raw: canvas, raw: canvas,
on_redraw: Rc::new(on_redraw),
on_blur: None, on_blur: None,
on_focus: None, on_focus: None,
on_keyboard_release: None, on_keyboard_release: None,
@ -104,11 +98,6 @@ impl Canvas {
&self.raw &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) pub fn on_blur<F>(&mut self, mut handler: F)
where where
F: 'static + FnMut(), F: 'static + FnMut(),

View file

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

View file

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