diff options
author | Matt Brubeck <mbrubeck@limpet.net> | 2015-08-14 07:24:50 -0700 |
---|---|---|
committer | Matt Brubeck <mbrubeck@limpet.net> | 2015-10-22 10:37:03 -0700 |
commit | fe7460f34d20d5f17d21d60e1053028b21c63ebc (patch) | |
tree | 6cc401775f503ce01b528021cc87bc7580fc7140 /components/script | |
parent | 4ed15a8853fc49d0940ed24d939fd0c407ee80a9 (diff) | |
download | servo-fe7460f34d20d5f17d21d60e1053028b21c63ebc.tar.gz servo-fe7460f34d20d5f17d21d60e1053028b21c63ebc.zip |
Dispatch touch events and perform default touch actions.
This is currently limited to simple single-touch actions. It does not include
momentum scrolling or pinch zooming.
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/document.rs | 53 | ||||
-rw-r--r-- | components/script/dom/touchevent.rs | 2 | ||||
-rw-r--r-- | components/script/script_task.rs | 35 |
3 files changed, 88 insertions, 2 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 835351cdc0d..f987d73747c 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -21,6 +21,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::js::RootedReference; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root}; +use dom::bindings::num::Finite; use dom::bindings::refcounted::Trusted; use dom::bindings::trace::RootedVec; use dom::bindings::utils::XMLName::InvalidXMLName; @@ -60,6 +61,9 @@ use dom::processinginstruction::ProcessingInstruction; use dom::range::Range; use dom::servohtmlparser::ServoHTMLParser; use dom::text::Text; +use dom::touch::Touch; +use dom::touchevent::TouchEvent; +use dom::touchlist::TouchList; use dom::treewalker::TreeWalker; use dom::uievent::UIEvent; use dom::window::{ReflowReason, Window}; @@ -699,6 +703,55 @@ impl Document { ReflowReason::MouseEvent); } + pub fn handle_touch_event(&self, + js_runtime: *mut JSRuntime, + identifier: i32, + point: Point2D<f32>, + event_name: String) -> bool { + let node = match self.hit_test(&point) { + Some(node_address) => node::from_untrusted_node_address(js_runtime, node_address), + None => return false + }; + let el = match node.downcast::<Element>() { + Some(el) => Root::from_ref(el), + None => { + let parent = node.r().GetParentNode(); + match parent.and_then(Root::downcast::<Element>) { + Some(parent) => parent, + None => return false + } + }, + }; + let target = el.upcast::<EventTarget>(); + + let x = Finite::wrap(point.x as f64); + let y = Finite::wrap(point.y as f64); + + let window = self.window.root(); + + let touch = Touch::new(window.r(), identifier, target, x, y, x, y); + let mut touches = RootedVec::new(); + touches.push(JS::from_rooted(&touch)); + let touches = TouchList::new(window.r(), touches.r()); + + let event = TouchEvent::new(window.r(), + event_name, + EventBubbles::Bubbles, + EventCancelable::Cancelable, + Some(window.r()), + 0i32, + &touches, &touches, &touches, + // FIXME: modifier keys + false, false, false, false); + let event = event.upcast::<Event>(); + let result = event.fire(target); + + window.r().reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::MouseEvent); + result + } + /// The entry point for all key processing for web content pub fn dispatch_key_event(&self, key: Key, diff --git a/components/script/dom/touchevent.rs b/components/script/dom/touchevent.rs index 99bac602bd6..5244e4c9e35 100644 --- a/components/script/dom/touchevent.rs +++ b/components/script/dom/touchevent.rs @@ -9,7 +9,7 @@ use dom::bindings::conversions::Castable; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; use dom::bindings::utils::reflect_dom_object; -use dom::event::{Event, EventBubbles, EventCancelable}; +use dom::event::{EventBubbles, EventCancelable}; use dom::touchlist::TouchList; use dom::uievent::UIEvent; use dom::window::Window; diff --git a/components/script/script_task.rs b/components/script/script_task.rs index a090d1c91ef..2b6f4c252d6 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -60,7 +60,7 @@ use layout_interface::{ReflowQueryType}; use layout_interface::{self, LayoutChan, NewLayoutTaskInfo, ReflowGoal, ScriptLayoutChan}; use libc; use mem::heap_size_of_self_and_children; -use msg::compositor_msg::{LayerId, ScriptToCompositorMsg}; +use msg::compositor_msg::{EventResult, LayerId, ScriptToCompositorMsg}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, FocusType, LoadData}; use msg::constellation_msg::{MozBrowserEvent, PipelineExitType, PipelineId}; @@ -79,6 +79,7 @@ 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, ConstellationControlMsg}; use script_traits::{InitialScriptState, MouseButton, NewLayoutInfo}; use script_traits::{OpaqueScriptLayoutChannel, ScriptState, ScriptTaskFactory}; @@ -1784,6 +1785,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(); + } + } + + 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(); @@ -1803,6 +1825,17 @@ impl ScriptTask { document.r().handle_mouse_event(self.js_runtime.rt(), button, point, mouse_event_type); } + fn handle_touch_event(&self, + pipeline_id: PipelineId, + identifier: i32, + point: Point2D<f32>, + event_name: &str) -> 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()) + } + /// https://html.spec.whatwg.org/multipage/#navigating-across-documents /// The entry point for content to notify that a new load has been requested /// for the given pipeline (specifically the "navigate" algorithm). |