add touch data to touch events

This commit is contained in:
Evan Almloff committed 2023-09-12 17:28:55 -05:00
1 parent b47064165e
commit c10700c962
8 files changed
+339 -160

No files matched your search

+2 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+163 -56
View File
@@ -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 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
}
}
#[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
}
fn shift_key(&self) -> bool {
self.shift_key
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;
/// Returns true if the "CTRL" key was down when the touch event was fired.
fn ctrl_key(&self) -> bool;
/// Returns true if the "META" key was down when the touch event was fired.
fn meta_key(&self) -> bool;
/// Returns true if the "SHIFT" key was down when the touch event was fired.
fn shift_key(&self) -> bool;
pub trait HasTouchData: ModifiersInteraction + std::any::Any {
/// Get the pointers that are currently down
fn touches(&self) -> Vec<TouchPoint>;
/// return self as Any
fn as_any(&self) -> &dyn std::any::Any;
}
pub struct TouchPoint {
inner: Box<dyn HasTouchPointData>,
}
impl<E: HasTouchPointData> From<E> for TouchPoint {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
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
View File
@@ -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())
}
}
+91 -34
View File
@@ -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,36 @@ 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();
fn ctrl_key(&self) -> bool {
self.ctrl_key()
}
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);
}
fn meta_key(&self) -> bool {
self.meta_key()
modifiers
}
}
fn shift_key(&self) -> bool {
self.shift_key()
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 {
@@ -180,6 +199,42 @@ impl HasTouchData for TouchEvent {
}
}
impl HasTouchPointData for Touch {
fn identifier(&self) -> i32 {
self.identifier()
}
fn radius(&self) -> ScreenPoint {
ScreenPoint::new(self.radius_x().into(), self.radius_y().into())
}
fn rotation(&self) -> f64 {
self.rotation_angle() as f64
}
fn force(&self) -> f64 {
self.force() as f64
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
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();