forcetouch events support

This enables Apple forcetouch DOM events. It requires the preference dom.forcetouch.enabled.

The DOM events are described here:
- https://developer.apple.com/library/mac/documentation/AppleApplications/Conceptual/SafariJSProgTopics/RespondingtoForceTouchEventsfromJavaScript.html

The Cocoa mechanism is documented here:
- 20000016-SW274
This commit is contained in:
Paul Rouget 2016-03-18 08:57:20 +01:00
parent 05a4dcdc3b
commit df6e7394d4
13 changed files with 245 additions and 8 deletions

View file

@ -37,7 +37,7 @@ use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
use profile_traits::time::{self, ProfilerCategory, profile}; use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent}; use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
use script_traits::{AnimationState, ConstellationControlMsg, LayoutControlMsg}; use script_traits::{AnimationState, ConstellationControlMsg, LayoutControlMsg};
use script_traits::{MouseButton, MouseEventType, TouchEventType, TouchId}; use script_traits::{MouseButton, MouseEventType, TouchpadPressurePhase, TouchEventType, TouchId};
use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fs::File; use std::fs::File;
@ -50,8 +50,8 @@ use time::{precise_time_ns, precise_time_s};
use touch::{TouchHandler, TouchAction}; use touch::{TouchHandler, TouchAction};
use url::Url; use url::Url;
use util::geometry::{PagePx, ScreenPx, ViewportPx}; use util::geometry::{PagePx, ScreenPx, ViewportPx};
use util::opts;
use util::print_tree::PrintTree; use util::print_tree::PrintTree;
use util::{opts, prefs};
use webrender; use webrender;
use webrender_traits::{self, ScrollEventPhase}; use webrender_traits::{self, ScrollEventPhase};
use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg}; use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg};
@ -1225,6 +1225,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.on_navigation_window_event(direction); self.on_navigation_window_event(direction);
} }
WindowEvent::TouchpadPressure(cursor, pressure, stage) => {
self.on_touchpad_pressure_event(cursor, pressure, stage);
}
WindowEvent::KeyEvent(key, state, modifiers) => { WindowEvent::KeyEvent(key, state, modifiers) => {
self.on_key_event(key, state, modifiers); self.on_key_event(key, state, modifiers);
} }
@ -1701,6 +1705,16 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.constellation_chan.send(ConstellationMsg::Navigate(None, direction)).unwrap() self.constellation_chan.send(ConstellationMsg::Navigate(None, direction)).unwrap()
} }
fn on_touchpad_pressure_event(&self, cursor: TypedPoint2D<DevicePixel, f32>, pressure: f32,
phase: TouchpadPressurePhase) {
if prefs::get_pref("dom.forcetouch.enabled").as_boolean().unwrap() {
match self.find_topmost_layer_at_point(cursor / self.scene.scale) {
Some(result) => result.layer.send_touchpad_pressure_event(self, result.point, pressure, phase),
None => {},
}
}
}
fn on_key_event(&self, key: Key, state: KeyState, modifiers: KeyModifiers) { fn on_key_event(&self, key: Key, state: KeyState, modifiers: KeyModifiers) {
self.constellation_chan.send(ConstellationMsg::KeyEvent(key, state, modifiers)).unwrap() self.constellation_chan.send(ConstellationMsg::KeyEvent(key, state, modifiers)).unwrap()
} }

View file

