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::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
54#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55pub(crate) enum PointerInputTaskOwner {
56 App(crate::render_state::AppContextId),
57}
58
59pub(crate) struct PointerInputTaskRegistry {
60 tasks: RefCell<HashMap<u64, Rc<PointerInputTaskInner>>>,
61}
62
63impl PointerInputTaskRegistry {
64 pub(crate) fn new() -> Self {
65 Self {
66 tasks: RefCell::new(HashMap::new()),
67 }
68 }
69
70 pub(crate) fn insert(&self, task_id: u64, task: Rc<PointerInputTaskInner>) {
71 self.tasks.borrow_mut().insert(task_id, task);
72 }
73
74 pub(crate) fn remove(&self, task_id: u64) {
75 self.tasks.borrow_mut().remove(&task_id);
76 }
77
78 pub(crate) fn request_poll(&self, task_id: u64, owner: PointerInputTaskOwner) {
79 if let Some(task) = self.tasks.borrow().get(&task_id).cloned() {
80 task.request_poll(owner, task_id);
81 }
82 }
83}
84
85#[derive(Clone)]
86struct PointerInputElement {
87 keys: Vec<KeyToken>,
88 handler: PointerInputHandler,
89 handler_id: u64,
90}
91
92impl PointerInputElement {
93 fn new(keys: Vec<KeyToken>, handler: PointerInputHandler) -> Self {
94 let handler_id = pointer_handler_identity(&handler);
95 Self {
96 keys,
97 handler,
98 handler_id,
99 }
100 }
101
102 fn key_count(&self) -> usize {
103 self.keys.len()
104 }
105
106 fn handler_id(&self) -> u64 {
107 self.handler_id
108 }
109}
110
111fn pointer_handler_identity(handler: &PointerInputHandler) -> u64 {
112 Rc::as_ptr(handler) as *const () as usize as u64
113}
114
115impl fmt::Debug for PointerInputElement {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 f.debug_struct("PointerInputElement")
118 .field("keys", &self.keys)
119 .field("handler", &Rc::as_ptr(&self.handler))
120 .field("handler_id", &self.handler_id)
121 .finish()
122 }
123}
124
125impl PartialEq for PointerInputElement {
126 fn eq(&self, other: &Self) -> bool {
127 self.keys == other.keys
131 }
132}
133
134impl Eq for PointerInputElement {}
135
136impl Hash for PointerInputElement {
137 fn hash<H: Hasher>(&self, state: &mut H) {
138 self.keys.hash(state);
141 }
142}
143
144impl ModifierNodeElement for PointerInputElement {
145 type Node = SuspendingPointerInputNode;
146
147 fn create(&self) -> Self::Node {
148 SuspendingPointerInputNode::new(self.keys.clone(), self.handler.clone())
149 }
150
151 fn update(&self, node: &mut Self::Node) {
152 node.update(self.keys.clone(), self.handler.clone());
153 }
154
155 fn capabilities(&self) -> NodeCapabilities {
156 NodeCapabilities::POINTER_INPUT
157 }
158}
159
160#[derive(Clone)]
161pub struct PointerInputScope {
162 state: Rc<PointerInputScopeState>,
163}
164
165impl PointerInputScope {
166 fn new(state: Rc<PointerInputScopeState>) -> Self {
167 Self { state }
168 }
169
170 pub fn size(&self) -> Size {
179 self.state.size.get()
180 }
181
182 pub async fn await_pointer_event_scope<R, F, Fut>(&self, block: F) -> R
183 where
184 F: FnOnce(AwaitPointerEventScope) -> Fut,
185 Fut: Future<Output = R>,
186 {
187 let scope = AwaitPointerEventScope {
188 state: self.state.clone(),
189 };
190 block(scope).await
191 }
192}
193
194#[derive(Clone)]
195pub struct AwaitPointerEventScope {
196 state: Rc<PointerInputScopeState>,
197}
198
199impl AwaitPointerEventScope {
200 pub fn size(&self) -> Size {
203 self.state.size.get()
204 }
205
206 pub async fn await_pointer_event(&self) -> PointerEvent {
207 NextPointerEvent {
208 state: self.state.clone(),
209 }
210 .await
211 }
212
213 pub async fn with_timeout_or_null<R, F, Fut>(&self, _time_millis: u64, block: F) -> Option<R>
214 where
215 F: FnOnce(&AwaitPointerEventScope) -> Fut,
216 Fut: Future<Output = R>,
217 {
218 Some(block(self).await)
219 }
220
221 pub async fn with_timeout<R, F, Fut>(&self, _time_millis: u64, block: F) -> R
222 where
223 F: FnOnce(&AwaitPointerEventScope) -> Fut,
224 Fut: Future<Output = R>,
225 {
226 block(self).await
227 }
228}
229
230struct NextPointerEvent {
231 state: Rc<PointerInputScopeState>,
232}
233
234impl Future for NextPointerEvent {
235 type Output = PointerEvent;
236
237 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
238 self.state.poll_event(cx)
239 }
240}
241
242struct PointerInputScopeState {
243 events: RefCell<VecDeque<PointerEvent>>,
244 waiting: RefCell<Option<Waker>>,
245 size: Rc<Cell<Size>>,
250}
251
252impl PointerInputScopeState {
253 fn new(size: Rc<Cell<Size>>) -> Self {
254 Self {
255 events: RefCell::new(VecDeque::new()),
256 waiting: RefCell::new(None),
257 size,
258 }
259 }
260
261 fn push_event(&self, event: PointerEvent) {
262 self.events.borrow_mut().push_back(event);
263 let waker = {
264 let mut waiting = self.waiting.borrow_mut();
265 waiting.take()
266 };
267 if let Some(waker) = waker {
268 waker.wake();
269 }
270 }
271
272 fn poll_event(&self, cx: &mut Context<'_>) -> Poll<PointerEvent> {
273 if let Some(event) = self.events.borrow_mut().pop_front() {
274 Poll::Ready(event)
275 } else {
276 self.waiting.replace(Some(cx.waker().clone()));
277 Poll::Pending
278 }
279 }
280}
281
282struct PointerEventDispatcher {
283 state: Rc<RefCell<Option<Rc<PointerInputScopeState>>>>,
284 handler: Rc<dyn Fn(PointerEvent)>,
285}
286
287impl PointerEventDispatcher {
288 fn new() -> Self {
289 let state = Rc::new(RefCell::new(None::<Rc<PointerInputScopeState>>));
290 let state_for_handler = state.clone();
291 let handler = Rc::new(move |event: PointerEvent| {
292 if let Some(inner) = state_for_handler.borrow().as_ref() {
293 inner.push_event(event);
294 }
295 });
296 Self { state, handler }
297 }
298
299 fn handler(&self) -> Rc<dyn Fn(PointerEvent)> {
300 self.handler.clone()
301 }
302
303 fn set_state(&self, state: Option<Rc<PointerInputScopeState>>) {
304 *self.state.borrow_mut() = state;
305 }
306}
307
308struct PointerInputTask {
309 id: u64,
310 owner: PointerInputTaskOwner,
311 inner: Rc<PointerInputTaskInner>,
312}
313
314impl PointerInputTask {
315 fn new(future: PointerInputFuture) -> Self {
316 let inner = Rc::new(PointerInputTaskInner::new(future));
317 let id = Rc::as_ptr(&inner) as usize as u64;
318 let owner = crate::render_state::register_pointer_input_task(id, inner.clone());
319 Self { id, owner, inner }
320 }
321
322 fn poll(&self) {
323 self.inner.poll(self.owner, self.id);
324 }
325
326 fn cancel(self) {
327 self.inner.cancel();
328 crate::render_state::remove_pointer_input_task(self.owner, self.id);
329 }
330}
331
332impl Drop for PointerInputTask {
333 fn drop(&mut self) {
334 self.inner.cancel();
335 crate::render_state::remove_pointer_input_task(self.owner, self.id);
336 }
337}
338
339pub(crate) struct PointerInputTaskInner {
340 future: RefCell<Option<PointerInputFuture>>,
341 is_polling: Cell<bool>,
342 needs_poll: Cell<bool>,
343}
344
345impl PointerInputTaskInner {
346 fn new(future: PointerInputFuture) -> Self {
347 Self {
348 future: RefCell::new(Some(future)),
349 is_polling: Cell::new(false),
350 needs_poll: Cell::new(false),
351 }
352 }
353
354 fn cancel(&self) {
355 self.future.borrow_mut().take();
356 }
357
358 fn request_poll(&self, owner: PointerInputTaskOwner, task_id: u64) {
359 if self.is_polling.get() {
360 self.needs_poll.set(true);
361 } else {
362 self.poll(owner, task_id);
363 }
364 }
365
366 fn poll(&self, owner: PointerInputTaskOwner, task_id: u64) {
367 if self.is_polling.replace(true) {
368 self.needs_poll.set(true);
369 return;
370 }
371 loop {
372 self.needs_poll.set(false);
373 let waker = waker(Arc::new(PointerInputTaskWaker { task_id, owner }));
374 let mut cx = Context::from_waker(&waker);
375 let mut future_slot = self.future.borrow_mut();
376 if let Some(future) = future_slot.as_mut() {
377 let poll_result = future.as_mut().poll(&mut cx);
378 if poll_result.is_ready() {
379 future_slot.take();
380 }
381 }
382 if !self.needs_poll.get() {
383 break;
384 }
385 }
386 self.is_polling.set(false);
387 }
388}
389
390struct PointerInputTaskWaker {
391 task_id: u64,
392 owner: PointerInputTaskOwner,
393}
394
395impl ArcWake for PointerInputTaskWaker {
396 fn wake_by_ref(arc_self: &Arc<Self>) {
397 crate::render_state::request_pointer_input_task_poll(arc_self.owner, arc_self.task_id);
398 }
399}
400
401pub struct SuspendingPointerInputNode {
402 keys: Vec<KeyToken>,
403 handler: PointerInputHandler,
404 dispatcher: PointerEventDispatcher,
405 task: Option<PointerInputTask>,
406 layout_size: Rc<Cell<Size>>,
411 state: NodeState,
412}
413
414impl SuspendingPointerInputNode {
415 fn new(keys: Vec<KeyToken>, handler: PointerInputHandler) -> Self {
416 Self {
417 keys,
418 handler,
419 dispatcher: PointerEventDispatcher::new(),
420 task: None,
421 layout_size: Rc::new(Cell::new(Size {
422 width: 0.0,
423 height: 0.0,
424 })),
425 state: NodeState::new(),
426 }
427 }
428
429 fn update(&mut self, keys: Vec<KeyToken>, handler: PointerInputHandler) {
430 let should_restart = self.keys != keys;
435 self.keys = keys;
436 self.handler = handler; if should_restart {
438 self.restart();
439 }
440 }
441
442 fn restart(&mut self) {
443 self.cancel();
444 self.start();
445 }
446
447 fn start(&mut self) {
448 let state = Rc::new(PointerInputScopeState::new(self.layout_size.clone()));
449 self.dispatcher.set_state(Some(state.clone()));
450 let scope = PointerInputScope::new(state);
451 let future = (self.handler)(scope);
452 let task = PointerInputTask::new(future);
453 task.poll();
454 self.task = Some(task);
455 }
456
457 fn cancel(&mut self) {
458 if let Some(task) = self.task.take() {
459 task.cancel();
460 }
461 self.dispatcher.set_state(None);
462 }
463}
464
465impl Drop for SuspendingPointerInputNode {
466 fn drop(&mut self) {
467 self.cancel();
468 }
469}
470
471impl ModifierNode for SuspendingPointerInputNode {
472 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {
473 self.start();
474 }
475
476 fn on_detach(&mut self) {
477 self.cancel();
478 }
479
480 fn on_reset(&mut self) {
481 }
485
486 impl_pointer_input_node!();
488}
489
490impl DelegatableNode for SuspendingPointerInputNode {
491 fn node_state(&self) -> &NodeState {
492 &self.state
493 }
494}
495
496impl PointerInputNode for SuspendingPointerInputNode {
497 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
498 Some(self.dispatcher.handler())
499 }
500
501 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
502 Some(self.layout_size.clone())
503 }
504}
505
506#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
507struct KeyToken {
508 type_id: TypeId,
509 hash: u64,
510}
511
512impl KeyToken {
513 fn new<T: Hash + 'static>(value: &T) -> Self {
514 let mut hasher = default::new();
515 value.hash(&mut hasher);
516 Self {
517 type_id: TypeId::of::<T>(),
518 hash: hasher.finish(),
519 }
520 }
521}