dioxus_html/events/
touch.rs1use dioxus_core::Event;
2use keyboard_types::Modifiers;
3
4use crate::geometry::*;
5use crate::{InteractionLocation, ModifiersInteraction};
6
7pub type TouchEvent = Event<TouchData>;
8pub struct TouchData {
9 inner: Box<dyn HasTouchData>,
10}
11
12impl<E: HasTouchData> From<E> for TouchData {
13 fn from(e: E) -> Self {
14 Self { inner: Box::new(e) }
15 }
16}
17
18impl std::fmt::Debug for TouchData {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 f.debug_struct("TouchData")
21 .field("modifiers", &self.modifiers())
22 .field("touches", &self.touches())
23 .field("touches_changed", &self.touches_changed())
24 .field("target_touches", &self.target_touches())
25 .finish()
26 }
27}
28
29impl PartialEq for TouchData {
30 fn eq(&self, other: &Self) -> bool {
31 self.modifiers() == other.modifiers()
32 }
33}
34
35impl TouchData {
36 pub fn new(inner: impl HasTouchData + 'static) -> Self {
38 Self {
39 inner: Box::new(inner),
40 }
41 }
42
43 pub fn touches(&self) -> Vec<TouchPoint> {
45 self.inner.touches()
46 }
47
48 pub fn touches_changed(&self) -> Vec<TouchPoint> {
50 self.inner.touches_changed()
51 }
52
53 pub fn target_touches(&self) -> Vec<TouchPoint> {
55 self.inner.target_touches()
56 }
57
58 #[inline(always)]
60 pub fn downcast<T: 'static>(&self) -> Option<&T> {
61 self.inner.as_any().downcast_ref::<T>()
62 }
63}
64
65impl ModifiersInteraction for TouchData {
66 fn modifiers(&self) -> Modifiers {
67 self.inner.modifiers()
68 }
69}
70
71#[cfg(feature = "serialize")]
72#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
74pub struct SerializedTouchData {
75 alt_key: bool,
76 ctrl_key: bool,
77 meta_key: bool,
78 shift_key: bool,
79 touches: Vec<SerializedTouchPoint>,
80 changed_touches: Vec<SerializedTouchPoint>,
81 target_touches: Vec<SerializedTouchPoint>,
82}
83
84#[cfg(feature = "serialize")]
85impl From<&TouchData> for SerializedTouchData {
86 fn from(data: &TouchData) -> Self {
87 let modifiers = data.modifiers();
88 Self {
89 alt_key: modifiers.contains(Modifiers::ALT),
90 ctrl_key: modifiers.contains(Modifiers::CONTROL),
91 meta_key: modifiers.contains(Modifiers::META),
92 shift_key: modifiers.contains(Modifiers::SHIFT),
93 touches: data.touches().iter().map(|t| t.into()).collect(),
94 changed_touches: data.touches_changed().iter().map(|t| t.into()).collect(),
95 target_touches: data.target_touches().iter().map(|t| t.into()).collect(),
96 }
97 }
98}
99
100#[cfg(feature = "serialize")]
101impl ModifiersInteraction for SerializedTouchData {
102 fn modifiers(&self) -> Modifiers {
103 let mut modifiers = Modifiers::default();
104 if self.alt_key {
105 modifiers.insert(Modifiers::ALT);
106 }
107 if self.ctrl_key {
108 modifiers.insert(Modifiers::CONTROL);
109 }
110 if self.meta_key {
111 modifiers.insert(Modifiers::META);
112 }
113 if self.shift_key {
114 modifiers.insert(Modifiers::SHIFT);
115 }
116 modifiers
117 }
118}
119
120#[cfg(feature = "serialize")]
121impl HasTouchData for SerializedTouchData {
122 fn touches(&self) -> Vec<TouchPoint> {
123 self.touches.clone().into_iter().map(Into::into).collect()
124 }
125
126 fn touches_changed(&self) -> Vec<TouchPoint> {
127 self.changed_touches
128 .clone()
129 .into_iter()
130 .map(Into::into)
131 .collect()
132 }
133
134 fn target_touches(&self) -> Vec<TouchPoint> {
135 self.target_touches
136 .clone()
137 .into_iter()
138 .map(Into::into)
139 .collect()
140 }
141
142 fn as_any(&self) -> &dyn std::any::Any {
143 self
144 }
145}
146
147#[cfg(feature = "serialize")]
148impl serde::Serialize for TouchData {
149 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
150 SerializedTouchData::from(self).serialize(serializer)
151 }
152}
153
154#[cfg(feature = "serialize")]
155impl<'de> serde::Deserialize<'de> for TouchData {
156 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
157 let data = SerializedTouchData::deserialize(deserializer)?;
158 Ok(Self {
159 inner: Box::new(data),
160 })
161 }
162}
163
164pub trait HasTouchData: ModifiersInteraction + std::any::Any {
165 fn touches(&self) -> Vec<TouchPoint>;
167
168 fn touches_changed(&self) -> Vec<TouchPoint>;
170
171 fn target_touches(&self) -> Vec<TouchPoint>;
173
174 fn as_any(&self) -> &dyn std::any::Any;
176}
177
178pub struct TouchPoint {
179 inner: Box<dyn HasTouchPointData>,
180}
181
182impl<E: HasTouchPointData> From<E> for TouchPoint {
183 fn from(e: E) -> Self {
184 Self { inner: Box::new(e) }
185 }
186}
187
188impl TouchPoint {
189 pub fn new(inner: impl HasTouchPointData + 'static) -> Self {
191 Self {
192 inner: Box::new(inner),
193 }
194 }
195
196 fn identifier(&self) -> i32 {
198 self.inner.identifier()
199 }
200
201 fn force(&self) -> f64 {
203 self.inner.force()
204 }
205
206 fn radius(&self) -> ScreenPoint {
208 self.inner.radius()
209 }
210
211 fn rotation(&self) -> f64 {
213 self.inner.rotation()
214 }
215
216 #[inline(always)]
218 pub fn downcast<T: 'static>(&self) -> Option<&T> {
219 self.inner.as_any().downcast_ref::<T>()
220 }
221}
222
223impl std::fmt::Debug for TouchPoint {
224 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225 f.debug_struct("TouchPoint")
226 .field("client_coordinates", &self.client_coordinates())
227 .field("page_coordinates", &self.page_coordinates())
228 .field("screen_coordinates", &self.screen_coordinates())
229 .field("identifier", &self.identifier())
230 .field("force", &self.force())
231 .field("radius", &self.radius())
232 .field("rotation", &self.rotation())
233 .finish()
234 }
235}
236
237impl InteractionLocation for TouchPoint {
238 fn client_coordinates(&self) -> ClientPoint {
239 self.inner.client_coordinates()
240 }
241
242 fn page_coordinates(&self) -> PagePoint {
243 self.inner.page_coordinates()
244 }
245
246 fn screen_coordinates(&self) -> ScreenPoint {
247 self.inner.screen_coordinates()
248 }
249}
250
251pub trait HasTouchPointData: InteractionLocation + std::any::Any {
253 fn identifier(&self) -> i32;
255
256 fn force(&self) -> f64;
258
259 fn radius(&self) -> ScreenPoint;
261
262 fn rotation(&self) -> f64;
264
265 fn as_any(&self) -> &dyn std::any::Any;
267}
268
269#[cfg(feature = "serialize")]
270#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
272struct SerializedTouchPoint {
273 identifier: i32,
274 client_x: f64,
275 client_y: f64,
276 page_x: f64,
277 page_y: f64,
278 screen_x: f64,
279 screen_y: f64,
280 force: f64,
281 radius_x: f64,
282 radius_y: f64,
283 rotation_angle: f64,
284}
285
286#[cfg(feature = "serialize")]
287impl From<&TouchPoint> for SerializedTouchPoint {
288 fn from(point: &TouchPoint) -> Self {
289 let client_coordinates = point.client_coordinates();
290
291 let page_coordinates = point.page_coordinates();
292 let screen_coordinates = point.screen_coordinates();
293 Self {
294 identifier: point.identifier(),
295 client_x: client_coordinates.x,
296 client_y: client_coordinates.y,
297 page_x: page_coordinates.x,
298 page_y: page_coordinates.y,
299 screen_x: screen_coordinates.x,
300 screen_y: screen_coordinates.y,
301 force: point.force(),
302 radius_x: point.radius().x,
303 radius_y: point.radius().y,
304 rotation_angle: point.rotation(),
305 }
306 }
307}
308
309#[cfg(feature = "serialize")]
310impl HasTouchPointData for SerializedTouchPoint {
311 fn identifier(&self) -> i32 {
313 self.identifier
314 }
315
316 fn force(&self) -> f64 {
318 self.force
319 }
320
321 fn radius(&self) -> ScreenPoint {
323 ScreenPoint::new(self.radius_x, self.radius_y)
324 }
325
326 fn rotation(&self) -> f64 {
328 self.rotation_angle
329 }
330
331 fn as_any(&self) -> &dyn std::any::Any {
333 self
334 }
335}
336
337#[cfg(feature = "serialize")]
338impl InteractionLocation for SerializedTouchPoint {
339 fn client_coordinates(&self) -> ClientPoint {
341 ClientPoint::new(self.client_x, self.client_y)
342 }
343
344 fn screen_coordinates(&self) -> ScreenPoint {
346 ScreenPoint::new(self.screen_x, self.screen_y)
347 }
348
349 fn page_coordinates(&self) -> PagePoint {
351 PagePoint::new(self.page_x, self.page_y)
352 }
353}
354
355impl_event! {
356 TouchData;
357 ontouchstart
359
360 ontouchmove
362
363 ontouchend
365
366 ontouchcancel
368}