1use super::raw::{IRawInputEventArgs, RawPointerEventArgs, RawPointerEventType};
2use super::{
3 CaptureSource, IInputDevice, IInputRoot, IPenDevice, IPointer, IPointerDevice, InputElement, IntermediatePoints,
4 KeyModifiers, MouseButton, Pointer, PointerEventArgs, PointerPointProperties, PointerPressedEventArgs,
5 PointerReleasedEventArgs, PointerType,
6};
7use crate::{Point, Rect, Ref, Size, Thickness};
8use std::any::Any;
9use std::cell::{Cell, RefCell};
10use std::collections::HashMap;
11use std::rc::Rc;
12
13pub struct PenDevice {
15 pointers: RefCell<HashMap<i64, Rc<Pointer>>>,
16 release_pointer_on_pen_up: bool,
17 click_count: Cell<i32>,
18 last_click_rect: Cell<Rect>,
19 last_click_time: Cell<u64>,
20 last_mouse_down_button: Cell<MouseButton>,
21 disposed: Cell<bool>,
22}
23
24impl PenDevice {
25 pub fn new(release_pointer_on_pen_up: bool) -> Rc<PenDevice> {
28 Rc::new(PenDevice {
29 pointers: RefCell::new(HashMap::new()),
30 release_pointer_on_pen_up,
31 click_count: Cell::new(0),
32 last_click_rect: Cell::new(Rect::default()),
33 last_click_time: Cell::new(0),
34 last_mouse_down_button: Cell::new(MouseButton::None),
35 disposed: Cell::new(false),
36 })
37 }
38
39 fn process_raw_pointer_event(&self, e: &RawPointerEventArgs) {
40 let existing = self.pointers.borrow().get(&e.raw_pointer_id()).cloned();
41
42 let pointer = match existing {
43 Some(pointer) => pointer,
44 None => {
45 if e.type_() == RawPointerEventType::LeftButtonUp || e.type_() == RawPointerEventType::TouchEnd {
46 return;
47 }
48
49 let is_primary = self.pointers.borrow().is_empty();
50 let pointer = Pointer::new(Pointer::get_next_free_id(), PointerType::Pen, is_primary);
51 self.pointers.borrow_mut().insert(e.raw_pointer_id(), pointer.clone());
52 pointer
53 }
54 };
55
56 let point = e.point();
57 let props = PointerPointProperties::with_pen_state_and_contact_rect(
58 e.input_modifiers(),
59 e.type_().to_update_kind(),
60 point.twist,
61 point.pressure,
62 point.x_tilt,
63 point.y_tilt,
64 point.contact_rect(),
65 );
66 let key_modifiers = e.input_modifiers().to_key_modifiers();
67 let hit_test = e.input_hit_test_result().1;
68
69 struct Release<'a> {
71 device: &'a PenDevice,
72 raw_pointer_id: i64,
73 pointer: Rc<Pointer>,
74 should_release: Cell<bool>,
75 }
76
77 impl Drop for Release<'_> {
78 fn drop(&mut self) {
79 if self.should_release.get() {
80 self.device.pointers.borrow_mut().remove(&self.raw_pointer_id);
81 self.pointer.dispose();
82 }
83 }
84 }
85
86 let release = Release {
87 device: self,
88 raw_pointer_id: e.raw_pointer_id(),
89 pointer: pointer.clone(),
90 should_release: Cell::new(false),
91 };
92
93 match e.type_() {
94 RawPointerEventType::LeaveWindow => release.should_release.set(true),
95 RawPointerEventType::CancelCapture => pointer.platform_capture_lost(),
96 RawPointerEventType::LeftButtonDown
97 | RawPointerEventType::RightButtonDown
98 | RawPointerEventType::MiddleButtonDown
99 | RawPointerEventType::XButton1Down
100 | RawPointerEventType::XButton2Down => {
101 let handled = self.pen_down(
102 &pointer,
103 e.timestamp(),
104 e.root(),
105 e.position(),
106 props,
107 key_modifiers,
108 hit_test,
109 e.platform_input_event_cookie(),
110 );
111 e.set_handled(handled);
112 }
113 RawPointerEventType::LeftButtonUp
114 | RawPointerEventType::RightButtonUp
115 | RawPointerEventType::MiddleButtonUp
116 | RawPointerEventType::XButton1Up
117 | RawPointerEventType::XButton2Up => {
118 if self.release_pointer_on_pen_up {
119 release.should_release.set(true);
120 }
121
122 let handled =
123 self.pen_up(&pointer, e.timestamp(), e.root(), e.position(), props, key_modifiers, hit_test);
124 e.set_handled(handled);
125 }
126 RawPointerEventType::Move => {
127 let handled = Self::pen_move(
128 &pointer,
129 e.timestamp(),
130 e.root(),
131 e.position(),
132 props,
133 key_modifiers,
134 hit_test,
135 e.intermediate_points(),
136 );
137 e.set_handled(handled);
138 }
139 _ => {}
140 }
141 }
142
143 #[allow(clippy::too_many_arguments)]
144 fn pen_down(
145 &self,
146 pointer: &Rc<Pointer>,
147 timestamp: u64,
148 root: &Rc<dyn IInputRoot>,
149 p: Point,
150 properties: PointerPointProperties,
151 input_modifiers: KeyModifiers,
152 hit_test: Option<Ref<InputElement>>,
153 platform_input_event_cookie: Option<Rc<dyn Any>>,
154 ) -> bool {
155 let Some(source) = pointer.captured().or(hit_test) else { return false };
156
157 pointer.capture_with_source(Some(&source), CaptureSource::Implicit);
158
159 if let Some(settings) = source.get_platform_settings() {
160 let double_click_time = settings.get_double_tap_time(PointerType::Pen).as_secs_f64() * 1000.0;
161 let double_click_size = settings.get_double_tap_size(PointerType::Pen);
162
163 if !self.last_click_rect.get().contains(p)
164 || timestamp.wrapping_sub(self.last_click_time.get()) as f64 > double_click_time
165 {
166 self.click_count.set(0);
167 }
168
169 self.click_count.set(self.click_count.get() + 1);
170 self.last_click_time.set(timestamp);
171 self.last_click_rect.set(
172 Rect::from_position_size(p, Size::default())
173 .inflate_thickness(Thickness::symmetric(double_click_size.width / 2.0, double_click_size.height / 2.0)),
174 );
175 }
176
177 self.last_mouse_down_button.set(properties.pointer_update_kind.get_mouse_button());
178
179 let e = PointerPressedEventArgs::new(
180 &source,
181 pointer.clone(),
182 &root.root_element(),
183 p,
184 timestamp,
185 properties,
186 input_modifiers,
187 self.click_count.get(),
188 )
189 .with_platform_input_event_cookie(platform_input_event_cookie);
190
191 source.raise_event(&e);
192 e.handled()
193 }
194
195 #[allow(clippy::too_many_arguments)]
196 fn pen_move(
197 pointer: &Rc<Pointer>,
198 timestamp: u64,
199 root: &Rc<dyn IInputRoot>,
200 p: Point,
201 properties: PointerPointProperties,
202 input_modifiers: KeyModifiers,
203 hit_test: Option<Ref<InputElement>>,
204 intermediate_points: Option<IntermediatePoints>,
205 ) -> bool {
206 let gesture_recognizer = pointer.captured_gesture_recognizer();
207 let source = gesture_recognizer
208 .as_ref()
209 .and_then(|recognizer| recognizer.target())
210 .or_else(|| pointer.captured())
211 .or(hit_test);
212 let Some(source) = source else { return false };
213
214 let e = PointerEventArgs::new(
215 Some(InputElement::pointer_moved_event()),
216 &source,
217 pointer.clone(),
218 Some(&root.root_element()),
219 p,
220 timestamp,
221 properties,
222 input_modifiers,
223 )
224 .with_previous_points(intermediate_points);
225
226 match &gesture_recognizer {
227 Some(gesture_recognizer) => gesture_recognizer.pointer_moved_internal(&e),
228 None => source.raise_event(&e),
229 }
230
231 e.handled()
232 }
233
234 #[allow(clippy::too_many_arguments)]
235 fn pen_up(
236 &self,
237 pointer: &Rc<Pointer>,
238 timestamp: u64,
239 root: &Rc<dyn IInputRoot>,
240 p: Point,
241 properties: PointerPointProperties,
242 input_modifiers: KeyModifiers,
243 hit_test: Option<Ref<InputElement>>,
244 ) -> bool {
245 let gesture_recognizer = pointer.captured_gesture_recognizer();
246 let source = gesture_recognizer
247 .as_ref()
248 .and_then(|recognizer| recognizer.target())
249 .or_else(|| pointer.captured())
250 .or(hit_test);
251 let Some(source) = source else { return false };
252
253 let e = PointerReleasedEventArgs::new(
254 &source,
255 pointer.clone(),
256 &root.root_element(),
257 p,
258 timestamp,
259 properties,
260 input_modifiers,
261 self.last_mouse_down_button.get(),
262 );
263
264 struct Finally<'a>(&'a PenDevice, &'a Pointer);
266
267 impl Drop for Finally<'_> {
268 fn drop(&mut self) {
269 self.1.capture_lost(CaptureSource::Implicit);
270 self.0.last_mouse_down_button.set(MouseButton::None);
271 }
272 }
273
274 {
275 let _finally = Finally(self, pointer);
276 match &gesture_recognizer {
277 Some(gesture_recognizer) => gesture_recognizer.pointer_released_internal(&e),
278 None => source.raise_event(&e),
279 }
280 }
281
282 e.handled()
283 }
284
285 pub fn dispose(&self) {
287 if self.disposed.get() {
288 return;
289 }
290
291 let values: Vec<_> = self.pointers.borrow_mut().drain().map(|(_, pointer)| pointer).collect();
292 self.disposed.set(true);
293
294 for p in values {
295 p.dispose();
296 }
297 }
298}
299
300impl IInputDevice for PenDevice {
301 fn process_raw_event(&self, e: &dyn IRawInputEventArgs) {
302 if !e.handled() {
303 if let Some(margs) = e.downcast_ref::<RawPointerEventArgs>() {
304 self.process_raw_pointer_event(margs);
305 }
306 }
307 }
308
309 fn as_any(&self) -> &dyn Any {
310 self
311 }
312
313 fn as_pointer_device(&self) -> Option<&dyn IPointerDevice> {
314 Some(self)
315 }
316}
317
318impl IPointerDevice for PenDevice {
319 fn try_get_pointer(&self, ev: &RawPointerEventArgs) -> Option<Rc<dyn IPointer>> {
320 self.pointers.borrow().get(&ev.raw_pointer_id()).map(|pointer| pointer.clone() as Rc<dyn IPointer>)
321 }
322}
323
324impl IPenDevice for PenDevice {}