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
214struct NextPointerEvent {
215 state: Rc<PointerInputScopeState>,
216}
217
218impl Future for NextPointerEvent {
219 type Output = PointerEvent;
220
221 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
222 self.state.poll_event(cx)
223 }
224}
225
226struct PointerInputScopeState {
227 events: RefCell<VecDeque<PointerEvent>>,
228 waiting: RefCell<Option<Waker>>,
229 size: Rc<Cell<Size>>,
234}
235
236impl PointerInputScopeState {
237 fn new(size: Rc<Cell<Size>>) -> Self {
238 Self {
239 events: RefCell::new(VecDeque::new()),
240 waiting: RefCell::new(None),
241 size,
242 }
243 }
244
245 fn push_event(&self, event: PointerEvent) {
246 self.events.borrow_mut().push_back(event);
247 let waker = {
248 let mut waiting = self.waiting.borrow_mut();
249 waiting.take()
250 };
251 if let Some(waker) = waker {
252 waker.wake();
253 }
254 }
255
256 fn poll_event(&self, cx: &mut Context<'_>) -> Poll<PointerEvent> {
257 if let Some(event) = self.events.borrow_mut().pop_front() {
258 Poll::Ready(event)
259 } else {
260 self.waiting.replace(Some(cx.waker().clone()));
261 Poll::Pending
262 }
263 }
264}
265
266struct PointerEventDispatcher {
267 state: Rc<RefCell<Option<Rc<PointerInputScopeState>>>>,
268 handler: Rc<dyn Fn(PointerEvent)>,
269}
270
271impl PointerEventDispatcher {
272 fn new() -> Self {
273 let state = Rc::new(RefCell::new(None::<Rc<PointerInputScopeState>>));
274 let state_for_handler = state.clone();
275 let handler = Rc::new(move |event: PointerEvent| {
276 if let Some(inner) = state_for_handler.borrow().as_ref() {
277 inner.push_event(event);
278 }
279 });
280 Self { state, handler }
281 }
282
283 fn handler(&self) -> Rc<dyn Fn(PointerEvent)> {
284 self.handler.clone()
285 }
286
287 fn set_state(&self, state: Option<Rc<PointerInputScopeState>>) {
288 *self.state.borrow_mut() = state;
289 }
290}
291
292struct PointerInputTask {
293 id: u64,
294 owner: PointerInputTaskOwner,
295 inner: Rc<PointerInputTaskInner>,
296}
297
298impl PointerInputTask {
299 fn new(future: PointerInputFuture) -> Self {
300 let inner = Rc::new(PointerInputTaskInner::new(future));
301 let id = Rc::as_ptr(&inner) as usize as u64;
302 let owner = crate::render_state::register_pointer_input_task(id, inner.clone());
303 Self { id, owner, inner }
304 }
305
306 fn poll(&self) {
307 self.inner.poll(self.owner, self.id);
308 }
309
310 fn cancel(self) {
311 self.inner.cancel();
312 crate::render_state::remove_pointer_input_task(self.owner, self.id);
313 }
314}
315
316impl Drop for PointerInputTask {
317 fn drop(&mut self) {
318 self.inner.cancel();
319 crate::render_state::remove_pointer_input_task(self.owner, self.id);
320 }
321}
322
323pub(crate) struct PointerInputTaskInner {
324 future: RefCell<Option<PointerInputFuture>>,
325 is_polling: Cell<bool>,
326 needs_poll: Cell<bool>,
327}
328
329impl PointerInputTaskInner {
330 fn new(future: PointerInputFuture) -> Self {
331 Self {
332 future: RefCell::new(Some(future)),
333 is_polling: Cell::new(false),
334 needs_poll: Cell::new(false),
335 }
336 }
337
338 fn cancel(&self) {
339 self.future.borrow_mut().take();
340 }
341
342 fn request_poll(&self, owner: PointerInputTaskOwner, task_id: u64) {
343 if self.is_polling.get() {
344 self.needs_poll.set(true);
345 } else {
346 self.poll(owner, task_id);
347 }
348 }
349
350 fn poll(&self, owner: PointerInputTaskOwner, task_id: u64) {
351 if self.is_polling.replace(true) {
352 self.needs_poll.set(true);
353 return;
354 }
355 loop {
356 self.needs_poll.set(false);
357 let waker = waker(Arc::new(PointerInputTaskWaker { task_id, owner }));
358 let mut cx = Context::from_waker(&waker);
359 let mut future_slot = self.future.borrow_mut();
360 if let Some(future) = future_slot.as_mut() {
361 let poll_result = future.as_mut().poll(&mut cx);
362 if poll_result.is_ready() {
363 future_slot.take();
364 }
365 }
366 if !self.needs_poll.get() {
367 break;
368 }
369 }
370 self.is_polling.set(false);
371 }
372}
373
374struct PointerInputTaskWaker {
375 task_id: u64,
376 owner: PointerInputTaskOwner,
377}
378
379impl ArcWake for PointerInputTaskWaker {
380 fn wake_by_ref(arc_self: &Arc<Self>) {
381 crate::render_state::request_pointer_input_task_poll(arc_self.owner, arc_self.task_id);
382 }
383}
384
385pub struct SuspendingPointerInputNode {
386 keys: Vec<KeyToken>,
387 handler: PointerInputHandler,
388 dispatcher: PointerEventDispatcher,
389 task: Option<PointerInputTask>,
390 layout_size: Rc<Cell<Size>>,
395 state: NodeState,
396}
397
398impl SuspendingPointerInputNode {
399 fn new(keys: Vec<KeyToken>, handler: PointerInputHandler) -> Self {
400 Self {
401 keys,
402 handler,
403 dispatcher: PointerEventDispatcher::new(),
404 task: None,
405 layout_size: Rc::new(Cell::new(Size {
406 width: 0.0,
407 height: 0.0,
408 })),
409 state: NodeState::new(),
410 }
411 }
412
413 fn update(&mut self, keys: Vec<KeyToken>, handler: PointerInputHandler) {
414 let should_restart = self.keys != keys;
419 self.keys = keys;
420 self.handler = handler; if should_restart {
422 self.restart();
423 }
424 }
425
426 fn restart(&mut self) {
427 self.cancel();
428 self.start();
429 }
430
431 fn start(&mut self) {
432 let state = Rc::new(PointerInputScopeState::new(self.layout_size.clone()));
433 self.dispatcher.set_state(Some(state.clone()));
434 let scope = PointerInputScope::new(state);
435 let future = (self.handler)(scope);
436 let task = PointerInputTask::new(future);
437 task.poll();
438 self.task = Some(task);
439 }
440
441 fn cancel(&mut self) {
442 if let Some(task) = self.task.take() {
443 task.cancel();
444 }
445 self.dispatcher.set_state(None);
446 }
447}
448
449impl Drop for SuspendingPointerInputNode {
450 fn drop(&mut self) {
451 self.cancel();
452 }
453}
454
455impl ModifierNode for SuspendingPointerInputNode {
456 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {
457 self.start();
458 }
459
460 fn on_detach(&mut self) {
461 self.cancel();
462 }
463
464 fn on_reset(&mut self) {
465 }
469
470 impl_pointer_input_node!();
472}
473
474impl DelegatableNode for SuspendingPointerInputNode {
475 fn node_state(&self) -> &NodeState {
476 &self.state
477 }
478}
479
480impl PointerInputNode for SuspendingPointerInputNode {
481 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
482 Some(self.dispatcher.handler())
483 }
484
485 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
486 Some(self.layout_size.clone())
487 }
488}
489
490#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
491struct KeyToken {
492 type_id: TypeId,
493 hash: u64,
494}
495
496impl KeyToken {
497 fn new<T: Hash + 'static>(value: &T) -> Self {
498 let mut hasher = default::new();
499 value.hash(&mut hasher);
500 Self {
501 type_id: TypeId::of::<T>(),
502 hash: hasher.finish(),
503 }
504 }
505}