1use ui_events::keyboard::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers};
31
32extern crate alloc;
33use alloc::vec::Vec;
34
35#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
36struct KeyInfo(Key, Location, Code);
37
38#[derive(Clone, Debug, Default)]
40pub struct KeyboardState {
41 just_pressed: Vec<KeyInfo>,
43 just_released: Vec<KeyInfo>,
45 down: Vec<KeyInfo>,
47 pub modifiers: Modifiers,
49}
50
51impl KeyboardState {
52 pub fn key_just_pressed(&self, key: Key) -> bool {
55 self.just_pressed.iter().any(|KeyInfo(k, ..)| k == &key)
56 }
57
58 pub fn key_str_just_pressed(&self, s: &str) -> bool {
67 self.just_pressed
68 .iter()
69 .any(|KeyInfo(k, ..)| matches!(k, Key::Character(c) if c == s))
70 }
71
72 pub fn key_just_pressed_location(&self, key: Key, location: Location) -> bool {
74 self.just_pressed
75 .iter()
76 .any(|KeyInfo(k, l, _)| k == &key && l == &location)
77 }
78
79 pub fn key_str_just_pressed_location(&self, s: &str, location: Location) -> bool {
88 self.just_pressed
89 .iter()
90 .any(|KeyInfo(k, l, ..)| l == &location && matches!(k, Key::Character(c) if c == s))
91 }
92
93 pub fn code_just_pressed(&self, code: Code) -> bool {
95 self.just_pressed.iter().any(|KeyInfo(_, _, c)| c == &code)
96 }
97
98 pub fn key_just_released(&self, key: Key) -> bool {
101 self.just_released.iter().any(|KeyInfo(k, ..)| k == &key)
102 }
103
104 pub fn key_str_just_released(&self, s: &str) -> bool {
113 self.just_released
114 .iter()
115 .any(|KeyInfo(k, ..)| matches!(k, Key::Character(c) if c == s))
116 }
117
118 pub fn key_just_released_location(&self, key: Key, location: Location) -> bool {
120 self.just_released
121 .iter()
122 .any(|KeyInfo(k, l, _)| k == &key && l == &location)
123 }
124
125 pub fn key_str_just_released_location(&self, s: &str, location: Location) -> bool {
134 self.just_released
135 .iter()
136 .any(|KeyInfo(k, l, ..)| l == &location && matches!(k, Key::Character(c) if c == s))
137 }
138
139 pub fn code_just_released(&self, code: Code) -> bool {
141 self.just_released.iter().any(|KeyInfo(_, _, c)| c == &code)
142 }
143
144 pub fn is_any_down(&self) -> bool {
146 !self.down.is_empty()
147 }
148
149 pub fn key_down(&self, key: Key) -> bool {
157 self.down.iter().any(|KeyInfo(k, ..)| k == &key)
158 }
159
160 pub fn key_str_down(&self, s: &str) -> bool {
168 self.down
169 .iter()
170 .any(|KeyInfo(k, ..)| matches!(k, Key::Character(c) if c == s))
171 }
172
173 pub fn key_down_location(&self, key: Key, location: Location) -> bool {
181 self.down
182 .iter()
183 .any(|KeyInfo(k, l, _)| k == &key && l == &location)
184 }
185
186 pub fn key_str_down_location(&self, s: &str, location: Location) -> bool {
194 self.down
195 .iter()
196 .any(|KeyInfo(k, l, ..)| l == &location && matches!(k, Key::Character(c) if c == s))
197 }
198
199 pub fn code_down(&self, code: Code) -> bool {
201 self.down.iter().any(|KeyInfo(_, _, c)| c == &code)
202 }
203
204 pub fn clear_frame(&mut self) {
206 self.just_pressed.clear();
207 self.just_released.clear();
208 }
209
210 pub fn process_keyboard_event(&mut self, event: KeyboardEvent) {
215 self.modifiers = event.modifiers;
216 let info = KeyInfo(event.key, event.location, event.code);
217 match event.state {
218 KeyState::Down => {
219 self.just_pressed.push(info.clone());
220 self.down.push(info.clone());
221 }
222 KeyState::Up => {
223 self.just_released.push(info.clone());
224 self.down.retain(|other| other != &info);
225 }
226 }
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use super::*;
233 use ui_events::keyboard::{Code, NamedKey};
234
235 fn make_key_down_event(key: Key) -> KeyboardEvent {
236 KeyboardEvent {
237 state: KeyState::Down,
238 key,
239 location: Location::Standard,
240 code: Code::Unidentified,
241 modifiers: Default::default(),
242 is_composing: false,
243 repeat: false,
244 }
245 }
246
247 fn make_key_up_event(key: Key) -> KeyboardEvent {
248 KeyboardEvent {
249 state: KeyState::Up,
250 key,
251 location: Location::Standard,
252 code: Code::Unidentified,
253 modifiers: Default::default(),
254 is_composing: false,
255 repeat: false,
256 }
257 }
258
259 #[test]
260 fn press_and_hold_a() {
261 let mut state = KeyboardState::default();
262 state.process_keyboard_event(make_key_down_event(Key::Character("A".into())));
263
264 assert!(state.key_just_pressed(Key::Character("A".into())));
265 assert!(state.key_str_just_pressed("A"));
266 assert!(state.key_str_just_pressed_location("A", Location::Standard));
267 assert!(!state.key_str_just_pressed_location("A", Location::Left));
268 assert!(state.key_down(Key::Character("A".into())));
269 assert!(state.key_str_down("A"));
270 assert!(state.key_str_down_location("A", Location::Standard));
271 assert!(!state.key_str_down_location("A", Location::Left));
272 assert!(!state.key_just_released(Key::Character("A".into())));
273 assert!(!state.key_str_just_released("A"));
274 assert!(!state.key_str_just_released_location("A", Location::Standard));
275 assert!(!state.key_str_just_released_location("A", Location::Left));
276
277 state.clear_frame();
278
279 assert!(!state.key_just_pressed(Key::Character("A".into())));
280 assert!(!state.key_str_just_pressed("A"));
281 assert!(!state.key_str_just_pressed_location("A", Location::Standard));
282 assert!(!state.key_str_just_pressed_location("A", Location::Left));
283 assert!(state.key_down(Key::Character("A".into())));
284 assert!(state.key_str_down("A"));
285 assert!(state.key_str_down_location("A", Location::Standard));
286 assert!(!state.key_str_down_location("A", Location::Left));
287 }
288
289 #[test]
290 fn press_and_release_a() {
291 let mut state = KeyboardState::default();
292 state.process_keyboard_event(make_key_down_event(Key::Character("A".into())));
293 state.process_keyboard_event(make_key_up_event(Key::Character("A".into())));
294
295 assert!(state.key_just_pressed(Key::Character("A".into())));
296 assert!(state.key_str_just_pressed("A"));
297 assert!(state.key_str_just_pressed_location("A", Location::Standard));
298 assert!(!state.key_str_just_pressed_location("A", Location::Left));
299 assert!(state.key_just_released(Key::Character("A".into())));
300 assert!(state.key_str_just_released("A"));
301 assert!(state.key_str_just_released_location("A", Location::Standard));
302 assert!(!state.key_str_just_released_location("A", Location::Left));
303 assert!(!state.key_down(Key::Character("A".into())));
304 assert!(!state.key_str_down("A"));
305 assert!(!state.key_str_down_location("A", Location::Standard));
306 assert!(!state.key_str_down_location("A", Location::Left));
307 }
308
309 #[test]
310 fn release_after_hold() {
311 let mut state = KeyboardState::default();
312 state.process_keyboard_event(make_key_down_event(Key::Character("A".into())));
313 state.clear_frame();
314 state.process_keyboard_event(make_key_up_event(Key::Character("A".into())));
315
316 assert!(!state.key_just_pressed(Key::Character("A".into())));
317 assert!(!state.key_str_just_pressed("A"));
318 assert!(!state.key_str_just_pressed_location("A", Location::Standard));
319 assert!(!state.key_str_just_pressed_location("A", Location::Left));
320 assert!(state.key_just_released(Key::Character("A".into())));
321 assert!(state.key_str_just_released("A"));
322 assert!(state.key_str_just_released_location("A", Location::Standard));
323 assert!(!state.key_str_just_released_location("A", Location::Left));
324 assert!(!state.key_down(Key::Character("A".into())));
325 assert!(!state.key_str_down("A"));
326 assert!(!state.key_str_down_location("A", Location::Standard));
327 assert!(!state.key_str_down_location("A", Location::Left));
328 }
329
330 fn make_code_down_event(code: Code) -> KeyboardEvent {
331 KeyboardEvent {
332 state: KeyState::Down,
333 key: Key::Named(NamedKey::Unidentified),
334 location: Location::Standard,
335 code,
336 modifiers: Default::default(),
337 is_composing: false,
338 repeat: false,
339 }
340 }
341
342 fn make_code_up_event(code: Code) -> KeyboardEvent {
343 KeyboardEvent {
344 state: KeyState::Up,
345 key: Key::Named(NamedKey::Unidentified),
346 location: Location::Standard,
347 code,
348 modifiers: Default::default(),
349 is_composing: false,
350 repeat: false,
351 }
352 }
353
354 #[test]
355 fn press_and_hold_a_code() {
356 let mut state = KeyboardState::default();
357 state.process_keyboard_event(make_code_down_event(Code::KeyA));
358
359 assert!(state.code_just_pressed(Code::KeyA));
360 assert!(state.code_down(Code::KeyA));
361 assert!(!state.code_just_released(Code::KeyA));
362
363 state.clear_frame();
364
365 assert!(!state.code_just_pressed(Code::KeyA));
366 assert!(state.code_down(Code::KeyA));
367 }
368
369 #[test]
370 fn press_and_release_a_code() {
371 let mut state = KeyboardState::default();
372 state.process_keyboard_event(make_code_down_event(Code::KeyA));
373 state.process_keyboard_event(make_code_up_event(Code::KeyA));
374
375 assert!(state.code_just_pressed(Code::KeyA));
376 assert!(state.code_just_released(Code::KeyA));
377 assert!(!state.code_down(Code::KeyA));
378 }
379
380 #[test]
381 fn release_after_hold_code() {
382 let mut state = KeyboardState::default();
383 state.process_keyboard_event(make_code_down_event(Code::KeyA));
384 state.clear_frame();
385 state.process_keyboard_event(make_code_up_event(Code::KeyA));
386
387 assert!(!state.code_just_pressed(Code::KeyA));
388 assert!(state.code_just_released(Code::KeyA));
389 assert!(!state.code_down(Code::KeyA));
390 }
391}