diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/document.rs | 68 | ||||
-rw-r--r-- | components/script/script_task.rs | 50 |
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 |