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_and_cx;
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_and_cx(
55 Box::new(WheelEvent::new_inherited()),
56 window,
57 proto,
58 cx,
59 )
60 }
61
62 #[allow(clippy::too_many_arguments)]
63 pub(crate) fn new(
64 cx: &mut JSContext,
65 window: &Window,
66 event_type: Atom,
67 can_bubble: EventBubbles,
68 cancelable: EventCancelable,
69 view: Option<&Window>,
70 detail: i32,
71 screen_point: Point2D<i32, CSSPixel>,
72 client_point: Point2D<i32, CSSPixel>,
73 page_point: Point2D<i32, CSSPixel>,
74 modifiers: Modifiers,
75 button: i16,
76 buttons: u16,
77 related_target: Option<&EventTarget>,
78 point_in_target: Option<Point2D<f32, CSSPixel>>,
79 delta_x: Finite<f64>,
80 delta_y: Finite<f64>,
81 delta_z: Finite<f64>,
82 delta_mode: u32,
83 ) -> DomRoot<WheelEvent> {
84 Self::new_with_proto(
85 cx,
86 window,
87 None,
88 event_type,
89 can_bubble,
90 cancelable,
91 view,
92 detail,
93 screen_point,
94 client_point,
95 page_point,
96 modifiers,
97 button,
98 buttons,
99 related_target,
100 point_in_target,
101 delta_x,
102 delta_y,
103 delta_z,
104 delta_mode,
105 )
106 }
107
108 #[allow(clippy::too_many_arguments)]
109 fn new_with_proto(
110 cx: &mut JSContext,
111 window: &Window,
112 proto: Option<HandleObject>,
113 event_type: Atom,
114 can_bubble: EventBubbles,
115 cancelable: EventCancelable,
116 view: Option<&Window>,
117 detail: i32,
118 screen_point: Point2D<i32, CSSPixel>,
119 client_point: Point2D<i32, CSSPixel>,
120 page_point: Point2D<i32, CSSPixel>,
121 modifiers: Modifiers,
122 button: i16,
123 buttons: u16,
124 related_target: Option<&EventTarget>,
125 point_in_target: Option<Point2D<f32, CSSPixel>>,
126 delta_x: Finite<f64>,
127 delta_y: Finite<f64>,
128 delta_z: Finite<f64>,
129 delta_mode: u32,
130 ) -> DomRoot<WheelEvent> {
131 let ev = WheelEvent::new_unintialized(cx, window, proto);
132 ev.intitialize_wheel_event(
133 event_type,
134 can_bubble,
135 cancelable,
136 view,
137 detail,
138 screen_point,
139 client_point,
140 page_point,
141 modifiers,
142 button,
143 buttons,
144 related_target,
145 point_in_target,
146 delta_x,
147 delta_y,
148 delta_z,
149 delta_mode,
150 );
151
152 ev
153 }
154
155 #[allow(clippy::too_many_arguments)]
156 pub(crate) fn intitialize_wheel_event(
157 &self,
158 event_type: Atom,
159 can_bubble: EventBubbles,
160 cancelable: EventCancelable,
161 view: Option<&Window>,
162 detail: i32,
163 screen_point: Point2D<i32, CSSPixel>,
164 client_point: Point2D<i32, CSSPixel>,
165 page_point: Point2D<i32, CSSPixel>,
166 modifiers: Modifiers,
167 button: i16,
168 buttons: u16,
169 related_target: Option<&EventTarget>,
170 point_in_target: Option<Point2D<f32, CSSPixel>>,
171 delta_x: Finite<f64>,
172 delta_y: Finite<f64>,
173 delta_z: Finite<f64>,
174 delta_mode: u32,
175 ) {
176 if self.upcast::<Event>().dispatching() {
177 return;
178 }
179
180 self.upcast::<MouseEvent>().initialize_mouse_event(
181 event_type,
182 can_bubble,
183 cancelable,
184 view,
185 detail,
186 screen_point,
187 client_point,
188 page_point,
189 modifiers,
190 button,
191 buttons,
192 related_target,
193 point_in_target,
194 );
195 self.delta_x.set(delta_x);
196 self.delta_y.set(delta_y);
197 self.delta_z.set(delta_z);
198 self.delta_mode.set(delta_mode);
199 }
200}
201
202impl WheelEventMethods<crate::DomTypeHolder> for WheelEvent {
203 fn Constructor(
205 cx: &mut JSContext,
206 window: &Window,
207 proto: Option<HandleObject>,
208 event_type: DOMString,
209 init: &WheelEventBinding::WheelEventInit,
210 ) -> Fallible<DomRoot<WheelEvent>> {
211 let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
212 let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
213 let scroll_offset = window.scroll_offset();
214
215 let page_point = Point2D::<i32, CSSPixel>::new(
216 scroll_offset.x as i32 + init.parent.clientX,
217 scroll_offset.y as i32 + init.parent.clientY,
218 );
219
220 let event = WheelEvent::new_with_proto(
221 cx,
222 window,
223 proto,
224 event_type.into(),
225 bubbles,
226 cancelable,
227 init.parent.parent.parent.view.as_deref(),
228 init.parent.parent.parent.detail,
229 Point2D::new(init.parent.screenX, init.parent.screenY),
230 Point2D::new(init.parent.clientX, init.parent.clientY),
231 Point2D::new(page_point.x, page_point.y),
232 init.parent.parent.modifiers(),
233 init.parent.button,
234 init.parent.buttons,
235 init.parent.relatedTarget.as_deref(),
236 None,
237 init.deltaX,
238 init.deltaY,
239 init.deltaZ,
240 init.deltaMode,
241 );
242
243 Ok(event)
244 }
245
246 fn DeltaX(&self) -> Finite<f64> {
248 self.delta_x.get()
249 }
250
251 fn DeltaY(&self) -> Finite<f64> {
253 self.delta_y.get()
254 }
255
256 fn DeltaZ(&self) -> Finite<f64> {
258 self.delta_z.get()
259 }
260
261 fn DeltaMode(&self) -> u32 {
263 self.delta_mode.get()
264 }
265
266 fn InitWheelEvent(
268 &self,
269 type_arg: DOMString,
270 can_bubble_arg: bool,
271 cancelable_arg: bool,
272 view_arg: Option<&Window>,
273 detail_arg: i32,
274 delta_x_arg: Finite<f64>,
275 delta_y_arg: Finite<f64>,
276 delta_z_arg: Finite<f64>,
277 delta_mode_arg: u32,
278 ) {
279 if self.upcast::<Event>().dispatching() {
280 return;
281 }
282
283 self.upcast::<MouseEvent>().InitMouseEvent(
284 type_arg,
285 can_bubble_arg,
286 cancelable_arg,
287 view_arg,
288 detail_arg,
289 self.mouseevent.ScreenX(),
290 self.mouseevent.ScreenY(),
291 self.mouseevent.ClientX(),
292 self.mouseevent.ClientY(),
293 self.mouseevent.CtrlKey(),
294 self.mouseevent.AltKey(),
295 self.mouseevent.ShiftKey(),
296 self.mouseevent.MetaKey(),
297 self.mouseevent.Button(),
298 self.mouseevent.GetRelatedTarget().as_deref(),
299 );
300 self.delta_x.set(delta_x_arg);
301 self.delta_y.set(delta_y_arg);
302 self.delta_z.set(delta_z_arg);
303 self.delta_mode.set(delta_mode_arg);
304 }
305
306 fn IsTrusted(&self) -> bool {
308 self.mouseevent.IsTrusted()
309 }
310}