keyflow 0.1.0

Cross-platform input simulation library for keyboard, mouse and hotkeys.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
use crate::{Button, Key};
use windows::Win32::UI::Input::KeyboardAndMouse::{
    MOUSE_EVENT_FLAGS, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN,
    MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_XDOWN,
    MOUSEEVENTF_XUP,
};

/// Windows scancode structure
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct WindowsScancode {
    /// The actual scancode value
    pub code: u16,
    /// extended scancode (0xE0xx)
    pub extended: bool,
}

impl WindowsScancode {
    pub const fn new(code: u16) -> Self {
        Self {
            code,
            extended: false,
        }
    }

    pub const fn extended(code: u16) -> Self {
        Self {
            code,
            extended: true,
        }
    }
}

/// Converts a [`Key`] to [`WindowsScancode`]
pub(crate) fn key_to_platform(key: Key) -> Option<WindowsScancode> {
    match key {
        Key::A => Some(WindowsScancode::new(0x1E)),
        Key::B => Some(WindowsScancode::new(0x30)),
        Key::C => Some(WindowsScancode::new(0x2E)),
        Key::D => Some(WindowsScancode::new(0x20)),
        Key::E => Some(WindowsScancode::new(0x12)),
        Key::F => Some(WindowsScancode::new(0x21)),
        Key::G => Some(WindowsScancode::new(0x22)),
        Key::H => Some(WindowsScancode::new(0x23)),
        Key::I => Some(WindowsScancode::new(0x17)),
        Key::J => Some(WindowsScancode::new(0x24)),
        Key::K => Some(WindowsScancode::new(0x25)),
        Key::L => Some(WindowsScancode::new(0x26)),
        Key::M => Some(WindowsScancode::new(0x32)),
        Key::N => Some(WindowsScancode::new(0x31)),
        Key::O => Some(WindowsScancode::new(0x18)),
        Key::P => Some(WindowsScancode::new(0x19)),
        Key::Q => Some(WindowsScancode::new(0x10)),
        Key::R => Some(WindowsScancode::new(0x13)),
        Key::S => Some(WindowsScancode::new(0x1F)),
        Key::T => Some(WindowsScancode::new(0x14)),
        Key::U => Some(WindowsScancode::new(0x16)),
        Key::V => Some(WindowsScancode::new(0x2F)),
        Key::W => Some(WindowsScancode::new(0x11)),
        Key::X => Some(WindowsScancode::new(0x2D)),
        Key::Y => Some(WindowsScancode::new(0x15)),
        Key::Z => Some(WindowsScancode::new(0x2C)),

        Key::Digit1 => Some(WindowsScancode::new(0x02)),
        Key::Digit2 => Some(WindowsScancode::new(0x03)),
        Key::Digit3 => Some(WindowsScancode::new(0x04)),
        Key::Digit4 => Some(WindowsScancode::new(0x05)),
        Key::Digit5 => Some(WindowsScancode::new(0x06)),
        Key::Digit6 => Some(WindowsScancode::new(0x07)),
        Key::Digit7 => Some(WindowsScancode::new(0x08)),
        Key::Digit8 => Some(WindowsScancode::new(0x09)),
        Key::Digit9 => Some(WindowsScancode::new(0x0A)),
        Key::Digit0 => Some(WindowsScancode::new(0x0B)),

        Key::F1 => Some(WindowsScancode::new(0x3B)),
        Key::F2 => Some(WindowsScancode::new(0x3C)),
        Key::F3 => Some(WindowsScancode::new(0x3D)),
        Key::F4 => Some(WindowsScancode::new(0x3E)),
        Key::F5 => Some(WindowsScancode::new(0x3F)),
        Key::F6 => Some(WindowsScancode::new(0x40)),
        Key::F7 => Some(WindowsScancode::new(0x41)),
        Key::F8 => Some(WindowsScancode::new(0x42)),
        Key::F9 => Some(WindowsScancode::new(0x43)),
        Key::F10 => Some(WindowsScancode::new(0x44)),
        Key::F11 => Some(WindowsScancode::new(0x57)),
        Key::F12 => Some(WindowsScancode::new(0x58)),
        Key::F13 => Some(WindowsScancode::new(0x64)),
        Key::F14 => Some(WindowsScancode::new(0x65)),
        Key::F15 => Some(WindowsScancode::new(0x66)),
        Key::F16 => Some(WindowsScancode::new(0x67)),
        Key::F17 => Some(WindowsScancode::new(0x68)),
        Key::F18 => Some(WindowsScancode::new(0x69)),
        Key::F19 => Some(WindowsScancode::new(0x6A)),
        Key::F20 => Some(WindowsScancode::new(0x6B)),
        Key::F21 => Some(WindowsScancode::new(0x6C)),
        Key::F22 => Some(WindowsScancode::new(0x6D)),
        Key::F23 => Some(WindowsScancode::new(0x6E)),
        Key::F24 => Some(WindowsScancode::new(0x76)),

        Key::ShiftLeft => Some(WindowsScancode::new(0x2A)),
        Key::ShiftRight => Some(WindowsScancode::new(0x36)),
        Key::ControlLeft => Some(WindowsScancode::new(0x1D)),
        Key::ControlRight => Some(WindowsScancode::extended(0x1D)),
        Key::AltLeft => Some(WindowsScancode::new(0x38)),
        Key::AltRight => Some(WindowsScancode::extended(0x38)),
        Key::MetaLeft => Some(WindowsScancode::extended(0x5B)),
        Key::MetaRight => Some(WindowsScancode::extended(0x5C)),

        Key::Escape => Some(WindowsScancode::new(0x01)),
        Key::Space => Some(WindowsScancode::new(0x39)),
        Key::Enter => Some(WindowsScancode::new(0x1C)),
        Key::Tab => Some(WindowsScancode::new(0x0F)),
        Key::Backspace => Some(WindowsScancode::new(0x0E)),
        Key::CapsLock => Some(WindowsScancode::new(0x3A)),
        Key::NumLock => Some(WindowsScancode::new(0x45)),
        Key::ScrollLock => Some(WindowsScancode::new(0x46)),

        Key::Backquote => Some(WindowsScancode::new(0x29)),
        Key::Minus => Some(WindowsScancode::new(0x0C)),
        Key::Equal => Some(WindowsScancode::new(0x0D)),
        Key::BracketLeft => Some(WindowsScancode::new(0x1A)),
        Key::BracketRight => Some(WindowsScancode::new(0x1B)),
        Key::Backslash => Some(WindowsScancode::new(0x2B)),
        Key::Semicolon => Some(WindowsScancode::new(0x27)),
        Key::Quote => Some(WindowsScancode::new(0x28)),
        Key::Comma => Some(WindowsScancode::new(0x33)),
        Key::Period => Some(WindowsScancode::new(0x34)),
        Key::Slash => Some(WindowsScancode::new(0x35)),

        Key::IsoBackslash => Some(WindowsScancode::new(0x56)),

        Key::Insert => Some(WindowsScancode::extended(0x52)),
        Key::Delete => Some(WindowsScancode::extended(0x53)),
        Key::Home => Some(WindowsScancode::extended(0x47)),
        Key::End => Some(WindowsScancode::extended(0x4F)),
        Key::PageUp => Some(WindowsScancode::extended(0x49)),
        Key::PageDown => Some(WindowsScancode::extended(0x51)),

        Key::ArrowUp => Some(WindowsScancode::extended(0x48)),
        Key::ArrowDown => Some(WindowsScancode::extended(0x50)),
        Key::ArrowLeft => Some(WindowsScancode::extended(0x4B)),
        Key::ArrowRight => Some(WindowsScancode::extended(0x4D)),

        Key::Numpad0 => Some(WindowsScancode::new(0x52)),
        Key::Numpad1 => Some(WindowsScancode::new(0x4F)),
        Key::Numpad2 => Some(WindowsScancode::new(0x50)),
        Key::Numpad3 => Some(WindowsScancode::new(0x51)),
        Key::Numpad4 => Some(WindowsScancode::new(0x4B)),
        Key::Numpad5 => Some(WindowsScancode::new(0x4C)),
        Key::Numpad6 => Some(WindowsScancode::new(0x4D)),
        Key::Numpad7 => Some(WindowsScancode::new(0x47)),
        Key::Numpad8 => Some(WindowsScancode::new(0x48)),
        Key::Numpad9 => Some(WindowsScancode::new(0x49)),
        Key::NumpadAdd => Some(WindowsScancode::new(0x4E)),
        Key::NumpadSubtract => Some(WindowsScancode::new(0x4A)),
        Key::NumpadMultiply => Some(WindowsScancode::new(0x37)),
        Key::NumpadDivide => Some(WindowsScancode::extended(0x35)),
        Key::NumpadDecimal => Some(WindowsScancode::new(0x53)),
        Key::NumpadEnter => Some(WindowsScancode::extended(0x1C)),
        Key::NumpadEqual => Some(WindowsScancode::new(0x59)),
        Key::NumpadComma => Some(WindowsScancode::new(0x7E)),

        Key::PrintScreen => Some(WindowsScancode::extended(0x37)),
        Key::Pause => Some(WindowsScancode::extended(0x46)),
        Key::ContextMenu => Some(WindowsScancode::extended(0x5D)),
        Key::Power => Some(WindowsScancode::extended(0x5E)),
        Key::Sleep => Some(WindowsScancode::extended(0x5F)),
        Key::Wake => Some(WindowsScancode::extended(0x63)),

        Key::VolumeMute => Some(WindowsScancode::extended(0x20)),
        Key::VolumeDown => Some(WindowsScancode::extended(0x2E)),
        Key::VolumeUp => Some(WindowsScancode::extended(0x30)),
        Key::MediaPlayPause => Some(WindowsScancode::extended(0x22)),
        Key::MediaStop => Some(WindowsScancode::extended(0x24)),
        Key::MediaTrackNext => Some(WindowsScancode::extended(0x19)),
        Key::MediaTrackPrevious => Some(WindowsScancode::extended(0x10)),

        Key::BrowserBack => Some(WindowsScancode::extended(0x6A)),
        Key::BrowserForward => Some(WindowsScancode::extended(0x69)),
        Key::BrowserRefresh => Some(WindowsScancode::extended(0x67)),
        Key::BrowserStop => Some(WindowsScancode::extended(0x68)),
        Key::BrowserSearch => Some(WindowsScancode::extended(0x65)),
        Key::BrowserFavorites => Some(WindowsScancode::extended(0x66)),
        Key::BrowserHome => Some(WindowsScancode::extended(0x32)),

        Key::LaunchMail => Some(WindowsScancode::extended(0x6C)),
        Key::LaunchMediaPlayer => Some(WindowsScancode::extended(0x6D)),
        Key::LaunchApp1 => Some(WindowsScancode::extended(0x6B)),
        Key::LaunchApp2 => Some(WindowsScancode::extended(0x21)),

        Key::NonConvert => Some(WindowsScancode::new(0x7B)),
        Key::Convert => Some(WindowsScancode::new(0x79)),
        Key::KanaMode => Some(WindowsScancode::new(0x70)),
        Key::IntlYen => Some(WindowsScancode::new(0x7D)),
        Key::IntlRo => Some(WindowsScancode::new(0x73)),
        Key::Lang1 => Some(WindowsScancode::new(0xF2)),
        Key::Lang2 => Some(WindowsScancode::new(0xF1)),
        Key::Lang3 => Some(WindowsScancode::new(0x78)),
        Key::Lang4 => Some(WindowsScancode::new(0x77)),

        Key::Help => Some(WindowsScancode::extended(0x63)),
        Key::Undo => Some(WindowsScancode::extended(0x08)),
        Key::Redo => Some(WindowsScancode::extended(0x07)),
        Key::Cut => Some(WindowsScancode::extended(0x04)),
        Key::Copy => Some(WindowsScancode::extended(0x18)),
        Key::Paste => Some(WindowsScancode::extended(0x0A)),
        Key::Find => Some(WindowsScancode::extended(0x65)),
    }
}

