script/dom/
wheelevent.rs

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 https://mozilla.org/MPL/2.0/. */
4
5use 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    /// <https://w3c.github.io/uievents/#dom-wheelevent-wheelevent>
199    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    /// <https://w3c.github.io/uievents/#widl-WheelEvent-deltaX>
242    fn DeltaX(&self) -> Finite<f64> {
243        self.delta_x.get()
244    }
245
246    /// <https://w3c.github.io/uievents/#widl-WheelEvent-deltaY>
247    fn DeltaY(&self) -> Finite<f64> {
248        self.delta_y.get()
249    }
250
251    /// <https://w3c.github.io/uievents/#widl-WheelEvent-deltaZ>
252    fn DeltaZ(&self) -> Finite<f64> {
253        self.delta_z.get()
254    }
255
256    /// <https://w3c.github.io/uievents/#widl-WheelEvent-deltaMode>
257    fn DeltaMode(&self) -> u32 {
258        self.delta_mode.get()
259    }
260
261    /// <https://w3c.github.io/uievents/#widl-WheelEvent-initWheelEvent>
262    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    /// <https://dom.spec.whatwg.org/#dom-event-istrusted>
302    fn IsTrusted(&self) -> bool {
303        self.mouseevent.IsTrusted()
304    }
305}