1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use euclid::Point2D;
9use js::context::JSContext;
10use js::rust::HandleObject;
11use keyboard_types::Modifiers;
12use script_bindings::reflector::reflect_dom_object_with_proto;
13use style::Atom;
14use style_traits::CSSPixel;
15
16use crate::dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
17use crate::dom::bindings::codegen::Bindings::WheelEventBinding;
18use crate::dom::bindings::codegen::Bindings::WheelEventBinding::WheelEventMethods;
19use crate::dom::bindings::error::Fallible;
20use crate::dom::bindings::inheritance::Castable;
21use crate::dom::bindings::num::Finite;
22use crate::dom::bindings::root::DomRoot;
23use crate::dom::bindings::str::DOMString;
24use crate::dom::event::{Event, EventBubbles, EventCancelable};
25use crate::dom::eventtarget::EventTarget;
26use crate::dom::mouseevent::MouseEvent;
27use crate::dom::window::Window;
28
29#[dom_struct]
30pub(crate) struct WheelEvent {
31 mouseevent: MouseEvent,
32 delta_x: Cell<Finite<f64>>,
33 delta_y: Cell<Finite<f64>>,
34 delta_z: Cell<Finite<f64>>,
35 delta_mode: Cell<u32>,
36}
37
38impl WheelEvent {
39 fn new_inherited() -> WheelEvent {
40 WheelEvent {
41 mouseevent: MouseEvent::new_inherited(),
42 delta_x: Cell::new(Finite::wrap(0.0)),
43 delta_y: Cell::new(Finite::wrap(0.0)),
44 delta_z: Cell::new(Finite::wrap(0.0)),
45 delta_mode: Cell::new(0),
46 }
47 }
48
49 fn new_unintialized(
50 cx: &mut JSContext,
51 window: &Window,
52 proto: Option<HandleObject>,
53 ) -> DomRoot<WheelEvent> {
54 reflect_dom_object_with_proto(cx, Box::new(WheelEvent::new_inherited()), window, proto)
55 }
56
57 #[allow(clippy::too_many_arguments)]
58 pub(crate) fn new(
59 cx: &mut JSContext,
60 window: &Window,
61 event_type: Atom,
62 can_bubble: EventBubbles,
63 cancelable: EventCancelable,
64 view: Option<&Window>,
65 detail: i32,
66 screen_point: Point2D<i32, CSSPixel>,
67 client_point: Point2D<i32, CSSPixel>,
68 page_point: Point2D<i32, CSSPixel>,
69 modifiers: Modifiers,
70 button: i16,
71 buttons: u16,
72 related_target: Option<&EventTarget>,
73 point_in_target: Option<Point2D<f32, CSSPixel>>,
74 delta_x: Finite<f64>,
75 delta_y: Finite<f64>,
76 delta_z: Finite<f64>,
77 delta_mode: u32,
78 ) -> DomRoot<WheelEvent> {
79 Self::new_with_proto(
80 cx,
81 window,
82 None,
83 event_type,
84 can_bubble,
85 cancelable,
86 view,
87 detail,
88 screen_point,
89 client_point,
90 page_point,
91 modifiers,
92 button,
93 buttons,
94 related_target,
95 point_in_target,
96 delta_x,
97 delta_y,
98 delta_z,
99 delta_mode,
100 )
101 }
102
103 #[allow(clippy::too_many_arguments)]
104 fn new_with_proto(
105 cx: &mut JSContext,
106 window: &Window,
107 proto: Option<HandleObject>,
108 event_type: Atom,
109 can_bubble: EventBubbles,
110 cancelable: EventCancelable,
111 view: Option<&Window>,
112 detail: i32,
113 screen_point: Point2D<i32, CSSPixel>,
114 client_point: Point2D<i32, CSSPixel>,
115 page_point: Point2D<i32, CSSPixel>,
116 modifiers: Modifiers,
117 button: i16,
118 buttons: u16,
119 related_target: Option<&EventTarget>,
120 point_in_target: Option<Point2D<f32, CSSPixel>>,
121 delta_x: Finite<f64>,
122 delta_y: Finite<f64>,
123 delta_z: Finite<f64>,
124 delta_mode: u32,
125 ) -> DomRoot<WheelEvent> {
126 let ev = WheelEvent::new_unintialized(cx, window, proto);
127 ev.intitialize_wheel_event(
128 event_type,
129 can_bubble,
130 cancelable,
131 view,
132 detail,
133 screen_point,
134 client_point,
135 page_point,
136 modifiers,
137 button,
138 buttons,
139 related_target,
140 point_in_target,
141 delta_x,
142 delta_y,
143 delta_z,
144 delta_mode,
145 );
146
147 ev
148 }
149
150 #[allow(clippy::too_many_arguments)]
151 pub(crate) fn intitialize_wheel_event(
152 &self,
153 event_type: Atom,
154 can_bubble: EventBubbles,
155 cancelable: EventCancelable,
156 view: Option<&Window>,
157 detail: i32,
158 screen_point: Point2D<i32, CSSPixel>,
159 client_point: Point2D<i32, CSSPixel>,
160 page_point: Point2D<i32, CSSPixel>,
161 modifiers: Modifiers,
162 button: i16,
163 buttons: u16,
164 related_target: Option<&EventTarget>,
165 point_in_target: Option<Point2D<f32, CSSPixel>>,
166 delta_x: Finite<f64>,
167 delta_y: Finite<f64>,
168 delta_z: Finite<f64>,
169 delta_mode: u32,
170 ) {
171 if self.upcast::<Event>().dispatching() {
172 return;
173 }
174
175 self.upcast::<MouseEvent>().initialize_mouse_event(
176 event_type,
177 can_bubble,
178 cancelable,
179 view,
180 detail,
181 screen_point,
182 client_point,
183 page_point,
184 modifiers,
185 button,
186 buttons,
187 related_target,
188 point_in_target,
189 None,
190 );
191 self.delta_x.set(delta_x);
192 self.delta_y.set(delta_y);
193 self.delta_z.set(delta_z);
194 self.delta_mode.set(delta_mode);
195 }
196}
197
198impl WheelEventMethods<crate::DomTypeHolder> for WheelEvent {
199 fn Constructor(
201 cx: &mut JSContext,
202 window: &Window,
203 proto: Option<HandleObject>,
204 event_type: DOMString,
205 init: &WheelEventBinding::WheelEventInit,
206 ) -> Fallible<DomRoot<WheelEvent>> {
207 let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
208 let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
209 let scroll_offset = window.scroll_offset();
210
211 let page_point = Point2D::<i32, CSSPixel>::new(
212 scroll_offset.x as i32 + init.parent.clientX,
213 scroll_offset.y as i32 + init.parent.clientY,
214 );
215
216 let event = WheelEvent::new_with_proto(
217 cx,
218 window,
219 proto,
220 event_type.into(),
221 bubbles,
222 cancelable,
223 init.parent.parent.parent.view.as_deref(),
224 init.parent.parent.parent.detail,
225 Point2D::new(init.parent.screenX, init.parent.screenY),
226 Point2D::new(init.parent.clientX, init.parent.clientY),
227 Point2D::new(page_point.x, page_point.y),
228 init.parent.parent.modifiers(),
229 init.parent.button,
230 init.parent.buttons,
231 init.parent.relatedTarget.as_deref(),
232 None,
233 init.deltaX,
234 init.deltaY,
235 init.deltaZ,
236 init.deltaMode,
237 );
238
239 Ok(event)
240 }
241
242 fn DeltaX(&self) -> Finite<f64> {
244 self.delta_x.get()
245 }
246
247 fn DeltaY(&self) -> Finite<f64> {
249 self.delta_y.get()
250 }
251
252 fn DeltaZ(&self) -> Finite<f64> {
254 self.delta_z.get()
255 }
256
257 fn DeltaMode(&self) -> u32 {
259 self.delta_mode.get()
260 }
261
262 fn InitWheelEvent(
264 &self,
265 type_arg: DOMString,
266 can_bubble_arg: bool,
267 cancelable_arg: bool,
268 view_arg: Option<&Window>,
269 detail_arg: i32,
270 delta_x_arg: Finite<f64>,
271 delta_y_arg: Finite<f64>,
272 delta_z_arg: Finite<f64>,
273 delta_mode_arg: u32,
274 ) {
275 if self.upcast::<Event>().dispatching() {
276 return;
277 }
278
279 self.upcast::<MouseEvent>().InitMouseEvent(
280 type_arg,
281 can_bubble_arg,
282 cancelable_arg,
283 view_arg,
284 detail_arg,
285 self.mouseevent.ScreenX(),
286 self.mouseevent.ScreenY(),
287 self.mouseevent.ClientX(),
288 self.mouseevent.ClientY(),
289 self.mouseevent.CtrlKey(),
290 self.mouseevent.AltKey(),
291 self.mouseevent.ShiftKey(),
292 self.mouseevent.MetaKey(),
293 self.mouseevent.Button(),
294 self.mouseevent.GetRelatedTarget().as_deref(),
295 );
296 self.delta_x.set(delta_x_arg);
297 self.delta_y.set(delta_y_arg);
298 self.delta_z.set(delta_z_arg);
299 self.delta_mode.set(delta_mode_arg);
300 }
301
302 fn IsTrusted(&self) -> bool {
304 self.mouseevent.IsTrusted()
305 }
306}