touch.rs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. use dioxus_core::Event;
  2. use keyboard_types::Modifiers;
  3. use crate::geometry::*;
  4. use crate::prelude::{InteractionLocation, ModifiersInteraction};
  5. pub type TouchEvent = Event<TouchData>;
  6. pub struct TouchData {
  7. inner: Box<dyn HasTouchData>,
  8. }
  9. impl<E: HasTouchData> From<E> for TouchData {
  10. fn from(e: E) -> Self {
  11. Self { inner: Box::new(e) }
  12. }
  13. }
  14. impl std::fmt::Debug for TouchData {
  15. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  16. f.debug_struct("TouchData")
  17. .field("modifiers", &self.modifiers())
  18. .field("touches", &self.touches())
  19. .field("touches_changed", &self.touches_changed())
  20. .field("target_touches", &self.target_touches())
  21. .finish()
  22. }
  23. }
  24. impl PartialEq for TouchData {
  25. fn eq(&self, other: &Self) -> bool {
  26. self.modifiers() == other.modifiers()
  27. }
  28. }
  29. impl TouchData {
  30. /// Create a new TouchData
  31. pub fn new(inner: impl HasTouchData + 'static) -> Self {
  32. Self {
  33. inner: Box::new(inner),
  34. }
  35. }
  36. /// Get the pointers that are currently down
  37. pub fn touches(&self) -> Vec<TouchPoint> {
  38. self.inner.touches()
  39. }
  40. /// Get the touches that have changed since the last event
  41. pub fn touches_changed(&self) -> Vec<TouchPoint> {
  42. self.inner.touches_changed()
  43. }
  44. /// Get the touches that started and stayed on the element that triggered this event
  45. pub fn target_touches(&self) -> Vec<TouchPoint> {
  46. self.inner.target_touches()
  47. }
  48. /// Downcast this event to a concrete event type
  49. pub fn downcast<T: 'static>(&self) -> Option<&T> {
  50. self.inner.as_any().downcast_ref::<T>()
  51. }
  52. }
  53. impl ModifiersInteraction for TouchData {
  54. fn modifiers(&self) -> Modifiers {
  55. self.inner.modifiers()
  56. }
  57. }
  58. #[cfg(feature = "serialize")]
  59. /// A serialized version of TouchData
  60. #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
  61. pub struct SerializedTouchData {
  62. alt_key: bool,
  63. ctrl_key: bool,
  64. meta_key: bool,
  65. shift_key: bool,
  66. touches: Vec<SerializedTouchPoint>,
  67. changed_touches: Vec<SerializedTouchPoint>,
  68. target_touches: Vec<SerializedTouchPoint>,
  69. }
  70. #[cfg(feature = "serialize")]
  71. impl From<&TouchData> for SerializedTouchData {
  72. fn from(data: &TouchData) -> Self {
  73. let modifiers = data.modifiers();
  74. Self {
  75. alt_key: modifiers.contains(Modifiers::ALT),
  76. ctrl_key: modifiers.contains(Modifiers::CONTROL),
  77. meta_key: modifiers.contains(Modifiers::META),
  78. shift_key: modifiers.contains(Modifiers::SHIFT),
  79. touches: data.touches().iter().map(|t| t.into()).collect(),
  80. changed_touches: data.touches_changed().iter().map(|t| t.into()).collect(),
  81. target_touches: data.target_touches().iter().map(|t| t.into()).collect(),
  82. }
  83. }
  84. }
  85. #[cfg(feature = "serialize")]
  86. impl ModifiersInteraction for SerializedTouchData {
  87. fn modifiers(&self) -> Modifiers {
  88. let mut modifiers = Modifiers::default();
  89. if self.alt_key {
  90. modifiers.insert(Modifiers::ALT);
  91. }
  92. if self.ctrl_key {
  93. modifiers.insert(Modifiers::CONTROL);
  94. }
  95. if self.meta_key {
  96. modifiers.insert(Modifiers::META);
  97. }
  98. if self.shift_key {
  99. modifiers.insert(Modifiers::SHIFT);
  100. }
  101. modifiers
  102. }
  103. }
  104. #[cfg(feature = "serialize")]
  105. impl HasTouchData for SerializedTouchData {
  106. fn touches(&self) -> Vec<TouchPoint> {
  107. self.touches.clone().into_iter().map(Into::into).collect()
  108. }
  109. fn touches_changed(&self) -> Vec<TouchPoint> {
  110. self.changed_touches
  111. .clone()
  112. .into_iter()
  113. .map(Into::into)
  114. .collect()
  115. }
  116. fn target_touches(&self) -> Vec<TouchPoint> {
  117. self.target_touches
  118. .clone()
  119. .into_iter()
  120. .map(Into::into)
  121. .collect()
  122. }
  123. fn as_any(&self) -> &dyn std::any::Any {
  124. self
  125. }
  126. }
  127. #[cfg(feature = "serialize")]
  128. impl serde::Serialize for TouchData {
  129. fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
  130. SerializedTouchData::from(self).serialize(serializer)
  131. }
  132. }
  133. #[cfg(feature = "serialize")]
  134. impl<'de> serde::Deserialize<'de> for TouchData {
  135. fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
  136. let data = SerializedTouchData::deserialize(deserializer)?;
  137. Ok(Self {
  138. inner: Box::new(data),
  139. })
  140. }
  141. }
  142. pub trait HasTouchData: ModifiersInteraction + std::any::Any {
  143. /// Get the touches that are currently down
  144. fn touches(&self) -> Vec<TouchPoint>;
  145. /// Get the touches that have changed since the last event
  146. fn touches_changed(&self) -> Vec<TouchPoint>;
  147. /// Get the touches that started and stayed on the element that triggered this event
  148. fn target_touches(&self) -> Vec<TouchPoint>;
  149. /// return self as Any
  150. fn as_any(&self) -> &dyn std::any::Any;
  151. }
  152. pub struct TouchPoint {
  153. inner: Box<dyn HasTouchPointData>,
  154. }
  155. impl<E: HasTouchPointData> From<E> for TouchPoint {
  156. fn from(e: E) -> Self {
  157. Self { inner: Box::new(e) }
  158. }
  159. }
  160. impl TouchPoint {
  161. /// Create a new TouchPoint
  162. pub fn new(inner: impl HasTouchPointData + 'static) -> Self {
  163. Self {
  164. inner: Box::new(inner),
  165. }
  166. }
  167. /// A unique identifier for this touch point that will be the same for the duration of the touch
  168. fn identifier(&self) -> i32 {
  169. self.inner.identifier()
  170. }
  171. /// the pressure of the touch
  172. fn force(&self) -> f64 {
  173. self.inner.force()
  174. }
  175. /// the radius of the touch
  176. fn radius(&self) -> ScreenPoint {
  177. self.inner.radius()
  178. }
  179. /// the rotation of the touch in degrees between 0 and 90
  180. fn rotation(&self) -> f64 {
  181. self.inner.rotation()
  182. }
  183. /// Downcast this event to a concrete event type
  184. pub fn downcast<T: 'static>(&self) -> Option<&T> {
  185. self.inner.as_any().downcast_ref::<T>()
  186. }
  187. }
  188. impl std::fmt::Debug for TouchPoint {
  189. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  190. f.debug_struct("TouchPoint")
  191. .field("client_coordinates", &self.client_coordinates())
  192. .field("page_coordinates", &self.page_coordinates())
  193. .field("screen_coordinates", &self.screen_coordinates())
  194. .field("identifier", &self.identifier())
  195. .field("force", &self.force())
  196. .field("radius", &self.radius())
  197. .field("rotation", &self.rotation())
  198. .finish()
  199. }
  200. }
  201. impl InteractionLocation for TouchPoint {
  202. fn client_coordinates(&self) -> ClientPoint {
  203. self.inner.client_coordinates()
  204. }
  205. fn page_coordinates(&self) -> PagePoint {
  206. self.inner.page_coordinates()
  207. }
  208. fn screen_coordinates(&self) -> ScreenPoint {
  209. self.inner.screen_coordinates()
  210. }
  211. }
  212. /// A trait for touch point data
  213. pub trait HasTouchPointData: InteractionLocation + std::any::Any {
  214. /// A unique identifier for this touch point that will be the same for the duration of the touch
  215. fn identifier(&self) -> i32;
  216. /// the pressure of the touch
  217. fn force(&self) -> f64;
  218. /// the radius of the touch
  219. fn radius(&self) -> ScreenPoint;
  220. /// the rotation of the touch in degrees between 0 and 90
  221. fn rotation(&self) -> f64;
  222. /// return self as Any
  223. fn as_any(&self) -> &dyn std::any::Any;
  224. }
  225. #[cfg(feature = "serialize")]
  226. /// A serialized version of TouchPoint
  227. #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
  228. struct SerializedTouchPoint {
  229. identifier: i32,
  230. client_x: f64,
  231. client_y: f64,
  232. page_x: f64,
  233. page_y: f64,
  234. screen_x: f64,
  235. screen_y: f64,
  236. force: f64,
  237. radius_x: f64,
  238. radius_y: f64,
  239. rotation_angle: f64,
  240. }
  241. #[cfg(feature = "serialize")]
  242. impl From<&TouchPoint> for SerializedTouchPoint {
  243. fn from(point: &TouchPoint) -> Self {
  244. let client_coordinates = point.client_coordinates();
  245. let page_coordinates = point.page_coordinates();
  246. let screen_coordinates = point.screen_coordinates();
  247. Self {
  248. identifier: point.identifier(),
  249. client_x: client_coordinates.x,
  250. client_y: client_coordinates.y,
  251. page_x: page_coordinates.x,
  252. page_y: page_coordinates.y,
  253. screen_x: screen_coordinates.x,
  254. screen_y: screen_coordinates.y,
  255. force: point.force(),
  256. radius_x: point.radius().x,
  257. radius_y: point.radius().y,
  258. rotation_angle: point.rotation(),
  259. }
  260. }
  261. }
  262. #[cfg(feature = "serialize")]
  263. impl HasTouchPointData for SerializedTouchPoint {
  264. /// A unique identifier for this touch point that will be the same for the duration of the touch
  265. fn identifier(&self) -> i32 {
  266. self.identifier
  267. }
  268. /// the pressure of the touch
  269. fn force(&self) -> f64 {
  270. self.force
  271. }
  272. /// the radius of the touch
  273. fn radius(&self) -> ScreenPoint {
  274. ScreenPoint::new(self.radius_x, self.radius_y)
  275. }
  276. /// the rotation of the touch in degrees between 0 and 90
  277. fn rotation(&self) -> f64 {
  278. self.rotation_angle
  279. }
  280. /// return self as Any
  281. fn as_any(&self) -> &dyn std::any::Any {
  282. self
  283. }
  284. }
  285. #[cfg(feature = "serialize")]
  286. impl InteractionLocation for SerializedTouchPoint {
  287. /// Gets the coordinates of the event relative to the browser viewport.
  288. fn client_coordinates(&self) -> ClientPoint {
  289. ClientPoint::new(self.client_x, self.client_y)
  290. }
  291. /// Gets the coordinates of the event relative to the screen.
  292. fn screen_coordinates(&self) -> ScreenPoint {
  293. ScreenPoint::new(self.screen_x, self.screen_y)
  294. }
  295. /// Gets the coordinates of the event relative to the page.
  296. fn page_coordinates(&self) -> PagePoint {
  297. PagePoint::new(self.page_x, self.page_y)
  298. }
  299. }
  300. impl_event! {
  301. TouchData;
  302. /// touchstart
  303. ontouchstart
  304. /// touchmove
  305. ontouchmove
  306. /// touchend
  307. ontouchend
  308. /// touchcancel
  309. ontouchcancel
  310. }