1
0
Эх сурвалжийг харах

add touch data to touch events

Evan Almloff 1 жил өмнө
parent
commit
c10700c962

+ 2 - 1
packages/html/Cargo.toml

@@ -29,12 +29,13 @@ serde_json = { version = "1", optional = true }
 optional = true
 version = "0.3.56"
 features = [
+    "Touch",
+    "TouchList",
     "TouchEvent",
     "MouseEvent",
     "InputEvent",
     "ClipboardEvent",
     "KeyboardEvent",
-    "TouchEvent",
     "WheelEvent",
     "AnimationEvent",
     "TransitionEvent",

+ 13 - 8
packages/html/src/events/drag.rs

@@ -62,10 +62,6 @@ impl InteractionLocation for DragData {
         self.inner.client_coordinates()
     }
 
-    fn element_coordinates(&self) -> ElementPoint {
-        self.inner.element_coordinates()
-    }
-
     fn page_coordinates(&self) -> PagePoint {
         self.inner.page_coordinates()
     }
@@ -73,6 +69,12 @@ impl InteractionLocation for DragData {
     fn screen_coordinates(&self) -> ScreenPoint {
         self.inner.screen_coordinates()
     }
+}
+
+impl InteractionElementOffset for DragData {
+    fn element_coordinates(&self) -> ElementPoint {
+        self.inner.element_coordinates()
+    }
 
     fn coordinates(&self) -> Coordinates {
         self.inner.coordinates()
@@ -128,10 +130,6 @@ impl InteractionLocation for SerializedDragData {
         self.mouse.client_coordinates()
     }
 
-    fn element_coordinates(&self) -> ElementPoint {
-        self.mouse.element_coordinates()
-    }
-
     fn page_coordinates(&self) -> PagePoint {
         self.mouse.page_coordinates()
     }
@@ -139,6 +137,13 @@ impl InteractionLocation for SerializedDragData {
     fn screen_coordinates(&self) -> ScreenPoint {
         self.mouse.screen_coordinates()
     }
+}
+
+#[cfg(feature = "serialize")]
+impl InteractionElementOffset for SerializedDragData {
+    fn element_coordinates(&self) -> ElementPoint {
+        self.mouse.element_coordinates()
+    }
 
     fn coordinates(&self) -> Coordinates {
         self.mouse.coordinates()

+ 24 - 21
packages/html/src/events/keyboard.rs

@@ -2,6 +2,8 @@ use dioxus_core::Event;
 use keyboard_types::{Code, Key, Location, Modifiers};
 use std::fmt::Debug;
 
+use crate::prelude::ModifiersInteraction;
+
 #[cfg(feature = "serialize")]
 fn resilient_deserialize_code<'de, D>(deserializer: D) -> Result<Code, D::Error>
 where
@@ -63,11 +65,6 @@ impl KeyboardData {
         self.inner.code()
     }
 
-    /// The set of modifier keys which were pressed when the event occurred
-    pub fn modifiers(&self) -> Modifiers {
-        self.inner.modifiers()
-    }
-
     /// The location of the key on the keyboard or other input device.
     pub fn location(&self) -> Location {
         self.inner.location()
@@ -84,6 +81,12 @@ impl KeyboardData {
     }
 }
 
+impl ModifiersInteraction for KeyboardData {
+    fn modifiers(&self) -> Modifiers {
+        self.inner.modifiers()
+    }
+}
+
 #[cfg(feature = "serialize")]
 /// A serialized version of KeyboardData
 #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
@@ -155,6 +158,21 @@ impl HasKeyboardData for SerializedKeyboardData {
         self.code
     }
 
+    fn location(&self) -> Location {
+        crate::input_data::decode_key_location(self.location)
+    }
+
+    fn is_auto_repeating(&self) -> bool {
+        self.repeat
+    }
+
+    fn as_any(&self) -> &dyn std::any::Any {
+        self
+    }
+}
+
+#[cfg(feature = "serialize")]
+impl ModifiersInteraction for SerializedKeyboardData {
     fn modifiers(&self) -> Modifiers {
         let mut modifiers = Modifiers::empty();
 
@@ -173,18 +191,6 @@ impl HasKeyboardData for SerializedKeyboardData {
 
         modifiers
     }
-
-    fn location(&self) -> Location {
-        crate::input_data::decode_key_location(self.location)
-    }
-
-    fn is_auto_repeating(&self) -> bool {
-        self.repeat
-    }
-
-    fn as_any(&self) -> &dyn std::any::Any {
-        self
-    }
 }
 
 #[cfg(feature = "serialize")]
@@ -217,16 +223,13 @@ impl_event! {
     onkeyup
 }
 
-pub trait HasKeyboardData: std::any::Any {
+pub trait HasKeyboardData: ModifiersInteraction + std::any::Any {
     /// The value of the key pressed by the user, taking into consideration the state of modifier keys such as Shift as well as the keyboard locale and layout.
     fn key(&self) -> Key;
 
     /// A physical key on the keyboard (as opposed to the character generated by pressing the key). In other words, this property returns a value that isn't altered by keyboard layout or the state of the modifier keys.
     fn code(&self) -> Code;
 
-    /// The set of modifier keys which were pressed when the event occurred
-    fn modifiers(&self) -> Modifiers;
-
     /// The location of the key on the keyboard or other input device.
     fn location(&self) -> Location;
 

+ 13 - 18
packages/html/src/events/mouse.rs

@@ -120,31 +120,23 @@ impl MouseData {
 }
 
 impl InteractionLocation for MouseData {
-    /// The event's coordinates relative to the application's viewport (as opposed to the coordinate within the page).
-    ///
-    /// For example, clicking in the top left corner of the viewport will always result in a mouse event with client coordinates (0., 0.), regardless of whether the page is scrolled horizontally.
     fn client_coordinates(&self) -> ClientPoint {
         self.inner.client_coordinates()
     }
 
-    /// The event's coordinates relative to the padding edge of the target element
-    ///
-    /// For example, clicking in the top left corner of an element will result in element coordinates (0., 0.)
-    fn element_coordinates(&self) -> ElementPoint {
-        self.inner.element_coordinates()
-    }
-
-    /// The event's coordinates relative to the entire document. This includes any portion of the document not currently visible.
-    ///
-    /// For example, if the page is scrolled 200 pixels to the right and 300 pixels down, clicking in the top left corner of the viewport would result in page coordinates (200., 300.)
     fn page_coordinates(&self) -> PagePoint {
         self.inner.page_coordinates()
     }
 
-    /// The event's coordinates relative to the entire screen. This takes into account the window's offset.
     fn screen_coordinates(&self) -> ScreenPoint {
         self.inner.screen_coordinates()
     }
+}
+
+impl InteractionElementOffset for MouseData {
+    fn element_coordinates(&self) -> ElementPoint {
+        self.inner.element_coordinates()
+    }
 
     fn coordinates(&self) -> Coordinates {
         self.inner.coordinates()
@@ -233,10 +225,6 @@ impl InteractionLocation for SerializedMouseData {
         self.point_data.client_coordinates()
     }
 
-    fn element_coordinates(&self) -> ElementPoint {
-        self.point_data.element_coordinates()
-    }
-
     fn page_coordinates(&self) -> PagePoint {
         self.point_data.page_coordinates()
     }
@@ -246,6 +234,13 @@ impl InteractionLocation for SerializedMouseData {
     }
 }
 
+#[cfg(feature = "serialize")]
+impl InteractionElementOffset for SerializedMouseData {
+    fn element_coordinates(&self) -> ElementPoint {
+        self.point_data.element_coordinates()
+    }
+}
+
 #[cfg(feature = "serialize")]
 impl ModifiersInteraction for SerializedMouseData {
     fn modifiers(&self) -> Modifiers {

+ 13 - 8
packages/html/src/events/pointer.rs

@@ -198,15 +198,17 @@ impl InteractionLocation for PointerData {
         self.inner.screen_coordinates()
     }
 
-    fn element_coordinates(&self) -> ElementPoint {
-        self.inner.element_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()
@@ -319,15 +321,18 @@ impl InteractionLocation for SerializedPointerData {
         self.point_data.screen_coordinates()
     }
 
-    fn element_coordinates(&self) -> ElementPoint {
-        self.point_data.element_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 {

+ 159 - 52
packages/html/src/events/touch.rs

@@ -1,4 +1,8 @@
 use dioxus_core::Event;
+use keyboard_types::Modifiers;
+
+use crate::geometry::*;
+use crate::prelude::{InteractionLocation, ModifiersInteraction};
 
 pub type TouchEvent = Event<TouchData>;
 pub struct TouchData {
@@ -14,20 +18,14 @@ impl<E: HasTouchData> From<E> for TouchData {
 impl std::fmt::Debug for TouchData {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("TouchData")
-            .field("alt_key", &self.alt_key())
-            .field("ctrl_key", &self.ctrl_key())
-            .field("meta_key", &self.meta_key())
-            .field("shift_key", &self.shift_key())
+            .field("modifiers", &self.modifiers())
             .finish()
     }
 }
 
 impl PartialEq for TouchData {
     fn eq(&self, other: &Self) -> bool {
-        self.alt_key() == other.alt_key()
-            && self.ctrl_key() == other.ctrl_key()
-            && self.meta_key() == other.meta_key()
-            && self.shift_key() == other.shift_key()
+        self.modifiers() == other.modifiers()
     }
 }
 
@@ -39,24 +37,9 @@ impl TouchData {
         }
     }
 
-    /// Returns true if the "ALT" key was down when the touch event was fired.
-    pub fn alt_key(&self) -> bool {
-        self.inner.alt_key()
-    }
-
-    /// Returns true if the "CTRL" key was down when the touch event was fired.
-    pub fn ctrl_key(&self) -> bool {
-        self.inner.ctrl_key()
-    }
-
-    /// Returns true if the "META" key was down when the touch event was fired.
-    pub fn meta_key(&self) -> bool {
-        self.inner.meta_key()
-    }
-
-    /// Returns true if the "SHIFT" key was down when the touch event was fired.
-    pub fn shift_key(&self) -> bool {
-        self.inner.shift_key()
+    /// Get the pointers that are currently down
+    pub fn touches(&self) -> Vec<TouchPoint> {
+        self.inner.touches()
     }
 
     /// Downcast this event to a concrete event type
@@ -65,6 +48,12 @@ impl TouchData {
     }
 }
 
+impl ModifiersInteraction for TouchData {
+    fn modifiers(&self) -> Modifiers {
+        self.inner.modifiers()
+    }
+}
+
 #[cfg(feature = "serialize")]
 /// A serialized version of TouchData
 #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
@@ -73,36 +62,47 @@ pub struct SerializedTouchData {
     ctrl_key: bool,
     meta_key: bool,
     shift_key: bool,
+    touches: Vec<SerializedTouchPoint>,
 }
 
 #[cfg(feature = "serialize")]
 impl From<&TouchData> for SerializedTouchData {
     fn from(data: &TouchData) -> Self {
+        let modifiers = data.modifiers();
         Self {
-            alt_key: data.alt_key(),
-            ctrl_key: data.ctrl_key(),
-            meta_key: data.meta_key(),
-            shift_key: data.shift_key(),
+            alt_key: modifiers.contains(Modifiers::ALT),
+            ctrl_key: modifiers.contains(Modifiers::CONTROL),
+            meta_key: modifiers.contains(Modifiers::META),
+            shift_key: modifiers.contains(Modifiers::SHIFT),
+            touches: data.touches().iter().map(|t| t.into()).collect(),
         }
     }
 }
 
 #[cfg(feature = "serialize")]
-impl HasTouchData for SerializedTouchData {
-    fn alt_key(&self) -> bool {
-        self.alt_key
-    }
-
-    fn ctrl_key(&self) -> bool {
-        self.ctrl_key
-    }
-
-    fn meta_key(&self) -> bool {
-        self.meta_key
+impl ModifiersInteraction for SerializedTouchData {
+    fn modifiers(&self) -> Modifiers {
+        let mut modifiers = Modifiers::default();
+        if self.alt_key {
+            modifiers.insert(Modifiers::ALT);
+        }
+        if self.ctrl_key {
+            modifiers.insert(Modifiers::CONTROL);
+        }
+        if self.meta_key {
+            modifiers.insert(Modifiers::META);
+        }
+        if self.shift_key {
+            modifiers.insert(Modifiers::SHIFT);
+        }
+        modifiers
     }
+}
 
-    fn shift_key(&self) -> bool {
-        self.shift_key
+#[cfg(feature = "serialize")]
+impl HasTouchData for SerializedTouchData {
+    fn touches(&self) -> Vec<TouchPoint> {
+        Vec::new()
     }
 
     fn as_any(&self) -> &dyn std::any::Any {
@@ -127,23 +127,130 @@ impl<'de> serde::Deserialize<'de> for TouchData {
     }
 }
 
-pub trait HasTouchData: std::any::Any {
-    /// Returns true if the "ALT" key was down when the touch event was fired.
-    fn alt_key(&self) -> bool;
+pub trait HasTouchData: ModifiersInteraction + std::any::Any {
+    /// Get the pointers that are currently down
+    fn touches(&self) -> Vec<TouchPoint>;
 
-    /// Returns true if the "CTRL" key was down when the touch event was fired.
-    fn ctrl_key(&self) -> bool;
+    /// return self as Any
+    fn as_any(&self) -> &dyn std::any::Any;
+}
+
+pub struct TouchPoint {
+    inner: Box<dyn HasTouchPointData>,
+}
 
-    /// Returns true if the "META" key was down when the touch event was fired.
-    fn meta_key(&self) -> bool;
+impl<E: HasTouchPointData> From<E> for TouchPoint {
+    fn from(e: E) -> Self {
+        Self { inner: Box::new(e) }
+    }
+}
 
-    /// Returns true if the "SHIFT" key was down when the touch event was fired.
-    fn shift_key(&self) -> bool;
+impl TouchPoint {
+    /// Create a new TouchPoint
+    pub fn new(inner: impl HasTouchPointData + 'static) -> Self {
+        Self {
+            inner: Box::new(inner),
+        }
+    }
+
+    /// A unique identifier for this touch point that will be the same for the duration of the touch
+    fn identifier(&self) -> i32 {
+        self.inner.identifier()
+    }
+
+    /// the pressure of the touch
+    fn force(&self) -> f64 {
+        self.inner.force()
+    }
+
+    /// the radius of the touch
+    fn radius(&self) -> ScreenPoint {
+        self.inner.radius()
+    }
+
+    /// the rotation of the touch in degrees between 0 and 90
+    fn rotation(&self) -> f64 {
+        self.inner.rotation()
+    }
+
+    /// Downcast this event to a concrete event type
+    pub fn downcast<T: 'static>(&self) -> Option<&T> {
+        self.inner.as_any().downcast_ref::<T>()
+    }
+}
+
+impl InteractionLocation for TouchPoint {
+    fn client_coordinates(&self) -> ClientPoint {
+        self.inner.client_coordinates()
+    }
+
+    fn page_coordinates(&self) -> PagePoint {
+        self.inner.page_coordinates()
+    }
+
+    fn screen_coordinates(&self) -> ScreenPoint {
+        self.inner.screen_coordinates()
+    }
+}
+
+/// A trait for touch point data
+pub trait HasTouchPointData: InteractionLocation + std::any::Any {
+    /// A unique identifier for this touch point that will be the same for the duration of the touch
+    fn identifier(&self) -> i32;
+
+    /// the pressure of the touch
+    fn force(&self) -> f64;
+
+    /// the radius of the touch
+    fn radius(&self) -> ScreenPoint;
+
+    /// the rotation of the touch in degrees between 0 and 90
+    fn rotation(&self) -> f64;
 
     /// return self as Any
     fn as_any(&self) -> &dyn std::any::Any;
 }
 
+#[cfg(feature = "serialize")]
+/// A serialized version of TouchPoint
+#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
+struct SerializedTouchPoint {
+    identifier: i32,
+    client_x: f64,
+    client_y: f64,
+    page_x: f64,
+    page_y: f64,
+    screen_x: f64,
+    screen_y: f64,
+    force: f64,
+    radius_x: f64,
+    radius_y: f64,
+    rotation_angle: f64,
+}
+
+#[cfg(feature = "serialize")]
+impl From<&TouchPoint> for SerializedTouchPoint {
+    fn from(point: &TouchPoint) -> Self {
+        let client_coordinates = point.client_coordinates();
+
+        let page_coordinates = point.page_coordinates();
+        let screen_coordinates = point.screen_coordinates();
+        Self {
+            identifier: point.identifier(),
+            client_x: client_coordinates.x,
+            client_y: client_coordinates.y,
+            page_x: page_coordinates.x,
+            page_y: page_coordinates.y,
+            screen_x: screen_coordinates.x,
+            screen_y: screen_coordinates.y,
+            force: point.force(),
+            radius_x: point.radius().x,
+            radius_y: point.radius().y,
+            rotation_angle: point.rotation(),
+        }
+    }
+}
+
 impl_event! {
     TouchData;
     /// touchstart

+ 20 - 14
packages/html/src/point_interaction.rs

@@ -7,6 +7,18 @@ use crate::{
 
 /// A interaction that contains data about the location of the event.
 pub trait InteractionLocation {
+    /// Gets the coordinates of the event relative to the browser viewport.
+    fn client_coordinates(&self) -> ClientPoint;
+
+    /// Gets the coordinates of the event relative to the screen.
+    fn screen_coordinates(&self) -> ScreenPoint;
+
+    /// Gets the coordinates of the event relative to the page.
+    fn page_coordinates(&self) -> PagePoint;
+}
+
+/// A interaction that contains data about the location of the event.
+pub trait InteractionElementOffset: InteractionLocation {
     /// Gets the coordinates of the event.
     fn coordinates(&self) -> Coordinates {
         Coordinates::new(
@@ -17,21 +29,12 @@ pub trait InteractionLocation {
         )
     }
 
-    /// Gets the coordinates of the event relative to the browser viewport.
-    fn client_coordinates(&self) -> ClientPoint;
-
-    /// Gets the coordinates of the event relative to the screen.
-    fn screen_coordinates(&self) -> ScreenPoint;
-
     /// Gets the coordinates of the event relative to the target element.
     fn element_coordinates(&self) -> ElementPoint;
-
-    /// Gets the coordinates of the event relative to the page.
-    fn page_coordinates(&self) -> PagePoint;
 }
 
 /// A interaction that contains data about the pointer button(s) that triggered the event.
-pub trait PointerInteraction: InteractionLocation + ModifiersInteraction {
+pub trait PointerInteraction: InteractionElementOffset + ModifiersInteraction {
     /// Gets the button that triggered the event.
     fn trigger_button(&self) -> Option<MouseButton>;
 
@@ -198,11 +201,14 @@ impl InteractionLocation for SerializedPointInteraction {
         ScreenPoint::new(self.screen_x.into(), self.screen_y.into())
     }
 
-    fn element_coordinates(&self) -> ElementPoint {
-        ElementPoint::new(self.offset_x.into(), self.offset_y.into())
-    }
-
     fn page_coordinates(&self) -> PagePoint {
         PagePoint::new(self.page_x.into(), self.page_y.into())
     }
 }
+
+#[cfg(feature = "serialize")]
+impl InteractionElementOffset for SerializedPointInteraction {
+    fn element_coordinates(&self) -> ElementPoint {
+        ElementPoint::new(self.offset_x.into(), self.offset_y.into())
+    }
+}

+ 89 - 32
packages/html/src/web_sys_bind/events.rs

@@ -1,6 +1,6 @@
 use crate::events::HasKeyboardData;
 use crate::events::{
-    AnimationData, CompositionData, HasTouchData, KeyboardData, MouseData, PointerData, TouchData,
+    AnimationData, CompositionData, KeyboardData, MouseData, PointerData, TouchData,
     TransitionData, WheelData,
 };
 use crate::geometry::{ClientPoint, ElementPoint, PagePoint, ScreenPoint};
@@ -10,8 +10,8 @@ use keyboard_types::{Code, Key, Modifiers};
 use std::str::FromStr;
 use wasm_bindgen::{JsCast, JsValue};
 use web_sys::{
-    AnimationEvent, CompositionEvent, Event, KeyboardEvent, MouseEvent, PointerEvent, TouchEvent,
-    TransitionEvent, WheelEvent,
+    AnimationEvent, CompositionEvent, Event, KeyboardEvent, MouseEvent, PointerEvent, Touch,
+    TouchEvent, TransitionEvent, WheelEvent,
 };
 
 macro_rules! uncheck_convert {
@@ -69,6 +69,20 @@ impl HasKeyboardData for KeyboardEvent {
         Code::from_str(self.code().as_str()).unwrap_or(Code::Unidentified)
     }
 
+    fn location(&self) -> keyboard_types::Location {
+        decode_key_location(self.location() as usize)
+    }
+
+    fn is_auto_repeating(&self) -> bool {
+        self.repeat()
+    }
+
+    fn as_any(&self) -> &dyn std::any::Any {
+        self
+    }
+}
+
+impl ModifiersInteraction for KeyboardEvent {
     fn modifiers(&self) -> Modifiers {
         let mut modifiers = Modifiers::empty();
 
@@ -87,18 +101,6 @@ impl HasKeyboardData for KeyboardEvent {
 
         modifiers
     }
-
-    fn location(&self) -> keyboard_types::Location {
-        decode_key_location(self.location() as usize)
-    }
-
-    fn is_auto_repeating(&self) -> bool {
-        self.repeat()
-    }
-
-    fn as_any(&self) -> &dyn std::any::Any {
-        self
-    }
 }
 
 impl HasDragData for MouseEvent {}
@@ -108,10 +110,6 @@ impl InteractionLocation for MouseEvent {
         ClientPoint::new(self.client_x().into(), self.client_y().into())
     }
 
-    fn element_coordinates(&self) -> ElementPoint {
-        ElementPoint::new(self.offset_x().into(), self.offset_y().into())
-    }
-
     fn page_coordinates(&self) -> PagePoint {
         PagePoint::new(self.page_x().into(), self.page_y().into())
     }
@@ -121,6 +119,12 @@ impl InteractionLocation for MouseEvent {
     }
 }
 
+impl InteractionElementOffset for MouseEvent {
+    fn element_coordinates(&self) -> ElementPoint {
+        ElementPoint::new(self.offset_x().into(), self.offset_y().into())
+    }
+}
+
 impl ModifiersInteraction for MouseEvent {
     fn modifiers(&self) -> Modifiers {
         let mut modifiers = Modifiers::empty();
@@ -158,21 +162,58 @@ impl HasMouseData for MouseEvent {
     }
 }
 
-impl HasTouchData for TouchEvent {
-    fn alt_key(&self) -> bool {
-        self.alt_key()
+impl ModifiersInteraction for TouchEvent {
+    fn modifiers(&self) -> Modifiers {
+        let mut modifiers = Modifiers::empty();
+
+        if self.alt_key() {
+            modifiers.insert(Modifiers::ALT);
+        }
+        if self.ctrl_key() {
+            modifiers.insert(Modifiers::CONTROL);
+        }
+        if self.meta_key() {
+            modifiers.insert(Modifiers::META);
+        }
+        if self.shift_key() {
+            modifiers.insert(Modifiers::SHIFT);
+        }
+
+        modifiers
+    }
+}
+
+impl crate::events::HasTouchData for TouchEvent {
+    fn touches(&self) -> Vec<TouchPoint> {
+        let touches = TouchEvent::touches(self);
+        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
+    }
+}
+
+impl HasTouchPointData for Touch {
+    fn identifier(&self) -> i32 {
+        self.identifier()
     }
 
-    fn ctrl_key(&self) -> bool {
-        self.ctrl_key()
+    fn radius(&self) -> ScreenPoint {
+        ScreenPoint::new(self.radius_x().into(), self.radius_y().into())
     }
 
-    fn meta_key(&self) -> bool {
-        self.meta_key()
+    fn rotation(&self) -> f64 {
+        self.rotation_angle() as f64
     }
 
-    fn shift_key(&self) -> bool {
-        self.shift_key()
+    fn force(&self) -> f64 {
+        self.force() as f64
     }
 
     fn as_any(&self) -> &dyn std::any::Any {
@@ -180,6 +221,20 @@ impl HasTouchData for TouchEvent {
     }
 }
 
+impl InteractionLocation for Touch {
+    fn client_coordinates(&self) -> ClientPoint {
+        ClientPoint::new(self.client_x().into(), self.client_y().into())
+    }
+
+    fn screen_coordinates(&self) -> ScreenPoint {
+        ScreenPoint::new(self.screen_x().into(), self.screen_y().into())
+    }
+
+    fn page_coordinates(&self) -> PagePoint {
+        PagePoint::new(self.page_x().into(), self.page_y().into())
+    }
+}
+
 impl HasPointerData for PointerEvent {
     fn pointer_id(&self) -> i32 {
         self.pointer_id()
@@ -235,15 +290,17 @@ impl InteractionLocation for PointerEvent {
         ScreenPoint::new(self.screen_x().into(), self.screen_y().into())
     }
 
-    fn element_coordinates(&self) -> ElementPoint {
-        ElementPoint::new(self.offset_x().into(), self.offset_y().into())
-    }
-
     fn page_coordinates(&self) -> PagePoint {
         PagePoint::new(self.page_x().into(), self.page_y().into())
     }
 }
 
+impl InteractionElementOffset for PointerEvent {
+    fn element_coordinates(&self) -> ElementPoint {
+        ElementPoint::new(self.offset_x().into(), self.offset_y().into())
+    }
+}
+
 impl ModifiersInteraction for PointerEvent {
     fn modifiers(&self) -> Modifiers {
         let mut modifiers = Modifiers::empty();