@ -14,9 +14,10 @@ use layers::geometry::LayerPixel;
use layers::layers::{Layer, LayerBufferSet}; use layers::layers::{Layer, LayerBufferSet};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use script_traits::CompositorEvent; use script_traits::CompositorEvent;
use script_traits::CompositorEvent::{MouseButtonEvent, MouseMoveEvent}; use script_traits::CompositorEvent::{MouseButtonEvent, MouseMoveEvent, TouchpadPressureEvent};
use script_traits::ConstellationControlMsg; use script_traits::ConstellationControlMsg;
use script_traits::MouseEventType; use script_traits::MouseEventType;
use script_traits::TouchpadPressurePhase;
use std::rc::Rc; use std::rc::Rc;
use windowing::{MouseWindowEvent, WindowMethods}; use windowing::{MouseWindowEvent, WindowMethods};
@ -139,6 +140,13 @@ pub trait CompositorLayer {
event: CompositorEvent) event: CompositorEvent)
where Window: WindowMethods; where Window: WindowMethods;
fn send_touchpad_pressure_event<Window>(&self,
compositor: &IOCompositor<Window>,
cursor: TypedPoint2D<LayerPixel, f32>,
pressure: f32,
phase: TouchpadPressurePhase)
where Window: WindowMethods;
fn clamp_scroll_offset_and_scroll_layer(&self, fn clamp_scroll_offset_and_scroll_layer(&self,
new_offset: TypedPoint2D<LayerPixel, f32>) new_offset: TypedPoint2D<LayerPixel, f32>)
-> ScrollEventResult; -> ScrollEventResult;
@ -399,6 +407,18 @@ impl CompositorLayer for Layer<CompositorData> {
} }
} }
fn send_touchpad_pressure_event<Window>(&self,
compositor: &IOCompositor<Window>,
cursor: TypedPoint2D<LayerPixel, f32>,
pressure: f32,
phase: TouchpadPressurePhase)
where Window: WindowMethods {
if let Some(pipeline) = compositor.pipeline(self.pipeline_id()) {
let message = TouchpadPressureEvent(cursor.to_untyped(), pressure, phase);
let _ = pipeline.script_chan.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
}
}
fn scroll_layer_and_all_child_layers(&self, new_offset: TypedPoint2D<LayerPixel, f32>) fn scroll_layer_and_all_child_layers(&self, new_offset: TypedPoint2D<LayerPixel, f32>)
-> bool { -> bool {
let mut result = false; let mut result = false;

View file

@ -13,7 +13,7 @@ use layers::geometry::DevicePixel;
use layers::platform::surface::NativeDisplay; use layers::platform::surface::NativeDisplay;
use msg::constellation_msg::{Key, KeyModifiers, KeyState}; use msg::constellation_msg::{Key, KeyModifiers, KeyState};
use net_traits::net_error_list::NetError; use net_traits::net_error_list::NetError;
use script_traits::{MouseButton, TouchEventType, TouchId}; use script_traits::{MouseButton, TouchpadPressurePhase, TouchEventType, TouchId};
use std::fmt::{Debug, Error, Formatter}; use std::fmt::{Debug, Error, Formatter};
use style_traits::cursor::Cursor; use style_traits::cursor::Cursor;
use url::Url; use url::Url;
@ -50,6 +50,8 @@ pub enum WindowEvent {
InitializeCompositing, InitializeCompositing,
/// Sent when the window is resized. /// Sent when the window is resized.
Resize(TypedSize2D<DevicePixel, u32>), Resize(TypedSize2D<DevicePixel, u32>),
/// Touchpad Pressure
TouchpadPressure(TypedPoint2D<DevicePixel, f32>, f32, TouchpadPressurePhase),
/// Sent when you want to override the viewport. /// Sent when you want to override the viewport.
Viewport(TypedPoint2D<DevicePixel, u32>, TypedSize2D<DevicePixel, u32>), Viewport(TypedPoint2D<DevicePixel, u32>, TypedSize2D<DevicePixel, u32>),
/// Sent when a new URL is to be loaded. /// Sent when a new URL is to be loaded.
@ -84,6 +86,7 @@ impl Debug for WindowEvent {
WindowEvent::Refresh => write!(f, "Refresh"), WindowEvent::Refresh => write!(f, "Refresh"),
WindowEvent::InitializeCompositing => write!(f, "InitializeCompositing"), WindowEvent::InitializeCompositing => write!(f, "InitializeCompositing"),
WindowEvent::Resize(..) => write!(f, "Resize"), WindowEvent::Resize(..) => write!(f, "Resize"),
WindowEvent::TouchpadPressure(..) => write!(f, "TouchpadPressure"),
WindowEvent::Viewport(..) => write!(f, "Viewport"), WindowEvent::Viewport(..) => write!(f, "Viewport"),
WindowEvent::KeyEvent(..) => write!(f, "Key"), WindowEvent::KeyEvent(..) => write!(f, "Key"),
WindowEvent::LoadUrl(..) => write!(f, "LoadUrl"), WindowEvent::LoadUrl(..) => write!(f, "LoadUrl"),

View file

@ -64,7 +64,7 @@ use net_traits::storage_thread::StorageType;
use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan;
use script_thread::ScriptChan; use script_thread::ScriptChan;
use script_traits::{LayoutMsg, ScriptMsg, TimerEventId, TimerSource, UntrustedNodeAddress}; use script_traits::{LayoutMsg, ScriptMsg, TimerEventId, TimerSource, TouchpadPressurePhase, UntrustedNodeAddress};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::boxed::FnBox; use std::boxed::FnBox;
@ -319,6 +319,7 @@ no_jsmanaged_fields!(AttrIdentifier);
no_jsmanaged_fields!(AttrValue); no_jsmanaged_fields!(AttrValue);
no_jsmanaged_fields!(ElementSnapshot); no_jsmanaged_fields!(ElementSnapshot);
no_jsmanaged_fields!(HttpsState); no_jsmanaged_fields!(HttpsState);
no_jsmanaged_fields!(TouchpadPressurePhase);
impl JSTraceable for ConstellationChan<ScriptMsg> { impl JSTraceable for ConstellationChan<ScriptMsg> {
#[inline] #[inline]

View file

@ -41,6 +41,7 @@ use dom::element::{Element, ElementCreator};
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use dom::focusevent::FocusEvent; use dom::focusevent::FocusEvent;
use dom::forcetouchevent::ForceTouchEvent;
use dom::htmlanchorelement::HTMLAnchorElement; use dom::htmlanchorelement::HTMLAnchorElement;
use dom::htmlappletelement::HTMLAppletElement; use dom::htmlappletelement::HTMLAppletElement;
use dom::htmlareaelement::HTMLAreaElement; use dom::htmlareaelement::HTMLAreaElement;
@ -97,7 +98,7 @@ use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, ScriptC
use script_traits::UntrustedNodeAddress; use script_traits::UntrustedNodeAddress;
use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent}; use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{ScriptMsg as ConstellationMsg, ScriptToCompositorMsg}; use script_traits::{ScriptMsg as ConstellationMsg, ScriptToCompositorMsg};
use script_traits::{TouchEventType, TouchId}; use script_traits::{TouchpadPressurePhase, TouchEventType, TouchId};
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::boxed::FnBox; use std::boxed::FnBox;
@ -218,6 +219,7 @@ pub struct Document {
css_errors_store: DOMRefCell<Vec<CSSError>>, css_errors_store: DOMRefCell<Vec<CSSError>>,
/// https://html.spec.whatwg.org/multipage/#concept-document-https-state /// https://html.spec.whatwg.org/multipage/#concept-document-https-state
https_state: Cell<HttpsState>, https_state: Cell<HttpsState>,
touchpad_pressure_phase: Cell<TouchpadPressurePhase>,
} }
#[derive(JSTraceable, HeapSizeOf)] #[derive(JSTraceable, HeapSizeOf)]
@ -732,6 +734,70 @@ impl Document {
ReflowReason::MouseEvent); ReflowReason::MouseEvent);
} }
pub fn handle_touchpad_pressure_event(&self,
js_runtime: *mut JSRuntime,
client_point: Point2D<f32>,
pressure: f32,
phase_now: TouchpadPressurePhase) {
let phase_before = self.touchpad_pressure_phase.get();
self.touchpad_pressure_phase.set(phase_now);
if phase_before == TouchpadPressurePhase::BeforeClick &&
phase_now == TouchpadPressurePhase::BeforeClick {
return;
}
let page_point = Point2D::new(client_point.x + self.window.PageXOffset() as f32,
client_point.y + self.window.PageYOffset() as f32);
let node = match self.window.hit_test_query(page_point, false) {
Some(node_address) => node::from_untrusted_node_address(js_runtime, node_address),
None => return
};
let el = match node.downcast::<Element>() {
Some(el) => Root::from_ref(el),
None => {
let parent = node.GetParentNode();
match parent.and_then(Root::downcast::<Element>) {
Some(parent) => parent,
None => return
}
},
};
let node = el.upcast::<Node>();
let target = node.upcast();
let force = match phase_now {
TouchpadPressurePhase::BeforeClick => pressure,
TouchpadPressurePhase::AfterFirstClick => 1. + pressure,
TouchpadPressurePhase::AfterSecondClick => 2. + pressure,
};
if phase_now != TouchpadPressurePhase::BeforeClick {
self.fire_forcetouch_event("servomouseforcechanged".to_owned(), target, force);
}
if phase_before != TouchpadPressurePhase::AfterSecondClick &&
phase_now == TouchpadPressurePhase::AfterSecondClick {
self.fire_forcetouch_event("servomouseforcedown".to_owned(), target, force);
}
if phase_before == TouchpadPressurePhase::AfterSecondClick &&
phase_now != TouchpadPressurePhase::AfterSecondClick {
self.fire_forcetouch_event("servomouseforceup".to_owned(), target, force);
}
}
fn fire_forcetouch_event(&self, event_name: String, target: &EventTarget, force: f32) {
let force_event = ForceTouchEvent::new(&self.window,
DOMString::from(event_name),
force);
let event = force_event.upcast::<Event>();
event.fire(target);
}
pub fn fire_mouse_event(&self, client_point: Point2D<f32>, target: &EventTarget, event_name: String) { pub fn fire_mouse_event(&self, client_point: Point2D<f32>, target: &EventTarget, event_name: String) {
let client_x = client_point.x.to_i32().unwrap_or(0); let client_x = client_point.x.to_i32().unwrap_or(0);
let client_y = client_point.y.to_i32().unwrap_or(0); let client_y = client_point.y.to_i32().unwrap_or(0);
@ -1593,6 +1659,7 @@ impl Document {
dom_complete: Cell::new(Default::default()), dom_complete: Cell::new(Default::default()),
css_errors_store: DOMRefCell::new(vec![]), css_errors_store: DOMRefCell::new(vec![]),
https_state: Cell::new(HttpsState::None), https_state: Cell::new(HttpsState::None),
touchpad_pressure_phase: Cell::new(TouchpadPressurePhase::BeforeClick),
} }
} }

