use dioxus_core::Event; use keyboard_types::Modifiers; use crate::{geometry::*, input_data::*, *}; /// A synthetic event that wraps a web-style [`PointerEvent`](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent) pub type PointerEvent = Event; pub struct PointerData { inner: Box, } impl PointerData { /// Create a new PointerData pub fn new(data: impl HasPointerData + 'static) -> Self { Self::from(data) } /// Downcast this event to a concrete event type #[inline(always)] pub fn downcast(&self) -> Option<&T> { self.inner.as_any().downcast_ref::() } } impl From for PointerData { fn from(e: E) -> Self { Self { inner: Box::new(e) } } } impl std::fmt::Debug for PointerData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("PointerData") .field("pointer_id", &self.pointer_id()) .field("width", &self.width()) .field("height", &self.height()) .field("pressure", &self.pressure()) .field("tangential_pressure", &self.tangential_pressure()) .field("tilt_x", &self.tilt_x()) .field("tilt_y", &self.tilt_y()) .field("twist", &self.twist()) .field("pointer_type", &self.pointer_type()) .field("is_primary", &self.is_primary()) .field("coordinates", &self.coordinates()) .field("modifiers", &self.modifiers()) .field("held_buttons", &self.held_buttons()) .field("trigger_button", &self.trigger_button()) .finish() } } impl PartialEq for PointerData { fn eq(&self, other: &Self) -> bool { self.pointer_id() == other.pointer_id() && self.width() == other.width() && self.height() == other.height() && self.pressure() == other.pressure() && self.tangential_pressure() == other.tangential_pressure() && self.tilt_x() == other.tilt_x() && self.tilt_y() == other.tilt_y() && self.twist() == other.twist() && self.pointer_type() == other.pointer_type() && self.is_primary() == other.is_primary() && self.coordinates() == other.coordinates() && self.modifiers() == other.modifiers() && self.held_buttons() == other.held_buttons() && self.trigger_button() == other.trigger_button() } } /// A trait for any object that has the data for a pointer event pub trait HasPointerData: PointerInteraction { /// Gets the unique identifier of the pointer causing the event. fn pointer_id(&self) -> i32; /// Gets the width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer. fn width(&self) -> i32; /// Gets the height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer. fn height(&self) -> i32; /// Gets the normalized pressure of the pointer input in the range of 0 to 1, fn pressure(&self) -> f32; /// Gets the normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range -1 to 1, fn tangential_pressure(&self) -> f32; /// 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. fn tilt_x(&self) -> i32; /// 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. fn tilt_y(&self) -> i32; /// 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. fn twist(&self) -> i32; /// Gets the device type that caused the event (mouse, pen, touch, etc.). fn pointer_type(&self) -> String; /// Gets if the pointer represents the primary pointer of this pointer type. fn is_primary(&self) -> bool; /// return self as Any fn as_any(&self) -> &dyn std::any::Any; } impl_event![ PointerData; /// pointerdown onpointerdown /// pointermove onpointermove /// pointerup onpointerup /// pointercancel onpointercancel /// gotpointercapture ongotpointercapture /// lostpointercapture onlostpointercapture /// pointerenter onpointerenter /// pointerleave onpointerleave /// pointerover onpointerover /// pointerout onpointerout ]; impl PointerData { /// Gets the unique identifier of the pointer causing the event. pub fn pointer_id(&self) -> i32 { self.inner.pointer_id() } /// Gets the width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer. pub fn width(&self) -> i32 { self.inner.width() } /// Gets the height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer. pub fn height(&self) -> i32 { self.inner.height() } /// Gets the normalized pressure of the pointer input in the range of 0 to 1, pub fn pressure(&self) -> f32 { self.inner.pressure() } /// Gets the normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range -1 to 1, pub fn tangential_pressure(&self) -> f32 { self.inner.tangential_pressure() } /// 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. pub fn tilt_x(&self) -> i32 { self.inner.tilt_x() } /// 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. pub fn tilt_y(&self) -> i32 { self.inner.tilt_y() } /// 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. pub fn twist(&self) -> i32 { self.inner.twist() } /// Gets the device type that caused the event (mouse, pen, touch, etc.). pub fn pointer_type(&self) -> String { self.inner.pointer_type() } /// Gets if the pointer represents the primary pointer of this pointer type. pub fn is_primary(&self) -> bool { self.inner.is_primary() } } impl InteractionLocation for PointerData { fn client_coordinates(&self) -> ClientPoint { self.inner.client_coordinates() } fn screen_coordinates(&self) -> ScreenPoint { self.inner.screen_coordinates() } fn page_coordinates(&self) -> PagePoint { self.inner.page_coordinates() } } impl InteractionElementOffset for PointerData { fn element_coordinates(&self) -> ElementPoint { self.inner.element_coordinates() } } impl ModifiersInteraction for PointerData { fn modifiers(&self) -> Modifiers { self.inner.modifiers() } } impl PointerInteraction for PointerData { fn held_buttons(&self) -> MouseButtonSet { self.inner.held_buttons() } fn trigger_button(&self) -> Option { self.inner.trigger_button() } } #[cfg(feature = "serialize")] /// A serialized version of PointerData #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)] pub struct SerializedPointerData { /// Common data for all pointer/mouse events #[serde(flatten)] point_data: crate::point_interaction::SerializedPointInteraction, /// The unique identifier of the pointer causing the event. pointer_id: i32, /// The width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer. width: i32, /// The height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer. height: i32, /// The normalized pressure of the pointer input in the range of 0 to 1, pressure: f32, /// The normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range -1 to 1, tangential_pressure: f32, /// 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. tilt_x: i32, /// 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. tilt_y: i32, /// 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. twist: i32, /// Indicates the device type that caused the event (mouse, pen, touch, etc.). pointer_type: String, /// Indicates if the pointer represents the primary pointer of this pointer type. is_primary: bool, } #[cfg(feature = "serialize")] impl HasPointerData for SerializedPointerData { fn pointer_id(&self) -> i32 { self.pointer_id } fn width(&self) -> i32 { self.width } fn height(&self) -> i32 { self.height } fn pressure(&self) -> f32 { self.pressure } fn tangential_pressure(&self) -> f32 { self.tangential_pressure } fn tilt_x(&self) -> i32 { self.tilt_x } fn tilt_y(&self) -> i32 { self.tilt_y } fn twist(&self) -> i32 { self.twist } fn pointer_type(&self) -> String { self.pointer_type.clone() } fn is_primary(&self) -> bool { self.is_primary } fn as_any(&self) -> &dyn std::any::Any { self } } #[cfg(feature = "serialize")] impl InteractionLocation for SerializedPointerData { fn client_coordinates(&self) -> ClientPoint { self.point_data.client_coordinates() } fn screen_coordinates(&self) -> ScreenPoint { self.point_data.screen_coordinates() } fn page_coordinates(&self) -> PagePoint { self.point_data.page_coordinates() } } #[cfg(feature = "serialize")] impl InteractionElementOffset for SerializedPointerData { fn element_coordinates(&self) -> ElementPoint { self.point_data.element_coordinates() } } #[cfg(feature = "serialize")] impl ModifiersInteraction for SerializedPointerData { fn modifiers(&self) -> Modifiers { self.point_data.modifiers() } } #[cfg(feature = "serialize")] impl PointerInteraction for SerializedPointerData { fn held_buttons(&self) -> MouseButtonSet { self.point_data.held_buttons() } fn trigger_button(&self) -> Option { self.point_data.trigger_button() } } #[cfg(feature = "serialize")] impl From<&PointerData> for SerializedPointerData { fn from(data: &PointerData) -> Self { Self { point_data: data.into(), pointer_id: data.pointer_id(), width: data.width(), height: data.height(), pressure: data.pressure(), tangential_pressure: data.tangential_pressure(), tilt_x: data.tilt_x(), tilt_y: data.tilt_y(), twist: data.twist(), pointer_type: data.pointer_type().to_string(), is_primary: data.is_primary(), } } } #[cfg(feature = "serialize")] impl serde::Serialize for PointerData { fn serialize(&self, serializer: S) -> Result { SerializedPointerData::from(self).serialize(serializer) } } #[cfg(feature = "serialize")] impl<'de> serde::Deserialize<'de> for PointerData { fn deserialize>(deserializer: D) -> Result { let data = SerializedPointerData::deserialize(deserializer)?; Ok(Self { inner: Box::new(data), }) } }