#[cfg(windows)]
mod windows;
#[cfg(windows)]
static SIM: windows::WindowsSimulate = windows::WindowsSimulate;
mod buf;
pub use buf::EventBuffer;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[repr(u8)]
pub enum Action {
Press,
Release,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[repr(u8)]
pub enum ScrollDirection {
Horizontal,
Vertical,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum Key {
MouseLeft,
MouseRight,
MouseMiddle,
MouseX(u8),
Backspace,
Tab,
Clear,
Enter,
Shift,
LeftShift,
RightShift,
Control,
LeftControl,
RightControl,
Menu,
LeftMenu,
RightMenu,
Home,
LeftWindows,
RightWindows,
Pause,
CapsLock,
Escape,
Space,
PageUp,
PageDown,
End,
Select,
Print,
Execute,
PrintScreen,
Insert,
Delete,
Help,
Apps,
Sleep,
BrowserBack,
BrowserForward,
BrowserRefresh,
BrowserStop,
BrowserSearch,
BrowserFavorites,
BrowserHome,
VolumeMute,
VolumeDown,
VolumeUp,
MediaNextTrack,
MediaPreviousTrack,
MediaStop,
MediaPlayPause,
LaunchMail,
SelectMedia,
LaunchApp1,
LaunchApp2,
Attn,
Crsel,
Exsel,
Ereof,
Play,
Zoom,
NoName,
Left,
Up,
Right,
Down,
Kana,
Hangul,
Junja,
Final,
Kanji,
Convert,
Nonconvert,
Accept,
ModeChange,
ProcessKey,
ImeOn,
ImeOff,
Oem1,
OemPlus,
OemComma,
OemMinus,
OemPeriod,
Oem2,
Oem3,
Oem4,
Oem5,
Oem6,
Oem7,
Oem8,
Oem102,
OemClear,
_0,
_1,
_2,
_3,
_4,
_5,
_6,
_7,
_8,
_9,
Numpad0,
Numpad1,
Numpad2,
Numpad3,
Numpad4,
Numpad5,
Numpad6,
Numpad7,
Numpad8,
Numpad9,
Multiply,
Add,
Subtract,
Decimal,
Divide,
Separator,
NumLock,
ScrollLock,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
}
impl Key {
#[inline(always)]
pub fn is_mouse_button(&self) -> bool {
matches!(self, Key::MouseLeft | Key::MouseMiddle | Key::MouseRight | Key::MouseX(_))
}
}
pub trait Keylike: Copy {
fn into_event(self, action: Action) -> Event;
#[inline(always)]
fn press(self) -> Event {
self.into_event(Action::Press)
}
#[inline(always)]
fn release(self) -> Event {
self.into_event(Action::Release)
}
#[inline]
fn press_release(self) -> std::iter::Chain<std::iter::Once<Event>, std::iter::Once<Event>> {
std::iter::once(self.press()).chain(std::iter::once(self.release()))
}
}
impl Keylike for Key {
#[inline(always)]
fn into_event(self, action: Action) -> Event {
Event::Key { key: self, action }
}
}
impl Keylike for char {
#[inline(always)]
fn into_event(self, action: Action) -> Event {
Event::Char {
character: self,
action,
}
}
}
#[derive(Clone, Debug)]
pub enum Event {
Key {
key: Key,
action: Action,
},
Char {
character: char,
action: Action,
},
MoveMouseAbsolute {
x: f32,
y: f32,
map_to_virtual_desktop: bool,
},
MoveMouseRelative {
dx: i32,
dy: i32,
},
Scroll {
delta: f32,
direction: ScrollDirection,
},
}
#[derive(Clone, Debug)]
pub enum Error {
UnsupportedKey(Key),
UnsupportedChar(char),
UnsupportedEvent(Event),
OsError {
code: u32,
message: String,
},
}
pub type Result<T> = std::result::Result<T, Error>;
pub trait Simulate {
fn send_events(&self, events: impl IntoIterator<Item = Event>) -> Result<()>;
}
#[inline(always)]
pub fn send_events(events: impl IntoIterator<Item = Event>) -> Result<()> {
SIM.send_events(events)
}
#[inline(always)]
pub fn send_event(event: Event) -> Result<()> {
send_events(Some(event))
}
#[inline]
pub fn send_multiple<K: Keylike>(keys: impl IntoIterator<Item = K>) -> Result<()> {
let iter = keys.into_iter().flat_map(Keylike::press_release);
send_events(iter)
}
#[inline(always)]
pub fn send(key: impl Keylike) -> Result<()> {
send_events(key.press_release())
}
#[inline(always)]
pub fn press(key: impl Keylike) -> Result<()> {
send_events(Some(key.press()))
}
#[inline(always)]
pub fn release(key: Key) -> Result<()> {
send_events(Some(key.release()))
}
#[inline(always)]
pub fn type_str(s: &str) -> Result<()> {
send_multiple(s.chars())
}
#[inline(always)]
pub fn move_mouse_relative(dx: i32, dy: i32) -> Result<()> {
send_events(Some(Event::MoveMouseRelative { dx, dy }))
}
#[inline(always)]
pub fn move_mouse_absolute(x: f32, y: f32) -> Result<()> {
send_events(Some(Event::MoveMouseAbsolute {
x,
y,
map_to_virtual_desktop: false,
}))
}
#[inline(always)]
pub fn send_scroll_event(delta: f32, direction: ScrollDirection) -> Result<()> {
send_events(Some(Event::Scroll { delta, direction }))
}
#[inline(always)]
pub fn scroll(delta: f32) -> Result<()> {
send_scroll_event(delta, ScrollDirection::Vertical)
}
#[inline(always)]
pub fn scroll_horizontal(delta: f32) -> Result<()> {
send_scroll_event(delta, ScrollDirection::Horizontal)
}