hassium_input_device_web/
keyboard.rs

1use input::{device::InputDevice, Scalar};
2use std::{any::Any, cell::RefCell, collections::HashSet, rc::Rc};
3use wasm_bindgen::{prelude::*, JsCast};
4use web_sys::*;
5
6/// (key character, code)
7pub type KeyCode = (char, String);
8
9pub struct WebKeyboardInputDevice {
10    element: EventTarget,
11    keys: Rc<RefCell<HashSet<String>>>,
12    sequence: Rc<RefCell<Vec<KeyCode>>>,
13    last_sequence: Vec<KeyCode>,
14}
15
16unsafe impl Send for WebKeyboardInputDevice {}
17unsafe impl Sync for WebKeyboardInputDevice {}
18
19impl WebKeyboardInputDevice {
20    pub fn new(element: EventTarget) -> Self {
21        Self {
22            element,
23            keys: Default::default(),
24            sequence: Rc::new(RefCell::new(Vec::with_capacity(128))),
25            last_sequence: Vec::with_capacity(128),
26        }
27    }
28
29    pub fn last_sequence(&self) -> &[KeyCode] {
30        &self.last_sequence
31    }
32}
33
34impl InputDevice for WebKeyboardInputDevice {
35    fn name(&self) -> &str {
36        "keyboard"
37    }
38
39    fn on_register(&mut self) {
40        {
41            let keys = self.keys.clone();
42            let sequence = self.sequence.clone();
43            let closure = Closure::wrap(Box::new(move |event: KeyboardEvent| {
44                let code = event.code();
45                let key = event.key();
46                keys.borrow_mut().insert(code.clone());
47                if key.len() > 1 {
48                    sequence.borrow_mut().push((0 as char, code));
49                } else if key.len() == 1 {
50                    sequence
51                        .borrow_mut()
52                        .push((key.chars().next().unwrap(), code));
53                }
54            }) as Box<dyn FnMut(_)>);
55            self.element
56                .add_event_listener_with_callback("keydown", closure.as_ref().unchecked_ref())
57                .unwrap();
58            closure.forget();
59        }
60        {
61            let keys = self.keys.clone();
62            let closure = Closure::wrap(Box::new(move |event: KeyboardEvent| {
63                keys.borrow_mut().remove(&event.code());
64            }) as Box<dyn FnMut(_)>);
65            self.element
66                .add_event_listener_with_callback("keyup", closure.as_ref().unchecked_ref())
67                .unwrap();
68            closure.forget();
69        }
70    }
71
72    fn on_unregister(&mut self) {
73        // TODO: cache callbacks, remove events and kill callbacks here.
74    }
75
76    fn process(&mut self) {
77        self.last_sequence.clear();
78        self.last_sequence.append(&mut self.sequence.borrow_mut());
79    }
80
81    fn query_axis(&self, name: &str) -> Option<Scalar> {
82        Some(if self.keys.borrow().contains(name) {
83            1.0
84        } else {
85            0.0
86        })
87    }
88
89    fn query_trigger(&self, name: &str) -> Option<bool> {
90        Some(self.keys.borrow().contains(name))
91    }
92
93    fn as_any(&self) -> &dyn Any {
94        self
95    }
96}