aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/document.rs69
-rw-r--r--components/script/dom/forcetouchevent.rs59
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/webidls/ForceTouchEvent.webidl35
-rw-r--r--components/script/script_thread.rs8
6 files changed, 172 insertions, 3 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 2491058750c..a23a5452f1c 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -64,7 +64,7 @@ use net_traits::storage_thread::StorageType;
use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan;
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 smallvec::SmallVec;
use std::boxed::FnBox;
@@ -319,6 +319,7 @@ no_jsmanaged_fields!(AttrIdentifier);
no_jsmanaged_fields!(AttrValue);
no_jsmanaged_fields!(ElementSnapshot);
no_jsmanaged_fields!(HttpsState);
+no_jsmanaged_fields!(TouchpadPressurePhase);
impl JSTraceable for ConstellationChan<ScriptMsg> {
#[inline]
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 703a7c90572..c99099e04f9 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -41,6 +41,7 @@ use dom::element::{Element, ElementCreator};
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
use dom::focusevent::FocusEvent;
+use dom::forcetouchevent::ForceTouchEvent;
use dom::htmlanchorelement::HTMLAnchorElement;
use dom::htmlappletelement::HTMLAppletElement;
use dom::htmlareaelement::HTMLAreaElement;
@@ -97,7 +98,7 @@ use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, ScriptC
use script_traits::UntrustedNodeAddress;
use script_traits::{AnimationState, MouseButton, MouseEventType, MozBrowserEvent};
use script_traits::{ScriptMsg as ConstellationMsg, ScriptToCompositorMsg};
-use script_traits::{TouchEventType, TouchId};
+use script_traits::{TouchpadPressurePhase, TouchEventType, TouchId};
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::boxed::FnBox;
@@ -218,6 +219,7 @@ pub struct Document {
css_errors_store: DOMRefCell<Vec<CSSError>>,
/// https://html.spec.whatwg.org/multipage/#concept-document-https-state
https_state: Cell<HttpsState>,
+ touchpad_pressure_phase: Cell<TouchpadPressurePhase>,
}
#[derive(JSTraceable, HeapSizeOf)]
@@ -732,6 +734,70 @@ impl Document {
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) {
let client_x = client_point.x.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()),
css_errors_store: DOMRefCell::new(vec![]),
https_state: Cell::new(HttpsState::None),
+ touchpad_pressure_phase: Cell::new(TouchpadPressurePhase::BeforeClick),
}
}
diff --git a/components/script/dom/forcetouchevent.rs b/components/script/dom/forcetouchevent.rs
new file mode 100644
index 00000000000..b0fd6376760
--- /dev/null
+++ b/components/script/dom/forcetouchevent.rs
@@ -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()
+ }
+}
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index 662f41dc7a9..36921d8be89 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -264,6 +264,7 @@ pub mod file;
pub mod filelist;
pub mod filereader;
pub mod focusevent;
+pub mod forcetouchevent;
pub mod formdata;
pub mod htmlanchorelement;
pub mod htmlappletelement;
diff --git a/components/script/dom/webidls/ForceTouchEvent.webidl b/components/script/dom/webidls/ForceTouchEvent.webidl
new file mode 100644
index 00000000000..a5f8ceef9a4
--- /dev/null
+++ b/components/script/dom/webidls/ForceTouchEvent.webidl
@@ -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;
+};
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 5cd38e80532..6726a6ca4e2 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -79,7 +79,7 @@ use parse::xml::{self, parse_xml};
use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
use profile_traits::time::{self, ProfilerCategory, profile};
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::{InitialScriptState, MouseButton, MouseEventType, MozBrowserEvent, NewLayoutInfo};
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) => {
let page = get_page(&self.root_page(), pipeline_id);
let document = page.document();