View file

@ -0,0 +1,59 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::Bindings::ForceTouchEventBinding;
use dom::bindings::codegen::Bindings::ForceTouchEventBinding::ForceTouchEventMethods;
use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root};
use dom::bindings::num::Finite;
use dom::bindings::reflector::reflect_dom_object;
use dom::uievent::UIEvent;
use dom::window::Window;
use util::str::DOMString;
#[dom_struct]
pub struct ForceTouchEvent {
uievent: UIEvent,
force: f32,
}
impl ForceTouchEvent {
fn new_inherited(force: f32) -> ForceTouchEvent {
ForceTouchEvent {
uievent: UIEvent::new_inherited(),
force: force,
}
}
pub fn new(window: &Window,
type_: DOMString,
force: f32) -> Root<ForceTouchEvent> {
let event = box ForceTouchEvent::new_inherited(force);
let ev = reflect_dom_object(event, GlobalRef::Window(window), ForceTouchEventBinding::Wrap);
ev.upcast::<UIEvent>().InitUIEvent(type_, true, true, Some(window), 0);
ev
}
}
impl<'a> ForceTouchEventMethods for &'a ForceTouchEvent {
fn ServoForce(&self) -> Finite<f32> {
Finite::wrap(self.force)
}
fn SERVO_FORCE_AT_MOUSE_DOWN(&self) -> Finite<f32> {
Finite::wrap(1.0)
}
fn SERVO_FORCE_AT_FORCE_MOUSE_DOWN(&self) -> Finite<f32> {
Finite::wrap(2.0)
}
// https://dom.spec.whatwg.org/#dom-event-istrusted
fn IsTrusted(&self) -> bool {
self.uievent.IsTrusted()
}
}

