1use super::raw::{IRawInputEventArgs, RawPointerEventArgs, RawPointerEventType};
2use super::{
3 CaptureSource, IInputDevice, IPointer, IPointerDevice, InputElement, MouseButton, Pointer, PointerEventArgs,
4 PointerPointProperties, PointerPressedEventArgs, PointerReleasedEventArgs, PointerType, RawInputModifiers,
5};
6use crate::{Rect, Size, Thickness};
7use std::any::Any;
8use std::cell::{Cell, RefCell};
9use std::collections::HashMap;
10use std::rc::Rc;
11
12pub struct TouchDevice {
17 pointers: RefCell<HashMap<i64, Rc<Pointer>>>,
18 disposed: Cell<bool>,
19 click_count: Cell<i32>,
20 last_click_rect: Cell<Rect>,
21 last_click_time: Cell<u64>,
22}
23
24impl TouchDevice {
25 pub fn new() -> Rc<TouchDevice> {
27 Rc::new(TouchDevice {
28 pointers: RefCell::new(HashMap::new()),
29 disposed: Cell::new(false),
30 click_count: Cell::new(0),
31 last_click_rect: Cell::new(Rect::default()),
32 last_click_time: Cell::new(0),
33 })
34 }
35
36 fn get_modifiers(modifiers: RawInputModifiers, is_left_button_down: bool) -> RawInputModifiers {
37 let mut rv = modifiers & RawInputModifiers::KEYBOARD_MASK;
38 if is_left_button_down {
39 rv |= RawInputModifiers::LEFT_MOUSE_BUTTON;
40 }
41 rv
42 }
43
44 pub fn dispose(&self) {
46 if self.disposed.get() {
47 return;
48 }
49
50 let values: Vec<_> = self.pointers.borrow_mut().drain().map(|(_, pointer)| pointer).collect();
51 self.disposed.set(true);
52
53 for p in values {
54 p.dispose();
55 }
56 }
57
58 pub fn platform_capture_lost(&self) {
61 let pointers: Vec<_> = self.pointers.borrow().values().cloned().collect();
62 for pointer in pointers {
63 pointer.platform_capture_lost();
64 }
65 }
66}
67
68impl IInputDevice for TouchDevice {
69 fn process_raw_event(&self, ev: &dyn IRawInputEventArgs) {
70 if ev.handled() || self.disposed.get() {
71 return;
72 }
73
74 let args = ev.downcast_ref::<RawPointerEventArgs>().expect("a touch device processes raw pointer events");
75 let hit = args.input_hit_test_result().1;
76 let existing = self.pointers.borrow().get(&args.raw_pointer_id()).cloned();
77
78 let pointer = match existing {
79 Some(pointer) => pointer,
80 None => {
81 if args.type_() == RawPointerEventType::TouchEnd {
82 return;
83 }
84
85 let is_primary = self.pointers.borrow().is_empty();
86 let pointer = Pointer::new(Pointer::get_next_free_id(), PointerType::Touch, is_primary);
87 self.pointers.borrow_mut().insert(args.raw_pointer_id(), pointer.clone());
88 pointer.capture_with_source(hit.as_ref(), CaptureSource::Implicit);
89 pointer
90 }
91 };
92
93 let root_element = args.root().root_element();
94 let mut target = pointer.captured().or(hit).unwrap_or_else(|| root_element.clone());
95 let gesture_recognizer = pointer.captured_gesture_recognizer();
96 let gesture_target = gesture_recognizer.as_ref().and_then(|recognizer| recognizer.target());
97 let update_kind = args.type_().to_update_kind();
98 let key_modifier = args.input_modifiers().to_key_modifiers();
99
100 if args.type_() == RawPointerEventType::TouchBegin {
101 if self.pointers.borrow().len() > 1 {
102 self.click_count.set(1);
103 self.last_click_time.set(0);
104 self.last_click_rect.set(Rect::default());
105 } else if let Some(settings) = target.get_platform_settings() {
106 let double_click_time = settings.get_double_tap_time(PointerType::Touch).as_secs_f64() * 1000.0;
107 let double_click_size = settings.get_double_tap_size(PointerType::Touch);
108
109 if !self.last_click_rect.get().contains(args.position())
110 || ev.timestamp().wrapping_sub(self.last_click_time.get()) as f64 > double_click_time
111 {
112 self.click_count.set(0);
113 }
114
115 self.click_count.set(self.click_count.get() + 1);
116 self.last_click_time.set(ev.timestamp());
117 self.last_click_rect.set(Rect::from_position_size(args.position(), Size::default()).inflate_thickness(
118 Thickness::symmetric(double_click_size.width / 2.0, double_click_size.height / 2.0),
119 ));
120 }
121
122 target.raise_event(
123 &PointerPressedEventArgs::new(
124 &target,
125 pointer.clone(),
126 &root_element,
127 args.position(),
128 ev.timestamp(),
129 PointerPointProperties::from_raw_point(
130 Self::get_modifiers(args.input_modifiers(), true),
131 update_kind,
132 args.point(),
133 ),
134 key_modifier,
135 self.click_count.get(),
136 )
137 .with_platform_input_event_cookie(args.platform_input_event_cookie()),
138 );
139 }
140
141 if args.type_() == RawPointerEventType::TouchEnd {
142 self.pointers.borrow_mut().remove(&args.raw_pointer_id());
143
144 target = gesture_target.clone().unwrap_or(target);
145
146 let e = PointerReleasedEventArgs::new(
147 &target,
148 pointer.clone(),
149 &root_element,
150 args.position(),
151 ev.timestamp(),
152 PointerPointProperties::from_raw_point(
153 Self::get_modifiers(args.input_modifiers(), false),
154 update_kind,
155 args.point(),
156 ),
157 key_modifier,
158 MouseButton::Left,
159 );
160
161 match (&gesture_target, pointer.captured_gesture_recognizer()) {
162 (Some(_), Some(recognizer)) => recognizer.pointer_released_internal(&e),
163 (Some(_), None) => {}
164 (None, _) => target.raise_event(&e),
165 }
166
167 pointer.capture_lost(CaptureSource::Implicit);
168 pointer.dispose();
169 }
170
171 if args.type_() == RawPointerEventType::TouchCancel {
172 self.pointers.borrow_mut().remove(&args.raw_pointer_id());
173 pointer.dispose();
174 }
175
176 if args.type_() == RawPointerEventType::TouchUpdate {
177 target = gesture_target.clone().unwrap_or(target);
178
179 let e = PointerEventArgs::new(
180 Some(InputElement::pointer_moved_event()),
181 &target,
182 pointer.clone(),
183 Some(&root_element),
184 args.position(),
185 ev.timestamp(),
186 PointerPointProperties::from_raw_point(
187 Self::get_modifiers(args.input_modifiers(), true),
188 update_kind,
189 args.point(),
190 ),
191 key_modifier,
192 )
193 .with_previous_points(args.intermediate_points());
194
195 match (&gesture_target, pointer.captured_gesture_recognizer()) {
196 (Some(_), Some(recognizer)) => recognizer.pointer_moved_internal(&e),
197 (Some(_), None) => {}
198 (None, _) => target.raise_event(&e),
199 }
200 }
201 }
202
203 fn as_any(&self) -> &dyn Any {
204 self
205 }
206
207 fn as_pointer_device(&self) -> Option<&dyn IPointerDevice> {
208 Some(self)
209 }
210}
211
212impl IPointerDevice for TouchDevice {
213 fn try_get_pointer(&self, ev: &RawPointerEventArgs) -> Option<Rc<dyn IPointer>> {
214 self.pointers.borrow().get(&ev.raw_pointer_id()).map(|pointer| pointer.clone() as Rc<dyn IPointer>)
215 }
216}