/// Convert Button to Windows mouse event flags and mouseData
/// Returns (flags, mouseData)
pub(crate) fn button_to_platform(
    button: Button,
    released: bool,
) -> Option<(MOUSE_EVENT_FLAGS, u32)> {
    match (button, released) {
        (Button::Left, false) => Some((MOUSEEVENTF_LEFTDOWN, 0)),
        (Button::Left, true) => Some((MOUSEEVENTF_LEFTUP, 0)),
        (Button::Right, false) => Some((MOUSEEVENTF_RIGHTDOWN, 0)),
        (Button::Right, true) => Some((MOUSEEVENTF_RIGHTUP, 0)),
        (Button::Middle, false) => Some((MOUSEEVENTF_MIDDLEDOWN, 0)),
        (Button::Middle, true) => Some((MOUSEEVENTF_MIDDLEUP, 0)),

        (Button::Extra1, false) => Some((MOUSEEVENTF_XDOWN, 1)),
        (Button::Extra1, true) => Some((MOUSEEVENTF_XUP, 1)),

        (Button::Extra2, false) => Some((MOUSEEVENTF_XDOWN, 2)),
        (Button::Extra2, true) => Some((MOUSEEVENTF_XUP, 2)),

        (Button::Extra3, _) => None,
        (Button::Extra4, _) => None,
    }
}