View file

@ -264,6 +264,7 @@ pub mod file;
pub mod filelist; pub mod filelist;
pub mod filereader; pub mod filereader;
pub mod focusevent; pub mod focusevent;
pub mod forcetouchevent;
pub mod formdata; pub mod formdata;
pub mod htmlanchorelement; pub mod htmlanchorelement;
pub mod htmlappletelement; pub mod htmlappletelement;

View file

@ -0,0 +1,35 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://developer.apple.com/library/mac/documentation/AppleApplications/Conceptual/SafariJSProgTopics/RespondingtoForceTouchEventsfromJavaScript.html
/**
* Events: (copy/paste from apple.com)
*
* webkitmouseforcewillbegin: This event occurs immediately before the mousedown event. It allows you to
* prevent the default system behavior, such as displaying a dictionary window when force clicking on a
* word, in order to perform a custom action instead. To prevent the default system behavior, call the
* preventDefault() method on the event.
* webkitmouseforcedown: This event occurs after the mousedown event, once enough force has been applied
* to register as a force click. The user receives haptic feedback representing the force click when this
* event occurs.
* webkitmouseforceup: This event occurs after a webkitmouseforcedown event, once enough force has been
* released to exit the force click operation. The user receives haptic feedback representing the exit
* from force click when this event occurs.
* webkitmouseforcechanged: This event occurs whenever a change in trackpad force is detected between the
* mousedown and mouseup events.
*
*/
[Pref="dom.forcetouch.enabled"]
interface ForceTouchEvent : UIEvent {
// Represents the amount of force required to perform a regular click.
readonly attribute float SERVO_FORCE_AT_MOUSE_DOWN;
// Represents the force required to perform a force click.
readonly attribute float SERVO_FORCE_AT_FORCE_MOUSE_DOWN;
// force level
readonly attribute float servoForce;
};

