aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/bindings/trace.rs7
-rw-r--r--components/script/dom/document.rs75
-rw-r--r--components/script/dom/webidls/Window.webidl7
-rw-r--r--components/script/dom/window.rs25
4 files changed, 110 insertions, 4 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index ab325ab804b..31f1a78f717 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -281,6 +281,13 @@ impl JSTraceable for Box<ScriptChan+Send> {
}
}
+impl JSTraceable for Box<Fn(f64, )> {
+ #[inline]
+ fn trace(&self, _trc: *mut JSTracer) {
+ // Do nothing
+ }
+}
+
impl<'a> JSTraceable for &'a str {
#[inline]
fn trace(&self, _: *mut JSTracer) {
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index f96dd134082..b5750f4a30c 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -11,6 +11,8 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter;
+use dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods;
+use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::{DocumentDerived, EventCast, HTMLBodyElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLHeadElementCast, ElementCast};
use dom::bindings::codegen::InheritTypes::{DocumentTypeCast, HTMLHtmlElementCast, NodeCast};
@@ -63,6 +65,7 @@ use dom::window::{Window, WindowHelpers, ReflowReason};
use layout_interface::{HitTestResponse, MouseOverResponse};
use msg::compositor_msg::ScriptListener;
+use msg::constellation_msg::AnimationState;
use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, FocusType, Key, KeyState, KeyModifiers, MozBrowserEvent};
use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL};
@@ -82,11 +85,12 @@ use url::Url;
use js::jsapi::JSRuntime;
use num::ToPrimitive;
+use std::iter::FromIterator;
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::ascii::AsciiExt;
-use std::cell::{Cell, Ref};
+use std::cell::{Cell, Ref, RefCell};
use std::default::Default;
use std::sync::mpsc::channel;
use time;
@@ -129,6 +133,12 @@ pub struct Document {
/// https://html.spec.whatwg.org/multipage/#concept-n-noscript
/// True if scripting is enabled for all scripts in this document
scripting_enabled: Cell<bool>,
+ /// https://html.spec.whatwg.org/multipage/#animation-frame-callback-identifier
+ /// Current identifier of animation frame callback
+ animation_frame_ident: Cell<i32>,
+ /// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks
+ /// List of animation frame callbacks
+ animation_frame_list: RefCell<HashMap<i32, Box<Fn(f64)>>>,
}
impl DocumentDerived for EventTarget {
@@ -238,6 +248,12 @@ pub trait DocumentHelpers<'a> {
fn set_current_script(self, script: Option<JSRef<HTMLScriptElement>>);
fn trigger_mozbrowser_event(self, event: MozBrowserEvent);
+ /// http://w3c.github.io/animation-timing/#dom-windowanimationtiming-requestanimationframe
+ fn request_animation_frame(self, callback: Box<Fn(f64, )>) -> i32;
+ /// http://w3c.github.io/animation-timing/#dom-windowanimationtiming-cancelanimationframe
+ fn cancel_animation_frame(self, ident: i32);
+ /// http://w3c.github.io/animation-timing/#dfn-invoke-callbacks-algorithm
+ fn invoke_animation_callbacks(self);
}
impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
@@ -793,6 +809,61 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
}
}
}
+
+ /// http://w3c.github.io/animation-timing/#dom-windowanimationtiming-requestanimationframe
+ fn request_animation_frame(self, callback: Box<Fn(f64, )>) -> i32 {
+ let window = self.window.root();
+ let window = window.r();
+ let ident = self.animation_frame_ident.get() + 1;
+
+ self.animation_frame_ident.set(ident);
+ self.animation_frame_list.borrow_mut().insert(ident, callback);
+
+ // TODO: Should tick animation only when document is visible
+ let ConstellationChan(ref chan) = window.constellation_chan();
+ let event = ConstellationMsg::ChangeRunningAnimationsState(window.pipeline(),
+ AnimationState::AnimationCallbacksPresent);
+ chan.send(event).unwrap();
+
+ ident
+ }
+
+ /// http://w3c.github.io/animation-timing/#dom-windowanimationtiming-cancelanimationframe
+ fn cancel_animation_frame(self, ident: i32) {
+ self.animation_frame_list.borrow_mut().remove(&ident);
+ if self.animation_frame_list.borrow().len() == 0 {
+ let window = self.window.root();
+ let window = window.r();
+ let ConstellationChan(ref chan) = window.constellation_chan();
+ let event = ConstellationMsg::ChangeRunningAnimationsState(window.pipeline(),
+ AnimationState::NoAnimationCallbacksPresent);
+ chan.send(event).unwrap();
+ }
+ }
+
+ /// http://w3c.github.io/animation-timing/#dfn-invoke-callbacks-algorithm
+ fn invoke_animation_callbacks(self) {
+ let animation_frame_list;
+ {
+ let mut list = self.animation_frame_list.borrow_mut();
+ animation_frame_list = Vec::from_iter(list.drain());
+
+ let window = self.window.root();
+ let window = window.r();
+ let ConstellationChan(ref chan) = window.constellation_chan();
+ let event = ConstellationMsg::ChangeRunningAnimationsState(window.pipeline(),
+ AnimationState::NoAnimationCallbacksPresent);
+ chan.send(event).unwrap();
+ }
+ let window = self.window.root();
+ let window = window.r();
+ let performance = window.Performance().root();
+ let performance = performance.r();
+
+ for (_, callback) in animation_frame_list {
+ callback(*performance.Now());
+ }
+ }
}
pub enum MouseEventType {
@@ -870,6 +941,8 @@ impl Document {
focused: Default::default(),
current_script: Default::default(),
scripting_enabled: Cell::new(true),
+ animation_frame_ident: Cell::new(0),
+ animation_frame_list: RefCell::new(HashMap::new()),
}
}
diff --git a/components/script/dom/webidls/Window.webidl b/components/script/dom/webidls/Window.webidl
index 8999d9e561d..08caf90004e 100644
--- a/components/script/dom/webidls/Window.webidl
+++ b/components/script/dom/webidls/Window.webidl
@@ -141,3 +141,10 @@ interface WindowLocalStorage {
readonly attribute Storage localStorage;
};
Window implements WindowLocalStorage;
+
+// http://w3c.github.io/animation-timing/#Window-interface-extensions
+partial interface Window {
+ long requestAnimationFrame(FrameRequestCallback callback);
+ void cancelAnimationFrame(long handle);
+};
+callback FrameRequestCallback = void (DOMHighResTimeStamp time);
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 37d79625334..296c481a602 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -3,11 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::cell::DOMRefCell;
+use dom::bindings::callback::ExceptionHandling;
use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerNonNull, EventHandlerNonNull};
-use dom::bindings::codegen::Bindings::FunctionBinding::Function;
-use dom::bindings::codegen::Bindings::WindowBinding;
-use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
+use dom::bindings::codegen::Bindings::FunctionBinding::Function;
+use dom::bindings::codegen::Bindings::WindowBinding::{self, WindowMethods, FrameRequestCallback};
use dom::bindings::codegen::InheritTypes::{NodeCast, EventTargetCast};
use dom::bindings::global::global_object_for_js_object;
use dom::bindings::error::{report_pending_exception, Fallible};
@@ -15,6 +15,7 @@ use dom::bindings::error::Error::InvalidCharacter;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, MutNullableHeap, OptionalRootable};
use dom::bindings::js::{Rootable, RootedReference, Temporary};
+use dom::bindings::num::Finite;
use dom::bindings::utils::{GlobalStaticData, Reflectable, WindowProxyHandler};
use dom::browsercontext::BrowserContext;
use dom::console::Console;
@@ -464,6 +465,24 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
fn Atob(self, atob: DOMString) -> Fallible<DOMString> {
base64_atob(atob)
}
+
+ /// http://w3c.github.io/animation-timing/#dom-windowanimationtiming-requestanimationframe
+ fn RequestAnimationFrame(self, callback: FrameRequestCallback) -> i32 {
+ let doc = self.Document().root();
+
+ let callback = move |now: f64| {
+ // TODO: @jdm The spec says that any exceptions should be suppressed;
+ callback.Call__(Finite::wrap(now), ExceptionHandling::Report).unwrap();
+ };
+
+ doc.r().request_animation_frame(Box::new(callback))
+ }
+
+ /// http://w3c.github.io/animation-timing/#dom-windowanimationtiming-cancelanimationframe
+ fn CancelAnimationFrame(self, ident: i32) {
+ let doc = self.Document().root();
+ doc.r().cancel_animation_frame(ident);
+ }
}
pub trait WindowHelpers {