diff options
Diffstat (limited to 'components/script/dom/mouseevent.rs')
-rw-r--r-- | components/script/dom/mouseevent.rs | 293 |
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); |