View file

@ -79,7 +79,7 @@ use parse::xml::{self, parse_xml};
use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan}; use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
use profile_traits::time::{self, ProfilerCategory, profile}; use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent}; use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
use script_traits::CompositorEvent::{TouchEvent}; use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent};
use script_traits::{CompositorEvent, ConstellationControlMsg, EventResult}; use script_traits::{CompositorEvent, ConstellationControlMsg, EventResult};
use script_traits::{InitialScriptState, MouseButton, MouseEventType, MozBrowserEvent, NewLayoutInfo}; use script_traits::{InitialScriptState, MouseButton, MouseEventType, MozBrowserEvent, NewLayoutInfo};
use script_traits::{LayoutMsg, OpaqueScriptLayoutChannel, ScriptMsg as ConstellationMsg}; use script_traits::{LayoutMsg, OpaqueScriptLayoutChannel, ScriptMsg as ConstellationMsg};
@ -1969,6 +1969,12 @@ impl ScriptThread {
} }
} }
TouchpadPressureEvent(point, pressure, phase) => {
let page = get_page(&self.root_page(), pipeline_id);
let document = page.document();
document.r().handle_touchpad_pressure_event(self.js_runtime.rt(), point, pressure, phase);
}
KeyEvent(key, state, modifiers) => { KeyEvent(key, state, modifiers) => {
let page = get_page(&self.root_page(), pipeline_id); let page = get_page(&self.root_page(), pipeline_id);
let document = page.document(); let document = page.document();

View file

@ -227,10 +227,23 @@ pub enum CompositorEvent {
MouseMoveEvent(Option<Point2D<f32>>), MouseMoveEvent(Option<Point2D<f32>>),
/// A touch event was generated with a touch ID and location. /// A touch event was generated with a touch ID and location.
TouchEvent(TouchEventType, TouchId, Point2D<f32>), TouchEvent(TouchEventType, TouchId, Point2D<f32>),
/// Touchpad pressure event
TouchpadPressureEvent(Point2D<f32>, f32, TouchpadPressurePhase),
/// A key was pressed. /// A key was pressed.
KeyEvent(Key, KeyState, KeyModifiers), KeyEvent(Key, KeyState, KeyModifiers),
} }
/// Touchpad pressure phase for TouchpadPressureEvent.
#[derive(Copy, Clone, HeapSizeOf, PartialEq, Deserialize, Serialize)]
pub enum TouchpadPressurePhase {
/// Pressure before a regular click.
BeforeClick,
/// Pressure after a regular click.
AfterFirstClick,
/// Pressure after a "forceTouch" click
AfterSecondClick,
}
/// An opaque wrapper around script<->layout channels to avoid leaking message types into /// An opaque wrapper around script<->layout channels to avoid leaking message types into
/// crates that don't need to know about them. /// crates that don't need to know about them.
pub struct OpaqueScriptLayoutChannel(pub (Box<Any + Send>, Box<Any + Send>)); pub struct OpaqueScriptLayoutChannel(pub (Box<Any + Send>, Box<Any + Send>));

View file

@ -20,7 +20,7 @@ use layers::platform::surface::NativeDisplay;
use msg::constellation_msg::{KeyState, NONE, CONTROL, SHIFT, ALT, SUPER}; use msg::constellation_msg::{KeyState, NONE, CONTROL, SHIFT, ALT, SUPER};
use msg::constellation_msg::{self, Key}; use msg::constellation_msg::{self, Key};
use net_traits::net_error_list::NetError; use net_traits::net_error_list::NetError;
use script_traits::TouchEventType; use script_traits::{TouchEventType, TouchpadPressurePhase};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::os::raw::c_void; use std::os::raw::c_void;
use std::rc::Rc; use std::rc::Rc;
@ -241,6 +241,12 @@ impl Window {
let point = Point2D::typed(touch.location.0 as f32, touch.location.1 as f32); 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)); self.event_queue.borrow_mut().push(WindowEvent::Touch(phase, id, point));
} }
Event::TouchpadPressure(pressure, stage) => {
let m = self.mouse_pos.get();
let point = Point2D::typed(m.x as f32, m.y as f32);
let phase = glutin_pressure_stage_to_touchpad_pressure_phase(stage);
self.event_queue.borrow_mut().push(WindowEvent::TouchpadPressure(point, pressure, phase));
}
Event::Refresh => { Event::Refresh => {
self.event_queue.borrow_mut().push(WindowEvent::Refresh); self.event_queue.borrow_mut().push(WindowEvent::Refresh);
} }
@ -812,6 +818,16 @@ fn glutin_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {
} }
} }
fn glutin_pressure_stage_to_touchpad_pressure_phase(stage: i64) -> TouchpadPressurePhase {
if stage < 1 {
TouchpadPressurePhase::BeforeClick
} else if stage < 2 {
TouchpadPressurePhase::AfterFirstClick
} else {
TouchpadPressurePhase::AfterSecondClick
}
}
// These functions aren't actually called. They are here as a link // These functions aren't actually called. They are here as a link
// hack because Skia references them. // hack because Skia references them.

View file

@ -1,4 +1,5 @@
{ {
"dom.forcetouch.enabled": false,
"dom.mouseevent.which.enabled": false, "dom.mouseevent.which.enabled": false,
"dom.mozbrowser.enabled": false, "dom.mozbrowser.enabled": false,
"gfx.webrender.enabled": false, "gfx.webrender.enabled": false,

View file

@ -23,6 +23,7 @@ var ecmaGlobals = [
"Float32Array", "Float32Array",
"Float64Array", "Float64Array",
"FocusEvent", "FocusEvent",
"ForceTouchEvent",
"Function", "Function",
"Infinity", "Infinity",
"Int16Array", "Int16Array",