1#[cfg(windows)]
2mod windows;
3#[cfg(windows)]
4static SIM: windows::WindowsSimulate = windows::WindowsSimulate;
5
6mod buf;
7pub use buf::EventBuffer;
8
9#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
11#[repr(u8)]
12pub enum Action {
13 Press,
15 Release,
17}
18
19#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
21#[repr(u8)]
22pub enum ScrollDirection {
23 Horizontal,
24 Vertical,
25}
26
27#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
29pub enum Key {
30 MouseLeft,
32 MouseRight,
33 MouseMiddle,
34 MouseX(u8),
35
36 Backspace,
39 Tab,
40 Clear,
41 Enter,
43 Shift,
44 LeftShift,
45 RightShift,
46 Control,
47 LeftControl,
48 RightControl,
49 Menu,
50 LeftMenu,
51 RightMenu,
52 Home,
53 LeftWindows,
54 RightWindows,
55 Pause,
56 CapsLock,
58 Escape,
59 Space,
60 PageUp,
62 PageDown,
64 End,
65 Select,
66 Print,
67 Execute,
68 PrintScreen,
70 Insert,
71 Delete,
72 Help,
73 Apps,
74 Sleep,
75 BrowserBack,
76 BrowserForward,
77 BrowserRefresh,
78 BrowserStop,
79 BrowserSearch,
80 BrowserFavorites,
81 BrowserHome,
82 VolumeMute,
83 VolumeDown,
84 VolumeUp,
85 MediaNextTrack,
86 MediaPreviousTrack,
87 MediaStop,
88 MediaPlayPause,
89 LaunchMail,
90 SelectMedia,
91 LaunchApp1,
92 LaunchApp2,
93
94 Attn,
95 Crsel,
96 Exsel,
97 Ereof,
98 Play,
99 Zoom,
100 NoName,
101
102 Left,
103 Up,
104 Right,
105 Down,
106
107 Kana,
108 Hangul,
109 Junja,
110 Final,
111 Kanji,
112 Convert,
113 Nonconvert,
114 Accept,
115 ModeChange,
116 ProcessKey,
118 ImeOn,
119 ImeOff,
120
121 Oem1,
123 OemPlus,
125 OemComma,
127 OemMinus,
129 OemPeriod,
131 Oem2,
133 Oem3,
135 Oem4,
137 Oem5,
139 Oem6,
141 Oem7,
143 Oem8,
145 Oem102,
147 OemClear,
148
149 _0,
150 _1,
151 _2,
152 _3,
153 _4,
154 _5,
155 _6,
156 _7,
157 _8,
158 _9,
159
160 Numpad0,
161 Numpad1,
162 Numpad2,
163 Numpad3,
164 Numpad4,
165 Numpad5,
166 Numpad6,
167 Numpad7,
168 Numpad8,
169 Numpad9,
170 Multiply,
171 Add,
172 Subtract,
173 Decimal,
174 Divide,
175 Separator,
176 NumLock,
177 ScrollLock,
178
179 A,
180 B,
181 C,
182 D,
183 E,
184 F,
185 G,
186 H,
187 I,
188 J,
189 K,
190 L,
191 M,
192 N,
193 O,
194 P,
195 Q,
196 R,
197 S,
198 T,
199 U,
200 V,
201 W,
202 X,
203 Y,
204 Z,
205
206 F1,
207 F2,
208 F3,
209 F4,
210 F5,
211 F6,
212 F7,
213 F8,
214 F9,
215 F10,
216 F11,
217 F12,
218 F13,
219 F14,
220 F15,
221 F16,
222 F17,
223 F18,
224 F19,
225 F20,
226 F21,
227 F22,
228 F23,
229 F24,
230}
231
232impl Key {
233 #[inline(always)]
235 pub fn is_mouse_button(&self) -> bool {
236 matches!(self, Key::MouseLeft | Key::MouseMiddle | Key::MouseRight | Key::MouseX(_))
237 }
238}
239
240pub trait Keylike: Copy {
242 fn into_event(self, action: Action) -> Event;
244
245 #[inline(always)]
247 fn press(self) -> Event {
248 self.into_event(Action::Press)
249 }
250
251 #[inline(always)]
253 fn release(self) -> Event {
254 self.into_event(Action::Release)
255 }
256
257 #[inline]
259 fn press_release(self) -> std::iter::Chain<std::iter::Once<Event>, std::iter::Once<Event>> {
260 std::iter::once(self.press()).chain(std::iter::once(self.release()))
261 }
262}
263
264impl Keylike for Key {
265 #[inline(always)]
266 fn into_event(self, action: Action) -> Event {
267 Event::Key { key: self, action }
268 }
269}
270
271impl Keylike for char {
272 #[inline(always)]
273 fn into_event(self, action: Action) -> Event {
274 Event::Char {
275 character: self,
276 action,
277 }
278 }
279}
280
281#[derive(Clone, Debug)]
283pub enum Event {
284 Key {
285 key: Key,
286 action: Action,
287 },
288
289 Char {
290 character: char,
291 action: Action,
292 },
293
294 MoveMouseAbsolute {
295 x: f32,
296 y: f32,
297 map_to_virtual_desktop: bool,
301 },
302
303 MoveMouseRelative {
304 dx: i32,
305 dy: i32,
306 },
307
308 Scroll {
309 delta: f32,
313 direction: ScrollDirection,
314 },
315}
316
317#[derive(Clone, Debug)]
318pub enum Error {
319 UnsupportedKey(Key),
321
322 UnsupportedChar(char),
324
325 UnsupportedEvent(Event),
327
328 OsError {
330 code: u32,
332 message: String,
334 },
335}
336
337pub type Result<T> = std::result::Result<T, Error>;
339
340pub trait Simulate {
342 fn send_events(&self, events: impl IntoIterator<Item = Event>) -> Result<()>;
344}
345
346#[inline(always)]
348pub fn send_events(events: impl IntoIterator<Item = Event>) -> Result<()> {
349 SIM.send_events(events)
350}
351
352#[inline(always)]
354pub fn send_event(event: Event) -> Result<()> {
355 send_events(Some(event))
356}
357
358#[inline]
360pub fn send_multiple<K: Keylike>(keys: impl IntoIterator<Item = K>) -> Result<()> {
361 let iter = keys.into_iter().flat_map(Keylike::press_release);
362 send_events(iter)
363}
364
365#[inline(always)]
367pub fn send(key: impl Keylike) -> Result<()> {
368 send_events(key.press_release())
369}
370
371#[inline(always)]
373pub fn press(key: impl Keylike) -> Result<()> {
374 send_events(Some(key.press()))
375}
376
377#[inline(always)]
379pub fn release(key: Key) -> Result<()> {
380 send_events(Some(key.release()))
381}
382
383#[inline(always)]
385pub fn type_str(s: &str) -> Result<()> {
386 send_multiple(s.chars())
387}
388
389#[inline(always)]
392pub fn move_mouse_relative(dx: i32, dy: i32) -> Result<()> {
393 send_events(Some(Event::MoveMouseRelative { dx, dy }))
394}
395
396#[inline(always)]
399pub fn move_mouse_absolute(x: f32, y: f32) -> Result<()> {
400 send_events(Some(Event::MoveMouseAbsolute {
401 x,
402 y,
403 map_to_virtual_desktop: false,
404 }))
405}
406
407#[inline(always)]
409pub fn send_scroll_event(delta: f32, direction: ScrollDirection) -> Result<()> {
410 send_events(Some(Event::Scroll { delta, direction }))
411}
412
413#[inline(always)]
415pub fn scroll(delta: f32) -> Result<()> {
416 send_scroll_event(delta, ScrollDirection::Vertical)
417}
418
419#[inline(always)]
421pub fn scroll_horizontal(delta: f32) -> Result<()> {
422 send_scroll_event(delta, ScrollDirection::Horizontal)
423}