1use crate::VKey;
5use windows::Win32::UI::Input::KeyboardAndMouse::GetAsyncKeyState;
6
7#[derive(Copy, Clone)]
14pub struct KeyboardState {
15 pub flags: [u128; 2],
16}
17
18impl KeyboardState {
19 pub fn new() -> KeyboardState {
21 KeyboardState { flags: [0, 0] }
22 }
23
24 pub fn keydown(&mut self, key: u16) {
30 let index = (key / 128) as usize;
31 let position = key % 128;
32 self.flags[index] |= 1 << position;
33 match key {
34 _ if key == VKey::LShift.to_vk_code() => self.keydown(VKey::Shift.to_vk_code()),
35 _ if key == VKey::RShift.to_vk_code() => self.keydown(VKey::Shift.to_vk_code()),
36 _ if key == VKey::LControl.to_vk_code() => self.keydown(VKey::Control.to_vk_code()),
37 _ if key == VKey::RControl.to_vk_code() => self.keydown(VKey::Control.to_vk_code()),
38 _ if key == VKey::LMenu.to_vk_code() => self.keydown(VKey::Menu.to_vk_code()),
39 _ if key == VKey::RMenu.to_vk_code() => self.keydown(VKey::Menu.to_vk_code()),
40 _ => {}
41 }
42 }
43
44 pub fn keyup(&mut self, key: u16) {
46 let index = (key / 128) as usize;
47 let position = key % 128;
48 self.flags[index] &= !(1 << position);
49 if (key == VKey::LShift.to_vk_code() || key == VKey::RShift.to_vk_code())
50 && !self.is_down(VKey::LShift.to_vk_code())
51 && !self.is_down(VKey::RShift.to_vk_code())
52 {
53 self.keyup(VKey::Shift.to_vk_code());
54 } else if (key == VKey::LControl.to_vk_code() || key == VKey::RControl.to_vk_code())
55 && !self.is_down(VKey::LControl.to_vk_code())
56 && !self.is_down(VKey::RControl.to_vk_code())
57 {
58 self.keyup(VKey::Control.to_vk_code());
59 } else if (key == VKey::LMenu.to_vk_code() || key == VKey::RMenu.to_vk_code())
60 && !self.is_down(VKey::LMenu.to_vk_code())
61 && !self.is_down(VKey::RMenu.to_vk_code())
62 {
63 self.keyup(VKey::Menu.to_vk_code());
64 }
65 }
66
67 pub fn is_down(&self, key: u16) -> bool {
69 let index = (key / 128) as usize;
70 let position = key % 128;
71 (self.flags[index] & (1 << position)) != 0
72 }
73
74 pub fn sync(&mut self) {
77 for vk_code in 0..128 {
78 let mask = 1u128 << vk_code;
79 if self.flags[0] & mask != 0 && !Self::get_async_key_state(vk_code) {
80 self.keyup(vk_code);
81 }
82 if self.flags[1] & mask != 0 && !Self::get_async_key_state(vk_code + 128) {
83 self.keyup(vk_code + 128);
84 }
85 }
86 }
87
88 pub fn clear(&mut self) {
90 self.flags = [0, 0];
91 }
92
93 pub fn get_async_key_state(key: u16) -> bool {
96 unsafe { (GetAsyncKeyState(key.into()) & -0x8000) != 0 }
97 }
98}
99
100impl std::fmt::Debug for KeyboardState {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 let mut keys = Vec::new();
103 for vk_code in 0..128 {
104 match vk_code {
105 _ if vk_code == VKey::Shift.to_vk_code() => continue,
106 _ if vk_code == VKey::Control.to_vk_code() => continue,
107 _ if vk_code == VKey::Menu.to_vk_code() => continue,
108 _ => {}
109 }
110 let mask = 1u128 << vk_code;
111 if self.flags[0] & mask != 0 {
112 keys.push(VKey::from_vk_code(vk_code));
113 }
114 if self.flags[1] & mask != 0 {
115 keys.push(VKey::from_vk_code(vk_code + 128));
116 }
117 }
118 f.debug_struct("KeyboardState")
119 .field("Keys", &keys)
122 .finish()
123 }
124}
125
126impl Default for KeyboardState {
127 fn default() -> Self {
128 Self::new()
129 }
130}
131
132impl PartialEq for KeyboardState {
133 fn eq(&self, other: &KeyboardState) -> bool {
134 self.flags == other.flags
135 }
136}
137
138impl Eq for KeyboardState {}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn test_new_keyboard_state() {
146 let keyboard = KeyboardState::new();
147 assert_eq!(
148 keyboard.flags,
149 [0, 0],
150 "New KeyboardState should have all flags cleared"
151 );
152 }
153
154 #[test]
155 fn test_keydown() {
156 let mut keyboard = KeyboardState::new();
157 keyboard.keydown(65);
158 assert_eq!(keyboard.flags[0], 1 << (65 % 128), "Key 65 should be set");
159
160 keyboard.keydown(129);
161 assert_eq!(keyboard.flags[1], 1 << (129 % 128), "Key 129 should be set");
162 }
163
164 #[test]
165 fn test_keyup() {
166 let mut keyboard = KeyboardState::new();
167 keyboard.keydown(65); keyboard.keyup(65); assert_eq!(keyboard.flags[0], 0, "Key 65 should be cleared");
170
171 keyboard.keydown(129); keyboard.keyup(129); assert_eq!(keyboard.flags[1], 0, "Key 129 should be cleared");
174 }
175
176 #[test]
177 fn test_clear() {
178 let mut keyboard = KeyboardState::new();
179 keyboard.keydown(65); keyboard.keydown(129); keyboard.clear(); assert_eq!(
183 keyboard.flags,
184 [0, 0],
185 "KeyboardState should be cleared after clear()"
186 );
187 }
188
189 #[test]
190 fn test_clone() {
191 let mut keyboard = KeyboardState::new();
192 keyboard.keydown(65); let cloned_keyboard = keyboard.clone();
194 assert_eq!(
195 keyboard, cloned_keyboard,
196 "Cloned KeyboardState should be equal to the original"
197 );
198
199 keyboard.keydown(129);
201 assert_ne!(
202 keyboard, cloned_keyboard,
203 "Cloned KeyboardState should not reflect changes to the original"
204 );
205 }
206
207 #[test]
208 fn test_equality() {
209 let mut keyboard1 = KeyboardState::new();
210 let mut keyboard2 = KeyboardState::new();
211
212 assert_eq!(
214 keyboard1, keyboard2,
215 "Two empty KeyboardState instances should be equal"
216 );
217
218 keyboard1.keydown(65);
220 assert_ne!(
221 keyboard1, keyboard2,
222 "KeyboardState instances with different flags should not be equal"
223 );
224
225 keyboard2.keydown(65);
227 assert_eq!(
228 keyboard1, keyboard2,
229 "KeyboardState instances with the same flags should be equal"
230 );
231 }
232
233 #[test]
234 fn test_multiple_keys() {
235 let mut keyboard = KeyboardState::new();
236
237 keyboard.keydown(65);
239 keyboard.keydown(70);
240 keyboard.keydown(129);
241
242 assert_eq!(true, keyboard.is_down(65), "Key 65 should be set");
243 assert_eq!(true, keyboard.is_down(70), "Key 70 should be set");
244 assert_eq!(true, keyboard.is_down(129), "Key 129 should be set");
245
246 keyboard.keyup(65);
248 keyboard.keyup(70);
249
250 assert_eq!(keyboard.flags[0], 0, "Key 65 should be cleared");
251 assert_eq!(keyboard.flags[0], 0, "Key 70 should be cleared");
252 assert_eq!(
253 keyboard.flags[1],
254 1 << (129 % 128),
255 "Key 129 should remain set"
256 );
257 }
258}