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