localghost/keyboard/
keyboard.rs

1use std::pin::Pin;
2use std::task::{Context, Poll};
3
4use futures_core::{ready, Stream};
5use pin_project::pin_project;
6use wasm_bindgen::JsCast;
7
8use crate::events::EventStream;
9use crate::keyboard::KeyboardEvent;
10use crate::prelude::*;
11use crate::utils;
12
13/// Browser keyboard API.
14///
15/// [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)
16#[derive(Debug)]
17pub struct Keyboard {
18    _priv: (),
19}
20
21impl Keyboard {
22    /// Create a new instance of `Keyboard`.
23    pub fn new() -> Self {
24        Self { _priv: () }
25    }
26
27    /// Create a stream for [`keydown`
28    /// events](https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event).
29    pub fn key_down(&self) -> KeyDownStream {
30        KeyDownStream {
31            listener: utils::document().on("keydown"),
32        }
33    }
34
35    /// Create a stream for [`keyup`
36    /// events](https://developer.mozilla.org/en-US/docs/Web/API/Element/keyup_event).
37    pub fn key_up(&self) -> KeyDownStream {
38        KeyDownStream {
39            listener: utils::document().on("keyup"),
40        }
41    }
42}
43
44impl Default for Keyboard {
45    fn default() -> Self {
46        Self::new()
47    }
48}
49
50/// A stream capturing `keydown` events.
51///
52/// This `struct` is created by the [`key_down`] method on [`Keyboard`]. See its
53/// documentation for more.
54///
55/// [`key_down`]: struct.Keyboard.html#method.key_down
56/// [`Keyboard`]: struct.Keyboard.html
57#[pin_project]
58#[derive(Debug)]
59pub struct KeyDownStream {
60    #[pin]
61    listener: EventStream,
62}
63
64impl Stream for KeyDownStream {
65    type Item = KeyboardEvent;
66
67    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
68        let this = self.project();
69        let ev = ready!(this.listener.poll_next(cx));
70        let ev = ev.map(|ev| {
71            let inner = ev
72                .into_raw()
73                .dyn_into::<web_sys::KeyboardEvent>()
74                .unwrap_throw();
75            KeyboardEvent { inner }
76        });
77        Poll::Ready(ev)
78    }
79}
80
81/// A stream capturing `keyup` events.
82///
83/// This `struct` is created by the [`key_up`] method on [`Keyboard`]. See its
84/// documentation for more.
85///
86/// [`key_up`]: struct.Keyboard.html#method.key_up
87/// [`Keyboard`]: struct.Keyboard.html
88#[pin_project]
89#[derive(Debug)]
90pub struct KeyUpStream {
91    #[pin]
92    listener: EventStream,
93}
94
95impl Stream for KeyUpStream {
96    type Item = KeyboardEvent;
97
98    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
99        let this = self.project();
100        let ev = ready!(this.listener.poll_next(cx));
101        let ev = ev.map(|ev| {
102            let inner = ev
103                .into_raw()
104                .dyn_into::<web_sys::KeyboardEvent>()
105                .unwrap_throw();
106            KeyboardEvent { inner }
107        });
108        Poll::Ready(ev)
109    }
110}