aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/document.rs68
-rw-r--r--components/script/script_task.rs50
2 files changed, 81 insertions, 37 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 781c53e2331..91e7dc05e44 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -13,6 +13,7 @@ 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::TouchBinding::TouchMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId, NodeTypeId};
use dom::bindings::codegen::UnionTypes::NodeOrString;
@@ -84,7 +85,7 @@ use net_traits::CookieSource::NonHTTP;
use net_traits::{AsyncResponseTarget, PendingAsyncLoad};
use num::ToPrimitive;
use script_task::{MainThreadScriptMsg, Runnable};
-use script_traits::{MouseButton, UntrustedNodeAddress};
+use script_traits::{MouseButton, TouchEventType, TouchId, UntrustedNodeAddress};
use selectors::states::*;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
@@ -175,8 +176,10 @@ pub struct Document {
/// This field is set to the document itself for inert documents.
/// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document
appropriate_template_contents_owner_document: MutNullableHeap<JS<Document>>,
- // The collection of ElementStates that have been changed since the last restyle.
+ /// The collection of ElementStates that have been changed since the last restyle.
element_state_changes: DOMRefCell<HashMap<JS<Element>, ElementState>>,
+ /// http://w3c.github.io/touch-events/#dfn-active-touch-point
+ active_touch_points: DOMRefCell<Vec<JS<Touch>>>,
}
impl PartialEq for Document {
@@ -728,9 +731,17 @@ impl Document {
pub fn handle_touch_event(&self,
js_runtime: *mut JSRuntime,
- identifier: i32,
- point: Point2D<f32>,
- event_name: String) -> bool {
+ event_type: TouchEventType,
+ TouchId(identifier): TouchId,
+ point: Point2D<f32>)
+ -> bool {
+ let event_name = match event_type {
+ TouchEventType::Down => "touchstart",
+ TouchEventType::Move => "touchmove",
+ TouchEventType::Up => "touchend",
+ TouchEventType::Cancel => "touchcancel",
+ };
+
let node = match self.hit_test(&point) {
Some(node_address) => node::from_untrusted_node_address(js_runtime, node_address),
None => return false
@@ -745,7 +756,7 @@ impl Document {
}
},
};
- let target = el.upcast::<EventTarget>();
+ let target = Root::upcast::<EventTarget>(el);
let window = &*self.window;
let client_x = Finite::wrap(point.x as f64);
@@ -753,26 +764,58 @@ impl Document {
let page_x = Finite::wrap(point.x as f64 + window.PageXOffset() as f64);
let page_y = Finite::wrap(point.y as f64 + window.PageYOffset() as f64);
- let touch = Touch::new(window, identifier, target,
+ let touch = Touch::new(window, identifier, target.r(),
client_x, client_y, // TODO: Get real screen coordinates?
client_x, client_y,
page_x, page_y);
+ match event_type {
+ TouchEventType::Down => {
+ // Add a new touch point
+ self.active_touch_points.borrow_mut().push(JS::from_rooted(&touch));
+ }
+ TouchEventType::Move => {
+ // Replace an existing touch point
+ let mut active_touch_points = self.active_touch_points.borrow_mut();
+ match active_touch_points.iter_mut().find(|t| t.Identifier() == identifier) {
+ Some(t) => *t = JS::from_rooted(&touch),
+ None => warn!("Got a touchmove event for a non-active touch point")
+ }
+ }
+ TouchEventType::Up |
+ TouchEventType::Cancel => {
+ // Remove an existing touch point
+ let mut active_touch_points = self.active_touch_points.borrow_mut();
+ match active_touch_points.iter().position(|t| t.Identifier() == identifier) {
+ Some(i) => { active_touch_points.swap_remove(i); }
+ None => warn!("Got a touchend event for a non-active touch point")
+ }
+ }
+ }
+
let mut touches = RootedVec::new();
- touches.push(JS::from_rooted(&touch));
- let touches = TouchList::new(window, touches.r());
+ touches.extend(self.active_touch_points.borrow().iter().cloned());
+
+ let mut changed_touches = RootedVec::new();
+ changed_touches.push(JS::from_rooted(&touch));
+
+ let mut target_touches = RootedVec::new();
+ target_touches.extend(self.active_touch_points.borrow().iter().filter(
+ |t| t.Target() == target).cloned());
let event = TouchEvent::new(window,
- event_name,
+ event_name.to_owned(),
EventBubbles::Bubbles,
EventCancelable::Cancelable,
Some(window),
0i32,
- &touches, &touches, &touches,
+ &TouchList::new(window, touches.r()),
+ &TouchList::new(window, changed_touches.r()),
+ &TouchList::new(window, target_touches.r()),
// FIXME: modifier keys
false, false, false, false);
let event = event.upcast::<Event>();
- let result = event.fire(target);
+ let result = event.fire(target.r());
window.reflow(ReflowGoal::ForDisplay,
ReflowQueryType::NoQuery,
@@ -1269,6 +1312,7 @@ impl Document {
base_element: Default::default(),
appropriate_template_contents_owner_document: Default::default(),
element_state_changes: DOMRefCell::new(HashMap::new()),
+ active_touch_points: DOMRefCell::new(Vec::new()),
}
}
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 4939a58e086..1fae6cda718 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -78,12 +78,12 @@ use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::CompositorEvent::{ClickEvent, ResizeEvent};
use script_traits::CompositorEvent::{KeyEvent, MouseMoveEvent};
-use script_traits::CompositorEvent::{MouseDownEvent, MouseUpEvent};
-use script_traits::CompositorEvent::{TouchDownEvent, TouchMoveEvent, TouchUpEvent};
+use script_traits::CompositorEvent::{MouseDownEvent, MouseUpEvent, TouchEvent};
use script_traits::{CompositorEvent, ConstellationControlMsg};
use script_traits::{InitialScriptState, MouseButton, NewLayoutInfo};
use script_traits::{OpaqueScriptLayoutChannel, ScriptState, ScriptTaskFactory};
use script_traits::{TimerEvent, TimerEventChan, TimerEventRequest, TimerSource};
+use script_traits::{TouchEventType, TouchId};
use std::any::Any;
use std::borrow::ToOwned;
use std::cell::{Cell, RefCell};
@@ -1764,27 +1764,27 @@ impl ScriptTask {
std_mem::swap(&mut *self.mouse_over_targets.borrow_mut(), &mut *mouse_over_targets);
}
- TouchDownEvent(identifier, point) => {
- let default_action_allowed =
- self.handle_touch_event(pipeline_id, identifier, point, "touchstart");
- if default_action_allowed {
- // TODO: Wait to see if preventDefault is called on the first touchmove event.
- self.compositor.borrow_mut().send(ScriptToCompositorMsg::TouchEventProcessed(
- EventResult::DefaultAllowed)).unwrap();
- } else {
- self.compositor.borrow_mut().send(ScriptToCompositorMsg::TouchEventProcessed(
- EventResult::DefaultPrevented)).unwrap();
+ TouchEvent(event_type, identifier, point) => {
+ let handled = self.handle_touch_event(pipeline_id, event_type, identifier, point);
+ match event_type {
+ TouchEventType::Down => {
+ if handled {
+ // TODO: Wait to see if preventDefault is called on the first touchmove event.
+ self.compositor.borrow_mut()
+ .send(ScriptToCompositorMsg::TouchEventProcessed(
+ EventResult::DefaultAllowed)).unwrap();
+ } else {
+ self.compositor.borrow_mut()
+ .send(ScriptToCompositorMsg::TouchEventProcessed(
+ EventResult::DefaultPrevented)).unwrap();
+ }
+ }
+ _ => {
+ // TODO: Calling preventDefault on a touchup event should prevent clicks.
+ }
}
}
- TouchMoveEvent(identifier, point) => {
- self.handle_touch_event(pipeline_id, identifier, point, "touchmove");
- }
-
- TouchUpEvent(identifier, point) => {
- self.handle_touch_event(pipeline_id, identifier, point, "touchend");
- }
-
KeyEvent(key, state, modifiers) => {
let page = get_page(&self.root_page(), pipeline_id);
let document = page.document();
@@ -1806,13 +1806,13 @@ impl ScriptTask {
fn handle_touch_event(&self,
pipeline_id: PipelineId,
- identifier: i32,
- point: Point2D<f32>,
- event_name: &str) -> bool {
+ event_type: TouchEventType,
+ identifier: TouchId,
+ point: Point2D<f32>)
+ -> bool {
let page = get_page(&self.root_page(), pipeline_id);
let document = page.document();
- document.r().handle_touch_event(self.js_runtime.rt(), identifier, point,
- event_name.to_owned())
+ document.r().handle_touch_event(self.js_runtime.rt(), event_type, identifier, point)
}
/// https://html.spec.whatwg.org/multipage/#navigating-across-documents