dioxus_html/events/
pointer.rs

1use dioxus_core::Event;
2use keyboard_types::Modifiers;
3
4use crate::{geometry::*, input_data::*, *};
5
6/// A synthetic event that wraps a web-style [`PointerEvent`](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent)
7pub type PointerEvent = Event<PointerData>;
8
9pub struct PointerData {
10    inner: Box<dyn HasPointerData>,
11}
12
13impl PointerData {
14    /// Create a new PointerData
15    pub fn new(data: impl HasPointerData + 'static) -> Self {
16        Self::from(data)
17    }
18
19    /// Downcast this event to a concrete event type
20    #[inline(always)]
21    pub fn downcast<T: 'static>(&self) -> Option<&T> {
22        self.inner.as_any().downcast_ref::<T>()
23    }
24}
25
26impl<E: HasPointerData + 'static> From<E> for PointerData {
27    fn from(e: E) -> Self {
28        Self { inner: Box::new(e) }
29    }
30}
31
32impl std::fmt::Debug for PointerData {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        f.debug_struct("PointerData")
35            .field("pointer_id", &self.pointer_id())
36            .field("width", &self.width())
37            .field("height", &self.height())
38            .field("pressure", &self.pressure())
39            .field("tangential_pressure", &self.tangential_pressure())
40            .field("tilt_x", &self.tilt_x())
41            .field("tilt_y", &self.tilt_y())
42            .field("twist", &self.twist())
43            .field("pointer_type", &self.pointer_type())
44            .field("is_primary", &self.is_primary())
45            .field("coordinates", &self.coordinates())
46            .field("modifiers", &self.modifiers())
47            .field("held_buttons", &self.held_buttons())
48            .field("trigger_button", &self.trigger_button())
49            .finish()
50    }
51}
52
53impl PartialEq for PointerData {
54    fn eq(&self, other: &Self) -> bool {
55        self.pointer_id() == other.pointer_id()
56            && self.width() == other.width()
57            && self.height() == other.height()
58            && self.pressure() == other.pressure()
59            && self.tangential_pressure() == other.tangential_pressure()
60            && self.tilt_x() == other.tilt_x()
61            && self.tilt_y() == other.tilt_y()
62            && self.twist() == other.twist()
63            && self.pointer_type() == other.pointer_type()
64            && self.is_primary() == other.is_primary()
65            && self.coordinates() == other.coordinates()
66            && self.modifiers() == other.modifiers()
67            && self.held_buttons() == other.held_buttons()
68            && self.trigger_button() == other.trigger_button()
69    }
70}
71
72/// A trait for any object that has the data for a pointer event
73pub trait HasPointerData: PointerInteraction {
74    /// Gets the unique identifier of the pointer causing the event.
75    fn pointer_id(&self) -> i32;
76
77    /// Gets the width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer.
78    fn width(&self) -> f64;
79
80    /// Gets the height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer.
81    fn height(&self) -> f64;
82
83    /// Gets the normalized pressure of the pointer input in the range of 0 to 1,
84    fn pressure(&self) -> f32;
85
86    /// Gets the normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range -1 to 1,
87    fn tangential_pressure(&self) -> f32;
88
89    /// Gets the plane angle (in degrees, in the range of -90 to 90) between the Y-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the Y axis.
90    fn tilt_x(&self) -> i32;
91
92    /// Gets the plane angle (in degrees, in the range of -90 to 90) between the X-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the X axis.
93    fn tilt_y(&self) -> i32;
94
95    /// Gets the clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.The clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.
96    fn twist(&self) -> i32;
97
98    /// Gets the device type that caused the event (mouse, pen, touch, etc.).
99    fn pointer_type(&self) -> String;
100
101    /// Gets if the pointer represents the primary pointer of this pointer type.
102    fn is_primary(&self) -> bool;
103
104    /// return self as Any
105    fn as_any(&self) -> &dyn std::any::Any;
106}
107
108impl_event![
109    PointerData;
110    /// pointerdown
111    onpointerdown
112
113    /// pointermove
114    onpointermove
115
116    /// pointerup
117    onpointerup
118
119    /// pointercancel
120    onpointercancel
121
122    /// gotpointercapture
123    ongotpointercapture
124
125    /// lostpointercapture
126    onlostpointercapture
127
128    /// pointerenter
129    onpointerenter
130
131    /// pointerleave
132    onpointerleave
133
134    /// pointerover
135    onpointerover
136
137    /// pointerout
138    onpointerout
139
140    /// auxclick
141    onauxclick
142];
143
144impl PointerData {
145    /// Gets the unique identifier of the pointer causing the event.
146    pub fn pointer_id(&self) -> i32 {
147        self.inner.pointer_id()
148    }
149
150    /// Gets the width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer.
151    pub fn width(&self) -> f64 {
152        self.inner.width()
153    }
154
155    /// Gets the height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer.
156    pub fn height(&self) -> f64 {
157        self.inner.height()
158    }
159
160    /// Gets the normalized pressure of the pointer input in the range of 0 to 1,
161    pub fn pressure(&self) -> f32 {
162        self.inner.pressure()
163    }
164
165    /// Gets the normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range -1 to 1,
166    pub fn tangential_pressure(&self) -> f32 {
167        self.inner.tangential_pressure()
168    }
169
170    /// Gets the plane angle (in degrees, in the range of -90 to 90) between the Y-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the Y axis.
171    pub fn tilt_x(&self) -> i32 {
172        self.inner.tilt_x()
173    }
174
175    /// Gets the plane angle (in degrees, in the range of -90 to 90) between the X-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the X axis.
176    pub fn tilt_y(&self) -> i32 {
177        self.inner.tilt_y()
178    }
179
180    /// Gets the clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.The clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.
181    pub fn twist(&self) -> i32 {
182        self.inner.twist()
183    }
184
185    /// Gets the device type that caused the event (mouse, pen, touch, etc.).
186    pub fn pointer_type(&self) -> String {
187        self.inner.pointer_type()
188    }
189
190    /// Gets if the pointer represents the primary pointer of this pointer type.
191    pub fn is_primary(&self) -> bool {
192        self.inner.is_primary()
193    }
194}
195
196impl InteractionLocation for PointerData {
197    fn client_coordinates(&self) -> ClientPoint {
198        self.inner.client_coordinates()
199    }
200
201    fn screen_coordinates(&self) -> ScreenPoint {
202        self.inner.screen_coordinates()
203    }
204
205    fn page_coordinates(&self) -> PagePoint {
206        self.inner.page_coordinates()
207    }
208}
209
210impl InteractionElementOffset for PointerData {
211    fn element_coordinates(&self) -> ElementPoint {
212        self.inner.element_coordinates()
213    }
214}
215
216impl ModifiersInteraction for PointerData {
217    fn modifiers(&self) -> Modifiers {
218        self.inner.modifiers()
219    }
220}
221
222impl PointerInteraction for PointerData {
223    fn held_buttons(&self) -> MouseButtonSet {
224        self.inner.held_buttons()
225    }
226
227    fn trigger_button(&self) -> Option<MouseButton> {
228        self.inner.trigger_button()
229    }
230}
231
232#[cfg(feature = "serialize")]
233/// A serialized version of PointerData
234#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
235pub struct SerializedPointerData {
236    /// Common data for all pointer/mouse events
237    #[serde(flatten)]
238    point_data: crate::point_interaction::SerializedPointInteraction,
239
240    /// The unique identifier of the pointer causing the event.
241    pointer_id: i32,
242
243    /// The width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer.
244    width: f64,
245
246    /// The height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer.
247    height: f64,
248
249    /// The normalized pressure of the pointer input in the range of 0 to 1,
250    pressure: f32,
251
252    /// The normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range -1 to 1,
253    tangential_pressure: f32,
254
255    /// The plane angle (in degrees, in the range of -90 to 90) between the Y-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the Y axis.
256    tilt_x: i32,
257
258    /// The plane angle (in degrees, in the range of -90 to 90) between the X-Z plane and the plane containing both the transducer (e.g. pen stylus) axis and the X axis.
259    tilt_y: i32,
260
261    /// The clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.The clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range 0 to 359.
262    twist: i32,
263
264    /// Indicates the device type that caused the event (mouse, pen, touch, etc.).
265    pointer_type: String,
266
267    /// Indicates if the pointer represents the primary pointer of this pointer type.
268    is_primary: bool,
269}
270
271#[cfg(feature = "serialize")]
272impl HasPointerData for SerializedPointerData {
273    fn pointer_id(&self) -> i32 {
274        self.pointer_id
275    }
276
277    fn width(&self) -> f64 {
278        self.width
279    }
280
281    fn height(&self) -> f64 {
282        self.height
283    }
284
285    fn pressure(&self) -> f32 {
286        self.pressure
287    }
288
289    fn tangential_pressure(&self) -> f32 {
290        self.tangential_pressure
291    }
292
293    fn tilt_x(&self) -> i32 {
294        self.tilt_x
295    }
296
297    fn tilt_y(&self) -> i32 {
298        self.tilt_y
299    }
300
301    fn twist(&self) -> i32 {
302        self.twist
303    }
304
305    fn pointer_type(&self) -> String {
306        self.pointer_type.clone()
307    }
308
309    fn is_primary(&self) -> bool {
310        self.is_primary
311    }
312
313    fn as_any(&self) -> &dyn std::any::Any {
314        self
315    }
316}
317
318#[cfg(feature = "serialize")]
319impl InteractionLocation for SerializedPointerData {
320    fn client_coordinates(&self) -> ClientPoint {
321        self.point_data.client_coordinates()
322    }
323
324    fn screen_coordinates(&self) -> ScreenPoint {
325        self.point_data.screen_coordinates()
326    }
327
328    fn page_coordinates(&self) -> PagePoint {
329        self.point_data.page_coordinates()
330    }
331}
332
333#[cfg(feature = "serialize")]
334impl InteractionElementOffset for SerializedPointerData {
335    fn element_coordinates(&self) -> ElementPoint {
336        self.point_data.element_coordinates()
337    }
338}
339
340#[cfg(feature = "serialize")]
341impl ModifiersInteraction for SerializedPointerData {
342    fn modifiers(&self) -> Modifiers {
343        self.point_data.modifiers()
344    }
345}
346
347#[cfg(feature = "serialize")]
348impl PointerInteraction for SerializedPointerData {
349    fn held_buttons(&self) -> MouseButtonSet {
350        self.point_data.held_buttons()
351    }
352
353    fn trigger_button(&self) -> Option<MouseButton> {
354        self.point_data.trigger_button()
355    }
356}
357
358#[cfg(feature = "serialize")]
359impl From<&PointerData> for SerializedPointerData {
360    fn from(data: &PointerData) -> Self {
361        Self {
362            point_data: data.into(),
363            pointer_id: data.pointer_id(),
364            width: data.width(),
365            height: data.height(),
366            pressure: data.pressure(),
367            tangential_pressure: data.tangential_pressure(),
368            tilt_x: data.tilt_x(),
369            tilt_y: data.tilt_y(),
370            twist: data.twist(),
371            pointer_type: data.pointer_type().to_string(),
372            is_primary: data.is_primary(),
373        }
374    }
375}
376
377#[cfg(feature = "serialize")]
378impl serde::Serialize for PointerData {
379    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
380        SerializedPointerData::from(self).serialize(serializer)
381    }
382}
383
384#[cfg(feature = "serialize")]
385impl<'de> serde::Deserialize<'de> for PointerData {
386    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
387        let data = SerializedPointerData::deserialize(deserializer)?;
388        Ok(Self {
389            inner: Box::new(data),
390        })
391    }
392}