script/dom/
touch.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::f64::consts::PI;
6
7use dom_struct::dom_struct;
8use euclid::Point2D;
9
10use crate::dom::bindings::codegen::Bindings::TouchBinding::TouchMethods;
11use crate::dom::bindings::num::Finite;
12use crate::dom::bindings::reflector::{Reflector, reflect_dom_object};
13use crate::dom::bindings::root::{DomRoot, MutDom};
14use crate::dom::bindings::str::DOMString;
15use crate::dom::event::{EventBubbles, EventCancelable};
16use crate::dom::eventtarget::EventTarget;
17use crate::dom::pointerevent::PointerEvent;
18use crate::dom::window::Window;
19use crate::script_runtime::CanGc;
20
21#[dom_struct]
22pub(crate) struct Touch {
23    reflector_: Reflector,
24    identifier: i32,
25    target: MutDom<EventTarget>,
26    screen_x: f64,
27    screen_y: f64,
28    client_x: f64,
29    client_y: f64,
30    page_x: f64,
31    page_y: f64,
32}
33
34impl Touch {
35    #[allow(clippy::too_many_arguments)]
36    fn new_inherited(
37        identifier: i32,
38        target: &EventTarget,
39        screen_x: Finite<f64>,
40        screen_y: Finite<f64>,
41        client_x: Finite<f64>,
42        client_y: Finite<f64>,
43        page_x: Finite<f64>,
44        page_y: Finite<f64>,
45    ) -> Touch {
46        Touch {
47            reflector_: Reflector::new(),
48            identifier,
49            target: MutDom::new(target),
50            screen_x: *screen_x,
51            screen_y: *screen_y,
52            client_x: *client_x,
53            client_y: *client_y,
54            page_x: *page_x,
55            page_y: *page_y,
56        }
57    }
58
59    #[allow(clippy::too_many_arguments)]
60    pub(crate) fn new(
61        window: &Window,
62        identifier: i32,
63        target: &EventTarget,
64        screen_x: Finite<f64>,
65        screen_y: Finite<f64>,
66        client_x: Finite<f64>,
67        client_y: Finite<f64>,
68        page_x: Finite<f64>,
69        page_y: Finite<f64>,
70        can_gc: CanGc,
71    ) -> DomRoot<Touch> {
72        reflect_dom_object(
73            Box::new(Touch::new_inherited(
74                identifier, target, screen_x, screen_y, client_x, client_y, page_x, page_y,
75            )),
76            window,
77            can_gc,
78        )
79    }
80
81    /// Create a PointerEvent from this Touch.
82    /// <https://w3c.github.io/pointerevents/#the-primary-pointer>
83    #[allow(clippy::too_many_arguments)]
84    pub(crate) fn to_pointer_event(
85        &self,
86        window: &Window,
87        event_type: &str,
88        pointer_id: i32,
89        is_primary: bool,
90        modifiers: keyboard_types::Modifiers,
91        is_cancelable: bool,
92        point_in_node: Option<euclid::Point2D<f32, style_traits::CSSPixel>>,
93        can_gc: CanGc,
94    ) -> DomRoot<PointerEvent> {
95        // Pressure is 0.5 for active touches, 0.0 for up/cancel
96        let pressure = if event_type == "pointerup" || event_type == "pointercancel" {
97            0.0
98        } else {
99            0.5
100        };
101
102        let button = if event_type == "pointermove" { -1 } else { 0 };
103
104        let buttons = if event_type == "pointermove" ||
105            event_type == "pointerover" ||
106            event_type == "pointerenter" ||
107            event_type == "pointerdown"
108        {
109            1
110        } else {
111            0
112        };
113
114        PointerEvent::new(
115            window,
116            DOMString::from(event_type),
117            EventBubbles::Bubbles,
118            EventCancelable::from(is_cancelable),
119            Some(window),
120            0, // detail
121            Point2D::new(*self.ScreenX() as i32, *self.ScreenY() as i32),
122            Point2D::new(*self.ClientX() as i32, *self.ClientY() as i32),
123            Point2D::new(*self.PageX() as i32, *self.PageY() as i32),
124            modifiers,
125            button,
126            buttons,
127            None, // related_target
128            point_in_node,
129            pointer_id,
130            1, // width (TODO: could get from touch if available)
131            1, // height (TODO: could get from touch if available)
132            pressure,
133            0.0,      // tangential_pressure
134            0,        // tilt_x
135            0,        // tilt_y
136            0,        // twist
137            PI / 2.0, // altitude_angle (perpendicular to surface)
138            0.0,      // azimuth_angle
139            DOMString::from("touch"),
140            is_primary,
141            vec![], // coalesced_events
142            vec![], // predicted_events
143            can_gc,
144        )
145    }
146}
147
148impl TouchMethods<crate::DomTypeHolder> for Touch {
149    /// <https://w3c.github.io/touch-events/#widl-Touch-identifier>
150    fn Identifier(&self) -> i32 {
151        self.identifier
152    }
153
154    /// <https://w3c.github.io/touch-events/#widl-Touch-target>
155    fn Target(&self) -> DomRoot<EventTarget> {
156        self.target.get()
157    }
158
159    /// <https://w3c.github.io/touch-events/#widl-Touch-screenX>
160    fn ScreenX(&self) -> Finite<f64> {
161        Finite::wrap(self.screen_x)
162    }
163
164    /// <https://w3c.github.io/touch-events/#widl-Touch-screenY>
165    fn ScreenY(&self) -> Finite<f64> {
166        Finite::wrap(self.screen_y)
167    }
168
169    /// <https://w3c.github.io/touch-events/#widl-Touch-clientX>
170    fn ClientX(&self) -> Finite<f64> {
171        Finite::wrap(self.client_x)
172    }
173
174    /// <https://w3c.github.io/touch-events/#widl-Touch-clientY>
175    fn ClientY(&self) -> Finite<f64> {
176        Finite::wrap(self.client_y)
177    }
178
179    /// <https://w3c.github.io/touch-events/#widl-Touch-clientX>
180    fn PageX(&self) -> Finite<f64> {
181        Finite::wrap(self.page_x)
182    }
183
184    /// <https://w3c.github.io/touch-events/#widl-Touch-clientY>
185    fn PageY(&self) -> Finite<f64> {
186        Finite::wrap(self.page_y)
187    }
188}