mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 13:31:29 +11:00
Implement requestAnimationFrame
for web (#1519)
* Use requestAnimationFrame for polling wasm * Implement `requestAnimationFrame` for stdweb Co-authored-by: Ryan G <ryanisaacg@users.noreply.github.com>
This commit is contained in:
parent
a8e777a5df
commit
1f24a09570
|
@ -1,6 +1,7 @@
|
|||
# Unreleased
|
||||
|
||||
- On X11, fix `ResumeTimeReached` being fired too early.
|
||||
- On Web, replaced zero timeout for `ControlFlow::Poll` with `requestAnimationFrame`
|
||||
- On Web, fix a possible panic during event handling
|
||||
|
||||
# 0.22.0 (2020-03-09)
|
||||
|
|
|
@ -72,7 +72,8 @@ impl<T> fmt::Debug for EventLoopWindowTarget<T> {
|
|||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ControlFlow {
|
||||
/// When the current loop iteration finishes, immediately begin a new iteration regardless of
|
||||
/// whether or not new events are available to process.
|
||||
/// whether or not new events are available to process. For web, events are sent when
|
||||
/// `requestAnimationFrame` fires.
|
||||
Poll,
|
||||
/// When the current loop iteration finishes, suspend the thread until another event arrives.
|
||||
Wait,
|
||||
|
|
|
@ -241,7 +241,7 @@ impl<T: 'static> Shared<T> {
|
|||
root::ControlFlow::Poll => {
|
||||
let cloned = self.clone();
|
||||
State::Poll {
|
||||
timeout: backend::Timeout::new(move || cloned.poll(), Duration::from_millis(0)),
|
||||
request: backend::AnimationFrameRequest::new(move || cloned.poll()),
|
||||
}
|
||||
}
|
||||
root::ControlFlow::Wait => State::Wait {
|
||||
|
|
|
@ -15,7 +15,7 @@ pub enum State {
|
|||
start: Instant,
|
||||
},
|
||||
Poll {
|
||||
timeout: backend::Timeout,
|
||||
request: backend::AnimationFrameRequest,
|
||||
},
|
||||
Exit,
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ mod event;
|
|||
mod timeout;
|
||||
|
||||
pub use self::canvas::Canvas;
|
||||
pub use self::timeout::Timeout;
|
||||
pub use self::timeout::{AnimationFrameRequest, Timeout};
|
||||
|
||||
use crate::dpi::{LogicalSize, Size};
|
||||
use crate::platform::web::WindowExtStdweb;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
use stdweb::web::{window, IWindowOrWorker, TimeoutHandle};
|
||||
use stdweb::web::{window, IWindowOrWorker, RequestAnimationFrameHandle, TimeoutHandle};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Timeout {
|
||||
|
@ -23,3 +25,39 @@ impl Drop for Timeout {
|
|||
handle.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnimationFrameRequest {
|
||||
handle: Option<RequestAnimationFrameHandle>,
|
||||
// track callback state, because `cancelAnimationFrame` is slow
|
||||
fired: Rc<Cell<bool>>,
|
||||
}
|
||||
|
||||
impl AnimationFrameRequest {
|
||||
pub fn new<F>(mut f: F) -> AnimationFrameRequest
|
||||
where
|
||||
F: 'static + FnMut(),
|
||||
{
|
||||
let fired = Rc::new(Cell::new(false));
|
||||
let c_fired = fired.clone();
|
||||
let handle = window().request_animation_frame(move |_| {
|
||||
(*c_fired).set(true);
|
||||
f();
|
||||
});
|
||||
|
||||
AnimationFrameRequest {
|
||||
handle: Some(handle),
|
||||
fired,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AnimationFrameRequest {
|
||||
fn drop(&mut self) {
|
||||
if !(*self.fired).get() {
|
||||
if let Some(handle) = self.handle.take() {
|
||||
handle.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ mod event;
|
|||
mod timeout;
|
||||
|
||||
pub use self::canvas::Canvas;
|
||||
pub use self::timeout::Timeout;
|
||||
pub use self::timeout::{AnimationFrameRequest, Timeout};
|
||||
|
||||
use crate::dpi::{LogicalSize, Size};
|
||||
use crate::platform::web::WindowExtWebSys;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
use wasm_bindgen::closure::Closure;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
@ -38,3 +40,48 @@ impl Drop for Timeout {
|
|||
window.clear_timeout_with_handle(self.handle);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnimationFrameRequest {
|
||||
handle: i32,
|
||||
// track callback state, because `cancelAnimationFrame` is slow
|
||||
fired: Rc<Cell<bool>>,
|
||||
_closure: Closure<dyn FnMut()>,
|
||||
}
|
||||
|
||||
impl AnimationFrameRequest {
|
||||
pub fn new<F>(mut f: F) -> AnimationFrameRequest
|
||||
where
|
||||
F: 'static + FnMut(),
|
||||
{
|
||||
let window = web_sys::window().expect("Failed to obtain window");
|
||||
|
||||
let fired = Rc::new(Cell::new(false));
|
||||
let c_fired = fired.clone();
|
||||
let closure = Closure::wrap(Box::new(move || {
|
||||
(*c_fired).set(true);
|
||||
f();
|
||||
}) as Box<dyn FnMut()>);
|
||||
|
||||
let handle = window
|
||||
.request_animation_frame(&closure.as_ref().unchecked_ref())
|
||||
.expect("Failed to request animation frame");
|
||||
|
||||
AnimationFrameRequest {
|
||||
handle,
|
||||
fired,
|
||||
_closure: closure,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AnimationFrameRequest {
|
||||
fn drop(&mut self) {
|
||||
if !(*self.fired).get() {
|
||||
let window = web_sys::window().expect("Failed to obtain window");
|
||||
window
|
||||
.cancel_animation_frame(self.handle)
|
||||
.expect("Failed to cancel animation frame");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue