1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use dom::bindings::codegen::Bindings::MouseEventBinding;
6 use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
7 use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
8 use dom::bindings::error::Fallible;
9 use dom::bindings::inheritance::Castable;
10 use dom::bindings::reflector::reflect_dom_object;
11 use dom::bindings::root::{DomRoot, MutNullableDom, RootedReference};
12 use dom::bindings::str::DOMString;
13 use dom::event::{Event, EventBubbles, EventCancelable};
14 use dom::eventtarget::EventTarget;
15 use dom::uievent::UIEvent;
16 use dom::window::Window;
17 use dom_struct::dom_struct;
18 use euclid::Point2D;
19 use servo_config::prefs::PREFS;
20 use std::cell::Cell;
21 use std::default::Default;
22 
23 #[dom_struct]
24 pub struct MouseEvent {
25     uievent: UIEvent,
26     screen_x: Cell<i32>,
27     screen_y: Cell<i32>,
28     client_x: Cell<i32>,
29     client_y: Cell<i32>,
30     ctrl_key: Cell<bool>,
31     shift_key: Cell<bool>,
32     alt_key: Cell<bool>,
33     meta_key: Cell<bool>,
34     button: Cell<i16>,
35     related_target: MutNullableDom<EventTarget>,
36     point_in_target: Cell<Option<Point2D<f32>>>
37 }
38 
39 impl MouseEvent {
new_inherited() -> MouseEvent40     fn new_inherited() -> MouseEvent {
41         MouseEvent {
42             uievent: UIEvent::new_inherited(),
43             screen_x: Cell::new(0),
44             screen_y: Cell::new(0),
45             client_x: Cell::new(0),
46             client_y: Cell::new(0),
47             ctrl_key: Cell::new(false),
48             shift_key: Cell::new(false),
49             alt_key: Cell::new(false),
50             meta_key: Cell::new(false),
51             button: Cell::new(0),
52             related_target: Default::default(),
53             point_in_target: Cell::new(None),
54         }
55     }
56 
new_uninitialized(window: &Window) -> DomRoot<MouseEvent>57     pub fn new_uninitialized(window: &Window) -> DomRoot<MouseEvent> {
58         reflect_dom_object(Box::new(MouseEvent::new_inherited()),
59                            window,
60                            MouseEventBinding::Wrap)
61     }
62 
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>, point_in_target: Option<Point2D<f32>> ) -> DomRoot<MouseEvent>63     pub fn new(
64         window: &Window,
65         type_: DOMString,
66         can_bubble: EventBubbles,
67         cancelable: EventCancelable,
68         view: Option<&Window>,
69         detail: i32,
70         screen_x: i32,
71         screen_y: i32,
72         client_x: i32,
73         client_y: i32,
74         ctrl_key: bool,
75         alt_key: bool,
76         shift_key: bool,
77         meta_key: bool,
78         button: i16,
79         related_target: Option<&EventTarget>,
80         point_in_target: Option<Point2D<f32>>
81     ) -> DomRoot<MouseEvent> {
82         let ev = MouseEvent::new_uninitialized(window);
83         ev.InitMouseEvent(
84             type_, bool::from(can_bubble), bool::from(cancelable),
85             view, detail,
86             screen_x, screen_y, client_x, client_y,
87             ctrl_key, alt_key, shift_key, meta_key,
88             button, related_target,
89         );
90         ev.point_in_target.set(point_in_target);
91         ev
92     }
93 
Constructor(window: &Window, type_: DOMString, init: &MouseEventBinding::MouseEventInit) -> Fallible<DomRoot<MouseEvent>>94     pub fn Constructor(window: &Window,
95                        type_: DOMString,
96                        init: &MouseEventBinding::MouseEventInit) -> Fallible<DomRoot<MouseEvent>> {
97         let bubbles = EventBubbles::from(init.parent.parent.parent.bubbles);
98         let cancelable = EventCancelable::from(init.parent.parent.parent.cancelable);
99         let event = MouseEvent::new(
100             window,
101             type_,
102             bubbles,
103             cancelable,
104             init.parent.parent.view.r(),
105             init.parent.parent.detail,
106             init.screenX, init.screenY,
107             init.clientX, init.clientY, init.parent.ctrlKey,
108             init.parent.altKey, init.parent.shiftKey, init.parent.metaKey,
109             init.button, init.relatedTarget.r(), None
110         );
111         Ok(event)
112     }
113 
point_in_target(&self) -> Option<Point2D<f32>>114     pub fn point_in_target(&self) -> Option<Point2D<f32>> {
115         self.point_in_target.get()
116     }
117 }
118 
119 impl MouseEventMethods for MouseEvent {
120     // https://w3c.github.io/uievents/#widl-MouseEvent-screenX
ScreenX(&self) -> i32121     fn ScreenX(&self) -> i32 {
122         self.screen_x.get()
123     }
124 
125     // https://w3c.github.io/uievents/#widl-MouseEvent-screenY
ScreenY(&self) -> i32126     fn ScreenY(&self) -> i32 {
127         self.screen_y.get()
128     }
129 
130     // https://w3c.github.io/uievents/#widl-MouseEvent-clientX
ClientX(&self) -> i32131     fn ClientX(&self) -> i32 {
132         self.client_x.get()
133     }
134 
135     // https://w3c.github.io/uievents/#widl-MouseEvent-clientY
ClientY(&self) -> i32136     fn ClientY(&self) -> i32 {
137         self.client_y.get()
138     }
139 
140     // https://w3c.github.io/uievents/#widl-MouseEvent-ctrlKey
CtrlKey(&self) -> bool141     fn CtrlKey(&self) -> bool {
142         self.ctrl_key.get()
143     }
144 
145     // https://w3c.github.io/uievents/#widl-MouseEvent-shiftKey
ShiftKey(&self) -> bool146     fn ShiftKey(&self) -> bool {
147         self.shift_key.get()
148     }
149 
150     // https://w3c.github.io/uievents/#widl-MouseEvent-altKey
AltKey(&self) -> bool151     fn AltKey(&self) -> bool {
152         self.alt_key.get()
153     }
154 
155     // https://w3c.github.io/uievents/#widl-MouseEvent-metaKey
MetaKey(&self) -> bool156     fn MetaKey(&self) -> bool {
157         self.meta_key.get()
158     }
159 
160     // https://w3c.github.io/uievents/#widl-MouseEvent-button
Button(&self) -> i16161     fn Button(&self) -> i16 {
162         self.button.get()
163     }
164 
165     // https://w3c.github.io/uievents/#widl-MouseEvent-relatedTarget
GetRelatedTarget(&self) -> Option<DomRoot<EventTarget>>166     fn GetRelatedTarget(&self) -> Option<DomRoot<EventTarget>> {
167         self.related_target.get()
168     }
169 
170     // See discussion at:
171     //  - https://github.com/servo/servo/issues/6643
172     //  - https://bugzilla.mozilla.org/show_bug.cgi?id=1186125
173     // This returns the same result as current gecko.
174     // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which
Which(&self) -> i32175     fn Which(&self) -> i32 {
176         if PREFS.get("dom.mouseevent.which.enabled").as_boolean().unwrap_or(false) {
177             (self.button.get() + 1) as i32
178         } else {
179             0
180         }
181     }
182 
183     // https://w3c.github.io/uievents/#widl-MouseEvent-initMouseEvent
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>, )184     fn InitMouseEvent(
185         &self,
186         type_arg: DOMString,
187         can_bubble_arg: bool,
188         cancelable_arg: bool,
189         view_arg: Option<&Window>,
190         detail_arg: i32,
191         screen_x_arg: i32,
192         screen_y_arg: i32,
193         client_x_arg: i32,
194         client_y_arg: i32,
195         ctrl_key_arg: bool,
196         alt_key_arg: bool,
197         shift_key_arg: bool,
198         meta_key_arg: bool,
199         button_arg: i16,
200         related_target_arg: Option<&EventTarget>,
201     ) {
202         if self.upcast::<Event>().dispatching() {
203             return;
204         }
205 
206         self.upcast::<UIEvent>()
207             .InitUIEvent(type_arg, can_bubble_arg, cancelable_arg, view_arg, detail_arg);
208         self.screen_x.set(screen_x_arg);
209         self.screen_y.set(screen_y_arg);
210         self.client_x.set(client_x_arg);
211         self.client_y.set(client_y_arg);
212         self.ctrl_key.set(ctrl_key_arg);
213         self.alt_key.set(alt_key_arg);
214         self.shift_key.set(shift_key_arg);
215         self.meta_key.set(meta_key_arg);
216         self.button.set(button_arg);
217         self.related_target.set(related_target_arg);
218     }
219 
220     // https://dom.spec.whatwg.org/#dom-event-istrusted
IsTrusted(&self) -> bool221     fn IsTrusted(&self) -> bool {
222         self.uievent.IsTrusted()
223     }
224 }
225