localghost/keyboard/
keyboard.rs1use 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#[derive(Debug)]
17pub struct Keyboard {
18 _priv: (),
19}
20
21impl Keyboard {
22 pub fn new() -> Self {
24 Self { _priv: () }
25 }
26
27 pub fn key_down(&self) -> KeyDownStream {
30 KeyDownStream {
31 listener: utils::document().on("keydown"),
32 }
33 }
34
35 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#[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#[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}