mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 21: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
|
# Unreleased
|
||||||
|
|
||||||
- On X11, fix `ResumeTimeReached` being fired too early.
|
- 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
|
- On Web, fix a possible panic during event handling
|
||||||
|
|
||||||
# 0.22.0 (2020-03-09)
|
# 0.22.0 (2020-03-09)
|
||||||
|
|
|
@ -72,7 +72,8 @@ impl<T> fmt::Debug for EventLoopWindowTarget<T> {
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum ControlFlow {
|
pub enum ControlFlow {
|
||||||
/// When the current loop iteration finishes, immediately begin a new iteration regardless of
|
/// 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,
|
Poll,
|
||||||
/// When the current loop iteration finishes, suspend the thread until another event arrives.
|
/// When the current loop iteration finishes, suspend the thread until another event arrives.
|
||||||
Wait,
|
Wait,
|
||||||
|
|
|
@ -241,7 +241,7 @@ impl<T: 'static> Shared<T> {
|
||||||
root::ControlFlow::Poll => {
|
root::ControlFlow::Poll => {
|
||||||
let cloned = self.clone();
|
let cloned = self.clone();
|
||||||
State::Poll {
|
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 {
|
root::ControlFlow::Wait => State::Wait {
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub enum State {
|
||||||
start: Instant,
|
start: Instant,
|
||||||
},
|
},
|
||||||
Poll {
|
Poll {
|
||||||
timeout: backend::Timeout,
|
request: backend::AnimationFrameRequest,
|
||||||
},
|
},
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ mod event;
|
||||||
mod timeout;
|
mod timeout;
|
||||||
|
|
||||||
pub use self::canvas::Canvas;
|
pub use self::canvas::Canvas;
|
||||||
pub use self::timeout::Timeout;
|
pub use self::timeout::{AnimationFrameRequest, Timeout};
|
||||||
|
|
||||||
use crate::dpi::{LogicalSize, Size};
|
use crate::dpi::{LogicalSize, Size};
|
||||||
use crate::platform::web::WindowExtStdweb;
|
use crate::platform::web::WindowExtStdweb;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use stdweb::web::{window, IWindowOrWorker, TimeoutHandle};
|
use stdweb::web::{window, IWindowOrWorker, RequestAnimationFrameHandle, TimeoutHandle};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Timeout {
|
pub struct Timeout {
|
||||||
|
@ -23,3 +25,39 @@ impl Drop for Timeout {
|
||||||
handle.clear();
|
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;
|
mod timeout;
|
||||||
|
|
||||||
pub use self::canvas::Canvas;
|
pub use self::canvas::Canvas;
|
||||||
pub use self::timeout::Timeout;
|
pub use self::timeout::{AnimationFrameRequest, Timeout};
|
||||||
|
|
||||||
use crate::dpi::{LogicalSize, Size};
|
use crate::dpi::{LogicalSize, Size};
|
||||||
use crate::platform::web::WindowExtWebSys;
|
use crate::platform::web::WindowExtWebSys;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use wasm_bindgen::closure::Closure;
|
use wasm_bindgen::closure::Closure;
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
|
@ -38,3 +40,48 @@ impl Drop for Timeout {
|
||||||
window.clear_timeout_with_handle(self.handle);
|
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