autogui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +20 -0
- data/LICENSE +29 -0
- data/README.md +431 -0
- data/bin/autogui +19 -0
- data/docs/api.md +186 -0
- data/docs/guide.md +243 -0
- data/docs/publishing.md +90 -0
- data/examples/hello.rb +20 -0
- data/examples/locate_demo.rb +16 -0
- data/lib/autogui/exceptions.rb +9 -0
- data/lib/autogui/geometry.rb +98 -0
- data/lib/autogui/image.rb +344 -0
- data/lib/autogui/keys.rb +50 -0
- data/lib/autogui/message_box.rb +125 -0
- data/lib/autogui/platform/darwin.rb +185 -0
- data/lib/autogui/platform/linux.rb +172 -0
- data/lib/autogui/platform/windows.rb +400 -0
- data/lib/autogui/platform.rb +41 -0
- data/lib/autogui/run.rb +168 -0
- data/lib/autogui/screenshot.rb +95 -0
- data/lib/autogui/tween.rb +254 -0
- data/lib/autogui/version.rb +5 -0
- data/lib/autogui/window.rb +170 -0
- data/lib/autogui.rb +738 -0
- metadata +90 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d3511abdbcca45728263b40b8e8a42fe1ab6918e6f06c954b6a34556451d3732
|
|
4
|
+
data.tar.gz: a2342704323c625b631235faaf9125ffd408bbb343c71b278374c960574ced32
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0fce037dcb816025469d84cd34602d2c8d7d03d61bb2b8211583e6204844c5043427fe91b6368fb7b8e7ba3a17a3bd8cf0d7ccaf600139a51fef0c21f3778671
|
|
7
|
+
data.tar.gz: 153b87b1e059f94f4a2309acad12becef177f4e1ac8c5458d60325bfc75d6736301a112aa54f64c268be65b03961157033679b3dfd896072203e93dcca208145
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] — 2026-09-03
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- First public release: Ruby port of Python PyAutoGUI.
|
|
13
|
+
- Mouse: move, drag, click, scroll, button down/up, tweens.
|
|
14
|
+
- Keyboard: write, press, hotkey, hold, key down/up, Unicode on Windows.
|
|
15
|
+
- Screenshots and locate (PNG/BMP, grayscale, confidence, region).
|
|
16
|
+
- Message boxes: alert, confirm, prompt, password.
|
|
17
|
+
- Window helpers on Windows (list, activate, move, resize, min/max/close).
|
|
18
|
+
- Fail-safe corners, `PAUSE`, screenshot logging, `run` mini-language.
|
|
19
|
+
- CLI: `autogui info|mouse|screenshot`.
|
|
20
|
+
- Windows (Win32/`Fiddle`), macOS (`osascript`/`screencapture`), Linux (`xdotool` + screenshot tools).
|
data/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Al Sweigart
|
|
4
|
+
Copyright (c) 2026 AutoGUI contributors
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
# AutoGUI
|
|
2
|
+
|
|
3
|
+
[](https://rubygems.org/gems/autogui)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
Ruby library for desktop GUI automation: mouse, keyboard, screenshots, image search, message boxes, and window control.
|
|
7
|
+
|
|
8
|
+
It is a Ruby port of Python [PyAutoGUI](https://pyautogui.readthedocs.io/). Call `AutoGUI` after `require "autogui"`. Snake_case is the Ruby API (`move_to`, `left_click`). CamelCase aliases match Python (`moveTo`, `leftClick`).
|
|
9
|
+
|
|
10
|
+
**No runtime gem dependencies.** Ruby 2.7+ and the standard library are enough.
|
|
11
|
+
|
|
12
|
+
> **Fail-safe:** moving the mouse into a corner of the primary screen raises `AutoGUI::FailSafeException` and stops the script. Leave `AutoGUI.FAILSAFE = true` unless you have a very good reason not to.
|
|
13
|
+
|
|
14
|
+
## Table of contents
|
|
15
|
+
|
|
16
|
+
- [Install](#install)
|
|
17
|
+
- [Quick start](#quick-start)
|
|
18
|
+
- [Safety](#safety)
|
|
19
|
+
- [Coordinates](#coordinates)
|
|
20
|
+
- [Mouse](#mouse)
|
|
21
|
+
- [Keyboard](#keyboard)
|
|
22
|
+
- [Screenshots and image search](#screenshots-and-image-search)
|
|
23
|
+
- [Message boxes](#message-boxes)
|
|
24
|
+
- [Windows](#windows)
|
|
25
|
+
- [Settings](#settings)
|
|
26
|
+
- [Tweens](#tweens)
|
|
27
|
+
- [Mini-language](#mini-language)
|
|
28
|
+
- [CLI](#cli)
|
|
29
|
+
- [Platforms](#platforms)
|
|
30
|
+
- [Exceptions](#exceptions)
|
|
31
|
+
- [API reference](#api-reference)
|
|
32
|
+
- [Development](#development)
|
|
33
|
+
- [License](#license)
|
|
34
|
+
|
|
35
|
+
Full method tables live in [docs/api.md](docs/api.md). A longer walkthrough is in [docs/guide.md](docs/guide.md).
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
### RubyGems
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
gem install autogui
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
require "autogui"
|
|
47
|
+
|
|
48
|
+
p AutoGUI.size
|
|
49
|
+
# => Size(width=1920, height=1080)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Bundler
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
# Gemfile
|
|
56
|
+
source "https://rubygems.org"
|
|
57
|
+
gem "autogui"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
bundle install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### From GitHub (before / besides RubyGems)
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
# Gemfile
|
|
68
|
+
gem "autogui", git: "https://github.com/pardeep2690/autogui.git"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Or build a `.gem` from the repo:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
git clone https://github.com/pardeep2690/autogui.git
|
|
75
|
+
cd autogui
|
|
76
|
+
gem build autogui.gemspec
|
|
77
|
+
gem install autogui-1.0.0.gem
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Platform extras
|
|
81
|
+
|
|
82
|
+
| OS | Mouse / keyboard | Screenshots | Notes |
|
|
83
|
+
| --- | --- | --- | --- |
|
|
84
|
+
| **Windows** | Win32 via stdlib `Fiddle` | GDI | Works out of the box |
|
|
85
|
+
| **macOS** | `osascript` | `screencapture` | Grant Accessibility to Terminal / Ruby |
|
|
86
|
+
| **Linux** | `xdotool` | `scrot`, ImageMagick `import`, or `grim` | Install those tools |
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
# Debian / Ubuntu
|
|
90
|
+
sudo apt-get install xdotool scrot
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Quick start
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
require "autogui"
|
|
97
|
+
|
|
98
|
+
AutoGUI.PAUSE = 0.25
|
|
99
|
+
AutoGUI.FAILSAFE = true
|
|
100
|
+
|
|
101
|
+
width, height = AutoGUI.size
|
|
102
|
+
x, y = AutoGUI.position
|
|
103
|
+
|
|
104
|
+
AutoGUI.move_to(width / 2, height / 2, duration: 0.4)
|
|
105
|
+
AutoGUI.click
|
|
106
|
+
AutoGUI.write("Hello from AutoGUI", interval: 0.02)
|
|
107
|
+
AutoGUI.press("enter")
|
|
108
|
+
AutoGUI.hotkey("ctrl", "s")
|
|
109
|
+
|
|
110
|
+
img = AutoGUI.screenshot("desktop.png")
|
|
111
|
+
box = AutoGUI.locate_on_screen("button.png")
|
|
112
|
+
AutoGUI.click(box) if box
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Give yourself a moment before the script takes over:
|
|
116
|
+
|
|
117
|
+
```ruby
|
|
118
|
+
AutoGUI.countdown(3) # prints 3 2 1
|
|
119
|
+
AutoGUI.click(100, 200)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Safety
|
|
123
|
+
|
|
124
|
+
Every public action (move, click, type, …) does two things:
|
|
125
|
+
|
|
126
|
+
1. **Fail-safe check** — if the cursor is on a corner listed in `AutoGUI.FAILSAFE_POINTS`, it raises `AutoGUI::FailSafeException`.
|
|
127
|
+
2. **Pause** — sleeps `AutoGUI.PAUSE` seconds (default `0.1`) so you can yank the mouse to a corner.
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
AutoGUI.FAILSAFE = true # default; do not disable in production scripts
|
|
131
|
+
AutoGUI.PAUSE = 0.1 # seconds after each call
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Corners of the primary monitor are registered at load time. Do not `move_to(0, 0)` while fail-safe is on.
|
|
135
|
+
|
|
136
|
+
Rescue it if you want a clean shutdown:
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
begin
|
|
140
|
+
AutoGUI.move_to(500, 500)
|
|
141
|
+
AutoGUI.click
|
|
142
|
+
rescue AutoGUI::FailSafeException
|
|
143
|
+
warn "aborted: mouse in a screen corner"
|
|
144
|
+
end
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Coordinates
|
|
148
|
+
|
|
149
|
+
Origin is the **top-left** of the primary display. `x` increases to the right, `y` increases downward.
|
|
150
|
+
|
|
151
|
+
```ruby
|
|
152
|
+
AutoGUI.size # Size(width:, height:) — also AutoGUI.resolution
|
|
153
|
+
AutoGUI.position # Point(x:, y:) of the cursor
|
|
154
|
+
AutoGUI.on_screen(100, 200) # true / false
|
|
155
|
+
AutoGUI.on_screen([100, 200])
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`Point`, `Size`, and `Box` unpack like arrays:
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
x, y = AutoGUI.position
|
|
162
|
+
w, h = AutoGUI.size
|
|
163
|
+
left, top, width, height = box
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Most mouse methods accept:
|
|
167
|
+
|
|
168
|
+
| Argument | Meaning |
|
|
169
|
+
| --- | --- |
|
|
170
|
+
| no args | current cursor position |
|
|
171
|
+
| `x, y` | absolute pixel |
|
|
172
|
+
| `[x, y]` | same |
|
|
173
|
+
| `[left, top, width, height]` or a `Box` | center of that box |
|
|
174
|
+
| `"needle.png"` | center of that image on screen (`locate_on_screen`) |
|
|
175
|
+
| `x: nil, y: 80` | keep current x, set y (and the reverse) |
|
|
176
|
+
|
|
177
|
+
## Mouse
|
|
178
|
+
|
|
179
|
+
Buttons: `"left"`, `"middle"`, `"right"`, `"primary"`, `"secondary"` (or `1` / `2` / `3`). `"primary"` is left unless the OS has swapped buttons.
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
AutoGUI.move_to(100, 150)
|
|
183
|
+
AutoGUI.move_to(100, 150, duration: 1.0, tween: AutoGUI.method(:easeInOutQuad))
|
|
184
|
+
AutoGUI.move(0, 10) # relative; aliases: move_rel
|
|
185
|
+
AutoGUI.drag_to(300, 400, duration: 0.5, button: "left")
|
|
186
|
+
AutoGUI.drag(50, 0) # relative drag
|
|
187
|
+
|
|
188
|
+
AutoGUI.click
|
|
189
|
+
AutoGUI.click(200, 220, clicks: 2, interval: 0.1, button: "right")
|
|
190
|
+
AutoGUI.left_click
|
|
191
|
+
AutoGUI.right_click
|
|
192
|
+
AutoGUI.middle_click
|
|
193
|
+
AutoGUI.double_click
|
|
194
|
+
AutoGUI.triple_click
|
|
195
|
+
|
|
196
|
+
AutoGUI.mouse_down(button: "left")
|
|
197
|
+
AutoGUI.mouse_up(button: "left")
|
|
198
|
+
|
|
199
|
+
AutoGUI.scroll(3) # positive = up, negative = down
|
|
200
|
+
AutoGUI.hscroll(-2) # horizontal where the OS supports it
|
|
201
|
+
AutoGUI.vscroll(3)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`duration:` below `AutoGUI.MINIMUM_DURATION` (0.1s) is treated as instant.
|
|
205
|
+
|
|
206
|
+
## Keyboard
|
|
207
|
+
|
|
208
|
+
Keys go to whatever window has focus.
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
AutoGUI.write("Hello world!", interval: 0.05)
|
|
212
|
+
AutoGUI.write(["a", "b", "left", "enter"]) # alias: typewrite
|
|
213
|
+
AutoGUI.press("enter")
|
|
214
|
+
AutoGUI.press("f1", presses: 3, interval: 0.2)
|
|
215
|
+
AutoGUI.press(["up", "up", "down"])
|
|
216
|
+
AutoGUI.hotkey("ctrl", "c") # alias: shortcut
|
|
217
|
+
AutoGUI.hold("shift") { AutoGUI.press(["left", "left"]) }
|
|
218
|
+
AutoGUI.key_down("ctrl")
|
|
219
|
+
AutoGUI.key_up("ctrl")
|
|
220
|
+
AutoGUI.valid_key?("esc") # => true
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`hold` **requires a block**; the key is released in `ensure`.
|
|
224
|
+
|
|
225
|
+
Common names (full list: `AutoGUI::KEYBOARD_KEYS`):
|
|
226
|
+
|
|
227
|
+
`enter` `return` `esc` `tab` `space` `backspace` `delete` `shift` `ctrl` `alt` `win` `command` `option` `up` `down` `left` `right` `home` `end` `pageup` `pagedown` `f1`…`f24` plus printable characters.
|
|
228
|
+
|
|
229
|
+
On Windows, non-ASCII characters in `write` are sent as Unicode.
|
|
230
|
+
|
|
231
|
+
## Screenshots and image search
|
|
232
|
+
|
|
233
|
+
```ruby
|
|
234
|
+
img = AutoGUI.screenshot # AutoGUI::Image
|
|
235
|
+
img.save("desktop.png")
|
|
236
|
+
AutoGUI.screenshot("desktop.png") # capture and save
|
|
237
|
+
AutoGUI.screenshot("crop.png", region: [0, 0, 300, 400]) # left, top, width, height
|
|
238
|
+
|
|
239
|
+
r, g, b = AutoGUI.pixel(100, 200)
|
|
240
|
+
AutoGUI.pixel_matches_color(100, 200, [255, 255, 255], tolerance: 10)
|
|
241
|
+
|
|
242
|
+
box = AutoGUI.locate_on_screen("button.png") # Box or nil
|
|
243
|
+
# Box(left:, top:, width:, height:)
|
|
244
|
+
pt = AutoGUI.locate_center_on_screen("button.png") # Point or nil
|
|
245
|
+
AutoGUI.click(box) if box
|
|
246
|
+
|
|
247
|
+
AutoGUI.locate_all_on_screen("icon.png").each { |b| p b }
|
|
248
|
+
AutoGUI.locate("needle.png", "haystack.png")
|
|
249
|
+
AutoGUI.center([10, 20, 40, 30]) # Point at the box center
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Needle files may be **PNG or BMP**. Matching is pure Ruby (no OpenCV).
|
|
253
|
+
|
|
254
|
+
```ruby
|
|
255
|
+
AutoGUI.locate_on_screen("needle.png", grayscale: true, confidence: 0.9)
|
|
256
|
+
AutoGUI.locate_on_screen("needle.png", region: [0, 0, 800, 600], minSearchTime: 5)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
| Option | Default | Meaning |
|
|
260
|
+
| --- | --- | --- |
|
|
261
|
+
| `grayscale:` | `false` | compare luminance only |
|
|
262
|
+
| `confidence:` | `nil` (exact pixels) | `0.0`–`1.0` mean-absolute-error score |
|
|
263
|
+
| `region:` | full screen | `[left, top, width, height]` |
|
|
264
|
+
| `minSearchTime:` | `0` | keep retrying that many seconds |
|
|
265
|
+
|
|
266
|
+
By default a miss returns `nil`. To raise instead:
|
|
267
|
+
|
|
268
|
+
```ruby
|
|
269
|
+
AutoGUI.use_image_not_found_exception!(true)
|
|
270
|
+
AutoGUI.locate_on_screen("missing.png")
|
|
271
|
+
# raises AutoGUI::ImageNotFoundException
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
`AutoGUI::Image` supports `getpixel`, `putpixel`, `crop`, `grayscale`, `save`, and `Image.open(path)`.
|
|
275
|
+
|
|
276
|
+
## Message boxes
|
|
277
|
+
|
|
278
|
+
```ruby
|
|
279
|
+
AutoGUI.alert("Done.")
|
|
280
|
+
choice = AutoGUI.confirm("Continue?") # "OK" or "Cancel"
|
|
281
|
+
name = AutoGUI.prompt("Your name?", "Title", "guest")
|
|
282
|
+
secret = AutoGUI.password("Password") # nil if cancelled
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
On Windows these use Win32 / VBScript dialogs. Elsewhere they use `osascript` or `zenity` when present.
|
|
286
|
+
|
|
287
|
+
## Windows
|
|
288
|
+
|
|
289
|
+
Window helpers are implemented for **Windows**. They return empty / `nil` on other OSes.
|
|
290
|
+
|
|
291
|
+
```ruby
|
|
292
|
+
AutoGUI.get_all_titles
|
|
293
|
+
AutoGUI.get_all_windows
|
|
294
|
+
AutoGUI.get_active_window
|
|
295
|
+
AutoGUI.get_active_window_title
|
|
296
|
+
AutoGUI.get_windows_with_title("Notepad") # substring, case-insensitive
|
|
297
|
+
AutoGUI.get_windows_at(400, 300)
|
|
298
|
+
|
|
299
|
+
win = AutoGUI.get_windows_with_title("Notepad").first
|
|
300
|
+
win&.activate
|
|
301
|
+
win&.move_to(40, 40)
|
|
302
|
+
win&.resize_to(800, 600)
|
|
303
|
+
win&.minimize
|
|
304
|
+
win&.maximize
|
|
305
|
+
win&.restore
|
|
306
|
+
win&.close
|
|
307
|
+
win.title
|
|
308
|
+
win.left
|
|
309
|
+
win.top
|
|
310
|
+
win.width
|
|
311
|
+
win.height
|
|
312
|
+
win.visible?
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
CamelCase aliases exist (`getAllTitles`, `getActiveWindow`, …).
|
|
316
|
+
|
|
317
|
+
## Settings
|
|
318
|
+
|
|
319
|
+
| Setting | Default | Role |
|
|
320
|
+
| --- | --- | --- |
|
|
321
|
+
| `AutoGUI.PAUSE` | `0.1` | seconds to sleep after each public call |
|
|
322
|
+
| `AutoGUI.FAILSAFE` | `true` | abort when the cursor is on a fail-safe point |
|
|
323
|
+
| `AutoGUI.FAILSAFE_POINTS` | four corners | `Point` list checked before actions |
|
|
324
|
+
| `AutoGUI.MINIMUM_DURATION` | `0.1` | shorter `duration:` moves are instant |
|
|
325
|
+
| `AutoGUI.MINIMUM_SLEEP` | `0.05` | floor between tween steps |
|
|
326
|
+
| `AutoGUI.DARWIN_CATCH_UP_TIME` | `0.01` | extra delay after macOS events |
|
|
327
|
+
| `AutoGUI.LOG_SCREENSHOTS` | `false` | save a PNG on each action |
|
|
328
|
+
| `AutoGUI.LOG_SCREENSHOTS_LIMIT` | `10` | rotate old log screenshots |
|
|
329
|
+
|
|
330
|
+
```ruby
|
|
331
|
+
AutoGUI.print_info
|
|
332
|
+
# Platform, Ruby version, AutoGUI version, executable, resolution, timestamp
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Tweens
|
|
336
|
+
|
|
337
|
+
Pass any callable that maps `0.0..1.0` → `0.0..1.0` as `tween:`:
|
|
338
|
+
|
|
339
|
+
```ruby
|
|
340
|
+
AutoGUI.move_to(800, 400, duration: 1.2, tween: AutoGUI.method(:easeInOutQuad))
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Built-ins: `linear`, `easeInQuad`, `easeOutQuad`, `easeInOutQuad`, `easeInCubic`, `easeOutCubic`, `easeInOutCubic`, `easeInQuart`, `easeOutQuart`, `easeInOutQuart`, `easeInQuint`, `easeOutQuint`, `easeInOutQuint`, `easeInSine`, `easeOutSine`, `easeInOutSine`, `easeInExpo`, `easeOutExpo`, `easeInOutExpo`, `easeInCirc`, `easeOutCirc`, `easeInOutCirc`, `easeInElastic`, `easeOutElastic`, `easeInOutElastic`, `easeInBack`, `easeOutBack`, `easeInOutBack`, `easeInBounce`, `easeOutBounce`, `easeInOutBounce`.
|
|
344
|
+
|
|
345
|
+
## Mini-language
|
|
346
|
+
|
|
347
|
+
```ruby
|
|
348
|
+
AutoGUI.run("c c g 100, 200 c")
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
| Token | Action |
|
|
352
|
+
| --- | --- |
|
|
353
|
+
| `c` `l` `m` `r` | click primary / left / middle / right |
|
|
354
|
+
| `su` `sd` | scroll up / down |
|
|
355
|
+
| `ss` | screenshot `screenshotN.png` |
|
|
356
|
+
| `gX,Y` / `g+X,-Y` | `move_to` / relative `move` |
|
|
357
|
+
| `dX,Y` / `d+X,-Y` | `drag_to` / relative `drag` |
|
|
358
|
+
| `k'enter'` | `press` |
|
|
359
|
+
| `w'hello'` | `write` |
|
|
360
|
+
| `h'ctrl,c'` | `hotkey` |
|
|
361
|
+
| `a'hi'` | `alert` |
|
|
362
|
+
| `s0.5` | `sleep` |
|
|
363
|
+
| `p0.2` | set `PAUSE` for the rest of this `run` (restored after) |
|
|
364
|
+
| `f3(cc)` | repeat inner commands 3 times |
|
|
365
|
+
|
|
366
|
+
Whitespace is ignored. Quotes must be single quotes.
|
|
367
|
+
|
|
368
|
+
## CLI
|
|
369
|
+
|
|
370
|
+
After `gem install autogui` the `autogui` executable is on your PATH:
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
autogui info
|
|
374
|
+
autogui mouse # live X/Y/RGB; Ctrl-C to quit
|
|
375
|
+
autogui screenshot out.png
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
From a git checkout: `ruby bin/autogui info`.
|
|
379
|
+
|
|
380
|
+
## Platforms
|
|
381
|
+
|
|
382
|
+
- **Windows** — `user32` / `gdi32` through `Fiddle`. DPI-aware. Unicode typing via `SendInput`. Window enumeration via `EnumWindows`.
|
|
383
|
+
- **macOS** — System Events through `osascript`; captures with `screencapture`. Enable Accessibility for the process running Ruby.
|
|
384
|
+
- **Linux** — `xdotool` for input; `scrot` / `import` / `grim` for captures.
|
|
385
|
+
|
|
386
|
+
## Exceptions
|
|
387
|
+
|
|
388
|
+
| Class | When |
|
|
389
|
+
| --- | --- |
|
|
390
|
+
| `AutoGUI::AutoGUIException` | invalid arguments, missing tools, bad images |
|
|
391
|
+
| `AutoGUI::FailSafeException` | cursor on a fail-safe corner |
|
|
392
|
+
| `AutoGUI::ImageNotFoundException` | locate\* miss *and* exceptions enabled |
|
|
393
|
+
|
|
394
|
+
## API reference
|
|
395
|
+
|
|
396
|
+
See **[docs/api.md](docs/api.md)** for every method, alias, return type, and option.
|
|
397
|
+
|
|
398
|
+
See **[docs/guide.md](docs/guide.md)** for recipes, coordinate details, and the command language.
|
|
399
|
+
|
|
400
|
+
See **[CHANGELOG.md](CHANGELOG.md)** for releases.
|
|
401
|
+
|
|
402
|
+
## Development
|
|
403
|
+
|
|
404
|
+
```
|
|
405
|
+
git clone https://github.com/pardeep2690/autogui.git
|
|
406
|
+
cd autogui
|
|
407
|
+
ruby -Ilib:test test/test_autogui.rb
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Live mouse tests stay skipped unless you opt in:
|
|
411
|
+
|
|
412
|
+
```
|
|
413
|
+
# Unix
|
|
414
|
+
AUTOGUI_LIVE=1 ruby -Ilib:test test/test_autogui.rb
|
|
415
|
+
|
|
416
|
+
# Windows PowerShell
|
|
417
|
+
$env:AUTOGUI_LIVE=1; ruby -Ilib:test test/test_autogui.rb
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Examples:
|
|
421
|
+
|
|
422
|
+
```
|
|
423
|
+
ruby -Ilib examples/hello.rb
|
|
424
|
+
ruby -Ilib examples/locate_demo.rb path/to/needle.png
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Publishing this gem to RubyGems is documented in [docs/publishing.md](docs/publishing.md).
|
|
428
|
+
|
|
429
|
+
## License
|
|
430
|
+
|
|
431
|
+
BSD 3-Clause. API and behavior follow [PyAutoGUI](https://github.com/asweigart/pyautogui) (Al Sweigart).
|
data/bin/autogui
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
5
|
+
require "autogui"
|
|
6
|
+
|
|
7
|
+
case ARGV[0]
|
|
8
|
+
when "info", nil
|
|
9
|
+
AutoGUI.printInfo
|
|
10
|
+
when "mouse", "mouseinfo", "position"
|
|
11
|
+
AutoGUI.displayMousePosition
|
|
12
|
+
when "screenshot"
|
|
13
|
+
path = ARGV[1] || "screenshot.png"
|
|
14
|
+
AutoGUI.screenshot(path)
|
|
15
|
+
puts "saved #{path}"
|
|
16
|
+
else
|
|
17
|
+
warn "usage: autogui [info|mouse|screenshot [file.png]]"
|
|
18
|
+
exit 1
|
|
19
|
+
end
|
data/docs/api.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# AutoGUI API reference
|
|
2
|
+
|
|
3
|
+
All methods below live on the `AutoGUI` module unless noted. Snake_case is canonical. CamelCase aliases are listed in the Alias column.
|
|
4
|
+
|
|
5
|
+
Return values that unpack (`Point`, `Size`, `Box`) also respond to `to_a`, `[]`, and named readers.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Screen and cursor
|
|
10
|
+
|
|
11
|
+
| Method | Alias | Returns | Notes |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| `size` | `resolution` | `Size` | Primary monitor width × height |
|
|
14
|
+
| `position(x = nil, y = nil)` | | `Point` | Override x and/or y if passed |
|
|
15
|
+
| `on_screen(x, y = nil)` | `onScreen` | `true`/`false` | Also accepts `[x, y]` |
|
|
16
|
+
| `pixel(x, y)` | | `[r, g, b]` | 0–255 each |
|
|
17
|
+
| `pixel_matches_color(x, y, rgb, tolerance: 0)` | `pixelMatchesColor` | `true`/`false` | `rgb` is `[r, g, b]` |
|
|
18
|
+
| `print_info(dont_print = false)` | `printInfo` | `String` | Also prints unless `dont_print` |
|
|
19
|
+
| `get_info` | `getInfo` | Array | platform, Ruby, version, executable, size, timestamp |
|
|
20
|
+
| `sleep(seconds)` | | `nil` | `Kernel.sleep` |
|
|
21
|
+
| `countdown(seconds)` | | `nil` | Prints `3 2 1` |
|
|
22
|
+
| `fail_safe_check` | `failSafeCheck` | `nil` or raises | Used internally |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Mouse
|
|
27
|
+
|
|
28
|
+
Shared keywords on movement/click helpers: `duration:` (seconds), `tween:` (callable), `logScreenshot:` (`true`/`false`/`nil`), `_pause:` (internal).
|
|
29
|
+
|
|
30
|
+
`x` / `y` follow [coordinate rules](guide.md#coordinates): numbers, `[x, y]`, a `Box`, or an image filename.
|
|
31
|
+
|
|
32
|
+
| Method | Alias | Notes |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `move_to(x = nil, y = nil, duration: 0)` | `moveTo` | Absolute move |
|
|
35
|
+
| `move(x = nil, y = nil, duration: 0)` | `move_rel`, `moveRel` | Relative move |
|
|
36
|
+
| `drag_to(x = nil, y = nil, duration: 0, button: "primary", mouseDownUp: true)` | `dragTo` | Drag while holding `button` |
|
|
37
|
+
| `drag(x = 0, y = 0, ...)` | `drag_rel`, `dragRel` | Relative drag |
|
|
38
|
+
| `click(x = nil, y = nil, clicks: 1, interval: 0, button: "primary", duration: 0)` | | |
|
|
39
|
+
| `left_click(...)` | `leftClick` | |
|
|
40
|
+
| `right_click(...)` | `rightClick` | |
|
|
41
|
+
| `middle_click(...)` | `middleClick` | |
|
|
42
|
+
| `double_click(..., button: "left")` | `doubleClick` | |
|
|
43
|
+
| `triple_click(..., button: "left")` | `tripleClick` | |
|
|
44
|
+
| `mouse_down(x = nil, y = nil, button: "primary")` | `mouseDown` | |
|
|
45
|
+
| `mouse_up(x = nil, y = nil, button: "primary")` | `mouseUp` | |
|
|
46
|
+
| `scroll(clicks, x = nil, y = nil)` | | Positive = up |
|
|
47
|
+
| `hscroll(clicks, x = nil, y = nil)` | | Horizontal |
|
|
48
|
+
| `vscroll(clicks, x = nil, y = nil)` | | Vertical (same as `scroll` on Windows) |
|
|
49
|
+
| `display_mouse_position(x_offset = 0, y_offset = 0)` | `displayMousePosition`, `mouseInfo`, `mouse_info` | Live HUD; Ctrl-C to quit |
|
|
50
|
+
|
|
51
|
+
Buttons: `"left"` `"middle"` `"right"` `"primary"` `"secondary"` or `1` `2` `3`. On Linux, `4`–`7` are extra buttons.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Keyboard
|
|
56
|
+
|
|
57
|
+
| Method | Alias | Notes |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| `write(message, interval: 0)` | `typewrite` | String of chars, or array of key names |
|
|
60
|
+
| `press(keys, presses: 1, interval: 0)` | | String or array of key names |
|
|
61
|
+
| `hotkey(*keys, interval: 0)` | `shortcut` | Down in order, up in reverse |
|
|
62
|
+
| `hold(keys) { ... }` | | Requires a block; releases in `ensure` |
|
|
63
|
+
| `key_down(key)` | `keyDown` | |
|
|
64
|
+
| `key_up(key)` | `keyUp` | |
|
|
65
|
+
| `valid_key?(key)` | `isValidKey`, `is_valid_key` | |
|
|
66
|
+
| `shift_character?(ch)` | `isShiftCharacter` | Uppercase or `~!@#$…` |
|
|
67
|
+
|
|
68
|
+
`keys` / `key` values are strings from `AutoGUI::KEYBOARD_KEYS` (also `AutoGUI::KEY_NAMES`).
|
|
69
|
+
|
|
70
|
+
Modifier aliases: `ctrl` = left ctrl, `alt` = left alt, `shift` = left shift, `win` / `command` = left Super/Cmd.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Screenshots and locate
|
|
75
|
+
|
|
76
|
+
| Method | Alias | Returns |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| `screenshot(path = nil, region: nil)` | `grab` | `Image`; saves if `path` given |
|
|
79
|
+
| `locate_on_screen(image, grayscale: false, confidence: nil, region: nil, minSearchTime: 0)` | `locateOnScreen` | `Box` or `nil` |
|
|
80
|
+
| `locate_center_on_screen(...)` | `locateCenterOnScreen` | `Point` or `nil` |
|
|
81
|
+
| `locate_all_on_screen(...)` | `locateAllOnScreen` | Enumerator of `Box` |
|
|
82
|
+
| `locate(needle, haystack, grayscale: false, confidence: nil)` | | `Box` or `nil` |
|
|
83
|
+
| `locate_all(needle, haystack, ...)` | `locateAll` | Enumerator of `Box` |
|
|
84
|
+
| `locate_on_window(image, title, ...)` | `locateOnWindow` | `Box` in that window |
|
|
85
|
+
| `center(box)` | | `Point` |
|
|
86
|
+
| `use_image_not_found_exception!(value = true)` | `useImageNotFoundException` | miss raises instead of `nil` |
|
|
87
|
+
|
|
88
|
+
`region` is `[left, top, width, height]`. `image` / `needle` / `haystack` may be a path or an `AutoGUI::Image`.
|
|
89
|
+
|
|
90
|
+
### `AutoGUI::Image`
|
|
91
|
+
|
|
92
|
+
| Method | Notes |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| `Image.open(path)` | PNG or uncompressed BMP |
|
|
95
|
+
| `Image.from_pixels(w, h, [[r,g,b], ...])` | |
|
|
96
|
+
| `#width` `#height` `#data` | RGB bytes, top-down |
|
|
97
|
+
| `#getpixel(x, y)` | `[r, g, b]` |
|
|
98
|
+
| `#putpixel(x, y, [r, g, b])` | |
|
|
99
|
+
| `#crop(left, top, width, height)` | new `Image` |
|
|
100
|
+
| `#grayscale` | new `Image` |
|
|
101
|
+
| `#save(path)` | `.png` or `.bmp` from extension |
|
|
102
|
+
| `#to_png` `#to_bmp` | binary strings |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Dialogs
|
|
107
|
+
|
|
108
|
+
| Method | Returns |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| `alert(text = "", title = "", button = "OK")` | button label |
|
|
111
|
+
| `confirm(text = "", title = "", buttons = ["OK", "Cancel"])` | chosen label |
|
|
112
|
+
| `prompt(text = "", title = "", default = "")` | string or `nil` |
|
|
113
|
+
| `password(text = "", title = "", default = "", mask = "*")` | string or `nil` |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Window objects (Windows OS)
|
|
118
|
+
|
|
119
|
+
Module functions:
|
|
120
|
+
|
|
121
|
+
| Method | Alias |
|
|
122
|
+
| --- | --- |
|
|
123
|
+
| `get_all_windows` | `getAllWindows` |
|
|
124
|
+
| `get_all_titles` | `getAllTitles` |
|
|
125
|
+
| `get_active_window` | `getActiveWindow` |
|
|
126
|
+
| `get_active_window_title` | `getActiveWindowTitle` |
|
|
127
|
+
| `get_windows_with_title(title)` | `getWindowsWithTitle` |
|
|
128
|
+
| `get_windows_at(x, y)` | `getWindowsAt` |
|
|
129
|
+
|
|
130
|
+
`AutoGUI::Window` instance:
|
|
131
|
+
|
|
132
|
+
| Method | Notes |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| `#title` `#hwnd` | |
|
|
135
|
+
| `#left` `#top` `#width` `#height` `#right` `#bottom` `#box` | |
|
|
136
|
+
| `#visible?` `#minimized?` `#maximized?` | |
|
|
137
|
+
| `#activate` `#minimize` `#maximize` `#restore` `#hide` `#close` | chainable |
|
|
138
|
+
| `#move_to(x, y)` | alias `moveTo` |
|
|
139
|
+
| `#resize_to(w, h)` | alias `resizeTo` |
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Geometry
|
|
144
|
+
|
|
145
|
+
```ruby
|
|
146
|
+
AutoGUI::Point.new(x, y) # #x #y
|
|
147
|
+
AutoGUI::Size.new(width, height) # #width #height
|
|
148
|
+
AutoGUI::Box.new(left, top, width, height)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
All three implement `#to_a`, `#to_ary` (so `x, y = point` works), `#[]`, and `#==` against arrays.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Tweens
|
|
156
|
+
|
|
157
|
+
`AutoGUI.linear(n)` and `AutoGUI.easeInQuad(n)` … `AutoGUI.easeInOutBounce(n)` — see the README. `n` must be in `0.0..1.0` or `AutoGUIException` is raised.
|
|
158
|
+
|
|
159
|
+
`get_point_on_line(x1, y1, x2, y2, n)` → `[x, y]` (`getPointOnLine`).
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Mini-language
|
|
164
|
+
|
|
165
|
+
`AutoGUI.run(command_string)` — tokens documented in the README and [guide.md](guide.md#mini-language).
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Constants
|
|
170
|
+
|
|
171
|
+
| Name | Value |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| `AutoGUI::VERSION` | gem version string |
|
|
174
|
+
| `AutoGUI::LEFT` `MIDDLE` `RIGHT` `PRIMARY` `SECONDARY` | button names |
|
|
175
|
+
| `AutoGUI::KEYBOARD_KEYS` | array of valid key strings (`KEY_NAMES`) |
|
|
176
|
+
| `AutoGUI::QWERTY` `QWERTZ` | layout strings |
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Exceptions
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
AutoGUI::AutoGUIException # StandardError
|
|
184
|
+
AutoGUI::FailSafeException # < AutoGUIException
|
|
185
|
+
AutoGUI::ImageNotFoundException # < AutoGUIException
|
|
186
|
+
```
|