/// Converts a [`WindowsScancode`] to [`Key`]
pub(crate) fn platform_to_key(scancode: u16, extended: bool) -> Option<Key> {
    match (scancode, extended) {
        (0x1E, false) => Some(Key::A),
        (0x30, false) => Some(Key::B),
        (0x2E, false) => Some(Key::C),
        (0x20, false) => Some(Key::D),
        (0x12, false) => Some(Key::E),
        (0x21, false) => Some(Key::F),
        (0x22, false) => Some(Key::G),
        (0x23, false) => Some(Key::H),
        (0x17, false) => Some(Key::I),
        (0x24, false) => Some(Key::J),
        (0x25, false) => Some(Key::K),
        (0x26, false) => Some(Key::L),
        (0x32, false) => Some(Key::M),
        (0x31, false) => Some(Key::N),
        (0x18, false) => Some(Key::O),
        (0x19, false) => Some(Key::P),
        (0x10, false) => Some(Key::Q),
        (0x13, false) => Some(Key::R),
        (0x1F, false) => Some(Key::S),
        (0x14, false) => Some(Key::T),
        (0x16, false) => Some(Key::U),
        (0x2F, false) => Some(Key::V),
        (0x11, false) => Some(Key::W),
        (0x2D, false) => Some(Key::X),
        (0x15, false) => Some(Key::Y),
        (0x2C, false) => Some(Key::Z),

        (0x02, false) => Some(Key::Digit1),
        (0x03, false) => Some(Key::Digit2),
        (0x04, false) => Some(Key::Digit3),
        (0x05, false) => Some(Key::Digit4),
        (0x06, false) => Some(Key::Digit5),
        (0x07, false) => Some(Key::Digit6),
        (0x08, false) => Some(Key::Digit7),
        (0x09, false) => Some(Key::Digit8),
        (0x0A, false) => Some(Key::Digit9),
        (0x0B, false) => Some(Key::Digit0),

        (0x3B, false) => Some(Key::F1),
        (0x3C, false) => Some(Key::F2),
        (0x3D, false) => Some(Key::F3),
        (0x3E, false) => Some(Key::F4),
        (0x3F, false) => Some(Key::F5),
        (0x40, false) => Some(Key::F6),
        (0x41, false) => Some(Key::F7),
        (0x42, false) => Some(Key::F8),
        (0x43, false) => Some(Key::F9),
        (0x44, false) => Some(Key::F10),
        (0x57, false) => Some(Key::F11),
        (0x58, false) => Some(Key::F12),
        (0x64, false) => Some(Key::F13),
        (0x65, false) => Some(Key::F14),
        (0x66, false) => Some(Key::F15),
        (0x67, false) => Some(Key::F16),
        (0x68, false) => Some(Key::F17),
        (0x69, false) => Some(Key::F18),
        (0x6A, false) => Some(Key::F19),
        (0x6B, false) => Some(Key::F20),
        (0x6C, false) => Some(Key::F21),
        (0x6D, false) => Some(Key::F22),
        (0x6E, false) => Some(Key::F23),
        (0x76, false) => Some(Key::F24),

        (0x2A, false) => Some(Key::ShiftLeft),
        (0x36, false) => Some(Key::ShiftRight),
        (0x1D, false) => Some(Key::ControlLeft),
        (0x1D, true) => Some(Key::ControlRight),
        (0x38, false) => Some(Key::AltLeft),
        (0x38, true) => Some(Key::AltRight),
        (0x5B, true) => Some(Key::MetaLeft),
        (0x5C, true) => Some(Key::MetaRight),

        (0x01, false) => Some(Key::Escape),
        (0x39, false) => Some(Key::Space),
        (0x1C, false) => Some(Key::Enter),
        (0x0F, false) => Some(Key::Tab),
        (0x0E, false) => Some(Key::Backspace),
        (0x3A, false) => Some(Key::CapsLock),
        (0x45, false) => Some(Key::NumLock),
        (0x46, false) => Some(Key::ScrollLock),

        (0x29, false) => Some(Key::Backquote),
        (0x0C, false) => Some(Key::Minus),
        (0x0D, false) => Some(Key::Equal),
        (0x1A, false) => Some(Key::BracketLeft),
        (0x1B, false) => Some(Key::BracketRight),
        (0x2B, false) => Some(Key::Backslash),
        (0x27, false) => Some(Key::Semicolon),
        (0x28, false) => Some(Key::Quote),
        (0x33, false) => Some(Key::Comma),
        (0x34, false) => Some(Key::Period),
        (0x35, false) => Some(Key::Slash),
        (0x56, false) => Some(Key::IsoBackslash),

        (0x52, true) => Some(Key::Insert),
        (0x53, true) => Some(Key::Delete),
        (0x47, true) => Some(Key::Home),
        (0x4F, true) => Some(Key::End),
        (0x49, true) => Some(Key::PageUp),
        (0x51, true) => Some(Key::PageDown),

        (0x48, true) => Some(Key::ArrowUp),
        (0x50, true) => Some(Key::ArrowDown),
        (0x4B, true) => Some(Key::ArrowLeft),
        (0x4D, true) => Some(Key::ArrowRight),

        (0x52, false) => Some(Key::Numpad0),
        (0x4F, false) => Some(Key::Numpad1),
        (0x50, false) => Some(Key::Numpad2),
        (0x51, false) => Some(Key::Numpad3),
        (0x4B, false) => Some(Key::Numpad4),
        (0x4C, false) => Some(Key::Numpad5),
        (0x4D, false) => Some(Key::Numpad6),
        (0x47, false) => Some(Key::Numpad7),
        (0x48, false) => Some(Key::Numpad8),
        (0x49, false) => Some(Key::Numpad9),
        (0x4E, false) => Some(Key::NumpadAdd),
        (0x4A, false) => Some(Key::NumpadSubtract),
        (0x37, false) => Some(Key::NumpadMultiply),
        (0x35, true) => Some(Key::NumpadDivide),
        (0x53, false) => Some(Key::NumpadDecimal),
        (0x1C, true) => Some(Key::NumpadEnter),
        (0x59, false) => Some(Key::NumpadEqual),
        (0x7E, false) => Some(Key::NumpadComma),

        (0x37, true) => Some(Key::PrintScreen),
        (0x46, true) => Some(Key::Pause),
        (0x5D, true) => Some(Key::ContextMenu),
        (0x5E, true) => Some(Key::Power),
        (0x5F, true) => Some(Key::Sleep),
        (0x63, true) => Some(Key::Wake),

        (0x20, true) => Some(Key::VolumeMute),
        (0x2E, true) => Some(Key::VolumeDown),
        (0x30, true) => Some(Key::VolumeUp),
        (0x22, true) => Some(Key::MediaPlayPause),
        (0x24, true) => Some(Key::MediaStop),
        (0x19, true) => Some(Key::MediaTrackNext),
        (0x10, true) => Some(Key::MediaTrackPrevious),

        (0x6A, true) => Some(Key::BrowserBack),
        (0x69, true) => Some(Key::BrowserForward),
        (0x67, true) => Some(Key::BrowserRefresh),
        (0x68, true) => Some(Key::BrowserStop),
        (0x65, true) => Some(Key::BrowserSearch),
        (0x66, true) => Some(Key::BrowserFavorites),
        (0x32, true) => Some(Key::BrowserHome),

        (0x6C, true) => Some(Key::LaunchMail),
        (0x6D, true) => Some(Key::LaunchMediaPlayer),
        (0x6B, true) => Some(Key::LaunchApp1),
        (0x21, true) => Some(Key::LaunchApp2),

        (0x7B, false) => Some(Key::NonConvert),
        (0x79, false) => Some(Key::Convert),
        (0x70, false) => Some(Key::KanaMode),
        (0x7D, false) => Some(Key::IntlYen),
        (0x73, false) => Some(Key::IntlRo),
        (0xF2, false) => Some(Key::Lang1),
        (0xF1, false) => Some(Key::Lang2),
        (0x78, false) => Some(Key::Lang3),
        (0x77, false) => Some(Key::Lang4),

        // (0x63, true) => Some(Key::Help),
        (0x08, true) => Some(Key::Undo),
        (0x07, true) => Some(Key::Redo),
        (0x04, true) => Some(Key::Cut),
        (0x18, true) => Some(Key::Copy),
        (0x0A, true) => Some(Key::Paste),
        // (0x65, true) => Some(Key::Find),
        _ => None,
    }
}