1use std::borrow::Cow;
11
12use windows::Win32::Devices::HumanInterfaceDevice::{
13 DIK_DELETE, DIK_DIVIDE, DIK_DOWNARROW, DIK_END, DIK_HOME, DIK_INSERT, DIK_LEFTARROW,
14 DIK_NUMPADENTER, DIK_PGDN, DIK_PGUP, DIK_RALT, DIK_RCONTROL, DIK_RIGHTARROW, DIK_UPARROW,
15};
16use windows::Win32::UI::Input::KeyboardAndMouse::GetKeyNameTextW;
17use windows::Win32::UI::Input::XboxController::{
18 XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_BUTTON_FLAGS,
19 XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
20 XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_LEFT_THUMB,
21 XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_RIGHT_THUMB, XINPUT_GAMEPAD_START,
22 XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
23};
24use windows::core::HSTRING;
25
26pub const MACRO_KEYBOARD_OFFSET: u32 = 0; pub const MACRO_NUM_KEYBOARD_KEYS: u32 = 256;
28
29pub const MACRO_MOUSE_BUTTON_OFFSET: u32 = MACRO_NUM_KEYBOARD_KEYS; pub const MACRO_NUM_MOUSE_BUTTONS: u32 = 8;
31
32pub const MACRO_MOUSE_WHEEL_OFFSET: u32 = MACRO_MOUSE_BUTTON_OFFSET + MACRO_NUM_MOUSE_BUTTONS; pub const MACRO_MOUSE_WHEEL_DIRECTIONS: u32 = 2;
34
35pub const MACRO_GAMEPAD_OFFSET: u32 = MACRO_MOUSE_WHEEL_OFFSET + MACRO_MOUSE_WHEEL_DIRECTIONS; pub const MACRO_NUM_GAMEPAD_BUTTONS: u32 = 16;
37
38pub const MAX_MACROS: u32 = MACRO_GAMEPAD_OFFSET + MACRO_NUM_GAMEPAD_BUTTONS; #[repr(u32)]
41#[derive(Debug, Copy, Clone, PartialEq, Eq)]
42pub enum GamepadButtonOffset {
43 DpadUp = MACRO_GAMEPAD_OFFSET,
44 DpadDown,
45 DpadLeft,
46 DpadRight,
47 Start,
48 Back,
49 LeftThumb,
50 RightThumb,
51 LeftShoulder,
52 RightShoulder,
53 A,
54 B,
55 X,
56 Y,
57 Lt,
58 Rt, }
60const _: () = assert!(GamepadButtonOffset::Rt as u32 == 281);
61
62impl GamepadButtonOffset {
63 const fn from_xinput(key_mask: XINPUT_GAMEPAD_BUTTON_FLAGS) -> Option<Self> {
64 Some(match key_mask {
68 XINPUT_GAMEPAD_DPAD_UP => Self::DpadUp,
69 XINPUT_GAMEPAD_DPAD_DOWN => Self::DpadDown,
70 XINPUT_GAMEPAD_DPAD_LEFT => Self::DpadLeft,
71 XINPUT_GAMEPAD_DPAD_RIGHT => Self::DpadRight,
72 XINPUT_GAMEPAD_START => Self::Start,
73 XINPUT_GAMEPAD_BACK => Self::Back,
74 XINPUT_GAMEPAD_LEFT_THUMB => Self::LeftThumb,
75 XINPUT_GAMEPAD_RIGHT_THUMB => Self::RightThumb,
76 XINPUT_GAMEPAD_LEFT_SHOULDER => Self::LeftShoulder,
77 XINPUT_GAMEPAD_RIGHT_SHOULDER => Self::RightShoulder,
78 XINPUT_GAMEPAD_A => Self::A,
79 XINPUT_GAMEPAD_B => Self::B,
80 XINPUT_GAMEPAD_X => Self::X,
81 XINPUT_GAMEPAD_Y => Self::Y,
82
83 other => {
84 match other.0 {
85 0x9 => Self::Lt, 0xA => Self::Rt, _ => return None, }
89 }
90 })
91 }
92
93 pub const fn to_xinput(&self) -> XINPUT_GAMEPAD_BUTTON_FLAGS {
94 match *self {
95 Self::DpadUp => XINPUT_GAMEPAD_DPAD_UP,
96 Self::DpadDown => XINPUT_GAMEPAD_DPAD_DOWN,
97 Self::DpadLeft => XINPUT_GAMEPAD_DPAD_LEFT,
98 Self::DpadRight => XINPUT_GAMEPAD_DPAD_RIGHT,
99 Self::Start => XINPUT_GAMEPAD_START,
100 Self::Back => XINPUT_GAMEPAD_BACK,
101 Self::LeftThumb => XINPUT_GAMEPAD_LEFT_THUMB,
102 Self::RightThumb => XINPUT_GAMEPAD_RIGHT_THUMB,
103 Self::LeftShoulder => XINPUT_GAMEPAD_LEFT_SHOULDER,
104 Self::RightShoulder => XINPUT_GAMEPAD_RIGHT_SHOULDER,
105 Self::A => XINPUT_GAMEPAD_A,
106 Self::B => XINPUT_GAMEPAD_B,
107 Self::X => XINPUT_GAMEPAD_X,
108 Self::Y => XINPUT_GAMEPAD_Y,
109 Self::Lt => XINPUT_GAMEPAD_BUTTON_FLAGS(0x9), Self::Rt => XINPUT_GAMEPAD_BUTTON_FLAGS(0xA), }
112
113 }
118
119 pub const fn to_str(&self) -> &'static str {
120 match self {
121 Self::DpadUp => "Gamepad DPad Up",
122 Self::DpadDown => "Gamepad DPad Down",
123 Self::DpadLeft => "Gamepad DPad Left",
124 Self::DpadRight => "Gamepad DPad Right",
125 Self::Start => "Gamepad Start",
126 Self::Back => "Gamepad Back",
127 Self::LeftThumb => "Gamepad Left Thumb",
128 Self::RightThumb => "Gamepad Right Thumb",
129 Self::LeftShoulder => "Gamepad Left Shoulder",
130 Self::RightShoulder => "Gamepad Right Shoulder",
131 Self::A => "Gamepad A",
132 Self::B => "Gamepad B",
133 Self::X => "Gamepad X",
134 Self::Y => "Gamepad Y",
135 Self::Lt => "Gamepad LT",
136 Self::Rt => "Gamepad RT",
137 }
138 }
139}
140
141#[repr(u32)]
145pub enum ScePadButton {
146 Share = 0x00000001,
147 L3 = 0x00000002,
148 R3 = 0x00000004,
149 Options = 0x00000008,
150 Up = 0x00000010,
151 Right = 0x00000020,
152 Down = 0x00000040,
153 Left = 0x00000080,
154 L2 = 0x00000100,
155 R2 = 0x00000200,
156 L1 = 0x00000400,
157 R1 = 0x00000800,
158 Triangle = 0x00001000,
159 Circle = 0x00002000,
160 Cross = 0x00004000,
161 Square = 0x00008000,
162 Playstation = 0x00010000,
163 TouchPad = 0x00100000,
164 Intercepted = 0x80000000,
165}
166
167impl ScePadButton {
168 pub const fn from_xinput(key_mask: XINPUT_GAMEPAD_BUTTON_FLAGS) -> Option<Self> {
169 Some(match key_mask {
170 XINPUT_GAMEPAD_DPAD_UP => Self::Up,
171 XINPUT_GAMEPAD_DPAD_DOWN => Self::Down,
172 XINPUT_GAMEPAD_DPAD_LEFT => Self::Left,
173 XINPUT_GAMEPAD_DPAD_RIGHT => Self::Right,
174 XINPUT_GAMEPAD_START => Self::Options,
175 XINPUT_GAMEPAD_BACK => Self::TouchPad,
176 XINPUT_GAMEPAD_LEFT_THUMB => Self::L3,
177 XINPUT_GAMEPAD_RIGHT_THUMB => Self::R3,
178 XINPUT_GAMEPAD_LEFT_SHOULDER => Self::L1,
179 XINPUT_GAMEPAD_RIGHT_SHOULDER => Self::R1,
180 XINPUT_GAMEPAD_A => Self::Cross,
181 XINPUT_GAMEPAD_B => Self::Circle,
182 XINPUT_GAMEPAD_X => Self::Square,
183 XINPUT_GAMEPAD_Y => Self::Triangle,
184 _ => return None,
185 })
186 }
187
188 pub fn to_xinput(&self) -> Option<XINPUT_GAMEPAD_BUTTON_FLAGS> {
189 Some(match *self {
190 Self::Up => XINPUT_GAMEPAD_DPAD_UP,
191 Self::Down => XINPUT_GAMEPAD_DPAD_DOWN,
192 Self::Left => XINPUT_GAMEPAD_DPAD_LEFT,
193 Self::Right => XINPUT_GAMEPAD_DPAD_RIGHT,
194 Self::Options => XINPUT_GAMEPAD_START,
195 Self::TouchPad => XINPUT_GAMEPAD_BACK,
196 Self::L3 => XINPUT_GAMEPAD_LEFT_THUMB,
197 Self::R3 => XINPUT_GAMEPAD_RIGHT_THUMB,
198 Self::L1 => XINPUT_GAMEPAD_LEFT_SHOULDER,
199 Self::R1 => XINPUT_GAMEPAD_RIGHT_SHOULDER,
200 Self::Share => todo!(),
201 Self::L2 => todo!(),
202 Self::R2 => todo!(),
203 Self::Triangle => XINPUT_GAMEPAD_Y,
204 Self::Circle => XINPUT_GAMEPAD_B,
205 Self::Cross => XINPUT_GAMEPAD_A,
206 Self::Square => XINPUT_GAMEPAD_X,
207 Self::Playstation | Self::Intercepted => return None,
208 })
209 }
210}
211
212pub fn get_key_name(key_code: u32) -> Cow<'static, str> {
213 if (MACRO_MOUSE_BUTTON_OFFSET..MACRO_GAMEPAD_OFFSET).contains(&key_code) {
214 get_mouse_button_name(key_code).unwrap_or("Unknown").into()
215 } else if (MACRO_GAMEPAD_OFFSET..MAX_MACROS).contains(&key_code) {
216 GamepadButtonOffset::from_xinput(XINPUT_GAMEPAD_BUTTON_FLAGS(key_code as u16))
217 .map_or("Unknown", |input| input.to_str())
218 .into()
219 } else {
220 get_keyboard_key_name(key_code).into()
221 }
222}
223
224fn get_keyboard_key_name(key_code: u32) -> String {
225 let mut scancode = key_code & 0xFF;
226
227 scancode = match scancode {
228 DIK_NUMPADENTER => 0x11C,
229 DIK_RCONTROL => 0x11D,
230 DIK_DIVIDE => 0x135,
231 DIK_RALT => 0x138,
232 DIK_HOME => 0x147,
233 DIK_UPARROW => 0x148,
234 DIK_PGUP => 0x149,
235 DIK_LEFTARROW => 0x14B,
236 DIK_RIGHTARROW => 0x14D,
237 DIK_END => 0x14F,
238 DIK_DOWNARROW => 0x150,
239 DIK_PGDN => 0x151,
240 DIK_INSERT => 0x152,
241 DIK_DELETE => 0x153,
242 _ => scancode,
243 };
244
245 let mut l_param = (scancode << 16) as i32;
246 if scancode == 0x45 {
247 l_param |= 1 << 24;
248 }
249
250 let mut buffer = [0_u16; 256];
251 let length = unsafe { GetKeyNameTextW(l_param, buffer.as_mut_slice()) };
252 if length > 0 {
253 return HSTRING::from_wide(&buffer[..length as usize]).to_string();
254 }
255
256 String::new()
257}
258
259const fn get_mouse_button_name(key_code: u32) -> Option<&'static str> {
260 Some(match key_code {
261 256 => "Left Mouse Button",
262 257 => "Right Mouse Button",
263 258 => "Middle Mouse Button",
264 259 => "Mouse Button 3",
265 260 => "Mouse Button 4",
266 261 => "Mouse Button 5",
267 262 => "Mouse Button 6",
268 263 => "Mouse Button 7",
269 264 => "Mouse Wheel Up",
270 265 => "Mouse Wheel Down",
271 _ => return None,
272 })
273}