Skip to main content

dioxus_html/events/
pointer.rs

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