1use std::{
4 io,
5 mem,
6};
7
8use num_enum::{
9 FromPrimitive,
10 IntoPrimitive,
11};
12use windows::Win32::UI::Input::KeyboardAndMouse::{
13 GetAsyncKeyState,
14 GetKeyState,
15 SendInput,
16 INPUT,
17 INPUT_0,
18 INPUT_KEYBOARD,
19 INPUT_MOUSE,
20 KEYBDINPUT,
21 KEYEVENTF_KEYUP,
22 MOUSEEVENTF_LEFTDOWN,
23 MOUSEEVENTF_LEFTUP,
24 MOUSEEVENTF_MIDDLEDOWN,
25 MOUSEEVENTF_MIDDLEUP,
26 MOUSEEVENTF_RIGHTDOWN,
27 MOUSEEVENTF_RIGHTUP,
28 MOUSEEVENTF_WHEEL,
29 MOUSEEVENTF_XDOWN,
30 MOUSEEVENTF_XUP,
31 MOUSEINPUT,
32 VIRTUAL_KEY,
33 VK_0,
34 VK_1,
35 VK_2,
36 VK_3,
37 VK_4,
38 VK_5,
39 VK_6,
40 VK_7,
41 VK_8,
42 VK_9,
43 VK_A,
44 VK_ADD,
45 VK_APPS,
46 VK_B,
47 VK_BACK,
48 VK_C,
49 VK_CAPITAL,
50 VK_D,
51 VK_DECIMAL,
52 VK_DELETE,
53 VK_DIVIDE,
54 VK_DOWN,
55 VK_E,
56 VK_END,
57 VK_ESCAPE,
58 VK_F,
59 VK_F1,
60 VK_F10,
61 VK_F11,
62 VK_F12,
63 VK_F2,
64 VK_F3,
65 VK_F4,
66 VK_F5,
67 VK_F6,
68 VK_F7,
69 VK_F8,
70 VK_F9,
71 VK_G,
72 VK_H,
73 VK_HOME,
74 VK_I,
75 VK_INSERT,
76 VK_J,
77 VK_K,
78 VK_L,
79 VK_LBUTTON,
80 VK_LCONTROL,
81 VK_LEFT,
82 VK_LMENU,
83 VK_LSHIFT,
84 VK_LWIN,
85 VK_M,
86 VK_MBUTTON,
87 VK_MULTIPLY,
88 VK_N,
89 VK_NEXT,
90 VK_NUMLOCK,
91 VK_NUMPAD0,
92 VK_NUMPAD1,
93 VK_NUMPAD2,
94 VK_NUMPAD3,
95 VK_NUMPAD4,
96 VK_NUMPAD5,
97 VK_NUMPAD6,
98 VK_NUMPAD7,
99 VK_NUMPAD8,
100 VK_NUMPAD9,
101 VK_O,
102 VK_OEM_1,
103 VK_OEM_102,
104 VK_OEM_2,
105 VK_OEM_3,
106 VK_OEM_4,
107 VK_OEM_5,
108 VK_OEM_6,
109 VK_OEM_7,
110 VK_OEM_8,
111 VK_OEM_COMMA,
112 VK_OEM_MINUS,
113 VK_OEM_PERIOD,
114 VK_OEM_PLUS,
115 VK_P,
116 VK_PAUSE,
117 VK_PRIOR,
118 VK_Q,
119 VK_R,
120 VK_RBUTTON,
121 VK_RCONTROL,
122 VK_RETURN,
123 VK_RIGHT,
124 VK_RMENU,
125 VK_RSHIFT,
126 VK_RWIN,
127 VK_S,
128 VK_SCROLL,
129 VK_SNAPSHOT,
130 VK_SPACE,
131 VK_SUBTRACT,
132 VK_T,
133 VK_TAB,
134 VK_U,
135 VK_UP,
136 VK_V,
137 VK_VOLUME_DOWN,
138 VK_VOLUME_MUTE,
139 VK_VOLUME_UP,
140 VK_W,
141 VK_X,
142 VK_XBUTTON1,
143 VK_XBUTTON2,
144 VK_Y,
145 VK_Z,
146};
147use windows::Win32::UI::WindowsAndMessaging::{
148 WHEEL_DELTA,
149 XBUTTON1,
150 XBUTTON2,
151};
152
153use crate::internal::ReturnValue;
154use private::*;
155
156pub mod hotkeys;
157
158pub trait GenericKey: GenericKeyInternal {
160 fn is_pressed(self) -> io::Result<bool> {
161 let result = unsafe {
162 GetAsyncKeyState(self.into())
163 .if_null_to_error(|| io::ErrorKind::PermissionDenied.into())? as u16
164 };
165 Ok(result >> (u16::BITS - 1) == 1)
166 }
167
168 fn press(self) -> io::Result<()> {
172 self.send_input(false)
173 }
174
175 fn release(self) -> io::Result<()> {
177 self.send_input(true)
178 }
179
180 fn send_combination(keys: &[Self]) -> io::Result<()> {
185 let raw_input_pairs: Vec<_> = keys
186 .iter()
187 .copied()
188 .map(|key: Self| {
189 let raw_input = key.get_press_raw_input(false);
190 let raw_input_release = key.get_press_raw_input(true);
191 (raw_input, raw_input_release)
192 })
193 .collect();
194 let raw_inputs: Vec<_> = raw_input_pairs
195 .iter()
196 .map(|x| x.0)
197 .chain(raw_input_pairs.iter().rev().map(|x| x.1))
198 .collect();
199 send_raw_inputs(raw_inputs.as_slice())
200 }
201}
202
203impl GenericKey for KeyboardKey {}
205impl GenericKey for MouseButton {}
206
207mod private {
208 use super::*;
209
210 pub trait GenericKeyInternal: Copy + Into<i32>
211 where
212 Self: Into<u16>,
214 {
215 fn send_input(self, is_release: bool) -> io::Result<()> {
216 let raw_input = self.get_press_raw_input(is_release);
217 send_raw_inputs(&[raw_input])
218 }
219 fn get_press_raw_input(self, is_release: bool) -> INPUT;
220 }
221
222 impl GenericKeyInternal for KeyboardKey {
223 fn get_press_raw_input(self, is_release: bool) -> INPUT {
224 let raw_key: u16 = self.into();
225 let raw_keybdinput = KEYBDINPUT {
226 wVk: VIRTUAL_KEY(raw_key),
227 dwFlags: if is_release {
228 KEYEVENTF_KEYUP
229 } else {
230 Default::default()
231 },
232 ..Default::default()
233 };
234 INPUT {
235 r#type: INPUT_KEYBOARD,
236 Anonymous: INPUT_0 { ki: raw_keybdinput },
237 }
238 }
239 }
240
241 impl GenericKeyInternal for MouseButton {
242 fn get_press_raw_input(self, is_release: bool) -> INPUT {
243 let (flags, mouse_data) = match (self, is_release) {
244 (MouseButton::Left, false) => (MOUSEEVENTF_LEFTDOWN, 0),
245 (MouseButton::Left, true) => (MOUSEEVENTF_LEFTUP, 0),
246 (MouseButton::Right, false) => (MOUSEEVENTF_RIGHTDOWN, 0),
247 (MouseButton::Right, true) => (MOUSEEVENTF_RIGHTUP, 0),
248 (MouseButton::Middle, false) => (MOUSEEVENTF_MIDDLEDOWN, 0),
249 (MouseButton::Middle, true) => (MOUSEEVENTF_MIDDLEUP, 0),
250 (MouseButton::X1, false) => (MOUSEEVENTF_XDOWN, XBUTTON1),
251 (MouseButton::X1, true) => (MOUSEEVENTF_XUP, XBUTTON1),
252 (MouseButton::X2, false) => (MOUSEEVENTF_XDOWN, XBUTTON2),
253 (MouseButton::X2, true) => (MOUSEEVENTF_XUP, XBUTTON2),
254 };
255 INPUT {
256 r#type: INPUT_MOUSE,
257 Anonymous: INPUT_0 {
258 mi: MOUSEINPUT {
259 mouseData: mouse_data.into(),
260 dwFlags: flags,
261 ..Default::default()
262 },
263 },
264 }
265 }
266 }
267}
268
269#[derive(FromPrimitive, IntoPrimitive, Copy, Clone, Eq, PartialEq, Hash, Debug)]
275#[repr(u16)]
276pub enum KeyboardKey {
277 Backspace = VK_BACK.0,
278 Tab = VK_TAB.0,
279 Return = VK_RETURN.0,
280 Pause = VK_PAUSE.0,
281 CapsLock = VK_CAPITAL.0,
282 Esc = VK_ESCAPE.0,
283 Space = VK_SPACE.0,
284 PgUp = VK_PRIOR.0,
285 PgDown = VK_NEXT.0,
286 End = VK_END.0,
287 Home = VK_HOME.0,
288 LeftArrow = VK_LEFT.0,
289 UpArrow = VK_UP.0,
290 RightArrow = VK_RIGHT.0,
291 DownArrow = VK_DOWN.0,
292 PrintScreen = VK_SNAPSHOT.0,
293 Insert = VK_INSERT.0,
294 Delete = VK_DELETE.0,
295 Number0 = VK_0.0,
296 Number1 = VK_1.0,
297 Number2 = VK_2.0,
298 Number3 = VK_3.0,
299 Number4 = VK_4.0,
300 Number5 = VK_5.0,
301 Number6 = VK_6.0,
302 Number7 = VK_7.0,
303 Number8 = VK_8.0,
304 Number9 = VK_9.0,
305 A = VK_A.0,
306 B = VK_B.0,
307 C = VK_C.0,
308 D = VK_D.0,
309 E = VK_E.0,
310 F = VK_F.0,
311 G = VK_G.0,
312 H = VK_H.0,
313 I = VK_I.0,
314 J = VK_J.0,
315 K = VK_K.0,
316 L = VK_L.0,
317 M = VK_M.0,
318 N = VK_N.0,
319 O = VK_O.0,
320 P = VK_P.0,
321 Q = VK_Q.0,
322 R = VK_R.0,
323 S = VK_S.0,
324 T = VK_T.0,
325 U = VK_U.0,
326 V = VK_V.0,
327 W = VK_W.0,
328 X = VK_X.0,
329 Y = VK_Y.0,
330 Z = VK_Z.0,
331 LeftWindows = VK_LWIN.0,
332 RightWindows = VK_RWIN.0,
333 Menu = VK_APPS.0,
334 Numpad0 = VK_NUMPAD0.0,
335 Numpad1 = VK_NUMPAD1.0,
336 Numpad2 = VK_NUMPAD2.0,
337 Numpad3 = VK_NUMPAD3.0,
338 Numpad4 = VK_NUMPAD4.0,
339 Numpad5 = VK_NUMPAD5.0,
340 Numpad6 = VK_NUMPAD6.0,
341 Numpad7 = VK_NUMPAD7.0,
342 Numpad8 = VK_NUMPAD8.0,
343 Numpad9 = VK_NUMPAD9.0,
344 Multiply = VK_MULTIPLY.0,
345 Add = VK_ADD.0,
346 Subtract = VK_SUBTRACT.0,
347 Decimal = VK_DECIMAL.0,
348 Divide = VK_DIVIDE.0,
349 F1 = VK_F1.0,
350 F2 = VK_F2.0,
351 F3 = VK_F3.0,
352 F4 = VK_F4.0,
353 F5 = VK_F5.0,
354 F6 = VK_F6.0,
355 F7 = VK_F7.0,
356 F8 = VK_F8.0,
357 F9 = VK_F9.0,
358 F10 = VK_F10.0,
359 F11 = VK_F11.0,
360 F12 = VK_F12.0,
361 NumLock = VK_NUMLOCK.0,
362 ScrollLock = VK_SCROLL.0,
363 LeftShift = VK_LSHIFT.0,
364 RightShift = VK_RSHIFT.0,
365 LeftCtrl = VK_LCONTROL.0,
366 RightCtrl = VK_RCONTROL.0,
367 LeftAlt = VK_LMENU.0,
368 RightAlt = VK_RMENU.0,
369 VolumeMute = VK_VOLUME_MUTE.0,
370 VolumeDown = VK_VOLUME_DOWN.0,
371 VolumeUp = VK_VOLUME_UP.0,
372 Oem1 = VK_OEM_1.0,
377 OemPlus = VK_OEM_PLUS.0,
379 OemComma = VK_OEM_COMMA.0,
381 OemMinus = VK_OEM_MINUS.0,
383 OemPeriod = VK_OEM_PERIOD.0,
385 Oem2 = VK_OEM_2.0,
390 Oem3 = VK_OEM_3.0,
395 Oem4 = VK_OEM_4.0,
400 Oem5 = VK_OEM_5.0,
405 Oem6 = VK_OEM_6.0,
410 Oem7 = VK_OEM_7.0,
415 Oem8 = VK_OEM_8.0,
416 Oem102 = VK_OEM_102.0,
421 #[num_enum(catch_all)]
423 Other(u16),
424}
425
426impl KeyboardKey {
427 pub fn is_lock_toggled(self) -> bool {
429 let result = unsafe { GetKeyState(self.into()) as u16 };
430 result & 1 == 1
431 }
432}
433
434impl From<KeyboardKey> for u32 {
435 fn from(value: KeyboardKey) -> Self {
436 Self::from(u16::from(value))
437 }
438}
439
440impl From<KeyboardKey> for i32 {
441 fn from(value: KeyboardKey) -> Self {
442 u16::from(value) as Self
443 }
444}
445
446fn send_raw_inputs(raw_inputs: &[INPUT]) -> io::Result<()> {
447 let raw_input_size = mem::size_of::<INPUT>()
448 .try_into()
449 .expect("Struct size conversion failed");
450
451 let expected_sent_size =
452 u32::try_from(raw_inputs.len()).expect("Inputs length conversion failed");
453 unsafe {
454 SendInput(raw_inputs, raw_input_size)
455 .if_null_get_last_error()?
456 .if_not_eq_to_error(expected_sent_size, || {
457 io::Error::from(io::ErrorKind::Interrupted)
458 })?;
459 }
460 Ok(())
461}
462
463#[derive(IntoPrimitive, Copy, Clone, Eq, PartialEq, Hash, Debug)]
467#[repr(u16)]
468pub enum MouseButton {
469 Left = VK_LBUTTON.0,
470 Right = VK_RBUTTON.0,
471 Middle = VK_MBUTTON.0,
472 X1 = VK_XBUTTON1.0,
473 X2 = VK_XBUTTON2.0,
474}
475
476impl From<MouseButton> for i32 {
477 fn from(value: MouseButton) -> Self {
478 u16::from(value) as Self
479 }
480}
481
482#[derive(Copy, Clone, Eq, PartialEq, Debug)]
484pub enum MouseScrollEvent {
485 Up,
489 Down,
493 Continuous(i16),
498}
499
500impl MouseScrollEvent {
501 const WHEEL_DELTA_INT: i16 = WHEEL_DELTA as _;
502
503 pub fn send(self) -> io::Result<()> {
505 self.send_amount(1)
506 }
507
508 pub fn send_amount(self, amount: u8) -> io::Result<()> {
510 let single_delta = match self {
511 MouseScrollEvent::Up => Self::WHEEL_DELTA_INT,
512 MouseScrollEvent::Down => -Self::WHEEL_DELTA_INT,
513 MouseScrollEvent::Continuous(delta) => delta,
514 };
515 let mouse_data = i32::from(single_delta) * i32::from(amount);
517 let raw_input = INPUT {
518 r#type: INPUT_MOUSE,
519 Anonymous: INPUT_0 {
520 mi: MOUSEINPUT {
521 mouseData: mouse_data as u32,
523 dwFlags: MOUSEEVENTF_WHEEL,
524 ..Default::default()
525 },
526 },
527 };
528 send_raw_inputs(&[raw_input])
529 }
530
531 #[allow(dead_code)]
532 pub(crate) fn from_raw_movement(raw_movement: u16) -> Self {
533 let raw_movement = raw_movement as i16;
534 const WHEEL_DELTA_INT: i16 = WHEEL_DELTA as _;
535 if raw_movement == WHEEL_DELTA_INT {
536 MouseScrollEvent::Up
537 } else if raw_movement == -WHEEL_DELTA_INT {
538 MouseScrollEvent::Down
539 } else {
540 MouseScrollEvent::Continuous(raw_movement)
541 }
542 }
543}