enigo_copy/lib.rs
1//! Enigo lets you simulate mouse and keyboard input-events as if they were
2//! made by the actual hardware. It is available on Linux (X11), macOS and
3//! Windows.
4//!
5//! It can be used for testing user interfaces on different platforms, building
6//! remote control applications or just automating tasks for user interfaces
7//! unaccessible by a public API or scripting language.
8//!
9//! This library is in an early alpha status, the API will change in
10//! in the future.
11//!
12//! In order to use the library, you only have to know about three
13//! things:
14//! - [`KeyboardControllable`] (trait): used to simulate a key click, enter text
15//! or something similar
16//! - [`MouseControllable`] (trait): do something with the mouse or you find out
17//! the display
18//! size
19//! - [`Enigo`] (struct): implements the two traits [`KeyboardControllable`] and
20//! [`MouseControllable`]
21//!
22//! A simple [DSL](https://en.wikipedia.org/wiki/Domain-specific_language)
23//! is available. It is documented in the [`dsl`] module.
24
25//! # Examples
26//! ```no_run
27//! use enigo::*;
28//! let mut enigo = Enigo::new();
29//! //paste
30//! enigo.key_down(Key::Control);
31//! enigo.key_click(Key::Layout('v'));
32//! enigo.key_up(Key::Control);
33//! ```
34//!
35//! ```no_run
36//! use enigo::*;
37//! let mut enigo = Enigo::new();
38//! enigo.mouse_move_to(500, 200);
39//! enigo.mouse_down(MouseButton::Left);
40//! enigo.mouse_move_relative(100, 100);
41//! enigo.mouse_up(MouseButton::Left);
42//! enigo.key_sequence("hello world");
43//! ```
44
45#![deny(clippy::pedantic)]
46#![allow(clippy::cast_lossless)]
47#![allow(clippy::cast_possible_truncation)]
48#![allow(clippy::cast_possible_wrap)]
49#![allow(clippy::cast_sign_loss)]
50#![allow(deprecated)]
51
52#[cfg(target_os = "macos")]
53#[macro_use]
54extern crate objc;
55
56// TODO(dustin) use interior mutability not &mut self
57
58#[cfg(target_os = "windows")]
59mod win;
60#[cfg(target_os = "windows")]
61pub use crate::win::Enigo;
62
63#[cfg(target_os = "macos")]
64mod macos;
65#[cfg(target_os = "macos")]
66pub use crate::macos::Enigo;
67
68#[cfg(target_os = "linux")]
69mod linux;
70#[cfg(target_os = "linux")]
71pub use crate::linux::Enigo;
72
73/// DSL parser module
74///
75/// The current status is that you can just print [unicode](http://unicode.org/) characters like [emoji](http://getemoji.com/) without the `{+SHIFT}`
76/// [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) or any other "special" key on the Linux, macOS and Windows operating system.
77pub mod dsl;
78
79#[cfg(feature = "with_serde")]
80#[macro_use]
81extern crate serde_derive;
82
83#[cfg(feature = "with_serde")]
84extern crate serde;
85
86#[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))]
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88/// [`MouseButton`] represents a mouse button and is used in e.g
89/// [`MouseControllable::mouse_click`].
90
91// Warning! If there are ANY CHANGES to this enum, we
92// need to change the size of the array in the macOS implementation of the Enigo
93// struct that stores the nth click for each MouseButton
94pub enum MouseButton {
95 /// Left mouse button
96 Left,
97 /// Middle mouse button
98 Middle,
99 /// Right mouse button
100 Right,
101
102 /// Scroll up button. It is better to use the
103 /// [MouseControllable::mouse_scroll_y] method to scroll.
104 ScrollUp,
105 /// Scroll down button. It is better to use the
106 /// [MouseControllable::mouse_scroll_y] method to scroll.
107 ScrollDown,
108 /// Scroll left button. It is better to use the
109 /// [MouseControllable::mouse_scroll_x] method to scroll.
110 ScrollLeft,
111 /// Scroll right button. It is better to use the
112 /// [MouseControllable::mouse_scroll_x] method to scroll.
113 ScrollRight,
114}
115
116/// Contains functions to control the mouse and to get the size of the display.
117/// Enigo uses a Cartesian coordinate system for specifying coordinates. The
118/// origin in this system is located in the top-left corner of the current
119/// screen, with positive values extending along the axes down and to the
120/// right of the origin point and it is measured in pixels. The same coordinate
121/// system is used on all operating systems.
122pub trait MouseControllable {
123 /// Move the mouse cursor to the specified x and y coordinates.
124 ///
125 /// The topleft corner of your monitor screen is x=0 y=0. Move
126 /// the cursor down the screen by increasing the y and to the right
127 /// by increasing x coordinate.
128 ///
129 /// # Example
130 ///
131 /// ```no_run
132 /// use enigo::*;
133 /// let mut enigo = Enigo::new();
134 /// enigo.mouse_move_to(500, 200);
135 /// ```
136 fn mouse_move_to(&mut self, x: i32, y: i32);
137
138 /// Move the mouse cursor the specified amount in the x and y
139 /// direction. A positive x value moves the mouse cursor `x` pixels to the
140 /// right. A negative value for `x` moves the mouse cursor to the left.
141 /// A positive value of y moves the mouse cursor down, a negative one
142 /// moves the mouse cursor up.
143 ///
144 /// # Example
145 ///
146 /// ```no_run
147 /// use enigo::*;
148 /// let mut enigo = Enigo::new();
149 /// enigo.mouse_move_relative(100, 100);
150 /// ```
151 fn mouse_move_relative(&mut self, x: i32, y: i32);
152
153 /// Push down the mouse button specified by the parameter
154 /// `button` of type [`MouseButton`] and hold it until it is released by
155 /// [`MouseControllable::mouse_up`].
156 /// Calls to [`MouseControllable::mouse_move_to`] or
157 /// [`MouseControllable::mouse_move_relative`] will
158 /// work like expected and will e.g. drag widgets or highlight text.
159 ///
160 /// # Example
161 ///
162 /// ```no_run
163 /// use enigo::*;
164 /// let mut enigo = Enigo::new();
165 /// enigo.mouse_down(MouseButton::Left);
166 /// ```
167 fn mouse_down(&mut self, button: MouseButton);
168
169 /// Release a pushed down mouse button
170 ///
171 /// Lift up a previously pushed down button (by invoking
172 /// [`MouseControllable::mouse_down`]).
173 /// If the button was not pushed down or consecutive calls without
174 /// invoking [`MouseControllable::mouse_down`] will emit lift up
175 /// events. It depends on the operating system whats actually happening
176 /// – my guess is it will just get ignored.
177 ///
178 /// # Example
179 ///
180 /// ```no_run
181 /// use enigo::*;
182 /// let mut enigo = Enigo::new();
183 /// enigo.mouse_down(MouseButton::Right);
184 /// enigo.mouse_up(MouseButton::Right);
185 /// ```
186 fn mouse_up(&mut self, button: MouseButton);
187
188 /// Click a mouse button
189 ///
190 /// It is essentially just a consecutive invocation of
191 /// [`MouseControllable::mouse_down`]
192 /// followed by a [`MouseControllable::mouse_up`]. Just for
193 /// convenience.
194 ///
195 /// # Example
196 ///
197 /// ```no_run
198 /// use enigo::*;
199 /// let mut enigo = Enigo::new();
200 /// enigo.mouse_click(MouseButton::Right);
201 /// ```
202 fn mouse_click(&mut self, button: MouseButton);
203
204 /// Scroll the mouse (wheel) left or right
205 ///
206 /// Positive numbers for `length` scroll to the right and negative ones to
207 /// the left. The value that is specified translates to `lines` defined
208 /// by the operating system and is essentially one 15° (click) rotation
209 /// on the mouse wheel. How many lines it moves depends on the current
210 /// setting in the operating system.
211 ///
212 /// # Example
213 ///
214 /// ```no_run
215 /// use enigo::*;
216 /// let mut enigo = Enigo::new();
217 /// enigo.mouse_scroll_x(2);
218 /// ```
219 fn mouse_scroll_x(&mut self, length: i32);
220
221 /// Scroll the mouse (wheel) up or down
222 ///
223 /// Positive numbers for `length` scroll down and negative ones up. The
224 /// value that is specified translates to `lines` defined by the
225 /// operating system and is essentially one 15° (click) rotation on the
226 /// mouse wheel. How many lines it moves depends on the current setting
227 /// in the operating system.
228 ///
229 /// # Example
230 ///
231 /// ```no_run
232 /// use enigo::*;
233 /// let mut enigo = Enigo::new();
234 /// enigo.mouse_scroll_y(2);
235 /// ```
236 fn mouse_scroll_y(&mut self, length: i32);
237
238 /// Get the (width, height) of the main display in screen coordinates
239 /// (pixels). This currently only works on the main display
240 ///
241 /// # Example
242 ///
243 /// ```no_run
244 /// use enigo::*;
245 /// let mut enigo = Enigo::new();
246 /// let (width, height) = enigo.main_display_size();
247 /// ```
248 #[must_use]
249 fn main_display_size(&self) -> (i32, i32);
250
251 /// Get the location of the mouse in screen coordinates (pixels).
252 ///
253 /// # Example
254 ///
255 /// ```no_run
256 /// use enigo::*;
257 /// let mut enigo = Enigo::new();
258 /// let (x, y) = enigo.mouse_location();
259 /// ```
260 #[must_use]
261 fn mouse_location(&self) -> (i32, i32);
262}
263
264/// A key on the keyboard.
265/// For alphabetical keys, use [`Key::Layout`] for a system independent key.
266/// If a key is missing, you can use the raw keycode with [`Key::Raw`].
267#[cfg_attr(feature = "with_serde", derive(Serialize, Deserialize))]
268#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
269pub enum Key {
270 /// alt key on Linux and Windows (option key on macOS)
271 Alt,
272 /// backspace key
273 Backspace,
274 /// caps lock key
275 CapsLock,
276 #[deprecated(since = "0.0.12", note = "now renamed to Meta")]
277 /// command key on macOS (super key on Linux, windows key on Windows)
278 Command,
279 /// control key
280 Control,
281 /// delete key
282 Delete,
283 /// down arrow key
284 DownArrow,
285 /// end key
286 End,
287 /// escape key (esc)
288 Escape,
289 /// F1 key
290 F1,
291 /// F2 key
292 F2,
293 /// F3 key
294 F3,
295 /// F4 key
296 F4,
297 /// F5 key
298 F5,
299 /// F6 key
300 F6,
301 /// F7 key
302 F7,
303 /// F8 key
304 F8,
305 /// F9 key
306 F9,
307 /// F10 key
308 F10,
309 /// F11 key
310 F11,
311 /// F12 key
312 F12,
313 /// F13 key
314 F13,
315 /// F14 key
316 F14,
317 /// F15 key
318 F15,
319 /// F16 key
320 F16,
321 /// F17 key
322 F17,
323 /// F18 key
324 F18,
325 /// F19 key
326 F19,
327 /// F20 key
328 F20,
329 /// home key
330 Home,
331 /// left arrow key
332 LeftArrow,
333 /// meta key (also known as "windows", "super", and "command")
334 Meta,
335 /// option key on macOS (alt key on Linux and Windows)
336 Option,
337 /// page down key
338 PageDown,
339 /// page up key
340 PageUp,
341 /// return key
342 Return,
343 /// right arrow key
344 RightArrow,
345 /// shift key
346 Shift,
347 /// space key
348 Space,
349 #[deprecated(since = "0.0.12", note = "now renamed to Meta")]
350 /// super key on linux (command key on macOS, windows key on Windows)
351 Super,
352 /// tab key (tabulator)
353 Tab,
354 /// up arrow key
355 UpArrow,
356 #[deprecated(since = "0.0.12", note = "now renamed to Meta")]
357 /// windows key on Windows (super key on Linux, command key on macOS)
358 Windows,
359 /// keyboard layout dependent key
360 Layout(char),
361 /// raw keycode eg 0x38
362 Raw(u16),
363}
364
365/// Contains functions to simulate key presses and to input text.
366///
367/// For the keyboard there are currently two modes you can use. The first mode
368/// is represented by the [`key_sequence`](KeyboardControllable::key_sequence)
369/// function. It's purpose is to simply write unicode characters. This is
370/// independent of the keyboard layout. Please note that
371/// you're not be able to use modifier keys like Control
372/// to influence the outcome. If you want to use modifier keys to e.g.
373/// copy/paste, use the Layout variant. Please note that this is indeed layout
374/// dependent.
375pub trait KeyboardControllable {
376 /// Type the string parsed with DSL.
377 ///
378 /// Typing {+SHIFT}hello{-SHIFT} becomes HELLO.
379 /// Please have a look at the [dsl] module for more information.
380 fn key_sequence_parse(&mut self, sequence: &str)
381 where
382 Self: Sized,
383 {
384 self.key_sequence_parse_try(sequence)
385 .expect("Could not parse sequence");
386 }
387
388 /// Same as [`KeyboardControllable::key_sequence_parse`] except returns any
389 /// errors
390 /// # Errors
391 ///
392 /// Returns a [`dsl::ParseError`] if the sequence cannot be parsed
393 fn key_sequence_parse_try(&mut self, sequence: &str) -> Result<(), dsl::ParseError>
394 where
395 Self: Sized,
396 {
397 dsl::eval(self, sequence)
398 }
399
400 /// Enter the text. You can use unicode here like: ❤️. This works
401 /// regardless of the current keyboardlayout. You cannot use this function
402 /// for entering shortcuts or something similar. For shortcuts, use the
403 /// [`KeyboardControllable::key_click`] method instead.
404 ///
405 /// # Example
406 ///
407 /// ```no_run
408 /// use enigo::*;
409 /// let mut enigo = Enigo::new();
410 /// enigo.key_sequence("hello world ❤️");
411 /// ```
412 fn key_sequence(&mut self, sequence: &str);
413
414 /// Press down the given key
415 fn key_down(&mut self, key: Key);
416
417 /// Release a pressed down key
418 fn key_up(&mut self, key: Key);
419
420 /// Press and release the key. It is the same as calling the
421 /// [`KeyboardControllable::key_down`] and
422 /// [`KeyboardControllable::key_up`] functions consecutively
423 fn key_click(&mut self, key: Key);
424}
425
426impl Enigo {
427 /// Constructs a new `Enigo` instance.
428 ///
429 /// # Example
430 ///
431 /// ```no_run
432 /// use enigo::*;
433 /// let mut enigo = Enigo::new();
434 /// ```
435 #[must_use]
436 pub fn new() -> Self {
437 Self::default()
438 }
439}
440
441use std::fmt;
442
443impl fmt::Debug for Enigo {
444 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
445 write!(f, "Enigo")
446 }
447}