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