/* 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; 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; 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::uievent::UIEvent; use crate::dom::window::Window; use dom_struct::dom_struct; use euclid::default::Point2D; use servo_config::pref; use std::cell::Cell; use std::default::Default; #[dom_struct] pub struct MouseEvent { uievent: UIEvent, screen_x: Cell, screen_y: Cell, client_x: Cell, client_y: Cell, ctrl_key: Cell, shift_key: Cell, alt_key: Cell, meta_key: Cell, button: Cell, buttons: Cell, related_target: MutNullableDom, point_in_target: Cell>>, } impl 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), 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) -> DomRoot { reflect_dom_object( Box::new(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, buttons: u16, related_target: Option<&EventTarget>, point_in_target: Option>, ) -> DomRoot { 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.buttons.set(buttons); ev.point_in_target.set(point_in_target); ev } pub fn Constructor( window: &Window, type_: DOMString, init: &MouseEventBinding::MouseEventInit, ) -> Fallible> { 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.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, 0, init.relatedTarget.as_deref(), None, ); Ok(event) } pub fn point_in_target(&self) -> Option> { self.point_in_target.get() } } impl MouseEventMethods for MouseEvent { // https://w3c.github.io/uievents/#widl-MouseEvent-screenX fn ScreenX(&self) -> i32 { self.screen_x.get() } // https://w3c.github.io/uievents/#widl-MouseEvent-screenY fn ScreenY(&self) -> i32 { self.screen_y.get() } // https://w3c.github.io/uievents/#widl-MouseEvent-clientX fn ClientX(&self) -> i32 { self.client_x.get() } // https://w3c.github.io/uievents/#widl-MouseEvent-clientY fn ClientY(&self) -> i32 { self.client_y.get() } // https://w3c.github.io/uievents/#widl-MouseEvent-ctrlKey fn CtrlKey(&self) -> bool { self.ctrl_key.get() } // https://w3c.github.io/uievents/#widl-MouseEvent-shiftKey fn ShiftKey(&self) -> bool { self.shift_key.get() } // https://w3c.github.io/uievents/#widl-MouseEvent-altKey fn AltKey(&self) -> bool { self.alt_key.get() } // https://w3c.github.io/uievents/#widl-MouseEvent-metaKey fn MetaKey(&self) -> bool { self.meta_key.get() } // https://w3c.github.io/uievents/#widl-MouseEvent-button fn Button(&self) -> i16 { 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> { self.related_target.get() } // See discussion at: // - https://github.com/servo/servo/issues/6643 // - https://bugzilla.mozilla.org/show_bug.cgi?id=1186125 // This returns the same result as current gecko. // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which fn Which(&self) -> i32 { if pref!(dom.mouse_event.which.enabled) { (self.button.get() + 1) as i32 } else { 0 } } // 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>, ) { if self.upcast::().dispatching() { return; } self.upcast::().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); self.client_y.set(client_y_arg); self.ctrl_key.set(ctrl_key_arg); self.alt_key.set(alt_key_arg); self.shift_key.set(shift_key_arg); self.meta_key.set(meta_key_arg); self.button.set(button_arg); self.related_target.set(related_target_arg); } // https://dom.spec.whatwg.org/#dom-event-istrusted fn IsTrusted(&self) -> bool { self.uievent.IsTrusted() } }