rdev/
rdev.rs

1#[cfg(feature = "serialize")]
2use serde::{Deserialize, Serialize};
3use std::time::SystemTime;
4use std::{fmt, fmt::Display};
5
6// /// Callback type to send to listen function.
7// pub type Callback = dyn FnMut(Event) -> ();
8
9/// Callback type to send to grab function.
10pub type GrabCallback = fn(event: Event) -> Option<Event>;
11
12/// Errors that occur when trying to capture OS events.
13/// Be careful on Mac, not setting accessibility does not cause an error
14/// it justs ignores events.
15#[derive(Debug)]
16#[non_exhaustive]
17pub enum ListenError {
18    /// MacOS
19    EventTapError,
20    /// MacOS
21    LoopSourceError,
22    /// Linux
23    MissingDisplayError,
24    /// Linux
25    KeyboardError,
26    /// Linux
27    RecordContextEnablingError,
28    /// Linux
29    RecordContextError,
30    /// Linux
31    XRecordExtensionError,
32    /// Windows
33    KeyHookError(u32),
34    /// Windows
35    MouseHookError(u32),
36}
37
38/// Errors that occur when trying to grab OS events.
39/// Be careful on Mac, not setting accessibility does not cause an error
40/// it justs ignores events.
41#[derive(Debug)]
42#[non_exhaustive]
43pub enum GrabError {
44    /// MacOS
45    EventTapError,
46    /// MacOS
47    LoopSourceError,
48    /// Linux
49    MissingDisplayError,
50    /// Linux
51    KeyboardError,
52    /// Windows
53    KeyHookError(u32),
54    /// Windows
55    MouseHookError(u32),
56    /// All
57    SimulateError,
58    IoError(std::io::Error),
59}
60/// Errors that occur when trying to get display size.
61#[non_exhaustive]
62#[derive(Debug)]
63pub enum DisplayError {
64    NoDisplay,
65    ConversionError,
66}
67
68impl From<SimulateError> for GrabError {
69    fn from(_: SimulateError) -> GrabError {
70        GrabError::SimulateError
71    }
72}
73
74impl From<std::io::Error> for GrabError {
75    fn from(err: std::io::Error) -> GrabError {
76        GrabError::IoError(err)
77    }
78}
79
80/// Marking an error when we tried to simulate and event
81#[derive(Debug)]
82pub struct SimulateError;
83
84impl Display for SimulateError {
85    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86        write!(f, "Could not simulate event")
87    }
88}
89
90impl std::error::Error for SimulateError {}
91
92/// Key names based on physical location on the device
93/// Merge Option(MacOS) and Alt(Windows, Linux) into Alt
94/// Merge Windows (Windows), Meta(Linux), Command(MacOS) into Meta
95/// Characters based on Qwerty layout, don't use this for characters as it WILL
96/// depend on the layout. Use Event.name instead. Key modifiers gives those keys
97/// a different value too.
98/// Careful, on Windows KpReturn does not exist, it' s strictly equivalent to Return, also Keypad keys
99/// get modified if NumLock is Off and ARE pagedown and so on.
100#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
101#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
102pub enum Key {
103    /// Alt key on Linux and Windows (option key on macOS)
104    Alt,
105    AltGr,
106    Backspace,
107    CapsLock,
108    ControlLeft,
109    ControlRight,
110    Delete,
111    DownArrow,
112    End,
113    Escape,
114    F1,
115    F10,
116    F11,
117    F12,
118    F2,
119    F3,
120    F4,
121    F5,
122    F6,
123    F7,
124    F8,
125    F9,
126    Home,
127    LeftArrow,
128    /// also known as "windows", "super", and "command"
129    MetaLeft,
130    /// also known as "windows", "super", and "command"
131    MetaRight,
132    PageDown,
133    PageUp,
134    Return,
135    RightArrow,
136    ShiftLeft,
137    ShiftRight,
138    Space,
139    Tab,
140    UpArrow,
141    PrintScreen,
142    ScrollLock,
143    Pause,
144    NumLock,
145    BackQuote,
146    Num1,
147    Num2,
148    Num3,
149    Num4,
150    Num5,
151    Num6,
152    Num7,
153    Num8,
154    Num9,
155    Num0,
156    Minus,
157    Equal,
158    KeyQ,
159    KeyW,
160    KeyE,
161    KeyR,
162    KeyT,
163    KeyY,
164    KeyU,
165    KeyI,
166    KeyO,
167    KeyP,
168    LeftBracket,
169    RightBracket,
170    KeyA,
171    KeyS,
172    KeyD,
173    KeyF,
174    KeyG,
175    KeyH,
176    KeyJ,
177    KeyK,
178    KeyL,
179    SemiColon,
180    Quote,
181    BackSlash,
182    IntlBackslash,
183    KeyZ,
184    KeyX,
185    KeyC,
186    KeyV,
187    KeyB,
188    KeyN,
189    KeyM,
190    Comma,
191    Dot,
192    Slash,
193    Insert,
194    KpReturn,
195    KpMinus,
196    KpPlus,
197    KpMultiply,
198    KpDivide,
199    Kp0,
200    Kp1,
201    Kp2,
202    Kp3,
203    Kp4,
204    Kp5,
205    Kp6,
206    Kp7,
207    Kp8,
208    Kp9,
209    KpDelete,
210    Function,
211    Unknown(u32),
212}
213
214/// Standard mouse buttons
215/// Some mice have more than 3 buttons. These are not defined, and different
216/// OSs will give different `Button::Unknown` values.
217#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
218#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
219pub enum Button {
220    Left,
221    Right,
222    Middle,
223    Unknown(u8),
224}
225
226/// In order to manage different OSs, the current EventType choices are a mix and
227/// match to account for all possible events.
228#[derive(Debug, Copy, Clone, PartialEq)]
229#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
230pub enum EventType {
231    /// The keys correspond to a standard qwerty layout, they don't correspond
232    /// To the actual letter a user would use, that requires some layout logic to be added.
233    KeyPress(Key),
234    KeyRelease(Key),
235    /// Mouse Button
236    ButtonPress(Button),
237    ButtonRelease(Button),
238    /// Values in pixels. `EventType::MouseMove{x: 0, y: 0}` corresponds to the
239    /// top left corner, with x increasing downward and y increasing rightward
240    MouseMove {
241        x: f64,
242        y: f64,
243    },
244    /// `delta_y` represents vertical scroll and `delta_x` represents horizontal scroll.
245    /// Positive values correspond to scrolling up or right and negative values
246    /// correspond to scrolling down or left
247    Wheel {
248        delta_x: i64,
249        delta_y: i64,
250    },
251}
252
253/// When events arrive from the OS they get some additional information added from
254/// EventType, which is the time when this event was received, and the name Option
255/// which contains what characters should be emmitted from that event. This relies
256/// on the OS layout and keyboard state machinery.
257/// Caveat: Dead keys don't function on Linux(X11) yet. You will receive None for
258/// a dead key, and the raw letter instead of accentuated letter.
259#[derive(Debug, Clone, PartialEq)]
260#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
261pub struct Event {
262    pub time: SystemTime,
263    pub name: Option<String>,
264    pub event_type: EventType,
265}
266
267/// We can define a dummy Keyboard, that we will use to detect
268/// what kind of EventType trigger some String. We get the currently used
269/// layout for now !
270/// Caveat : This is layout dependent. If your app needs to support
271/// layout switching don't use this !
272/// Caveat: On Linux, the dead keys mechanism is not implemented.
273/// Caveat: Only shift and dead keys are implemented, Alt+unicode code on windows
274/// won't work.
275///
276/// ```no_run
277/// use rdev::{Keyboard, EventType, Key, KeyboardState};
278///
279/// let mut keyboard = Keyboard::new().unwrap();
280/// let string = keyboard.add(&EventType::KeyPress(Key::KeyS));
281/// // string == Some("s")
282/// ```
283pub trait KeyboardState {
284    /// Changes the keyboard state as if this event happened. we don't
285    /// really hit the OS here, which might come handy to test what should happen
286    /// if we were to hit said key.
287    fn add(&mut self, event_type: &EventType) -> Option<String>;
288
289    /// Resets the keyboard state as if we never touched it (no shift, caps_lock and so on)
290    fn reset(&mut self);
291}