1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use euclid::Point2D;
9use js::rust::HandleObject;
10use keyboard_types::Modifiers;
11use style::Atom;
12use style_traits::CSSPixel;
13
14use crate::dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
15use crate::dom::bindings::codegen::Bindings::WheelEventBinding;
16use crate::dom::bindings::codegen::Bindings::WheelEventBinding::WheelEventMethods;
17use crate::dom::bindings::error::Fallible;
18use crate::dom::bindings::inheritance::Castable;
19use crate::dom::bindings::num::Finite;
20use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
21use crate::dom::bindings::root::DomRoot;
22use crate::dom::bindings::str::DOMString;
23use crate::dom::event::{Event, EventBubbles, EventCancelable};
24use crate::dom::eventtarget::EventTarget;
25use crate::dom::mouseevent::MouseEvent;
26use crate::dom::window::Window;
27use crate::script_runtime::CanGc;
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 window: &Window,
51 proto: Option<HandleObject>,
52 can_gc: CanGc,
53 ) -> DomRoot<WheelEvent> {
54 reflect_dom_object_with_proto(Box::new(WheelEvent::new_inherited()), window, proto, can_gc)
55 }
56
57 #[allow(clippy::too_many_arguments)]
58 pub(crate) fn new(
59 window: &Window,
60 event_type: Atom,
61 can_bubble: EventBubbles,
62 cancelable: EventCancelable,
63 view: Option<&Window>,
64 detail: i32,
65 screen_point: Point2D<i32, CSSPixel>,
66 client_point: Point2D<i32, CSSPixel>,
67 page_point: Point2D<i32, CSSPixel>,
68 modifiers: Modifiers,
69 button: i16,
70 buttons: u16,
71 related_target: Option<&EventTarget>,
72 point_in_target: Option<Point2D<f32, CSSPixel>>,
73 delta_x: Finite<f64>,
74 delta_y: Finite<f64>,
75 delta_z: Finite<f64>,
76 delta_mode: u32,
77 can_gc: CanGc,
78 ) -> DomRoot<WheelEvent> {
79 Self::new_with_proto(
80 window,
81 None,
82 event_type,
83 can_bubble,
84 cancelable,
85 view,
86 detail,
87 screen_point,
88 client_point,
89 page_point,
90 modifiers,
91 button,
92 buttons,
93 related_target,
94 point_in_target,
95 delta_x,
96 delta_y,
97 delta_z,
98 delta_mode,
99 can_gc,
100 )
101 }
102
103 #[allow(clippy::too_many_arguments)]
104 fn new_with_proto(
105 window: &Window,
106 proto: Option<HandleObject>,
107 event_type: Atom,
108 can_bubble: EventBubbles,
109 cancelable: EventCancelable,
110 view: Option<&Window>,
111 detail: i32,
112 screen_point: Point2D<i32, CSSPixel>,
113 client_point: Point2D<i32, CSSPixel>,
114 page_point: Point2D<i32, CSSPixel>,
115 modifiers: Modifiers,
116 button: i16,
117 buttons: u16,
118 related_target: Option<&EventTarget>,
119 point_in_target: Option<Point2D<f32, CSSPixel>>,
120 delta_x: Finite<f64>,
121 delta_y: Finite<f64>,
122 delta_z: Finite<f64>,
123 delta_mode: u32,
124 can_gc: CanGc,
125 ) -> DomRoot<WheelEvent> {
126 let ev = WheelEvent::new_unintialized(window, proto, can_gc);
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 );
190 self.delta_x.set(delta_x);
191 self.delta_y.set(delta_y);
192 self.delta_z.set(delta_z);
193 self.delta_mode.set(delta_mode);
194 }
195}
196
197impl WheelEventMethods<crate::DomTypeHolder> for WheelEvent {
198 fn Constructor(
200 window: &Window,
201 proto: Option<HandleObject>,
202 can_gc: CanGc,
203 event_type: DOMString,
204 init: &WheelEventBinding::WheelEventInit,
205 ) -> Fallible<DomRoot<WheelEvent>> {
206 let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
207 let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
208 let scroll_offset = window.scroll_offset();
209
210 let page_point = Point2D::<i32, CSSPixel>::new(
211 scroll_offset.x as i32 + init.parent.clientX,
212 scroll_offset.y as i32 + init.parent.clientY,
213 );
214
215 let event = WheelEvent::new_with_proto(
216 window,
217 proto,
218 event_type.into(),
219 bubbles,
220 cancelable,
221 init.parent.parent.parent.view.as_deref(),
222 init.parent.parent.parent.detail,
223 Point2D::new(init.parent.screenX, init.parent.screenY),
224 Point2D::new(init.parent.clientX, init.parent.clientY),
225 Point2D::new(page_point.x, page_point.y),
226 init.parent.parent.modifiers(),
227 init.parent.button,
228 init.parent.buttons,
229 init.parent.relatedTarget.as_deref(),
230 None,
231 init.deltaX,
232 init.deltaY,
233 init.deltaZ,
234 init.deltaMode,
235 can_gc,
236 );
237
238 Ok(event)
239 }
240
241 fn DeltaX(&self) -> Finite<f64> {
243 self.delta_x.get()
244 }
245
246 fn DeltaY(&self) -> Finite<f64> {
248 self.delta_y.get()
249 }
250
251 fn DeltaZ(&self) -> Finite<f64> {
253 self.delta_z.get()
254 }
255
256 fn DeltaMode(&self) -> u32 {
258 self.delta_mode.get()
259 }
260
261 fn InitWheelEvent(
263 &self,
264 type_arg: DOMString,
265 can_bubble_arg: bool,
266 cancelable_arg: bool,
267 view_arg: Option<&Window>,
268 detail_arg: i32,
269 delta_x_arg: Finite<f64>,
270 delta_y_arg: Finite<f64>,
271 delta_z_arg: Finite<f64>,
272 delta_mode_arg: u32,
273 ) {
274 if self.upcast::<Event>().dispatching() {
275 return;
276 }
277
278 self.upcast::<MouseEvent>().InitMouseEvent(
279 type_arg,
280 can_bubble_arg,
281 cancelable_arg,
282 view_arg,
283 detail_arg,
284 self.mouseevent.ScreenX(),
285 self.mouseevent.ScreenY(),
286 self.mouseevent.ClientX(),
287 self.mouseevent.ClientY(),
288 self.mouseevent.CtrlKey(),
289 self.mouseevent.AltKey(),
290 self.mouseevent.ShiftKey(),
291 self.mouseevent.MetaKey(),
292 self.mouseevent.Button(),
293 self.mouseevent.GetRelatedTarget().as_deref(),
294 );
295 self.delta_x.set(delta_x_arg);
296 self.delta_y.set(delta_y_arg);
297 self.delta_z.set(delta_z_arg);
298 self.delta_mode.set(delta_mode_arg);
299 }
300
301 fn IsTrusted(&self) -> bool {
303 self.mouseevent.IsTrusted()
304 }
305}