1use std::f64::consts::PI;
6
7use dom_struct::dom_struct;
8use euclid::Point2D;
9use js::context::JSContext;
10use js::rust::HandleObject;
11use script_bindings::inheritance::Castable;
12use script_bindings::reflector::{
13 Reflector, reflect_dom_object_with_cx, reflect_dom_object_with_proto,
14};
15
16use crate::dom::bindings::codegen::Bindings::TouchBinding::{TouchInit, TouchMethods};
17use crate::dom::bindings::num::Finite;
18use crate::dom::bindings::root::{DomRoot, MutDom};
19use crate::dom::event::{Event, EventBubbles, EventCancelable};
20use crate::dom::eventtarget::EventTarget;
21use crate::dom::pointerevent::PointerEvent;
22use crate::dom::window::Window;
23
24#[dom_struct]
25pub(crate) struct Touch {
26 reflector_: Reflector,
27 identifier: i32,
28 target: MutDom<EventTarget>,
29 screen_x: f64,
30 screen_y: f64,
31 client_x: f64,
32 client_y: f64,
33 page_x: f64,
34 page_y: f64,
35}
36
37impl Touch {
38 #[allow(clippy::too_many_arguments)]
39 fn new_inherited(
40 identifier: i32,
41 target: &EventTarget,
42 screen_x: Finite<f64>,
43 screen_y: Finite<f64>,
44 client_x: Finite<f64>,
45 client_y: Finite<f64>,
46 page_x: Finite<f64>,
47 page_y: Finite<f64>,
48 ) -> Touch {
49 Touch {
50 reflector_: Reflector::new(),
51 identifier,
52 target: MutDom::new(target),
53 screen_x: *screen_x,
54 screen_y: *screen_y,
55 client_x: *client_x,
56 client_y: *client_y,
57 page_x: *page_x,
58 page_y: *page_y,
59 }
60 }
61
62 #[allow(clippy::too_many_arguments)]
63 pub(crate) fn new(
64 cx: &mut JSContext,
65 window: &Window,
66 identifier: i32,
67 target: &EventTarget,
68 screen_x: Finite<f64>,
69 screen_y: Finite<f64>,
70 client_x: Finite<f64>,
71 client_y: Finite<f64>,
72 page_x: Finite<f64>,
73 page_y: Finite<f64>,
74 ) -> DomRoot<Touch> {
75 reflect_dom_object_with_cx(
76 Box::new(Touch::new_inherited(
77 identifier, target, screen_x, screen_y, client_x, client_y, page_x, page_y,
78 )),
79 window,
80 cx,
81 )
82 }
83
84 #[allow(clippy::too_many_arguments)]
85 fn new_with_proto(
86 cx: &mut JSContext,
87 window: &Window,
88 proto: Option<HandleObject>,
89 identifier: i32,
90 target: &EventTarget,
91 screen_x: Finite<f64>,
92 screen_y: Finite<f64>,
93 client_x: Finite<f64>,
94 client_y: Finite<f64>,
95 page_x: Finite<f64>,
96 page_y: Finite<f64>,
97 ) -> DomRoot<Touch> {
98 reflect_dom_object_with_proto(
99 cx,
100 Box::new(Touch::new_inherited(
101 identifier, target, screen_x, screen_y, client_x, client_y, page_x, page_y,
102 )),
103 window,
104 proto,
105 )
106 }
107
108 #[allow(clippy::too_many_arguments)]
111 pub(crate) fn to_pointer_event(
112 &self,
113 cx: &mut JSContext,
114 window: &Window,
115 event_type: &str,
116 pointer_id: i32,
117 is_primary: bool,
118 pointer_type: &str,
119 modifiers: keyboard_types::Modifiers,
120 is_cancelable: bool,
121 point_in_node: Option<euclid::Point2D<f32, style_traits::CSSPixel>>,
122 ) -> DomRoot<PointerEvent> {
123 let pressure = if event_type == "pointerup" ||
127 event_type == "pointercancel" ||
128 event_type == "pointerout" ||
129 event_type == "pointerleave"
130 {
131 0.0
132 } else {
133 0.5
134 };
135
136 let button = if event_type == "pointermove" ||
140 event_type == "pointerover" ||
141 event_type == "pointerenter" ||
142 event_type == "pointerout" ||
143 event_type == "pointerleave"
144 {
145 -1
146 } else {
147 0
148 };
149
150 let buttons = if event_type == "pointermove" ||
153 event_type == "pointerover" ||
154 event_type == "pointerenter" ||
155 event_type == "pointerdown"
156 {
157 1
158 } else {
159 0
160 };
161
162 let (bubbles, cancelable) = match event_type {
164 "pointerenter" | "pointerleave" => {
165 (EventBubbles::DoesNotBubble, EventCancelable::NotCancelable)
166 },
167 _ => (EventBubbles::Bubbles, EventCancelable::from(is_cancelable)),
168 };
169
170 let pointer_event = PointerEvent::new(
171 cx,
172 window,
173 event_type.into(),
174 bubbles,
175 cancelable,
176 Some(window),
177 0, Point2D::new(*self.ScreenX() as i32, *self.ScreenY() as i32),
179 Point2D::new(*self.ClientX() as i32, *self.ClientY() as i32),
180 Point2D::new(*self.PageX() as i32, *self.PageY() as i32),
181 modifiers,
182 button,
183 buttons,
184 None, point_in_node,
186 pointer_id,
187 1, 1, pressure,
190 0.0, 0, 0, 0, PI / 2.0, 0.0, pointer_type.into(),
197 is_primary,
198 vec![], vec![], );
201
202 let composed = !matches!(event_type, "pointerenter" | "pointerleave");
206 pointer_event.upcast::<Event>().set_composed(composed);
207
208 pointer_event
209 }
210}
211
212impl TouchMethods<crate::DomTypeHolder> for Touch {
213 #[allow(clippy::too_many_arguments)]
215 fn Constructor(
216 cx: &mut JSContext,
217 window: &Window,
218 proto: Option<HandleObject>,
219 touch_init_dict: &TouchInit,
220 ) -> DomRoot<Touch> {
221 Touch::new_with_proto(
222 cx,
223 window,
224 proto,
225 touch_init_dict.identifier,
226 &touch_init_dict.target,
227 touch_init_dict.screenX,
228 touch_init_dict.screenY,
229 touch_init_dict.clientX,
230 touch_init_dict.clientY,
231 touch_init_dict.pageX,
232 touch_init_dict.pageY,
233 )
234 }
235
236 fn Identifier(&self) -> i32 {
238 self.identifier
239 }
240
241 fn Target(&self) -> DomRoot<EventTarget> {
243 self.target.get()
244 }
245
246 fn ScreenX(&self) -> Finite<f64> {
248 Finite::wrap(self.screen_x)
249 }
250
251 fn ScreenY(&self) -> Finite<f64> {
253 Finite::wrap(self.screen_y)
254 }
255
256 fn ClientX(&self) -> Finite<f64> {
258 Finite::wrap(self.client_x)
259 }
260
261 fn ClientY(&self) -> Finite<f64> {
263 Finite::wrap(self.client_y)
264 }
265
266 fn PageX(&self) -> Finite<f64> {
268 Finite::wrap(self.page_x)
269 }
270
271 fn PageY(&self) -> Finite<f64> {
273 Finite::wrap(self.page_y)
274 }
275}