Skip to content

Commit

Permalink
Implement requestAnimationFrame for stdweb
Browse files Browse the repository at this point in the history
  • Loading branch information
chemicstry committed Mar 27, 2020
1 parent 6d471da commit 1cf674a
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Unreleased

- On X11, fix `ResumeTimeReached` being fired too early.
- Added `Clone` implementation for `'static` events.
- On Web, replaced zero timeout for `ControlFlow::Poll` with `requestAnimationFrame`

# 0.22.0 (2020-03-09)

Expand Down
3 changes: 2 additions & 1 deletion src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/web/stdweb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
40 changes: 39 additions & 1 deletion src/platform_impl/web/stdweb/timeout.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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();
}
}
}
}
5 changes: 1 addition & 4 deletions src/platform_impl/web/web_sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ mod event;
mod timeout;

pub use self::canvas::Canvas;
pub use self::timeout::{
Timeout,
AnimationFrameRequest,
};
pub use self::timeout::{AnimationFrameRequest, Timeout};

use crate::dpi::{LogicalSize, Size};
use crate::platform::web::WindowExtWebSys;
Expand Down
12 changes: 7 additions & 5 deletions src/platform_impl/web/web_sys/timeout.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::time::Duration;
use std::rc::Rc;
use std::cell::Cell;
use std::rc::Rc;
use std::time::Duration;
use wasm_bindgen::closure::Closure;
use wasm_bindgen::JsCast;

Expand Down Expand Up @@ -44,7 +44,7 @@ impl Drop for Timeout {
#[derive(Debug)]
pub struct AnimationFrameRequest {
handle: i32,
// track callback state, because cancel_animation_frame is expensive
// track callback state, because `cancelAnimationFrame` is slow
fired: Rc<Cell<bool>>,
_closure: Closure<dyn FnMut()>,
}
Expand All @@ -70,7 +70,7 @@ impl AnimationFrameRequest {
AnimationFrameRequest {
handle,
fired,
_closure: closure
_closure: closure,
}
}
}
Expand All @@ -79,7 +79,9 @@ 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);
window
.cancel_animation_frame(self.handle)
.expect("Failed to cancel animation frame");
}
}
}

0 comments on commit 1cf674a

Please sign in to comment.