aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorMatt Brubeck <mbrubeck@limpet.net>2015-08-14 07:24:50 -0700
committerMatt Brubeck <mbrubeck@limpet.net>2015-10-22 10:37:03 -0700
commitfe7460f34d20d5f17d21d60e1053028b21c63ebc (patch)
tree6cc401775f503ce01b528021cc87bc7580fc7140 /components/script
parent4ed15a8853fc49d0940ed24d939fd0c407ee80a9 (diff)
downloadservo-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.rs53
-rw-r--r--components/script/dom/touchevent.rs2
-rw-r--r--components/script/script_task.rs35
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).