1use super::gesture_recognizers::GestureRecognizer;
2use super::{
3 IPointer, InputElement, PointerCaptureChangingEventArgs, PointerCaptureLostEventArgs, PointerType,
4};
5use crate::reactive::IDisposable;
6use crate::{Ref, Visual, VisualTreeAttachmentEventArgs};
7use std::any::Any;
8use std::cell::{Cell, RefCell};
9use std::rc::{Rc, Weak};
10use std::sync::atomic::{AtomicI32, Ordering};
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum CaptureSource {
15 Explicit,
17 Implicit,
20 Platform,
22}
23
24static NEXT_FREE_POINTER_ID: AtomicI32 = AtomicI32::new(1000);
25
26type PlatformCapture = Box<dyn Fn(Option<&Ref<InputElement>>)>;
29
30pub struct Pointer {
33 this: Weak<Pointer>,
34 id: i32,
35 type_: PointerType,
36 is_primary: bool,
37 disposed: Cell<bool>,
38 captured: RefCell<Option<Ref<InputElement>>>,
39 captured_gesture_recognizer: RefCell<Option<Ref<GestureRecognizer>>>,
40 capture_source: Cell<CaptureSource>,
41 is_gesture_recognition_skipped: Cell<bool>,
42 capture_detached: RefCell<Option<Rc<dyn IDisposable>>>,
43 platform_capture: Option<PlatformCapture>,
44}
45
46impl Pointer {
47 pub fn get_next_free_id() -> i32 {
49 NEXT_FREE_POINTER_ID.fetch_add(1, Ordering::Relaxed)
50 }
51
52 pub fn new(id: i32, type_: PointerType, is_primary: bool) -> Rc<Pointer> {
54 Self::create(id, type_, is_primary, None)
55 }
56
57 pub fn with_platform_capture(
60 id: i32,
61 type_: PointerType,
62 is_primary: bool,
63 platform_capture: impl Fn(Option<&Ref<InputElement>>) + 'static,
64 ) -> Rc<Pointer> {
65 Self::create(id, type_, is_primary, Some(Box::new(platform_capture)))
66 }
67
68 fn create(id: i32, type_: PointerType, is_primary: bool, platform_capture: Option<PlatformCapture>) -> Rc<Pointer> {
69 Rc::new_cyclic(|this| Pointer {
70 this: this.clone(),
71 id,
72 type_,
73 is_primary,
74 disposed: Cell::new(false),
75 captured: RefCell::new(None),
76 captured_gesture_recognizer: RefCell::new(None),
77 capture_source: Cell::new(CaptureSource::Platform),
78 is_gesture_recognition_skipped: Cell::new(false),
79 capture_detached: RefCell::new(None),
80 platform_capture,
81 })
82 }
83
84 fn find_common_parent(
87 control1: Option<&Ref<InputElement>>,
88 control2: Option<&Ref<InputElement>>,
89 ) -> Option<Ref<InputElement>> {
90 let (c1, c2) = (control1?, control2?);
91
92 c2.get_self_and_visual_ancestors()
93 .filter_map(|v| v.downcast::<InputElement>().ok())
94 .find(|candidate| candidate == c1 || candidate.is_visual_ancestor_of(c1))
95 }
96
97 fn platform_capture(&self, element: Option<&Ref<InputElement>>) {
98 if let Some(platform_capture) = &self.platform_capture {
99 platform_capture(element);
100 }
101 }
102
103 pub fn platform_capture_lost(&self) {
105 self.capture_lost(CaptureSource::Platform);
106 }
107
108 pub(crate) fn capture_lost(&self, source: CaptureSource) {
109 if self.disposed.get() {
110 return;
111 }
112
113 self.capture_lost_core(source);
114 }
115
116 fn capture_lost_core(&self, source: CaptureSource) {
117 self.capture_core(None, None, source);
118 self.is_gesture_recognition_skipped.set(false);
119 }
120
121 pub fn capture_with_source(&self, control: Option<&Ref<InputElement>>, source: CaptureSource) {
124 if self.disposed.get() {
125 debug_assert!(control.is_none(), "Capturing a pointer that no longer exists.");
126 return;
127 }
128
129 self.capture_core(control.cloned(), None, source);
130 }
131
132 fn effective_capturer(&self) -> Option<Ref<InputElement>> {
135 self.captured_gesture_recognizer().and_then(|recognizer| recognizer.target()).or_else(|| self.captured())
136 }
137
138 pub fn captured_gesture_recognizer(&self) -> Option<Ref<GestureRecognizer>> {
140 self.captured_gesture_recognizer.borrow().clone()
141 }
142
143 fn capture_core(
144 &self,
145 control: Option<Ref<InputElement>>,
146 gesture_recognizer: Option<Ref<GestureRecognizer>>,
147 source: CaptureSource,
148 ) {
149 let old_capture = self.captured();
150 let old_gesture_recognizer = self.captured_gesture_recognizer();
151 let old_source = self.capture_source.get();
152 let old_effective_capturer = self.effective_capturer();
153
154 if old_capture == control && old_gesture_recognizer == gesture_recognizer && old_source == source {
157 return;
158 }
159
160 let this: Rc<dyn IPointer> = match self.this.upgrade() {
161 Some(this) => this,
162 None => return,
163 };
164
165 let mut common_parent = None;
166
167 if old_capture.is_some() || control.is_some() {
168 common_parent = Self::find_common_parent(control.as_ref(), old_capture.as_ref());
169
170 let visual: &Visual = old_capture.as_ref().or(control.as_ref()).expect("one of them is set");
173
174 for notify_target in
175 visual.get_self_and_visual_ancestors().filter_map(|v| v.downcast::<InputElement>().ok())
176 {
177 let args = PointerCaptureChangingEventArgs::new(¬ify_target, this.clone(), control.clone(), source);
178 notify_target.raise_event(&args);
179
180 if args.handled() {
181 return;
182 }
183
184 if Some(¬ify_target) == common_parent.as_ref() {
185 break;
186 }
187 }
188 }
189
190 if old_capture.is_some() {
191 let subscription = self.capture_detached.take();
192 if let Some(subscription) = subscription {
193 subscription.dispose();
194 }
195 }
196
197 let this_pointer = this.clone();
198 if old_gesture_recognizer != gesture_recognizer {
199 if let Some(old) = &old_gesture_recognizer {
200 old.pointer_capture_lost_internal(&this_pointer);
201 }
202 }
203
204 drop(self.captured.replace(control.clone()));
205 drop(self.captured_gesture_recognizer.replace(gesture_recognizer));
206 self.capture_source.set(source);
207
208 let effective_capturer = self.effective_capturer();
211 if old_effective_capturer != effective_capturer && source != CaptureSource::Platform {
212 self.platform_capture(effective_capturer.as_ref());
213 }
214
215 if let Some(old_visual) = &old_capture {
216 for notify_target in
217 old_visual.get_self_and_visual_ancestors().filter_map(|v| v.downcast::<InputElement>().ok())
218 {
219 if Some(¬ify_target) == common_parent.as_ref() {
220 break;
221 }
222
223 notify_target.raise_event(&PointerCaptureLostEventArgs::new(¬ify_target, this.clone()));
224 }
225 }
226
227 if let Some(new_visual) = &control {
228 let weak = self.this.clone();
229 let subscription = new_visual.detached_from_visual_tree(move |e| {
230 if let Some(pointer) = weak.upgrade() {
231 pointer.on_capture_detached(e);
232 }
233 });
234 let old = self.capture_detached.replace(Some(subscription));
235 if let Some(old) = old {
236 old.dispose();
237 }
238 }
239
240 if self.captured.borrow().is_none() && self.captured_gesture_recognizer.borrow().is_none() {
241 self.is_gesture_recognition_skipped.set(false);
242 }
243
244 if self.type_ != PointerType::Touch {
247 let old_input_root = old_capture.as_ref().and_then(|v| v.get_input_root());
248 let new_input_root = control.as_ref().and_then(|v| v.get_input_root());
249
250 if let Some(old_input_root) = &old_input_root {
251 old_input_root.pointer_over_invalidated();
252 }
253
254 let same_root = match (&old_input_root, &new_input_root) {
255 (Some(a), Some(b)) => std::ptr::addr_eq(Rc::as_ptr(a), Rc::as_ptr(b)),
256 (None, None) => true,
257 _ => false,
258 };
259
260 if !same_root {
261 if let Some(new_input_root) = &new_input_root {
262 new_input_root.pointer_over_invalidated();
263 }
264 }
265 }
266 }
267
268 fn get_next_capture(parent: Option<&Ref<Visual>>) -> Option<Ref<InputElement>> {
269 parent.and_then(|parent| parent.find_ancestor_of_type::<InputElement>(true))
270 }
271
272 fn on_capture_detached(&self, e: &VisualTreeAttachmentEventArgs) {
273 let next = Self::get_next_capture(e.attachment_point());
274 self.capture(next.as_ref());
275 }
276
277 pub(crate) fn capture_gesture_recognizer(&self, gesture_recognizer: Option<&Ref<GestureRecognizer>>) {
280 if self.disposed.get() {
281 debug_assert!(
282 gesture_recognizer.is_none(),
283 "Capturing a pointer that no longer exists to a gesture recognizer."
284 );
285 return;
286 }
287
288 self.capture_core(None, gesture_recognizer.cloned(), CaptureSource::Explicit);
289 }
290
291 pub fn capture_source(&self) -> CaptureSource {
293 self.capture_source.get()
294 }
295
296 pub fn is_gesture_recognition_skipped(&self) -> bool {
299 self.is_gesture_recognition_skipped.get()
300 }
301
302 pub fn set_is_gesture_recognition_skipped(&self, value: bool) {
304 self.is_gesture_recognition_skipped.set(value)
305 }
306
307 pub fn dispose(&self) {
310 if self.disposed.get() {
311 return;
312 }
313
314 self.disposed.set(true);
318 self.capture_lost_core(CaptureSource::Platform);
319 }
320}
321
322impl IPointer for Pointer {
323 fn id(&self) -> i32 {
324 self.id
325 }
326
327 fn capture(&self, control: Option<&Ref<InputElement>>) {
328 self.capture_with_source(control, CaptureSource::Explicit);
329 }
330
331 fn captured(&self) -> Option<Ref<InputElement>> {
332 self.captured.borrow().clone()
333 }
334
335 fn type_(&self) -> PointerType {
336 self.type_
337 }
338
339 fn is_primary(&self) -> bool {
340 self.is_primary
341 }
342
343 fn as_any(&self) -> &dyn Any {
344 self
345 }
346}