aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/mouseevent.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/mouseevent.rs')
-rw-r--r--components/script/dom/mouseevent.rs293
1 files changed, 216 insertions, 77 deletions
diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs
index f19c37df868..d5fbe6b15e8 100644
--- a/components/script/dom/mouseevent.rs
+++ b/components/script/dom/mouseevent.rs
@@ -1,21 +1,24 @@
/* 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::MouseEventBinding;
-use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
-use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
-use dom::bindings::error::Fallible;
-use dom::bindings::inheritance::Castable;
-use dom::bindings::js::{MutNullableJS, Root, RootedReference};
-use dom::bindings::reflector::reflect_dom_object;
-use dom::bindings::str::DOMString;
-use dom::event::{Event, EventBubbles, EventCancelable};
-use dom::eventtarget::EventTarget;
-use dom::uievent::UIEvent;
-use dom::window::Window;
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMethods;
+use crate::dom::bindings::codegen::Bindings::MouseEventBinding;
+use crate::dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
+use crate::dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
+use crate::dom::bindings::error::Fallible;
+use crate::dom::bindings::inheritance::Castable;
+use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
+use crate::dom::bindings::root::{DomRoot, MutNullableDom};
+use crate::dom::bindings::str::DOMString;
+use crate::dom::event::{Event, EventBubbles, EventCancelable};
+use crate::dom::eventtarget::EventTarget;
+use crate::dom::node::Node;
+use crate::dom::uievent::UIEvent;
+use crate::dom::window::Window;
use dom_struct::dom_struct;
-use servo_config::prefs::PREFS;
+use euclid::default::Point2D;
+use servo_config::pref;
use std::cell::Cell;
use std::default::Default;
@@ -26,79 +29,131 @@ pub struct MouseEvent {
screen_y: Cell<i32>,
client_x: Cell<i32>,
client_y: Cell<i32>,
+ page_x: Cell<i32>,
+ page_y: Cell<i32>,
+ x: Cell<i32>,
+ y: Cell<i32>,
+ offset_x: Cell<i32>,
+ offset_y: Cell<i32>,
ctrl_key: Cell<bool>,
shift_key: Cell<bool>,
alt_key: Cell<bool>,
meta_key: Cell<bool>,
button: Cell<i16>,
- related_target: MutNullableJS<EventTarget>,
+ buttons: Cell<u16>,
+ related_target: MutNullableDom<EventTarget>,
+ point_in_target: Cell<Option<Point2D<f32>>>,
}
impl MouseEvent {
- fn new_inherited() -> MouseEvent {
+ pub fn new_inherited() -> MouseEvent {
MouseEvent {
uievent: UIEvent::new_inherited(),
screen_x: Cell::new(0),
screen_y: Cell::new(0),
client_x: Cell::new(0),
client_y: Cell::new(0),
+ page_x: Cell::new(0),
+ page_y: Cell::new(0),
+ x: Cell::new(0),
+ y: Cell::new(0),
+ offset_x: Cell::new(0),
+ offset_y: Cell::new(0),
ctrl_key: Cell::new(false),
shift_key: Cell::new(false),
alt_key: Cell::new(false),
meta_key: Cell::new(false),
button: Cell::new(0),
+ buttons: Cell::new(0),
related_target: Default::default(),
+ point_in_target: Cell::new(None),
}
}
- pub fn new_uninitialized(window: &Window) -> Root<MouseEvent> {
- reflect_dom_object(box MouseEvent::new_inherited(),
- window,
- MouseEventBinding::Wrap)
- }
-
- pub fn new(window: &Window,
- type_: DOMString,
- can_bubble: EventBubbles,
- cancelable: EventCancelable,
- view: Option<&Window>,
- detail: i32,
- screen_x: i32,
- screen_y: i32,
- client_x: i32,
- client_y: i32,
- ctrl_key: bool,
- alt_key: bool,
- shift_key: bool,
- meta_key: bool,
- button: i16,
- related_target: Option<&EventTarget>) -> Root<MouseEvent> {
+ pub fn new_uninitialized(window: &Window) -> DomRoot<MouseEvent> {
+ reflect_dom_object(Box::new(MouseEvent::new_inherited()), window)
+ }
+
+ pub fn new(
+ window: &Window,
+ type_: DOMString,
+ can_bubble: EventBubbles,
+ cancelable: EventCancelable,
+ view: Option<&Window>,
+ detail: i32,
+ screen_x: i32,
+ screen_y: i32,
+ client_x: i32,
+ client_y: i32,
+ ctrl_key: bool,
+ alt_key: bool,
+ shift_key: bool,
+ meta_key: bool,
+ button: i16,
+ buttons: u16,
+ related_target: Option<&EventTarget>,
+ point_in_target: Option<Point2D<f32>>,
+ ) -> DomRoot<MouseEvent> {
let ev = MouseEvent::new_uninitialized(window);
- ev.InitMouseEvent(type_, bool::from(can_bubble), bool::from(cancelable),
- view, detail,
- screen_x, screen_y, client_x, client_y,
- ctrl_key, alt_key, shift_key, meta_key,
- button, related_target);
+ ev.InitMouseEvent(
+ type_,
+ bool::from(can_bubble),
+ bool::from(cancelable),
+ view,
+ detail,
+ screen_x,
+ screen_y,
+ client_x,
+ client_y,
+ ctrl_key,
+ alt_key,
+ shift_key,
+ meta_key,
+ button,
+ related_target,
+ );
+ ev.buttons.set(buttons);
+ ev.point_in_target.set(point_in_target);
+ // TODO: Set proper values in https://github.com/servo/servo/issues/24415
+ ev.page_x.set(client_x);
+ ev.page_y.set(client_y);
ev
}
- pub fn Constructor(window: &Window,
- type_: DOMString,
- init: &MouseEventBinding::MouseEventInit) -> Fallible<Root<MouseEvent>> {
+ #[allow(non_snake_case)]
+ pub fn Constructor(
+ window: &Window,
+ type_: DOMString,
+ init: &MouseEventBinding::MouseEventInit,
+ ) -> Fallible<DomRoot<MouseEvent>> {
let bubbles = EventBubbles::from(init.parent.parent.parent.bubbles);
let cancelable = EventCancelable::from(init.parent.parent.parent.cancelable);
- let event = MouseEvent::new(window,
- type_,
- bubbles,
- cancelable,
- init.parent.parent.view.r(),
- init.parent.parent.detail,
- init.screenX, init.screenY,
- init.clientX, init.clientY, init.parent.ctrlKey,
- init.parent.altKey, init.parent.shiftKey, init.parent.metaKey,
- init.button, init.relatedTarget.r());
+ let event = MouseEvent::new(
+ window,
+ type_,
+ bubbles,
+ cancelable,
+ init.parent.parent.view.as_deref(),
+ init.parent.parent.detail,
+ init.screenX,
+ init.screenY,
+ init.clientX,
+ init.clientY,
+ init.parent.ctrlKey,
+ init.parent.altKey,
+ init.parent.shiftKey,
+ init.parent.metaKey,
+ init.button,
+ init.buttons,
+ init.relatedTarget.as_deref(),
+ None,
+ );
Ok(event)
}
+
+ pub fn point_in_target(&self) -> Option<Point2D<f32>> {
+ self.point_in_target.get()
+ }
}
impl MouseEventMethods for MouseEvent {
@@ -122,6 +177,78 @@ impl MouseEventMethods for MouseEvent {
self.client_y.get()
}
+ // https://drafts.csswg.org/cssom-view/#dom-mouseevent-pagex
+ fn PageX(&self) -> i32 {
+ if self.upcast::<Event>().dispatching() {
+ self.page_x.get()
+ } else {
+ let global = self.global();
+ let window = global.as_window();
+ window.current_viewport().origin.x.to_px() + self.client_x.get()
+ }
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-mouseevent-pagey
+ fn PageY(&self) -> i32 {
+ if self.upcast::<Event>().dispatching() {
+ self.page_y.get()
+ } else {
+ let global = self.global();
+ let window = global.as_window();
+ window.current_viewport().origin.y.to_px() + self.client_y.get()
+ }
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-mouseevent-x
+ fn X(&self) -> i32 {
+ self.client_x.get()
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-mouseevent-y
+ fn Y(&self) -> i32 {
+ self.client_y.get()
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsetx
+ fn OffsetX(&self) -> i32 {
+ let event = self.upcast::<Event>();
+ if event.dispatching() {
+ match event.GetTarget() {
+ Some(target) => {
+ if let Some(node) = target.downcast::<Node>() {
+ let rect = node.client_rect();
+ self.client_x.get() - rect.origin.x
+ } else {
+ self.offset_x.get()
+ }
+ },
+ None => self.offset_x.get(),
+ }
+ } else {
+ self.PageX()
+ }
+ }
+
+ // https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsety
+ fn OffsetY(&self) -> i32 {
+ let event = self.upcast::<Event>();
+ if event.dispatching() {
+ match event.GetTarget() {
+ Some(target) => {
+ if let Some(node) = target.downcast::<Node>() {
+ let rect = node.client_rect();
+ self.client_y.get() - rect.origin.y
+ } else {
+ self.offset_y.get()
+ }
+ },
+ None => self.offset_y.get(),
+ }
+ } else {
+ self.PageY()
+ }
+ }
+
// https://w3c.github.io/uievents/#widl-MouseEvent-ctrlKey
fn CtrlKey(&self) -> bool {
self.ctrl_key.get()
@@ -147,8 +274,13 @@ impl MouseEventMethods for MouseEvent {
self.button.get()
}
+ // https://w3c.github.io/uievents/#dom-mouseevent-buttons
+ fn Buttons(&self) -> u16 {
+ self.buttons.get()
+ }
+
// https://w3c.github.io/uievents/#widl-MouseEvent-relatedTarget
- fn GetRelatedTarget(&self) -> Option<Root<EventTarget>> {
+ fn GetRelatedTarget(&self) -> Option<DomRoot<EventTarget>> {
self.related_target.get()
}
@@ -158,7 +290,7 @@ impl MouseEventMethods for MouseEvent {
// This returns the same result as current gecko.
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which
fn Which(&self) -> i32 {
- if PREFS.get("dom.mouseevent.which.enabled").as_boolean().unwrap_or(false) {
+ if pref!(dom.mouse_event.which.enabled) {
(self.button.get() + 1) as i32
} else {
0
@@ -166,28 +298,35 @@ impl MouseEventMethods for MouseEvent {
}
// https://w3c.github.io/uievents/#widl-MouseEvent-initMouseEvent
- fn InitMouseEvent(&self,
- type_arg: DOMString,
- can_bubble_arg: bool,
- cancelable_arg: bool,
- view_arg: Option<&Window>,
- detail_arg: i32,
- screen_x_arg: i32,
- screen_y_arg: i32,
- client_x_arg: i32,
- client_y_arg: i32,
- ctrl_key_arg: bool,
- alt_key_arg: bool,
- shift_key_arg: bool,
- meta_key_arg: bool,
- button_arg: i16,
- related_target_arg: Option<&EventTarget>) {
+ fn InitMouseEvent(
+ &self,
+ type_arg: DOMString,
+ can_bubble_arg: bool,
+ cancelable_arg: bool,
+ view_arg: Option<&Window>,
+ detail_arg: i32,
+ screen_x_arg: i32,
+ screen_y_arg: i32,
+ client_x_arg: i32,
+ client_y_arg: i32,
+ ctrl_key_arg: bool,
+ alt_key_arg: bool,
+ shift_key_arg: bool,
+ meta_key_arg: bool,
+ button_arg: i16,
+ related_target_arg: Option<&EventTarget>,
+ ) {
if self.upcast::<Event>().dispatching() {
return;
}
- self.upcast::<UIEvent>()
- .InitUIEvent(type_arg, can_bubble_arg, cancelable_arg, view_arg, detail_arg);
+ self.upcast::<UIEvent>().InitUIEvent(
+ type_arg,
+ can_bubble_arg,
+ cancelable_arg,
+ view_arg,
+ detail_arg,
+ );
self.screen_x.set(screen_x_arg);
self.screen_y.set(screen_y_arg);
self.client_x.set(client_x_arg);