aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorRobert Snakard <robert.snakard@gmail.com>2019-02-24 21:24:36 +0000
committerJosh Matthews <josh@joshmatthews.net>2019-06-09 13:25:01 -0400
commit35bca991ad4db3fe52ff6dd30bb3f7c567ba26e9 (patch)
tree4e7682b0903234354e4a82fbcbe51f1e2dbeb0fa /components/script/dom
parent8f11b52d9a80a51ddf80212817b87efc20bef8d6 (diff)
downloadservo-35bca991ad4db3fe52ff6dd30bb3f7c567ba26e9.tar.gz
servo-35bca991ad4db3fe52ff6dd30bb3f7c567ba26e9.zip
Implement WheelEvent Interface
Note: The WheelEvent interface supports rotation in all 3 spatial dimensions. This implementation only supports two due to limitations in the Glutin compositor. The wheelevent interface is a dom interface that triggers for any attached device that can rotate in one or more spatial dimensions. Traditionally this is the mouse wheel though other devices could be used as well. E.g. the trackball on a trackball mouse.
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/document.rs52
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/mouseevent.rs2
-rw-r--r--components/script/dom/webidls/WheelEvent.webidl33
-rw-r--r--components/script/dom/wheelevent.rs163
5 files changed, 249 insertions, 2 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 3583e7b8842..1122fa52552 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -97,6 +97,7 @@ use crate::dom::treewalker::TreeWalker;
use crate::dom::uievent::UIEvent;
use crate::dom::virtualmethods::vtable_for;
use crate::dom::webglcontextevent::WebGLContextEvent;
+use crate::dom::wheelevent::WheelEvent;
use crate::dom::window::{ReflowReason, Window};
use crate::dom::windowproxy::WindowProxy;
use crate::fetch::FetchCanceller;
@@ -135,7 +136,9 @@ use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataR
use ref_slice::ref_slice;
use script_layout_interface::message::{Msg, ReflowGoal};
use script_traits::{AnimationState, DocumentActivity, MouseButton, MouseEventType};
-use script_traits::{MsDuration, ScriptMsg, TouchEventType, TouchId, UntrustedNodeAddress};
+use script_traits::{
+ MsDuration, ScriptMsg, TouchEventType, TouchId, UntrustedNodeAddress, WheelDelta,
+};
use servo_arc::Arc;
use servo_atoms::Atom;
use servo_config::pref;
@@ -1219,6 +1222,53 @@ impl Document {
}
#[allow(unsafe_code)]
+ pub fn handle_wheel_event(
+ &self,
+ js_runtime: *mut JSRuntime,
+ delta: WheelDelta,
+ client_point: Point2D<f32>,
+ node_address: Option<UntrustedNodeAddress>,
+ ) {
+ let wheel_event_type_string = "wheel".to_owned();
+ debug!("{}: at {:?}", wheel_event_type_string, client_point);
+
+ let el = node_address.and_then(|address| {
+ let node = unsafe { node::from_untrusted_node_address(js_runtime, address) };
+ node.inclusive_ancestors(ShadowIncluding::No)
+ .filter_map(DomRoot::downcast::<Element>)
+ .next()
+ });
+
+ let el = match el {
+ Some(el) => el,
+ None => return,
+ };
+
+ let node = el.upcast::<Node>();
+ debug!("{}: on {:?}", wheel_event_type_string, node.debug_str());
+
+ // https://w3c.github.io/uievents/#event-wheelevents
+ let event = WheelEvent::new(
+ &self.window,
+ DOMString::from(wheel_event_type_string),
+ EventBubbles::Bubbles,
+ EventCancelable::Cancelable,
+ Some(&self.window),
+ 0i32,
+ Finite::wrap(delta.x),
+ Finite::wrap(delta.y),
+ Finite::wrap(delta.z),
+ delta.mode as u32,
+ );
+
+ let event = event.upcast::<Event>();
+ event.set_trusted(true);
+
+ let target = node.upcast();
+ event.fire(target);
+ }
+
+ #[allow(unsafe_code)]
pub fn handle_touch_event(
&self,
js_runtime: *mut JSRuntime,
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index cf8d8a49389..b4365a405b2 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -528,6 +528,7 @@ pub mod webgltexture;
pub mod webgluniformlocation;
pub mod webglvertexarrayobjectoes;
pub mod websocket;
+pub mod wheelevent;
pub mod window;
pub mod windowproxy;
pub mod worker;
diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs
index 6fcadbbeaf8..7a54a20925b 100644
--- a/components/script/dom/mouseevent.rs
+++ b/components/script/dom/mouseevent.rs
@@ -38,7 +38,7 @@ pub struct MouseEvent {
}
impl MouseEvent {
- fn new_inherited() -> MouseEvent {
+ pub fn new_inherited() -> MouseEvent {
MouseEvent {
uievent: UIEvent::new_inherited(),
screen_x: Cell::new(0),
diff --git a/components/script/dom/webidls/WheelEvent.webidl b/components/script/dom/webidls/WheelEvent.webidl
new file mode 100644
index 00000000000..a38b87dd97d
--- /dev/null
+++ b/components/script/dom/webidls/WheelEvent.webidl
@@ -0,0 +1,33 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+// https://w3c.github.io/uievents/#interface-wheelevent
+[Constructor(DOMString typeArg, optional WheelEventInit wheelEventInitDict),
+ Exposed=Window]
+interface WheelEvent : MouseEvent {
+ const unsigned long DOM_DELTA_PIXEL = 0x00;
+ const unsigned long DOM_DELTA_LINE = 0x01;
+ const unsigned long DOM_DELTA_PAGE = 0x02;
+ readonly attribute double deltaX;
+ readonly attribute double deltaY;
+ readonly attribute double deltaZ;
+ readonly attribute unsigned long deltaMode;
+};
+
+// https://w3c.github.io/uievents/#idl-wheeleventinit
+dictionary WheelEventInit : MouseEventInit {
+ double deltaX = 0.0;
+ double deltaY = 0.0;
+ double deltaZ = 0.0;
+ unsigned long deltaMode = 0;
+};
+
+// https://w3c.github.io/uievents/#idl-interface-WheelEvent-initializers
+partial interface WheelEvent {
+ // Deprecated in DOM Level 3
+ void initWheelEvent (DOMString typeArg, boolean bubblesArg, boolean cancelableArg,
+ Window? viewArg, long detailArg,
+ double deltaX, double deltaY,
+ double deltaZ, unsigned long deltaMode);
+};
diff --git a/components/script/dom/wheelevent.rs b/components/script/dom/wheelevent.rs
new file mode 100644
index 00000000000..0fd23db8da8
--- /dev/null
+++ b/components/script/dom/wheelevent.rs
@@ -0,0 +1,163 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+use crate::dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
+use crate::dom::bindings::codegen::Bindings::WheelEventBinding;
+use crate::dom::bindings::codegen::Bindings::WheelEventBinding::WheelEventMethods;
+use crate::dom::bindings::error::Fallible;
+use crate::dom::bindings::inheritance::Castable;
+use crate::dom::bindings::num::Finite;
+use crate::dom::bindings::reflector::reflect_dom_object;
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::bindings::str::DOMString;
+use crate::dom::event::{Event, EventBubbles, EventCancelable};
+use crate::dom::mouseevent::MouseEvent;
+use crate::dom::window::Window;
+use dom_struct::dom_struct;
+use std::cell::Cell;
+
+#[dom_struct]
+pub struct WheelEvent {
+ mouseevent: MouseEvent,
+ delta_x: Cell<Finite<f64>>,
+ delta_y: Cell<Finite<f64>>,
+ delta_z: Cell<Finite<f64>>,
+ delta_mode: Cell<u32>,
+}
+
+impl WheelEvent {
+ fn new_inherited() -> WheelEvent {
+ WheelEvent {
+ mouseevent: MouseEvent::new_inherited(),
+ delta_x: Cell::new(Finite::wrap(0.0)),
+ delta_y: Cell::new(Finite::wrap(0.0)),
+ delta_z: Cell::new(Finite::wrap(0.0)),
+ delta_mode: Cell::new(0),
+ }
+ }
+
+ pub fn new_unintialized(window: &Window) -> DomRoot<WheelEvent> {
+ reflect_dom_object(
+ Box::new(WheelEvent::new_inherited()),
+ window,
+ WheelEventBinding::Wrap,
+ )
+ }
+
+ pub fn new(
+ window: &Window,
+ type_: DOMString,
+ can_bubble: EventBubbles,
+ cancelable: EventCancelable,
+ view: Option<&Window>,
+ detail: i32,
+ delta_x: Finite<f64>,
+ delta_y: Finite<f64>,
+ delta_z: Finite<f64>,
+ delta_mode: u32,
+ ) -> DomRoot<WheelEvent> {
+ let ev = WheelEvent::new_unintialized(window);
+ ev.InitWheelEvent(
+ type_,
+ bool::from(can_bubble),
+ bool::from(cancelable),
+ view,
+ detail,
+ delta_x,
+ delta_y,
+ delta_z,
+ delta_mode,
+ );
+
+ ev
+ }
+
+ pub fn Constructor(
+ window: &Window,
+ type_: DOMString,
+ init: &WheelEventBinding::WheelEventInit,
+ ) -> Fallible<DomRoot<WheelEvent>> {
+ let event = WheelEvent::new(
+ window,
+ type_,
+ EventBubbles::from(init.parent.parent.parent.parent.bubbles),
+ EventCancelable::from(init.parent.parent.parent.parent.cancelable),
+ init.parent.parent.parent.view.deref(),
+ init.parent.parent.parent.detail,
+ init.deltaX,
+ init.deltaY,
+ init.deltaZ,
+ init.deltaMode,
+ );
+
+ Ok(event)
+ }
+}
+
+impl WheelEventMethods for WheelEvent {
+ // https://w3c.github.io/uievents/#widl-WheelEvent-deltaX
+ fn DeltaX(&self) -> Finite<f64> {
+ self.delta_x.get()
+ }
+
+ // https://w3c.github.io/uievents/#widl-WheelEvent-deltaY
+ fn DeltaY(&self) -> Finite<f64> {
+ self.delta_y.get()
+ }
+
+ // https://w3c.github.io/uievents/#widl-WheelEvent-deltaZ
+ fn DeltaZ(&self) -> Finite<f64> {
+ self.delta_z.get()
+ }
+
+ // https://w3c.github.io/uievents/#widl-WheelEvent-deltaMode
+ fn DeltaMode(&self) -> u32 {
+ self.delta_mode.get()
+ }
+
+ // https://w3c.github.io/uievents/#widl-WheelEvent-initWheelEvent
+ fn InitWheelEvent(
+ &self,
+ type_arg: DOMString,
+ can_bubble_arg: bool,
+ cancelable_arg: bool,
+ view_arg: Option<&Window>,
+ detail_arg: i32,
+ delta_x_arg: Finite<f64>,
+ delta_y_arg: Finite<f64>,
+ delta_z_arg: Finite<f64>,
+ delta_mode_arg: u32,
+ ) {
+ if self.upcast::<Event>().dispatching() {
+ return;
+ }
+
+ self.upcast::<MouseEvent>().InitMouseEvent(
+ type_arg,
+ can_bubble_arg,
+ cancelable_arg,
+ view_arg,
+ detail_arg,
+ self.mouseevent.ScreenX(),
+ self.mouseevent.ScreenY(),
+ self.mouseevent.ClientX(),
+ self.mouseevent.ClientY(),
+ self.mouseevent.CtrlKey(),
+ self.mouseevent.AltKey(),
+ self.mouseevent.ShiftKey(),
+ self.mouseevent.MetaKey(),
+ self.mouseevent.Button(),
+ self.mouseevent.GetRelatedTarget().deref(),
+ );
+ self.delta_x.set(delta_x_arg);
+ self.delta_y.set(delta_y_arg);
+ self.delta_z.set(delta_z_arg);
+ self.delta_mode.set(delta_mode_arg);
+ }
+
+ // https://dom.spec.whatwg.org/#dom-event-istrusted
+ fn IsTrusted(&self) -> bool {
+ self.mouseevent.IsTrusted()
+ }
+}