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