1use crate::rdev::{EventType, Key, KeyboardState};
2use crate::windows::common::{get_code, get_scan_code, FALSE, TRUE};
3use crate::windows::keycodes::code_from_key;
4use std::ptr::null_mut;
5use winapi::shared::minwindef::{BYTE, HKL, LPARAM, UINT};
6use winapi::um::processthreadsapi::GetCurrentThreadId;
7use winapi::um::winuser;
8use winapi::um::winuser::{
9 GetForegroundWindow, GetKeyState, GetKeyboardLayout, GetKeyboardState,
10 GetWindowThreadProcessId, ToUnicodeEx, VK_CAPITAL, VK_LSHIFT, VK_RSHIFT, VK_SHIFT,
11};
12
13const VK_SHIFT_: usize = VK_SHIFT as usize;
14const VK_CAPITAL_: usize = VK_CAPITAL as usize;
15const VK_LSHIFT_: usize = VK_LSHIFT as usize;
16const VK_RSHIFT_: usize = VK_RSHIFT as usize;
17const HIGHBIT: u8 = 0x80;
18
19pub struct Keyboard {
20 last_code: UINT,
21 last_scan_code: UINT,
22 last_state: [BYTE; 256],
23 last_is_dead: bool,
24}
25
26impl Keyboard {
27 pub fn new() -> Option<Keyboard> {
28 Some(Keyboard {
29 last_code: 0,
30 last_scan_code: 0,
31 last_state: [0; 256],
32 last_is_dead: false,
33 })
34 }
35
36 pub(crate) unsafe fn get_name(&mut self, lpdata: LPARAM) -> Option<String> {
37 let code = get_code(lpdata);
40 let scan_code = get_scan_code(lpdata);
41
42 self.set_global_state()?;
43 self.get_code_name(code, scan_code)
44 }
45
46 pub(crate) unsafe fn set_global_state(&mut self) -> Option<()> {
47 let mut state = [0_u8; 256];
48 let state_ptr = state.as_mut_ptr();
49
50 let _shift = GetKeyState(VK_SHIFT);
51 let current_window_thread_id = GetWindowThreadProcessId(GetForegroundWindow(), null_mut());
52 let thread_id = GetCurrentThreadId();
53 let status = if winuser::AttachThreadInput(thread_id, current_window_thread_id, TRUE) == 1 {
55 let status = GetKeyboardState(state_ptr);
57
58 winuser::AttachThreadInput(thread_id, current_window_thread_id, FALSE);
60 status
61 } else {
62 GetKeyboardState(state_ptr)
64 };
65
66 if status != 1 {
67 return None;
68 }
69 self.last_state = state;
70 Some(())
71 }
72
73 pub(crate) unsafe fn get_code_name(&mut self, code: UINT, scan_code: UINT) -> Option<String> {
74 let current_window_thread_id = GetWindowThreadProcessId(GetForegroundWindow(), null_mut());
75 let state_ptr = self.last_state.as_mut_ptr();
76 const BUF_LEN: i32 = 32;
77 let mut buff = [0_u16; BUF_LEN as usize];
78 let buff_ptr = buff.as_mut_ptr();
79 let layout = GetKeyboardLayout(current_window_thread_id);
80 let len = ToUnicodeEx(code, scan_code, state_ptr, buff_ptr, 8 - 1, 0, layout);
81
82 let mut is_dead = false;
83 let result = match len {
84 0 => None,
85 -1 => {
86 is_dead = true;
87 self.clear_keyboard_buffer(code, scan_code, layout);
88 None
89 }
90 len if len > 0 => String::from_utf16(&buff[..len as usize]).ok(),
91 _ => None,
92 };
93
94 if self.last_code != 0 && self.last_is_dead {
95 buff = [0; 32];
96 let buff_ptr = buff.as_mut_ptr();
97 let last_state_ptr = self.last_state.as_mut_ptr();
98 ToUnicodeEx(
99 self.last_code,
100 self.last_scan_code,
101 last_state_ptr,
102 buff_ptr,
103 BUF_LEN,
104 0,
105 layout,
106 );
107 self.last_code = 0;
108 } else {
109 self.last_code = code;
110 self.last_scan_code = scan_code;
111 self.last_is_dead = is_dead;
112 }
113 result
114 }
115
116 unsafe fn clear_keyboard_buffer(&self, code: UINT, scan_code: UINT, layout: HKL) {
117 const BUF_LEN: i32 = 32;
118 let mut buff = [0_u16; BUF_LEN as usize];
119 let buff_ptr = buff.as_mut_ptr();
120 let mut state = [0_u8; 256];
121 let state_ptr = state.as_mut_ptr();
122
123 let mut len = -1;
124 while len < 0 {
125 len = ToUnicodeEx(code, scan_code, state_ptr, buff_ptr, BUF_LEN, 0, layout);
126 }
127 }
128}
129
130impl KeyboardState for Keyboard {
131 fn add(&mut self, event_type: &EventType) -> Option<String> {
132 match event_type {
133 EventType::KeyPress(key) => match key {
134 Key::ShiftLeft => {
135 self.last_state[VK_SHIFT_] |= HIGHBIT;
136 self.last_state[VK_LSHIFT_] |= HIGHBIT;
137 None
138 }
139 Key::ShiftRight => {
140 self.last_state[VK_SHIFT_] |= HIGHBIT;
141 self.last_state[VK_RSHIFT_] |= HIGHBIT;
142 None
143 }
144 Key::CapsLock => {
145 self.last_state[VK_CAPITAL_] ^= HIGHBIT;
146 None
147 }
148 key => {
149 let code = code_from_key(*key)?;
150 unsafe { self.get_code_name(code.into(), 0) }
151 }
152 },
153 EventType::KeyRelease(key) => match key {
154 Key::ShiftLeft => {
155 self.last_state[VK_SHIFT_] &= !HIGHBIT;
156 self.last_state[VK_LSHIFT_] &= !HIGHBIT;
157 None
158 }
159 Key::ShiftRight => {
160 self.last_state[VK_SHIFT_] &= !HIGHBIT;
161 self.last_state[VK_RSHIFT_] &= HIGHBIT;
162 None
163 }
164 _ => None,
165 },
166
167 _ => None,
168 }
169 }
170
171 fn reset(&mut self) {
172 self.last_state[16] = 0;
173 self.last_state[20] = 0;
174 }
175}