aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Brubeck <mbrubeck@limpet.net>2015-10-22 16:15:26 -0700
committerMatt Brubeck <mbrubeck@limpet.net>2015-11-03 08:56:34 -0800
commitef93650db944c0865da9f0c0b198dbc89fc46bd4 (patch)
treec175a4ab6f72edde8426d1b1022ee9de32c6acda
parent5c11c88e92ccbc3013501096d5625778774c9fee (diff)
downloadservo-ef93650db944c0865da9f0c0b198dbc89fc46bd4.tar.gz
servo-ef93650db944c0865da9f0c0b198dbc89fc46bd4.zip
Handle multi-touch events from glutin
-rw-r--r--components/compositing/compositor.rs162
-rw-r--r--components/compositing/windowing.rs6
-rw-r--r--components/script/dom/document.rs68
-rw-r--r--components/script/script_task.rs50
-rw-r--r--components/script_traits/lib.rs27
-rw-r--r--components/util/opts.rs6
-rw-r--r--ports/glutin/window.rs14
7 files changed, 229 insertions, 104 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index 3482d730be4..de02b59d67a 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -35,8 +35,9 @@ use msg::constellation_msg::{NavigationDirection, PipelineId, WindowSizeData};
use pipeline::CompositionPipeline;
use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
use profile_traits::time::{self, ProfilerCategory, profile};
-use script_traits::CompositorEvent::{TouchDownEvent, TouchMoveEvent, TouchUpEvent};
+use script_traits::CompositorEvent::TouchEvent;
use script_traits::{ConstellationControlMsg, LayoutControlMsg, MouseButton};
+use script_traits::{TouchEventType, TouchId};
use scrolling::ScrollingTimerProxy;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{HashMap, HashSet};
@@ -72,23 +73,6 @@ enum ReadyState {
ReadyToSaveImage,
}
-/// The states of the touch input state machine.
-///
-/// TODO: Currently Add support for "flinging" (scrolling inertia), pinch zooming, better
-/// support for multiple touch points.
-enum TouchState {
- /// Not tracking any touch point
- Nothing,
- /// A touchstart event was dispatched to the page, but the response wasn't received yet.
- WaitingForScript,
- /// Script is consuming the current touch point; don't perform default actions.
- DefaultPrevented,
- /// A single touch point is active and may perform click or pan default actions.
- Touching,
- /// A single touch point is active and has started panning.
- Panning,
-}
-
/// NB: Never block on the constellation, because sometimes the constellation blocks on us.
pub struct IOCompositor<Window: WindowMethods> {
/// The application window.
@@ -201,6 +185,27 @@ pub struct IOCompositor<Window: WindowMethods> {
pending_subpages: HashSet<PipelineId>,
}
+/// The states of the touch input state machine.
+///
+/// TODO: Currently Add support for "flinging" (scrolling inertia), pinch zooming.
+enum TouchState {
+ /// Not tracking any touch point
+ Nothing,
+ /// A touchstart event was dispatched to the page, but the response wasn't received yet.
+ /// Contains the number of active touch points.
+ WaitingForScript(u32),
+ /// Script is consuming the current touch sequence; don't perform default actions.
+ /// Contains the number of active touch points.
+ DefaultPrevented(u32),
+ /// A single touch point is active and may perform click or pan default actions.
+ Touching,
+ /// A single touch point is active and has started panning.
+ Panning,
+ /// A multi-touch gesture is in progress. Contains the number of active touch points.
+ MultiTouch(u32),
+}
+
+
pub struct ScrollEvent {
delta: TypedPoint2D<DevicePixel, f32>,
cursor: TypedPoint2D<DevicePixel, i32>,
@@ -537,10 +542,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
(Msg::TouchEventProcessed(result), ShutdownState::NotShuttingDown) => {
match self.touch_gesture_state {
- TouchState::WaitingForScript => {
+ TouchState::WaitingForScript(n) => {
self.touch_gesture_state = match result {
- EventResult::DefaultAllowed => TouchState::Touching,
- EventResult::DefaultPrevented => TouchState::DefaultPrevented,
+ EventResult::DefaultPrevented => TouchState::DefaultPrevented(n),
+ EventResult::DefaultAllowed => if n > 1 {
+ TouchState::MultiTouch(n)
+ } else {
+ TouchState::Touching
+ }
};
}
_ => {}
@@ -1056,6 +1065,15 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.on_mouse_window_move_event_class(cursor);
}
+ WindowEvent::Touch(event_type, identifier, location) => {
+ match event_type {
+ TouchEventType::Down => self.on_touch_down(identifier, location),
+ TouchEventType::Move => self.on_touch_move(identifier, location),
+ TouchEventType::Up => self.on_touch_up(identifier, location),
+ TouchEventType::Cancel => self.on_touch_cancel(identifier, location),
+ }
+ }
+
WindowEvent::Scroll(delta, cursor) => {
self.on_scroll_window_event(delta, cursor);
}
@@ -1127,8 +1145,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
if opts::get().convert_mouse_to_touch {
match mouse_window_event {
MouseWindowEvent::Click(_, _) => {}
- MouseWindowEvent::MouseDown(_, p) => self.on_touch_down(0, p),
- MouseWindowEvent::MouseUp(_, p) => self.on_touch_up(0, p),
+ MouseWindowEvent::MouseDown(_, p) => self.on_touch_down(TouchId(0), p),
+ MouseWindowEvent::MouseUp(_, p) => self.on_touch_up(TouchId(0), p),
}
return
}
@@ -1146,7 +1164,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
fn on_mouse_window_move_event_class(&mut self, cursor: TypedPoint2D<DevicePixel, f32>) {
if opts::get().convert_mouse_to_touch {
- self.on_touch_move(0, cursor);
+ self.on_touch_move(TouchId(0), cursor);
return
}
@@ -1156,31 +1174,40 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}
- fn on_touch_down(&mut self, identifier: i32, point: TypedPoint2D<DevicePixel, f32>) {
- match self.touch_gesture_state {
+ fn on_touch_down(&mut self, identifier: TouchId, point: TypedPoint2D<DevicePixel, f32>) {
+ self.touch_gesture_state = match self.touch_gesture_state {
TouchState::Nothing => {
// TODO: Don't wait for script if we know the page has no touch event listeners.
self.first_touch_point = Some(point);
self.last_touch_point = Some(point);
- self.touch_gesture_state = TouchState::WaitingForScript;
+ TouchState::WaitingForScript(1)
}
- TouchState::WaitingForScript => {
- // TODO: Queue events while waiting for script?
+ TouchState::Touching |
+ TouchState::Panning => {
+ // Was a single-touch sequence; now a multi-touch sequence:
+ TouchState::MultiTouch(2)
}
- TouchState::DefaultPrevented => {}
- TouchState::Touching => {}
- TouchState::Panning => {}
- }
+ TouchState::WaitingForScript(n) => {
+ TouchState::WaitingForScript(n + 1)
+ }
+ TouchState::DefaultPrevented(n) => {
+ TouchState::DefaultPrevented(n + 1)
+ }
+ TouchState::MultiTouch(n) => {
+ TouchState::MultiTouch(n + 1)
+ }
+ };
if let Some(result) = self.find_topmost_layer_at_point(point / self.scene.scale) {
- result.layer.send_event(self, TouchDownEvent(identifier, result.point.to_untyped()));
+ result.layer.send_event(self, TouchEvent(TouchEventType::Down, identifier,
+ result.point.to_untyped()));
}
}
- fn on_touch_move(&mut self, identifier: i32, point: TypedPoint2D<DevicePixel, f32>) {
+ fn on_touch_move(&mut self, identifier: TouchId, point: TypedPoint2D<DevicePixel, f32>) {
match self.touch_gesture_state {
TouchState::Nothing => warn!("Got unexpected touch move event"),
- TouchState::WaitingForScript => {
+ TouchState::WaitingForScript(_) => {
// TODO: Queue events while waiting for script?
}
TouchState::Touching => {
@@ -1209,40 +1236,67 @@ impl<Window: WindowMethods> IOCompositor<Window> {
None => warn!("last_touch_point not set")
}
}
- TouchState::DefaultPrevented => {
+ TouchState::DefaultPrevented(_) => {
// Send the event to script.
if let Some(result) = self.find_topmost_layer_at_point(point / self.scene.scale) {
- result.layer.send_event(self,
- TouchMoveEvent(identifier, result.point.to_untyped()));
+ result.layer.send_event(self, TouchEvent(TouchEventType::Move, identifier,
+ result.point.to_untyped()));
}
}
+ TouchState::MultiTouch(_) => {
+ // TODO: Pinch zooming.
+ }
}
self.last_touch_point = Some(point);
}
- fn on_touch_up(&mut self, identifier: i32, point: TypedPoint2D<DevicePixel, f32>) {
- // TODO: Track the number of active touch points, and don't reset stuff until it is zero.
- self.first_touch_point = None;
- self.last_touch_point = None;
-
+ fn on_touch_up(&mut self, identifier: TouchId, point: TypedPoint2D<DevicePixel, f32>) {
// Send the event to script.
if let Some(result) = self.find_topmost_layer_at_point(point / self.scene.scale) {
- result.layer.send_event(self, TouchUpEvent(identifier, result.point.to_untyped()));
+ result.layer.send_event(self, TouchEvent(TouchEventType::Up, identifier,
+ result.point.to_untyped()));
}
- match self.touch_gesture_state {
- TouchState::Nothing => warn!("Got unexpected touch up event"),
-
- TouchState::WaitingForScript => {}
+ self.touch_gesture_state = match self.touch_gesture_state {
TouchState::Touching => {
// TODO: If the duration exceeds some threshold, send a contextmenu event instead.
// TODO: Don't send a click if preventDefault is called on the touchend event.
self.simulate_mouse_click(point);
- }
- TouchState::Panning => {}
- TouchState::DefaultPrevented => {}
- }
- self.touch_gesture_state = TouchState::Nothing;
+ TouchState::Nothing
+ }
+ TouchState::Nothing |
+ TouchState::Panning |
+ TouchState::WaitingForScript(1) |
+ TouchState::DefaultPrevented(1) |
+ TouchState::MultiTouch(1) => {
+ TouchState::Nothing
+ }
+ TouchState::WaitingForScript(n) => TouchState::WaitingForScript(n - 1),
+ TouchState::DefaultPrevented(n) => TouchState::DefaultPrevented(n - 1),
+ TouchState::MultiTouch(n) => TouchState::MultiTouch(n - 1),
+ };
+ }
+
+ fn on_touch_cancel(&mut self, identifier: TouchId, point: TypedPoint2D<DevicePixel, f32>) {
+ // Send the event to script.
+ if let Some(result) = self.find_topmost_layer_at_point(point / self.scene.scale) {
+ result.layer.send_event(self, TouchEvent(TouchEventType::Cancel, identifier,
+ result.point.to_untyped()));
+ }
+
+ self.touch_gesture_state = match self.touch_gesture_state {
+ TouchState::Nothing |
+ TouchState::Touching |
+ TouchState::Panning |
+ TouchState::WaitingForScript(1) |
+ TouchState::DefaultPrevented(1) |
+ TouchState::MultiTouch(1) => {
+ TouchState::Nothing
+ }
+ TouchState::WaitingForScript(n) => TouchState::WaitingForScript(n - 1),
+ TouchState::DefaultPrevented(n) => TouchState::DefaultPrevented(n - 1),
+ TouchState::MultiTouch(n) => TouchState::MultiTouch(n - 1),
+ };
}
/// http://w3c.github.io/touch-events/#mouse-events
diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs
index d335038c70a..d129a6deb5b 100644
--- a/components/compositing/windowing.rs
+++ b/components/compositing/windowing.rs
@@ -13,7 +13,7 @@ use layers::geometry::DevicePixel;
use layers::platform::surface::NativeDisplay;
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
use net_traits::net_error_list::NetError;
-use script_traits::MouseButton;
+use script_traits::{MouseButton, TouchEventType, TouchId};
use std::fmt::{Debug, Error, Formatter};
use std::rc::Rc;
use url::Url;
@@ -27,6 +27,7 @@ pub enum MouseWindowEvent {
MouseUp(MouseButton, TypedPoint2D<DevicePixel, f32>),
}
+
#[derive(Clone)]
pub enum WindowNavigateMsg {
Forward,
@@ -59,6 +60,8 @@ pub enum WindowEvent {
MouseWindowEventClass(MouseWindowEvent),
/// Sent when a mouse move.
MouseWindowMoveEventClass(TypedPoint2D<DevicePixel, f32>),
+ /// Touch event: type, identifier, point
+ Touch(TouchEventType, TouchId, TypedPoint2D<DevicePixel, f32>),
/// Sent when the user scrolls. The first point is the delta and the second point is the
/// origin.
Scroll(TypedPoint2D<DevicePixel, f32>, TypedPoint2D<DevicePixel, i32>),
@@ -88,6 +91,7 @@ impl Debug for WindowEvent {
WindowEvent::LoadUrl(..) => write!(f, "LoadUrl"),
WindowEvent::MouseWindowEventClass(..) => write!(f, "Mouse"),
WindowEvent::MouseWindowMoveEventClass(..) => write!(f, "MouseMove"),
+ WindowEvent::Touch(..) => write!(f, "Touch"),
WindowEvent::Scroll(..) => write!(f, "Scroll"),
WindowEvent::Zoom(..) => write!(f, "Zoom"),
WindowEvent::PinchZoom(..) => write!(f, "PinchZoom"),
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
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index eda5cf1b459..2db79ff93d3 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -158,6 +158,25 @@ pub enum MouseButton {
Right,
}
+/// The type of input represented by a multi-touch event.
+#[derive(Clone, Copy, Debug)]
+pub enum TouchEventType {
+ /// A new touch point came in contact with the screen.
+ Down,
+ /// An existing touch point changed location.
+ Move,
+ /// A touch point was removed from the screen.
+ Up,
+ /// The system stopped tracking a touch point.
+ Cancel,
+}
+
+/// An opaque identifier for a touch point.
+///
+/// http://w3c.github.io/touch-events/#widl-Touch-identifier
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub struct TouchId(pub i32);
+
/// Events from the compositor that the script task needs to know about
pub enum CompositorEvent {
/// The window was resized.
@@ -170,12 +189,8 @@ pub enum CompositorEvent {
MouseUpEvent(MouseButton, Point2D<f32>),
/// The mouse was moved over a point.
MouseMoveEvent(Point2D<f32>),
- /// A touch began at a point.
- TouchDownEvent(i32, Point2D<f32>),
- /// A touch was moved over a point.
- TouchMoveEvent(i32, Point2D<f32>),
- /// A touch ended at a point.
- TouchUpEvent(i32, Point2D<f32>),
+ /// A touch event was generated with a touch ID and location.
+ TouchEvent(TouchEventType, TouchId, Point2D<f32>),
/// A key was pressed.
KeyEvent(Key, KeyState, KeyModifiers),
}
diff --git a/components/util/opts.rs b/components/util/opts.rs
index 9f68ffb432b..31e3eb899ea 100644
--- a/components/util/opts.rs
+++ b/components/util/opts.rs
@@ -272,12 +272,6 @@ impl DebugOptions {
pub fn new(debug_string: &str) -> Result<DebugOptions, &str> {
let mut debug_options = DebugOptions::default();
- // FIXME: Glutin currently converts touch input to mouse events on Android.
- // Convert it back to touch events.
- if cfg!(target_os = "android") {
- debug_options.convert_mouse_to_touch = true;
- }
-
for option in debug_string.split(',') {
match option {
"help" => debug_options.help = true,
diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs
index af8cf8a242b..42b296b9245 100644
--- a/ports/glutin/window.rs
+++ b/ports/glutin/window.rs
@@ -16,6 +16,7 @@ use gleam::gl;
use glutin;
#[cfg(feature = "window")]
use glutin::{Api, ElementState, Event, GlRequest, MouseButton, VirtualKeyCode, MouseScrollDelta};
+use glutin::{TouchPhase};
use layers::geometry::DevicePixel;
use layers::platform::surface::NativeDisplay;
#[cfg(feature = "window")]
@@ -157,6 +158,8 @@ impl Window {
}
fn handle_window_event(&self, event: glutin::Event) -> bool {
+ use script_traits::{TouchEventType, TouchId};
+
match event {
Event::KeyboardInput(element_state, _scan_code, virtual_key_code) => {
if virtual_key_code.is_some() {
@@ -216,6 +219,17 @@ impl Window {
self.pinch_zoom(factor);
}
},
+ Event::Touch(touch) => {
+ let phase = match touch.phase {
+ TouchPhase::Started => TouchEventType::Down,
+ TouchPhase::Moved => TouchEventType::Move,
+ TouchPhase::Ended => TouchEventType::Up,
+ TouchPhase::Cancelled => TouchEventType::Cancel,
+ };
+ let id = TouchId(touch.id as i32);
+ let point = Point2D::typed(touch.location.0 as f32, touch.location.1 as f32);
+ self.event_queue.borrow_mut().push(WindowEvent::Touch(phase, id, point));
+ }
Event::Refresh => {
self.event_queue.borrow_mut().push(WindowEvent::Refresh);
}