aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/document.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/document.rs')
-rw-r--r--components/script/dom/document.rs136
1 files changed, 116 insertions, 20 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 692c597d7af..9c3b0b00511 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};
@@ -81,14 +84,15 @@ use string_cache::{Atom, QualName};
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 std::num::ToPrimitive;
use time;
#[derive(PartialEq)]
@@ -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 {
@@ -220,8 +230,6 @@ pub trait DocumentHelpers<'a> {
fn title_changed(self);
fn send_title_to_compositor(self);
fn dirty_all_nodes(self);
- fn handle_click_event(self, js_runtime: *mut JSRuntime,
- button: MouseButton, point: Point2D<f32>);
fn dispatch_key_event(self, key: Key, state: KeyState,
modifiers: KeyModifiers, compositor: &mut Box<ScriptListener+'static>);
fn node_from_nodes_and_strings(self, nodes: Vec<NodeOrString>)
@@ -229,6 +237,9 @@ pub trait DocumentHelpers<'a> {
fn get_body_attribute(self, local_name: &Atom) -> DOMString;
fn set_body_attribute(self, local_name: &Atom, value: DOMString);
+ fn handle_mouse_event(self, js_runtime: *mut JSRuntime,
+ button: MouseButton, point: Point2D<f32>,
+ mouse_event_type: MouseEventType);
/// Handles a mouse-move event coming from the compositor.
fn handle_mouse_move_event(self,
js_runtime: *mut JSRuntime,
@@ -237,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> {
@@ -511,9 +528,15 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
}
}
- fn handle_click_event(self, js_runtime: *mut JSRuntime,
- _button: MouseButton, point: Point2D<f32>) {
- debug!("ClickEvent: clicked at {:?}", point);
+ fn handle_mouse_event(self, js_runtime: *mut JSRuntime,
+ _button: MouseButton, point: Point2D<f32>,
+ mouse_event_type: MouseEventType) {
+ let mouse_event_type_string = match mouse_event_type {
+ MouseEventType::Click => "click".to_owned(),
+ MouseEventType::MouseUp => "mouseup".to_owned(),
+ MouseEventType::MouseDown => "mousedown".to_owned(),
+ };
+ debug!("{}: at {:?}", mouse_event_type_string, point);
let node = match self.hit_test(&point) {
Some(node_address) => {
debug!("node address is {:?}", node_address.0);
@@ -525,7 +548,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
let el = match ElementCast::to_ref(node.r()) {
Some(el) => Temporary::from_rooted(el),
None => {
- let parent = node.r().parent_node();
+ let parent = node.r().GetParentNode();
match parent.and_then(ElementCast::to_temporary) {
Some(parent) => parent,
None => return,
@@ -534,13 +557,15 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
}.root();
let node: JSRef<Node> = NodeCast::from_ref(el.r());
- debug!("clicked on {:?}", node.debug_str());
+ debug!("{} on {:?}", mouse_event_type_string, node.debug_str());
// Prevent click event if form control element is disabled.
- if node.click_event_filter_by_disabled_state() {
- return;
- }
+ if let MouseEventType::Click = mouse_event_type {
+ if node.click_event_filter_by_disabled_state() {
+ return;
+ }
- self.begin_focus_transaction();
+ self.begin_focus_transaction();
+ }
let window = self.window.root();
@@ -548,7 +573,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
let x = point.x as i32;
let y = point.y as i32;
let event = MouseEvent::new(window.r(),
- "click".to_owned(),
+ mouse_event_type_string,
EventBubbles::Bubbles,
EventCancelable::Cancelable,
Some(window.r()),
@@ -562,9 +587,17 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#trusted-events
event.set_trusted(true);
// https://html.spec.whatwg.org/multipage/#run-authentic-click-activation-steps
- el.r().authentic_click_activation(event);
+ match mouse_event_type {
+ MouseEventType::Click => el.r().authentic_click_activation(event),
+ _ => {
+ let target: JSRef<EventTarget> = EventTargetCast::from_ref(node);
+ event.fire(target);
+ },
+ }
- self.commit_focus_transaction(FocusType::Element);
+ if let MouseEventType::Click = mouse_event_type {
+ self.commit_focus_transaction(FocusType::Element);
+ }
window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::MouseEvent);
}
@@ -668,8 +701,8 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
let props = KeyboardEvent::key_properties(key, modifiers);
let keyevent = KeyboardEvent::new(window.r(), ev_type, true, true,
- Some(window.r()), 0,
- props.key.to_owned(), props.code.to_owned(),
+ Some(window.r()), 0, Some(key),
+ props.key_string.to_owned(), props.code.to_owned(),
props.location, is_repeating, is_composing,
ctrl, alt, shift, meta,
None, props.key_code).root();
@@ -681,8 +714,8 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
if state != KeyState::Released && props.is_printable() && !prevented {
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#keypress-event-order
let event = KeyboardEvent::new(window.r(), "keypress".to_owned(),
- true, true, Some(window.r()),
- 0, props.key.to_owned(), props.code.to_owned(),
+ true, true, Some(window.r()), 0, Some(key),
+ props.key_string.to_owned(), props.code.to_owned(),
props.location, is_repeating, is_composing,
ctrl, alt, shift, meta,
props.char_code, 0).root();
@@ -776,6 +809,67 @@ 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 {
+ Click,
+ MouseDown,
+ MouseUp,
}
#[derive(PartialEq)]
@@ -847,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()),
}
}