1use super::{inspector_metadata, Modifier, PointerEvent};
2use cranpose_foundation::{
3 impl_pointer_input_node, DelegatableNode, ModifierNode, ModifierNodeContext,
4 ModifierNodeElement, NodeCapabilities, NodeState, PointerInputNode,
5};
6use cranpose_ui_graphics::Size;
7use futures_task::{waker, ArcWake};
8use std::any::TypeId;
9use std::cell::{Cell, RefCell};
10use std::collections::{hash_map::DefaultHasher, HashMap, VecDeque};
11use std::fmt;
12use std::future::Future;
13use std::hash::{Hash, Hasher};
14use std::pin::Pin;
15use std::rc::Rc;
16use std::sync::atomic::{AtomicU64, Ordering};
17use std::sync::Arc;
18use std::task::{Context, Poll, Waker};
19
20impl Modifier {
21 pub fn pointer_input<K, F, Fut>(self, key: K, handler: F) -> Self
22 where
23 K: Hash + 'static,
24 F: Fn(PointerInputScope) -> Fut + 'static,
25 Fut: Future<Output = ()> + 'static,
26 {
27 let element =
28 PointerInputElement::new(vec![KeyToken::new(&key)], pointer_input_handler(handler));
29 let key_count = element.key_count();
30 let handler_id = element.handler_id();
31 self.then(
32 Self::with_element(element).with_inspector_metadata(inspector_metadata(
33 "pointerInput",
34 move |info| {
35 info.add_property("keyCount", key_count.to_string());
36 info.add_property("handlerId", handler_id.to_string());
37 },
38 )),
39 )
40 }
41}
42
43fn pointer_input_handler<F, Fut>(handler: F) -> PointerInputHandler
44where
45 F: Fn(PointerInputScope) -> Fut + 'static,
46 Fut: Future<Output = ()> + 'static,
47{
48 Rc::new(move |scope| Box::pin(handler(scope.clone())))
49}
50
51type PointerInputFuture = Pin<Box<dyn Future<Output = ()>>>;
52type PointerInputHandler = Rc<dyn Fn(PointerInputScope) -> PointerInputFuture>;
53
54thread_local! {
55 static POINTER_INPUT_TASKS: RefCell<HashMap<u64, Rc<PointerInputTaskInner>>> = RefCell::new(HashMap::new());
56}
57
58#[derive(Clone)]
59struct PointerInputElement {
60 keys: Vec<KeyToken>,
61 handler: PointerInputHandler,
62 handler_id: u64,
63}
64
65impl PointerInputElement {
66 fn new(keys: Vec<KeyToken>, handler: PointerInputHandler) -> Self {
67 static NEXT_HANDLER_ID: AtomicU64 = AtomicU64::new(1);
68 let handler_id = NEXT_HANDLER_ID.fetch_add(1, Ordering::Relaxed);
69 Self {
70 keys,
71 handler,
72 handler_id,
73 }
74 }
75
76 fn key_count(&self) -> usize {
77 self.keys.len()
78 }
79
80 fn handler_id(&self) -> u64 {
81 self.handler_id
82 }
83}
84
85impl fmt::Debug for PointerInputElement {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 f.debug_struct("PointerInputElement")
88 .field("keys", &self.keys)
89 .field("handler", &Rc::as_ptr(&self.handler))
90 .field("handler_id", &self.handler_id)
91 .finish()
92 }
93}
94
95impl PartialEq for PointerInputElement {
96 fn eq(&self, other: &Self) -> bool {
97 self.keys == other.keys
101 }
102}
103
104impl Eq for PointerInputElement {}
105
106impl Hash for PointerInputElement {
107 fn hash<H: Hasher>(&self, state: &mut H) {
108 self.keys.hash(state);
111 }
112}
113
114impl ModifierNodeElement for PointerInputElement {
115 type Node = SuspendingPointerInputNode;
116
117 fn create(&self) -> Self::Node {
118 SuspendingPointerInputNode::new(self.keys.clone(), self.handler.clone())
119 }
120
121 fn update(&self, node: &mut Self::Node) {
122 node.update(self.keys.clone(), self.handler.clone());
123 }
124
125 fn capabilities(&self) -> NodeCapabilities {
126 NodeCapabilities::POINTER_INPUT
127 }
128}
129
130#[derive(Clone)]
131pub struct PointerInputScope {
132 state: Rc<PointerInputScopeState>,
133}
134
135impl PointerInputScope {
136 fn new(state: Rc<PointerInputScopeState>) -> Self {
137 Self { state }
138 }
139
140 pub fn size(&self) -> Size {
141 self.state.size.get()
142 }
143
144 pub async fn await_pointer_event_scope<R, F, Fut>(&self, block: F) -> R
145 where
146 F: FnOnce(AwaitPointerEventScope) -> Fut,
147 Fut: Future<Output = R>,
148 {
149 let scope = AwaitPointerEventScope {
150 state: self.state.clone(),
151 };
152 block(scope).await
153 }
154}
155
156#[derive(Clone)]
157pub struct AwaitPointerEventScope {
158 state: Rc<PointerInputScopeState>,
159}
160
161impl AwaitPointerEventScope {
162 pub fn size(&self) -> Size {
163 self.state.size.get()
164 }
165
166 pub async fn await_pointer_event(&self) -> PointerEvent {
167 NextPointerEvent {
168 state: self.state.clone(),
169 }
170 .await
171 }
172
173 pub async fn with_timeout_or_null<R, F, Fut>(&self, _time_millis: u64, block: F) -> Option<R>
174 where
175 F: FnOnce(&AwaitPointerEventScope) -> Fut,
176 Fut: Future<Output = R>,
177 {
178 Some(block(self).await)
179 }
180
181 pub async fn with_timeout<R, F, Fut>(&self, _time_millis: u64, block: F) -> R
182 where
183 F: FnOnce(&AwaitPointerEventScope) -> Fut,
184 Fut: Future<Output = R>,
185 {
186 block(self).await
187 }
188}
189
190struct NextPointerEvent {
191 state: Rc<PointerInputScopeState>,
192}
193
194impl Future for NextPointerEvent {
195 type Output = PointerEvent;
196
197 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
198 self.state.poll_event(cx)
199 }
200}
201
202struct PointerInputScopeState {
203 events: RefCell<VecDeque<PointerEvent>>,
204 waiting: RefCell<Option<Waker>>,
205 size: Cell<Size>,
206}
207
208impl PointerInputScopeState {
209 fn new() -> Self {
210 Self {
211 events: RefCell::new(VecDeque::new()),
212 waiting: RefCell::new(None),
213 size: Cell::new(Size {
214 width: 0.0,
215 height: 0.0,
216 }),
217 }
218 }
219
220 fn push_event(&self, event: PointerEvent) {
221 self.events.borrow_mut().push_back(event);
222 let waker = {
223 let mut waiting = self.waiting.borrow_mut();
224 waiting.take()
225 };
226 if let Some(waker) = waker {
227 waker.wake();
228 }
229 }
230
231 fn poll_event(&self, cx: &mut Context<'_>) -> Poll<PointerEvent> {
232 if let Some(event) = self.events.borrow_mut().pop_front() {
233 Poll::Ready(event)
234 } else {
235 self.waiting.replace(Some(cx.waker().clone()));
236 Poll::Pending
237 }
238 }
239}
240
241struct PointerEventDispatcher {
242 state: Rc<RefCell<Option<Rc<PointerInputScopeState>>>>,
243 handler: Rc<dyn Fn(PointerEvent)>,
244}
245
246impl PointerEventDispatcher {
247 fn new() -> Self {
248 let state = Rc::new(RefCell::new(None::<Rc<PointerInputScopeState>>));
249 let state_for_handler = state.clone();
250 let handler = Rc::new(move |event: PointerEvent| {
251 if let Some(inner) = state_for_handler.borrow().as_ref() {
252 inner.push_event(event);
253 }
254 });
255 Self { state, handler }
256 }
257
258 fn handler(&self) -> Rc<dyn Fn(PointerEvent)> {
259 self.handler.clone()
260 }
261
262 fn set_state(&self, state: Option<Rc<PointerInputScopeState>>) {
263 *self.state.borrow_mut() = state;
264 }
265}
266
267struct PointerInputTask {
268 id: u64,
269 inner: Rc<PointerInputTaskInner>,
270}
271
272impl PointerInputTask {
273 fn new(future: PointerInputFuture) -> Self {
274 static NEXT_TASK_ID: AtomicU64 = AtomicU64::new(1);
275 let id = NEXT_TASK_ID.fetch_add(1, Ordering::Relaxed);
276 let inner = Rc::new(PointerInputTaskInner::new(future));
277 POINTER_INPUT_TASKS.with(|registry| {
278 registry.borrow_mut().insert(id, inner.clone());
279 });
280 Self { id, inner }
281 }
282
283 fn poll(&self) {
284 self.inner.poll(self.id);
285 }
286
287 fn cancel(self) {
288 self.inner.cancel();
289 POINTER_INPUT_TASKS.with(|registry| {
290 registry.borrow_mut().remove(&self.id);
291 });
292 }
293}
294
295impl Drop for PointerInputTask {
296 fn drop(&mut self) {
297 }
304}
305
306struct PointerInputTaskInner {
307 future: RefCell<Option<PointerInputFuture>>,
308 is_polling: Cell<bool>,
309 needs_poll: Cell<bool>,
310}
311
312impl PointerInputTaskInner {
313 fn new(future: PointerInputFuture) -> Self {
314 Self {
315 future: RefCell::new(Some(future)),
316 is_polling: Cell::new(false),
317 needs_poll: Cell::new(false),
318 }
319 }
320
321 fn cancel(&self) {
322 self.future.borrow_mut().take();
323 }
324
325 fn request_poll(&self, task_id: u64) {
326 if self.is_polling.get() {
327 self.needs_poll.set(true);
328 } else {
329 self.poll(task_id);
330 }
331 }
332
333 fn poll(&self, task_id: u64) {
334 if self.is_polling.replace(true) {
335 self.needs_poll.set(true);
336 return;
337 }
338 loop {
339 self.needs_poll.set(false);
340 let waker = waker(Arc::new(PointerInputTaskWaker { task_id }));
341 let mut cx = Context::from_waker(&waker);
342 let mut future_slot = self.future.borrow_mut();
343 if let Some(future) = future_slot.as_mut() {
344 let poll_result = future.as_mut().poll(&mut cx);
345 if poll_result.is_ready() {
346 future_slot.take();
347 }
348 }
349 if !self.needs_poll.get() {
350 break;
351 }
352 }
353 self.is_polling.set(false);
354 }
355}
356
357struct PointerInputTaskWaker {
358 task_id: u64,
359}
360
361impl ArcWake for PointerInputTaskWaker {
362 fn wake_by_ref(arc_self: &Arc<Self>) {
363 POINTER_INPUT_TASKS.with(|registry| {
364 if let Some(task) = registry.borrow().get(&arc_self.task_id).cloned() {
365 task.request_poll(arc_self.task_id);
366 }
367 });
368 }
369}
370
371pub struct SuspendingPointerInputNode {
372 keys: Vec<KeyToken>,
373 handler: PointerInputHandler,
374 dispatcher: PointerEventDispatcher,
375 task: Option<PointerInputTask>,
376 state: NodeState,
377}
378
379impl SuspendingPointerInputNode {
380 fn new(keys: Vec<KeyToken>, handler: PointerInputHandler) -> Self {
381 Self {
382 keys,
383 handler,
384 dispatcher: PointerEventDispatcher::new(),
385 task: None,
386 state: NodeState::new(),
387 }
388 }
389
390 fn update(&mut self, keys: Vec<KeyToken>, handler: PointerInputHandler) {
391 let should_restart = self.keys != keys;
396 self.keys = keys;
397 self.handler = handler; if should_restart {
399 self.restart();
400 }
401 }
402
403 fn restart(&mut self) {
404 self.cancel();
405 self.start();
406 }
407
408 fn start(&mut self) {
409 let state = Rc::new(PointerInputScopeState::new());
410 self.dispatcher.set_state(Some(state.clone()));
411 let scope = PointerInputScope::new(state);
412 let future = (self.handler)(scope);
413 let task = PointerInputTask::new(future);
414 task.poll();
415 self.task = Some(task);
416 }
417
418 fn cancel(&mut self) {
419 if let Some(task) = self.task.take() {
420 task.cancel();
421 }
422 self.dispatcher.set_state(None);
423 }
424}
425
426impl Drop for SuspendingPointerInputNode {
427 fn drop(&mut self) {
428 }
430}
431
432impl ModifierNode for SuspendingPointerInputNode {
433 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {
434 self.start();
435 }
436
437 fn on_detach(&mut self) {
438 self.cancel();
439 }
440
441 fn on_reset(&mut self) {
442 }
446
447 impl_pointer_input_node!();
449}
450
451impl DelegatableNode for SuspendingPointerInputNode {
452 fn node_state(&self) -> &NodeState {
453 &self.state
454 }
455}
456
457impl PointerInputNode for SuspendingPointerInputNode {
458 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
459 Some(self.dispatcher.handler())
460 }
461}
462
463#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
464struct KeyToken {
465 type_id: TypeId,
466 hash: u64,
467}
468
469impl KeyToken {
470 fn new<T: Hash + 'static>(value: &T) -> Self {
471 let mut hasher = DefaultHasher::new();
472 value.hash(&mut hasher);
473 Self {
474 type_id: TypeId::of::<T>(),
475 hash: hasher.finish(),
476 }
477 }
478}