From 27f4b3f3451c1550e2df376fbf80559c024bb8ee Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Tue, 12 Sep 2023 17:45:07 -0500 Subject: [PATCH] add touches_changed and target_touches --- packages/html/src/events/touch.rs | 103 ++++++++++++++++++++++- packages/html/src/web_sys_bind/events.rs | 20 +++++ 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/packages/html/src/events/touch.rs b/packages/html/src/events/touch.rs index 83fdbb0b4..b30ace17c 100644 --- a/packages/html/src/events/touch.rs +++ b/packages/html/src/events/touch.rs @@ -19,6 +19,9 @@ impl std::fmt::Debug for TouchData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("TouchData") .field("modifiers", &self.modifiers()) + .field("touches", &self.touches()) + .field("touches_changed", &self.touches_changed()) + .field("target_touches", &self.target_touches()) .finish() } } @@ -42,6 +45,16 @@ impl TouchData { self.inner.touches() } + /// Get the touches that have changed since the last event + pub fn touches_changed(&self) -> Vec { + self.inner.touches_changed() + } + + /// Get the touches that started and stayed on the element that triggered this event + pub fn target_touches(&self) -> Vec { + self.inner.target_touches() + } + /// Downcast this event to a concrete event type pub fn downcast(&self) -> Option<&T> { self.inner.as_any().downcast_ref::() @@ -63,6 +76,8 @@ pub struct SerializedTouchData { meta_key: bool, shift_key: bool, touches: Vec, + changed_touches: Vec, + target_touches: Vec, } #[cfg(feature = "serialize")] @@ -75,6 +90,8 @@ impl From<&TouchData> for SerializedTouchData { meta_key: modifiers.contains(Modifiers::META), shift_key: modifiers.contains(Modifiers::SHIFT), touches: data.touches().iter().map(|t| t.into()).collect(), + changed_touches: data.touches_changed().iter().map(|t| t.into()).collect(), + target_touches: data.target_touches().iter().map(|t| t.into()).collect(), } } } @@ -102,7 +119,23 @@ impl ModifiersInteraction for SerializedTouchData { #[cfg(feature = "serialize")] impl HasTouchData for SerializedTouchData { fn touches(&self) -> Vec { - Vec::new() + self.touches.clone().into_iter().map(Into::into).collect() + } + + fn touches_changed(&self) -> Vec { + self.changed_touches + .clone() + .into_iter() + .map(Into::into) + .collect() + } + + fn target_touches(&self) -> Vec { + self.target_touches + .clone() + .into_iter() + .map(Into::into) + .collect() } fn as_any(&self) -> &dyn std::any::Any { @@ -128,9 +161,15 @@ impl<'de> serde::Deserialize<'de> for TouchData { } pub trait HasTouchData: ModifiersInteraction + std::any::Any { - /// Get the pointers that are currently down + /// Get the touches that are currently down fn touches(&self) -> Vec; + /// Get the touches that have changed since the last event + fn touches_changed(&self) -> Vec; + + /// Get the touches that started and stayed on the element that triggered this event + fn target_touches(&self) -> Vec; + /// return self as Any fn as_any(&self) -> &dyn std::any::Any; } @@ -179,6 +218,20 @@ impl TouchPoint { } } +impl std::fmt::Debug for TouchPoint { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TouchPoint") + .field("client_coordinates", &self.client_coordinates()) + .field("page_coordinates", &self.page_coordinates()) + .field("screen_coordinates", &self.screen_coordinates()) + .field("identifier", &self.identifier()) + .field("force", &self.force()) + .field("radius", &self.radius()) + .field("rotation", &self.rotation()) + .finish() + } +} + impl InteractionLocation for TouchPoint { fn client_coordinates(&self) -> ClientPoint { self.inner.client_coordinates() @@ -251,6 +304,52 @@ impl From<&TouchPoint> for SerializedTouchPoint { } } +#[cfg(feature = "serialize")] +impl HasTouchPointData for SerializedTouchPoint { + /// A unique identifier for this touch point that will be the same for the duration of the touch + fn identifier(&self) -> i32 { + self.identifier + } + + /// the pressure of the touch + fn force(&self) -> f64 { + self.force + } + + /// the radius of the touch + fn radius(&self) -> ScreenPoint { + ScreenPoint::new(self.radius_x, self.radius_y) + } + + /// the rotation of the touch in degrees between 0 and 90 + fn rotation(&self) -> f64 { + self.rotation_angle + } + + /// return self as Any + fn as_any(&self) -> &dyn std::any::Any { + self + } +} + +#[cfg(feature = "serialize")] +impl InteractionLocation for SerializedTouchPoint { + /// Gets the coordinates of the event relative to the browser viewport. + fn client_coordinates(&self) -> ClientPoint { + ClientPoint::new(self.client_x, self.client_y) + } + + /// Gets the coordinates of the event relative to the screen. + fn screen_coordinates(&self) -> ScreenPoint { + ScreenPoint::new(self.screen_x, self.screen_y) + } + + /// Gets the coordinates of the event relative to the page. + fn page_coordinates(&self) -> PagePoint { + PagePoint::new(self.page_x, self.page_y) + } +} + impl_event! { TouchData; /// touchstart diff --git a/packages/html/src/web_sys_bind/events.rs b/packages/html/src/web_sys_bind/events.rs index 055d1cc12..b1e6c5341 100644 --- a/packages/html/src/web_sys_bind/events.rs +++ b/packages/html/src/web_sys_bind/events.rs @@ -194,6 +194,26 @@ impl crate::events::HasTouchData for TouchEvent { result } + fn touches_changed(&self) -> Vec { + let touches = self.changed_touches(); + let mut result = Vec::with_capacity(touches.length() as usize); + for i in 0..touches.length() { + let touch = touches.get(i).unwrap(); + result.push(TouchPoint::new(touch)); + } + result + } + + fn target_touches(&self) -> Vec { + let touches = self.target_touches(); + let mut result = Vec::with_capacity(touches.length() as usize); + for i in 0..touches.length() { + let touch = touches.get(i).unwrap(); + result.push(TouchPoint::new(touch)); + } + result + } + fn as_any(&self) -> &dyn std::any::Any { self }