1use crate::{Event, Input, Motion};
2
3#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
5pub enum Touch {
6 Start,
9 Move,
12 End,
15 Cancel,
18}
19
20#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, PartialOrd, Debug)]
31pub struct TouchArgs {
32 pub device: i64,
34 pub id: i64,
36 pub position_3d: [f64; 3],
38 pub pressure_3d: [f64; 3],
40 pub is_3d: bool,
42 pub touch: Touch,
44}
45
46impl TouchArgs {
47 pub fn new(device: i64, id: i64, position: [f64; 2], pressure: f64, touch: Touch) -> TouchArgs {
49 TouchArgs {
50 device,
51 id,
52 position_3d: [position[0], position[1], 0.0],
53 pressure_3d: [0.0, 0.0, pressure],
54 is_3d: false,
55 touch,
56 }
57 }
58
59 pub fn new_3d(
63 device: i64,
64 id: i64,
65 position_3d: [f64; 3],
66 pressure_3d: [f64; 3],
67 touch: Touch,
68 ) -> TouchArgs {
69 TouchArgs {
70 device,
71 id,
72 position_3d,
73 pressure_3d,
74 is_3d: true,
75 touch,
76 }
77 }
78
79 pub fn position(&self) -> [f64; 2] {
81 [self.position_3d[0], self.position_3d[1]]
82 }
83
84 pub fn position_3d(&self) -> [f64; 3] {
86 self.position_3d
87 }
88
89 pub fn pressure(&self) -> f64 {
91 let px = self.pressure_3d[0];
92 let py = self.pressure_3d[1];
93 let pz = self.pressure_3d[2];
94 (px * px + py * py + pz * pz).sqrt()
95 }
96
97 pub fn pressure_3d(&self) -> [f64; 3] {
99 self.pressure_3d
100 }
101}
102
103pub trait TouchEvent: Sized {
105 fn from_touch_args(args: &TouchArgs, old_event: &Self) -> Option<Self>;
109 fn touch<U, F>(&self, f: F) -> Option<U>
111 where
112 F: FnMut(&TouchArgs) -> U;
113 fn touch_args(&self) -> Option<TouchArgs> {
115 self.touch(|args| *args)
116 }
117}
118
119impl TouchEvent for Event {
120 fn from_touch_args(args: &TouchArgs, old_event: &Self) -> Option<Self> {
121 let timestamp = if let Event::Input(_, x) = old_event {
122 *x
123 } else {
124 None
125 };
126 Some(Event::Input(Input::Move(Motion::Touch(*args)), timestamp))
127 }
128
129 fn touch<U, F>(&self, mut f: F) -> Option<U>
130 where
131 F: FnMut(&TouchArgs) -> U,
132 {
133 match *self {
134 Event::Input(Input::Move(Motion::Touch(ref args)), _) => Some(f(args)),
135 _ => None,
136 }
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn test_input_touch() {
146 let pos = [0.0; 2];
147 let e: Event = TouchArgs::new(0, 0, pos, 1.0, Touch::Start).into();
148 let a: Option<Event> =
149 TouchEvent::from_touch_args(&TouchArgs::new(0, 0, pos, 1.0, Touch::Start), &e);
150 let b: Option<Event> = a
151 .clone()
152 .unwrap()
153 .touch(|t| {
154 TouchEvent::from_touch_args(
155 &TouchArgs::new(t.device, t.id, t.position(), t.pressure(), Touch::Start),
156 a.as_ref().unwrap(),
157 )
158 })
159 .unwrap();
160 assert_eq!(a, b);
161 }
162
163 #[test]
164 fn test_input_touch_3d() {
165 use super::super::Event;
166
167 let pos = [0.0; 3];
168 let pressure = [0.0, 0.0, 1.0];
169 let e: Event = TouchArgs::new_3d(0, 0, pos, pressure, Touch::Start).into();
170 let a: Option<Event> =
171 TouchEvent::from_touch_args(&TouchArgs::new_3d(0, 0, pos, pressure, Touch::Start), &e);
172 let b: Option<Event> = a
173 .clone()
174 .unwrap()
175 .touch(|t| {
176 TouchEvent::from_touch_args(
177 &TouchArgs::new_3d(
178 t.device,
179 t.id,
180 t.position_3d(),
181 t.pressure_3d(),
182 Touch::Start,
183 ),
184 a.as_ref().unwrap(),
185 )
186 })
187 .unwrap();
188 assert_eq!(a, b);
189 }
190}