hassium_input_device_web/
mouse.rs

1use input::{device::InputDevice, Scalar};
2use std::{any::Any, cell::Cell, rc::Rc};
3use wasm_bindgen::{prelude::*, JsCast};
4use web_sys::*;
5
6pub struct WebMouseInputDevice {
7    element: EventTarget,
8    position: Rc<Cell<(Scalar, Scalar)>>,
9    left_button: Rc<Cell<bool>>,
10    right_button: Rc<Cell<bool>>,
11    middle_button: Rc<Cell<bool>>,
12}
13
14unsafe impl Send for WebMouseInputDevice {}
15unsafe impl Sync for WebMouseInputDevice {}
16
17impl WebMouseInputDevice {
18    pub fn new(element: EventTarget) -> Self {
19        Self {
20            element,
21            position: Default::default(),
22            left_button: Default::default(),
23            right_button: Default::default(),
24            middle_button: Default::default(),
25        }
26    }
27}
28
29impl InputDevice for WebMouseInputDevice {
30    fn name(&self) -> &str {
31        "mouse"
32    }
33
34    fn on_register(&mut self) {
35        {
36            let left_button = self.left_button.clone();
37            let right_button = self.right_button.clone();
38            let middle_button = self.middle_button.clone();
39            let closure = Closure::wrap(Box::new(move |event: MouseEvent| match event.button() {
40                0 => left_button.set(true),
41                2 => right_button.set(true),
42                1 => middle_button.set(true),
43                _ => {}
44            }) as Box<dyn FnMut(_)>);
45            self.element
46                .add_event_listener_with_callback("mousedown", closure.as_ref().unchecked_ref())
47                .unwrap();
48            closure.forget();
49        }
50        {
51            let left_button = self.left_button.clone();
52            let right_button = self.right_button.clone();
53            let middle_button = self.middle_button.clone();
54            let closure = Closure::wrap(Box::new(move |event: MouseEvent| match event.button() {
55                0 => left_button.set(false),
56                2 => right_button.set(false),
57                1 => middle_button.set(false),
58                _ => {}
59            }) as Box<dyn FnMut(_)>);
60            self.element
61                .add_event_listener_with_callback("mouseup", closure.as_ref().unchecked_ref())
62                .unwrap();
63            closure.forget();
64        }
65        {
66            let position = self.position.clone();
67            let closure = Closure::wrap(Box::new(move |event: MouseEvent| {
68                position.set((event.client_x() as Scalar, event.client_y() as Scalar));
69            }) as Box<dyn FnMut(_)>);
70            self.element
71                .add_event_listener_with_callback("mousemove", closure.as_ref().unchecked_ref())
72                .unwrap();
73            closure.forget();
74        }
75    }
76
77    fn on_unregister(&mut self) {
78        // TODO: cache callbacks, remove events and kill callbacks here.
79    }
80
81    fn process(&mut self) {}
82
83    fn query_axis(&self, name: &str) -> Option<Scalar> {
84        match name {
85            "x" => Some(self.position.get().0),
86            "y" => Some(self.position.get().1),
87            _ => None,
88        }
89    }
90
91    fn query_trigger(&self, name: &str) -> Option<bool> {
92        match name {
93            "left" => Some(self.left_button.get()),
94            "right" => Some(self.right_button.get()),
95            "middle" => Some(self.middle_button.get()),
96            _ => None,
97        }
98    }
99
100    fn as_any(&self) -> &dyn Any {
101        self
102    }
103}