cranpose_ui/
unhandled_keys.rs1use std::{cell::RefCell, rc::Rc};
2
3use cranpose_core::{DisposableEffect, remember};
4use cranpose_macros::composable;
5
6use crate::KeyEvent;
7
8pub(crate) type KeyHandler = Rc<RefCell<Rc<dyn Fn(&KeyEvent) -> bool>>>;
9
10#[composable]
31pub fn UnhandledKeyEvents(handler: impl Fn(&KeyEvent) -> bool + 'static) {
32 let latest: KeyHandler = remember(|| {
33 let placeholder: Rc<dyn Fn(&KeyEvent) -> bool> = Rc::new(|_: &KeyEvent| false);
34 Rc::new(RefCell::new(placeholder))
35 })
36 .with(Rc::clone);
37 *latest.borrow_mut() = Rc::new(handler);
38 DisposableEffect((), move |scope| {
39 let id = crate::thread_state::cells(|cells| {
40 let id = cells.last_unhandled_key_handler_id.get() + 1;
41 cells.last_unhandled_key_handler_id.set(id);
42 id
43 });
44 crate::thread_state::with(|state| {
45 state.unhandled_key_handlers.borrow_mut().push((id, latest));
46 });
47 scope.on_dispose(move || {
48 crate::thread_state::try_with(|state| {
49 state
50 .unhandled_key_handlers
51 .borrow_mut()
52 .retain(|(held, _)| *held != id);
53 });
54 })
55 });
56}
57
58pub fn dispatch_unhandled_key_event(event: &KeyEvent) -> bool {
62 let handlers: Vec<KeyHandler> = crate::thread_state::with(|state| {
63 state
64 .unhandled_key_handlers
65 .borrow()
66 .iter()
67 .rev()
68 .map(|(_, handler)| Rc::clone(handler))
69 .collect()
70 });
71 handlers.into_iter().any(|handler| {
72 let current = Rc::clone(&handler.borrow());
73 current(event)
74 })
75}