rust-mouse 0.1.0__tar.gz

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.
@@ -0,0 +1,67 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ jobs:
9
+ build:
10
+ name: Build wheels (${{ matrix.os }})
11
+ runs-on: ${{ matrix.os }}
12
+ strategy:
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Build wheels
19
+ uses: PyO3/maturin-action@v1
20
+ with:
21
+ args: --release --out dist --find-interpreter
22
+ sccache: "true"
23
+ manylinux: auto
24
+
25
+ - name: Upload wheels
26
+ uses: actions/upload-artifact@v4
27
+ with:
28
+ name: wheels-${{ matrix.os }}
29
+ path: dist
30
+
31
+ build-sdist:
32
+ name: Build source distribution
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+
37
+ - name: Build sdist
38
+ uses: PyO3/maturin-action@v1
39
+ with:
40
+ command: sdist
41
+ args: --out dist
42
+
43
+ - name: Upload sdist
44
+ uses: actions/upload-artifact@v4
45
+ with:
46
+ name: wheels-sdist
47
+ path: dist
48
+
49
+ pypi-publish:
50
+ name: Upload release to PyPI
51
+ runs-on: ubuntu-latest
52
+ needs: [build, build-sdist]
53
+ environment:
54
+ name: pypi
55
+ url: https://pypi.org/p/rust-mouse
56
+ permissions:
57
+ id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
58
+ steps:
59
+ - name: Download all wheels
60
+ uses: actions/download-artifact@v4
61
+ with:
62
+ pattern: wheels-*
63
+ merge-multiple: true
64
+ path: dist
65
+
66
+ - name: Publish package distributions to PyPI
67
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,74 @@
1
+ /target
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ .pytest_cache/
6
+ *.py[cod]
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ .venv/
14
+ env/
15
+ bin/
16
+ build/
17
+ develop-eggs/
18
+ dist/
19
+ eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ include/
26
+ man/
27
+ venv/
28
+ *.egg-info/
29
+ .installed.cfg
30
+ *.egg
31
+
32
+ # Installer logs
33
+ pip-log.txt
34
+ pip-delete-this-directory.txt
35
+ pip-selfcheck.json
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .coverage
41
+ .cache
42
+ nosetests.xml
43
+ coverage.xml
44
+
45
+ # Translations
46
+ *.mo
47
+
48
+ # Mr Developer
49
+ .mr.developer.cfg
50
+ .project
51
+ .pydevproject
52
+
53
+ # Rope
54
+ .ropeproject
55
+
56
+ # Django stuff:
57
+ *.log
58
+ *.pot
59
+
60
+ .DS_Store
61
+
62
+ # Sphinx documentation
63
+ docs/_build/
64
+
65
+ # PyCharm
66
+ .idea/
67
+
68
+ # VSCode
69
+ .vscode/
70
+
71
+ # Pyenv
72
+ .python-version
73
+
74
+ uv.lock
@@ -0,0 +1,662 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "autocfg"
7
+ version = "1.5.0"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
10
+
11
+ [[package]]
12
+ name = "bitflags"
13
+ version = "2.11.0"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
16
+
17
+ [[package]]
18
+ name = "cfg-if"
19
+ version = "1.0.4"
20
+ source = "registry+https://github.com/rust-lang/crates.io-index"
21
+ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
22
+
23
+ [[package]]
24
+ name = "core-foundation"
25
+ version = "0.10.1"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
28
+ dependencies = [
29
+ "core-foundation-sys",
30
+ "libc",
31
+ ]
32
+
33
+ [[package]]
34
+ name = "core-foundation-sys"
35
+ version = "0.8.7"
36
+ source = "registry+https://github.com/rust-lang/crates.io-index"
37
+ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
38
+
39
+ [[package]]
40
+ name = "core-graphics"
41
+ version = "0.25.0"
42
+ source = "registry+https://github.com/rust-lang/crates.io-index"
43
+ checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97"
44
+ dependencies = [
45
+ "bitflags",
46
+ "core-foundation",
47
+ "core-graphics-types",
48
+ "foreign-types",
49
+ "libc",
50
+ ]
51
+
52
+ [[package]]
53
+ name = "core-graphics-types"
54
+ version = "0.2.0"
55
+ source = "registry+https://github.com/rust-lang/crates.io-index"
56
+ checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
57
+ dependencies = [
58
+ "bitflags",
59
+ "core-foundation",
60
+ "libc",
61
+ ]
62
+
63
+ [[package]]
64
+ name = "dispatch2"
65
+ version = "0.3.1"
66
+ source = "registry+https://github.com/rust-lang/crates.io-index"
67
+ checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
68
+ dependencies = [
69
+ "bitflags",
70
+ "objc2",
71
+ ]
72
+
73
+ [[package]]
74
+ name = "enigo"
75
+ version = "0.6.1"
76
+ source = "registry+https://github.com/rust-lang/crates.io-index"
77
+ checksum = "71c6c56e50f7acae2906a0dcbb34529ca647e40421119ad5d12e7f8ba6e50010"
78
+ dependencies = [
79
+ "core-foundation",
80
+ "core-graphics",
81
+ "foreign-types-shared",
82
+ "libc",
83
+ "log",
84
+ "nom",
85
+ "objc2",
86
+ "objc2-app-kit",
87
+ "objc2-foundation",
88
+ "windows",
89
+ "x11rb",
90
+ "xkbcommon",
91
+ "xkeysym",
92
+ ]
93
+
94
+ [[package]]
95
+ name = "errno"
96
+ version = "0.3.14"
97
+ source = "registry+https://github.com/rust-lang/crates.io-index"
98
+ checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
99
+ dependencies = [
100
+ "libc",
101
+ "windows-sys",
102
+ ]
103
+
104
+ [[package]]
105
+ name = "foreign-types"
106
+ version = "0.5.0"
107
+ source = "registry+https://github.com/rust-lang/crates.io-index"
108
+ checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
109
+ dependencies = [
110
+ "foreign-types-macros",
111
+ "foreign-types-shared",
112
+ ]
113
+
114
+ [[package]]
115
+ name = "foreign-types-macros"
116
+ version = "0.2.3"
117
+ source = "registry+https://github.com/rust-lang/crates.io-index"
118
+ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
119
+ dependencies = [
120
+ "proc-macro2",
121
+ "quote",
122
+ "syn",
123
+ ]
124
+
125
+ [[package]]
126
+ name = "foreign-types-shared"
127
+ version = "0.3.1"
128
+ source = "registry+https://github.com/rust-lang/crates.io-index"
129
+ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
130
+
131
+ [[package]]
132
+ name = "gethostname"
133
+ version = "1.1.0"
134
+ source = "registry+https://github.com/rust-lang/crates.io-index"
135
+ checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8"
136
+ dependencies = [
137
+ "rustix",
138
+ "windows-link 0.2.1",
139
+ ]
140
+
141
+ [[package]]
142
+ name = "getrandom"
143
+ version = "0.3.4"
144
+ source = "registry+https://github.com/rust-lang/crates.io-index"
145
+ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
146
+ dependencies = [
147
+ "cfg-if",
148
+ "libc",
149
+ "r-efi",
150
+ "wasip2",
151
+ ]
152
+
153
+ [[package]]
154
+ name = "heck"
155
+ version = "0.5.0"
156
+ source = "registry+https://github.com/rust-lang/crates.io-index"
157
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
158
+
159
+ [[package]]
160
+ name = "indoc"
161
+ version = "2.0.7"
162
+ source = "registry+https://github.com/rust-lang/crates.io-index"
163
+ checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
164
+ dependencies = [
165
+ "rustversion",
166
+ ]
167
+
168
+ [[package]]
169
+ name = "libc"
170
+ version = "0.2.182"
171
+ source = "registry+https://github.com/rust-lang/crates.io-index"
172
+ checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
173
+
174
+ [[package]]
175
+ name = "linux-raw-sys"
176
+ version = "0.12.1"
177
+ source = "registry+https://github.com/rust-lang/crates.io-index"
178
+ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
179
+
180
+ [[package]]
181
+ name = "log"
182
+ version = "0.4.29"
183
+ source = "registry+https://github.com/rust-lang/crates.io-index"
184
+ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
185
+
186
+ [[package]]
187
+ name = "memchr"
188
+ version = "2.8.0"
189
+ source = "registry+https://github.com/rust-lang/crates.io-index"
190
+ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
191
+
192
+ [[package]]
193
+ name = "memmap2"
194
+ version = "0.9.10"
195
+ source = "registry+https://github.com/rust-lang/crates.io-index"
196
+ checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3"
197
+ dependencies = [
198
+ "libc",
199
+ ]
200
+
201
+ [[package]]
202
+ name = "memoffset"
203
+ version = "0.9.1"
204
+ source = "registry+https://github.com/rust-lang/crates.io-index"
205
+ checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
206
+ dependencies = [
207
+ "autocfg",
208
+ ]
209
+
210
+ [[package]]
211
+ name = "nom"
212
+ version = "8.0.0"
213
+ source = "registry+https://github.com/rust-lang/crates.io-index"
214
+ checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
215
+ dependencies = [
216
+ "memchr",
217
+ ]
218
+
219
+ [[package]]
220
+ name = "objc2"
221
+ version = "0.6.4"
222
+ source = "registry+https://github.com/rust-lang/crates.io-index"
223
+ checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
224
+ dependencies = [
225
+ "objc2-encode",
226
+ ]
227
+
228
+ [[package]]
229
+ name = "objc2-app-kit"
230
+ version = "0.3.2"
231
+ source = "registry+https://github.com/rust-lang/crates.io-index"
232
+ checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
233
+ dependencies = [
234
+ "bitflags",
235
+ "objc2",
236
+ "objc2-foundation",
237
+ ]
238
+
239
+ [[package]]
240
+ name = "objc2-core-foundation"
241
+ version = "0.3.2"
242
+ source = "registry+https://github.com/rust-lang/crates.io-index"
243
+ checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
244
+ dependencies = [
245
+ "bitflags",
246
+ "dispatch2",
247
+ "objc2",
248
+ ]
249
+
250
+ [[package]]
251
+ name = "objc2-encode"
252
+ version = "4.1.0"
253
+ source = "registry+https://github.com/rust-lang/crates.io-index"
254
+ checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
255
+
256
+ [[package]]
257
+ name = "objc2-foundation"
258
+ version = "0.3.2"
259
+ source = "registry+https://github.com/rust-lang/crates.io-index"
260
+ checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
261
+ dependencies = [
262
+ "bitflags",
263
+ "objc2",
264
+ "objc2-core-foundation",
265
+ ]
266
+
267
+ [[package]]
268
+ name = "once_cell"
269
+ version = "1.21.3"
270
+ source = "registry+https://github.com/rust-lang/crates.io-index"
271
+ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
272
+
273
+ [[package]]
274
+ name = "portable-atomic"
275
+ version = "1.13.1"
276
+ source = "registry+https://github.com/rust-lang/crates.io-index"
277
+ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
278
+
279
+ [[package]]
280
+ name = "ppv-lite86"
281
+ version = "0.2.21"
282
+ source = "registry+https://github.com/rust-lang/crates.io-index"
283
+ checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
284
+ dependencies = [
285
+ "zerocopy",
286
+ ]
287
+
288
+ [[package]]
289
+ name = "proc-macro2"
290
+ version = "1.0.106"
291
+ source = "registry+https://github.com/rust-lang/crates.io-index"
292
+ checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
293
+ dependencies = [
294
+ "unicode-ident",
295
+ ]
296
+
297
+ [[package]]
298
+ name = "pyo3"
299
+ version = "0.27.2"
300
+ source = "registry+https://github.com/rust-lang/crates.io-index"
301
+ checksum = "ab53c047fcd1a1d2a8820fe84f05d6be69e9526be40cb03b73f86b6b03e6d87d"
302
+ dependencies = [
303
+ "indoc",
304
+ "libc",
305
+ "memoffset",
306
+ "once_cell",
307
+ "portable-atomic",
308
+ "pyo3-build-config",
309
+ "pyo3-ffi",
310
+ "pyo3-macros",
311
+ "unindent",
312
+ ]
313
+
314
+ [[package]]
315
+ name = "pyo3-build-config"
316
+ version = "0.27.2"
317
+ source = "registry+https://github.com/rust-lang/crates.io-index"
318
+ checksum = "b455933107de8642b4487ed26d912c2d899dec6114884214a0b3bb3be9261ea6"
319
+ dependencies = [
320
+ "target-lexicon",
321
+ ]
322
+
323
+ [[package]]
324
+ name = "pyo3-ffi"
325
+ version = "0.27.2"
326
+ source = "registry+https://github.com/rust-lang/crates.io-index"
327
+ checksum = "1c85c9cbfaddf651b1221594209aed57e9e5cff63c4d11d1feead529b872a089"
328
+ dependencies = [
329
+ "libc",
330
+ "pyo3-build-config",
331
+ ]
332
+
333
+ [[package]]
334
+ name = "pyo3-macros"
335
+ version = "0.27.2"
336
+ source = "registry+https://github.com/rust-lang/crates.io-index"
337
+ checksum = "0a5b10c9bf9888125d917fb4d2ca2d25c8df94c7ab5a52e13313a07e050a3b02"
338
+ dependencies = [
339
+ "proc-macro2",
340
+ "pyo3-macros-backend",
341
+ "quote",
342
+ "syn",
343
+ ]
344
+
345
+ [[package]]
346
+ name = "pyo3-macros-backend"
347
+ version = "0.27.2"
348
+ source = "registry+https://github.com/rust-lang/crates.io-index"
349
+ checksum = "03b51720d314836e53327f5871d4c0cfb4fb37cc2c4a11cc71907a86342c40f9"
350
+ dependencies = [
351
+ "heck",
352
+ "proc-macro2",
353
+ "pyo3-build-config",
354
+ "quote",
355
+ "syn",
356
+ ]
357
+
358
+ [[package]]
359
+ name = "quote"
360
+ version = "1.0.45"
361
+ source = "registry+https://github.com/rust-lang/crates.io-index"
362
+ checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
363
+ dependencies = [
364
+ "proc-macro2",
365
+ ]
366
+
367
+ [[package]]
368
+ name = "r-efi"
369
+ version = "5.3.0"
370
+ source = "registry+https://github.com/rust-lang/crates.io-index"
371
+ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
372
+
373
+ [[package]]
374
+ name = "rand"
375
+ version = "0.9.2"
376
+ source = "registry+https://github.com/rust-lang/crates.io-index"
377
+ checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
378
+ dependencies = [
379
+ "rand_chacha",
380
+ "rand_core",
381
+ ]
382
+
383
+ [[package]]
384
+ name = "rand_chacha"
385
+ version = "0.9.0"
386
+ source = "registry+https://github.com/rust-lang/crates.io-index"
387
+ checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
388
+ dependencies = [
389
+ "ppv-lite86",
390
+ "rand_core",
391
+ ]
392
+
393
+ [[package]]
394
+ name = "rand_core"
395
+ version = "0.9.5"
396
+ source = "registry+https://github.com/rust-lang/crates.io-index"
397
+ checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
398
+ dependencies = [
399
+ "getrandom",
400
+ ]
401
+
402
+ [[package]]
403
+ name = "rust_mouse"
404
+ version = "0.1.0"
405
+ dependencies = [
406
+ "enigo",
407
+ "pyo3",
408
+ "rand",
409
+ "spin_sleep",
410
+ ]
411
+
412
+ [[package]]
413
+ name = "rustix"
414
+ version = "1.1.4"
415
+ source = "registry+https://github.com/rust-lang/crates.io-index"
416
+ checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
417
+ dependencies = [
418
+ "bitflags",
419
+ "errno",
420
+ "libc",
421
+ "linux-raw-sys",
422
+ "windows-sys",
423
+ ]
424
+
425
+ [[package]]
426
+ name = "rustversion"
427
+ version = "1.0.22"
428
+ source = "registry+https://github.com/rust-lang/crates.io-index"
429
+ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
430
+
431
+ [[package]]
432
+ name = "spin_sleep"
433
+ version = "1.3.3"
434
+ source = "registry+https://github.com/rust-lang/crates.io-index"
435
+ checksum = "9c07347b7c0301b9adba4350bdcf09c039d0e7160922050db0439b3c6723c8ab"
436
+ dependencies = [
437
+ "windows-sys",
438
+ ]
439
+
440
+ [[package]]
441
+ name = "syn"
442
+ version = "2.0.117"
443
+ source = "registry+https://github.com/rust-lang/crates.io-index"
444
+ checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
445
+ dependencies = [
446
+ "proc-macro2",
447
+ "quote",
448
+ "unicode-ident",
449
+ ]
450
+
451
+ [[package]]
452
+ name = "target-lexicon"
453
+ version = "0.13.5"
454
+ source = "registry+https://github.com/rust-lang/crates.io-index"
455
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
456
+
457
+ [[package]]
458
+ name = "unicode-ident"
459
+ version = "1.0.24"
460
+ source = "registry+https://github.com/rust-lang/crates.io-index"
461
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
462
+
463
+ [[package]]
464
+ name = "unindent"
465
+ version = "0.2.4"
466
+ source = "registry+https://github.com/rust-lang/crates.io-index"
467
+ checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
468
+
469
+ [[package]]
470
+ name = "wasip2"
471
+ version = "1.0.2+wasi-0.2.9"
472
+ source = "registry+https://github.com/rust-lang/crates.io-index"
473
+ checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
474
+ dependencies = [
475
+ "wit-bindgen",
476
+ ]
477
+
478
+ [[package]]
479
+ name = "windows"
480
+ version = "0.61.3"
481
+ source = "registry+https://github.com/rust-lang/crates.io-index"
482
+ checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
483
+ dependencies = [
484
+ "windows-collections",
485
+ "windows-core",
486
+ "windows-future",
487
+ "windows-link 0.1.3",
488
+ "windows-numerics",
489
+ ]
490
+
491
+ [[package]]
492
+ name = "windows-collections"
493
+ version = "0.2.0"
494
+ source = "registry+https://github.com/rust-lang/crates.io-index"
495
+ checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
496
+ dependencies = [
497
+ "windows-core",
498
+ ]
499
+
500
+ [[package]]
501
+ name = "windows-core"
502
+ version = "0.61.2"
503
+ source = "registry+https://github.com/rust-lang/crates.io-index"
504
+ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
505
+ dependencies = [
506
+ "windows-implement",
507
+ "windows-interface",
508
+ "windows-link 0.1.3",
509
+ "windows-result",
510
+ "windows-strings",
511
+ ]
512
+
513
+ [[package]]
514
+ name = "windows-future"
515
+ version = "0.2.1"
516
+ source = "registry+https://github.com/rust-lang/crates.io-index"
517
+ checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
518
+ dependencies = [
519
+ "windows-core",
520
+ "windows-link 0.1.3",
521
+ "windows-threading",
522
+ ]
523
+
524
+ [[package]]
525
+ name = "windows-implement"
526
+ version = "0.60.2"
527
+ source = "registry+https://github.com/rust-lang/crates.io-index"
528
+ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
529
+ dependencies = [
530
+ "proc-macro2",
531
+ "quote",
532
+ "syn",
533
+ ]
534
+
535
+ [[package]]
536
+ name = "windows-interface"
537
+ version = "0.59.3"
538
+ source = "registry+https://github.com/rust-lang/crates.io-index"
539
+ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
540
+ dependencies = [
541
+ "proc-macro2",
542
+ "quote",
543
+ "syn",
544
+ ]
545
+
546
+ [[package]]
547
+ name = "windows-link"
548
+ version = "0.1.3"
549
+ source = "registry+https://github.com/rust-lang/crates.io-index"
550
+ checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
551
+
552
+ [[package]]
553
+ name = "windows-link"
554
+ version = "0.2.1"
555
+ source = "registry+https://github.com/rust-lang/crates.io-index"
556
+ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
557
+
558
+ [[package]]
559
+ name = "windows-numerics"
560
+ version = "0.2.0"
561
+ source = "registry+https://github.com/rust-lang/crates.io-index"
562
+ checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
563
+ dependencies = [
564
+ "windows-core",
565
+ "windows-link 0.1.3",
566
+ ]
567
+
568
+ [[package]]
569
+ name = "windows-result"
570
+ version = "0.3.4"
571
+ source = "registry+https://github.com/rust-lang/crates.io-index"
572
+ checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
573
+ dependencies = [
574
+ "windows-link 0.1.3",
575
+ ]
576
+
577
+ [[package]]
578
+ name = "windows-strings"
579
+ version = "0.4.2"
580
+ source = "registry+https://github.com/rust-lang/crates.io-index"
581
+ checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
582
+ dependencies = [
583
+ "windows-link 0.1.3",
584
+ ]
585
+
586
+ [[package]]
587
+ name = "windows-sys"
588
+ version = "0.61.2"
589
+ source = "registry+https://github.com/rust-lang/crates.io-index"
590
+ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
591
+ dependencies = [
592
+ "windows-link 0.2.1",
593
+ ]
594
+
595
+ [[package]]
596
+ name = "windows-threading"
597
+ version = "0.1.0"
598
+ source = "registry+https://github.com/rust-lang/crates.io-index"
599
+ checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
600
+ dependencies = [
601
+ "windows-link 0.1.3",
602
+ ]
603
+
604
+ [[package]]
605
+ name = "wit-bindgen"
606
+ version = "0.51.0"
607
+ source = "registry+https://github.com/rust-lang/crates.io-index"
608
+ checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
609
+
610
+ [[package]]
611
+ name = "x11rb"
612
+ version = "0.13.2"
613
+ source = "registry+https://github.com/rust-lang/crates.io-index"
614
+ checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414"
615
+ dependencies = [
616
+ "gethostname",
617
+ "rustix",
618
+ "x11rb-protocol",
619
+ ]
620
+
621
+ [[package]]
622
+ name = "x11rb-protocol"
623
+ version = "0.13.2"
624
+ source = "registry+https://github.com/rust-lang/crates.io-index"
625
+ checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd"
626
+
627
+ [[package]]
628
+ name = "xkbcommon"
629
+ version = "0.9.0"
630
+ source = "registry+https://github.com/rust-lang/crates.io-index"
631
+ checksum = "a7a974f48060a14e95705c01f24ad9c3345022f4d97441b8a36beb7ed5c4a02d"
632
+ dependencies = [
633
+ "libc",
634
+ "memmap2",
635
+ "xkeysym",
636
+ ]
637
+
638
+ [[package]]
639
+ name = "xkeysym"
640
+ version = "0.2.1"
641
+ source = "registry+https://github.com/rust-lang/crates.io-index"
642
+ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
643
+
644
+ [[package]]
645
+ name = "zerocopy"
646
+ version = "0.8.40"
647
+ source = "registry+https://github.com/rust-lang/crates.io-index"
648
+ checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5"
649
+ dependencies = [
650
+ "zerocopy-derive",
651
+ ]
652
+
653
+ [[package]]
654
+ name = "zerocopy-derive"
655
+ version = "0.8.40"
656
+ source = "registry+https://github.com/rust-lang/crates.io-index"
657
+ checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953"
658
+ dependencies = [
659
+ "proc-macro2",
660
+ "quote",
661
+ "syn",
662
+ ]
@@ -0,0 +1,15 @@
1
+ [package]
2
+ name = "rust_mouse"
3
+ version = "0.1.0"
4
+ edition = "2024"
5
+
6
+ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
+ [lib]
8
+ name = "rust_mouse"
9
+ crate-type = ["cdylib"]
10
+
11
+ [dependencies]
12
+ enigo = "0.6.1"
13
+ pyo3 = "0.27.0"
14
+ rand = "0.9.2"
15
+ spin_sleep = "1.3.3"
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: rust-mouse
3
+ Version: 0.1.0
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
7
+ Requires-Python: >=3.10
@@ -0,0 +1,13 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.10,<2.0"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ name = "rust-mouse"
7
+ requires-python = ">=3.10"
8
+ classifiers = [
9
+ "Programming Language :: Rust",
10
+ "Programming Language :: Python :: Implementation :: CPython",
11
+ "Programming Language :: Python :: Implementation :: PyPy",
12
+ ]
13
+ dynamic = ["version"]
File without changes
@@ -0,0 +1,339 @@
1
+ use enigo::{Coordinate, Enigo, Mouse, Settings};
2
+ use pyo3::prelude::*;
3
+ use rand::{rng, Rng};
4
+ use std::f64::consts::PI;
5
+ use std::time::Duration;
6
+
7
+ #[derive(Clone, Copy, Debug)]
8
+ struct Point {
9
+ x: f64,
10
+ y: f64,
11
+ }
12
+
13
+ impl Point {
14
+ fn new(x: f64, y: f64) -> Self {
15
+ Point { x, y }
16
+ }
17
+
18
+ fn distance_to(&self, other: &Point) -> f64 {
19
+ ((self.x - other.x).powi(2) + (self.y - other.y).powi(2)).sqrt()
20
+ }
21
+ }
22
+
23
+ #[derive(Clone, Copy, Debug)]
24
+ enum EasingFunction {
25
+ QuarticOut,
26
+ CubicOut,
27
+ QuintOut,
28
+ ExpoOut,
29
+ SineOut,
30
+ CircOut,
31
+ }
32
+
33
+ impl EasingFunction {
34
+ fn random(rng: &mut impl Rng) -> Self {
35
+ match rng.random_range(0..6) {
36
+ 0 => EasingFunction::QuarticOut,
37
+ 1 => EasingFunction::CubicOut,
38
+ 2 => EasingFunction::QuintOut,
39
+ 3 => EasingFunction::ExpoOut,
40
+ 4 => EasingFunction::SineOut,
41
+ _ => EasingFunction::CircOut,
42
+ }
43
+ }
44
+
45
+ fn apply(&self, x: f64) -> f64 {
46
+ match self {
47
+ EasingFunction::QuarticOut => 1.0 - (1.0 - x).powi(4),
48
+ EasingFunction::CubicOut => 1.0 - (1.0 - x).powi(3),
49
+ EasingFunction::QuintOut => 1.0 - (1.0 - x).powi(5),
50
+ EasingFunction::ExpoOut => {
51
+ if x >= 1.0 { 1.0 } else { 1.0 - 2.0_f64.powf(-10.0 * x) }
52
+ }
53
+ EasingFunction::SineOut => (x * PI / 2.0).sin(),
54
+ EasingFunction::CircOut => (1.0 - (1.0 - x).powi(2)).sqrt(),
55
+ }
56
+ }
57
+ }
58
+
59
+ fn cubic_bezier(t: f64, p0: Point, p1: Point, p2: Point, p3: Point) -> Point {
60
+ let u = 1.0 - t;
61
+ let tt = t * t;
62
+ let uu = u * u;
63
+ let uuu = uu * u;
64
+ let ttt = tt * t;
65
+
66
+ let x = uuu * p0.x + 3.0 * uu * t * p1.x + 3.0 * u * tt * p2.x + ttt * p3.x;
67
+ let y = uuu * p0.y + 3.0 * uu * t * p1.y + 3.0 * u * tt * p2.y + ttt * p3.y;
68
+
69
+ Point::new(x, y)
70
+ }
71
+
72
+ fn calculate_fitts_duration(distance: f64, target_width: f64, rng: &mut impl Rng) -> u64 {
73
+ let a = 200.0;
74
+ let b = 250.0;
75
+ let id = (distance / target_width + 1.0).log2();
76
+ let base_duration = a + b * id;
77
+ let random_factor = rng.random_range(0.85..1.15);
78
+ (base_duration * random_factor).round() as u64
79
+ }
80
+
81
+ fn multi_octave_noise(t: f64, phase_x: f64, phase_y: f64, octaves: u8) -> Point {
82
+ let mut x_noise = 0.0;
83
+ let mut y_noise = 0.0;
84
+ let mut amplitude = 1.0;
85
+ let mut frequency = 1.0;
86
+
87
+ for _ in 0..octaves {
88
+ x_noise += ((t * frequency * 2.0 * PI + phase_x).sin()
89
+ + (t * frequency * 7.0 * PI + phase_x * 1.3).sin() * 0.5) * amplitude;
90
+ y_noise += ((t * frequency * 3.0 * PI + phase_y).cos()
91
+ + (t * frequency * 5.0 * PI + phase_y * 0.7).cos() * 0.5) * amplitude;
92
+ amplitude *= 0.5;
93
+ frequency *= 2.0;
94
+ }
95
+
96
+ Point::new(x_noise, y_noise)
97
+ }
98
+
99
+ fn calculate_tremor(t: f64, magnitude: f64, phase_x: f64, phase_y: f64, speed_factor: f64) -> Point {
100
+ let noise = multi_octave_noise(t, phase_x, phase_y, 3);
101
+
102
+ let drift_x = (t * 2.0 * PI + phase_x).sin();
103
+ let drift_y = (t * 3.0 * PI + phase_y).cos();
104
+
105
+ let jitter_x = (t * 12.0 * PI + phase_x).sin() * 0.3;
106
+ let jitter_y = (t * 12.0 * PI + phase_y).cos() * 0.3;
107
+
108
+ let damping = 1.0 - t.powi(2);
109
+ let speed_multiplier = 1.0 + speed_factor * 0.5;
110
+
111
+ Point::new(
112
+ (drift_x + jitter_x + noise.x * 0.3) * magnitude * damping * speed_multiplier,
113
+ (drift_y + jitter_y + noise.y * 0.3) * magnitude * damping * speed_multiplier,
114
+ )
115
+ }
116
+
117
+ fn apply_arrival_drift(enigo: &mut Enigo, target: Point, rng: &mut impl Rng) -> PyResult<()> {
118
+ if rng.random_bool(0.2) {
119
+ return Ok(());
120
+ }
121
+
122
+ let drift_count = rng.random_range(2..=5);
123
+ let pattern = rng.random_range(0..3);
124
+
125
+ for i in 0..drift_count {
126
+ let t = i as f64 / drift_count as f64;
127
+ let drift_range = rng.random_range(1.0..3.0);
128
+
129
+ let (dx, dy) = match pattern {
130
+ 0 => {
131
+ let angle = t * 2.0 * PI + rng.random_range(0.0..PI);
132
+ (angle.cos() * drift_range, angle.sin() * drift_range)
133
+ }
134
+ 1 => {
135
+ let offset = rng.random_range(-drift_range..drift_range);
136
+ if i % 2 == 0 { (offset, 0.0) } else { (0.0, offset) }
137
+ }
138
+ _ => {
139
+ let angle = t * 4.0 * PI;
140
+ (angle.cos() * drift_range * 0.5, angle.sin() * drift_range)
141
+ }
142
+ };
143
+
144
+ let new_x = target.x + dx;
145
+ let new_y = target.y + dy;
146
+
147
+ let _ = enigo.move_mouse(new_x as i32, new_y as i32, Coordinate::Abs);
148
+ spin_sleep::sleep(Duration::from_millis(rng.random_range(30..=80)));
149
+ }
150
+
151
+ let _ = enigo.move_mouse(target.x as i32, target.y as i32, Coordinate::Abs);
152
+ Ok(())
153
+ }
154
+
155
+ fn should_add_mistake(rng: &mut impl Rng, overshoot: bool) -> bool {
156
+ !overshoot && rng.random_bool(0.05)
157
+ }
158
+
159
+ fn calculate_pause_points(distance: f64, rng: &mut impl Rng) -> Vec<f64> {
160
+ if distance < 500.0 {
161
+ return vec![];
162
+ }
163
+
164
+ let pause_count = if distance > 1000.0 {
165
+ rng.random_range(1..=2)
166
+ } else {
167
+ if rng.random_bool(0.5) { 1 } else { 0 }
168
+ };
169
+
170
+ let mut pauses = Vec::new();
171
+ for _ in 0..pause_count {
172
+ pauses.push(rng.random_range(0.3..0.7));
173
+ }
174
+ pauses.sort_by(|a, b| a.partial_cmp(b).unwrap());
175
+ pauses
176
+ }
177
+
178
+ fn apply_pause_with_drift(enigo: &mut Enigo, current: Point, rng: &mut impl Rng) -> PyResult<()> {
179
+ let pause_duration = rng.random_range(50..=200);
180
+ let wobble_count = rng.random_range(2..=4);
181
+
182
+ for _ in 0..wobble_count {
183
+ let wobble_x = current.x + rng.random_range(-3.0..3.0);
184
+ let wobble_y = current.y + rng.random_range(-3.0..3.0);
185
+ let _ = enigo.move_mouse(wobble_x as i32, wobble_y as i32, Coordinate::Abs);
186
+ spin_sleep::sleep(Duration::from_millis(pause_duration / wobble_count));
187
+ }
188
+
189
+ Ok(())
190
+ }
191
+
192
+ #[pyfunction]
193
+ #[pyo3(signature = (target_x, target_y, duration_ms=None, deviation=50.0, overshoot=false, allow_pauses=None))]
194
+ fn move_mouse_human(
195
+ target_x: f64,
196
+ target_y: f64,
197
+ duration_ms: Option<u64>,
198
+ deviation: f64,
199
+ overshoot: bool,
200
+ allow_pauses: Option<bool>,
201
+ ) -> PyResult<()> {
202
+ let settings = Settings::default();
203
+ let mut enigo = Enigo::new(&settings)
204
+ .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
205
+
206
+ let mut rng = rng();
207
+
208
+ let init_delay = rng.random_range(50..=200);
209
+ spin_sleep::sleep(Duration::from_millis(init_delay));
210
+
211
+ let (current_x, current_y) = enigo.location()
212
+ .map_err(|e| PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()))?;
213
+
214
+ let start = Point::new(current_x as f64, current_y as f64);
215
+ let end = Point::new(target_x, target_y);
216
+
217
+ if start.x == end.x && start.y == end.y {
218
+ return Ok(());
219
+ }
220
+
221
+ let distance = start.distance_to(&end);
222
+
223
+ let movement_duration = match duration_ms {
224
+ Some(dur) => dur,
225
+ None => {
226
+ let target_width = if distance < 100.0 { 50.0 } else { 100.0 };
227
+ calculate_fitts_duration(distance, target_width, &mut rng)
228
+ }
229
+ };
230
+
231
+ let dist_x = end.x - start.x;
232
+ let dist_y = end.y - start.y;
233
+
234
+ let should_mistake = should_add_mistake(&mut rng, overshoot);
235
+ let mistake_direction = if should_mistake {
236
+ Some((rng.random_range(-0.15..0.15), rng.random_range(-0.15..0.15)))
237
+ } else {
238
+ None
239
+ };
240
+
241
+ let p1_factor = rng.random_range(0.15..0.35);
242
+ let p2_factor = rng.random_range(0.75..0.90);
243
+
244
+ let arc_direction = if rng.random_bool(0.5) { 1.0 } else { -1.0 };
245
+ let wide_arc = rng.random_bool(0.15);
246
+ let arc_deviation = if wide_arc { deviation * 2.0 } else { deviation };
247
+
248
+ let p1 = if let Some((dx, dy)) = mistake_direction {
249
+ Point::new(
250
+ start.x + dist_x * dx,
251
+ start.y + dist_y * dy,
252
+ )
253
+ } else {
254
+ Point::new(
255
+ start.x + dist_x * p1_factor + rng.random_range(0.0..arc_deviation) * arc_direction,
256
+ start.y + dist_y * p1_factor + rng.random_range(0.0..arc_deviation) * arc_direction,
257
+ )
258
+ };
259
+
260
+ let overshoot_factor = if overshoot || should_mistake {
261
+ rng.random_range(1.08..1.18)
262
+ } else {
263
+ 1.0
264
+ };
265
+
266
+ let p2 = Point::new(
267
+ start.x + dist_x * p2_factor * overshoot_factor + rng.random_range(-10.0..10.0),
268
+ start.y + dist_y * p2_factor * overshoot_factor + rng.random_range(-10.0..10.0),
269
+ );
270
+
271
+ let phase_x = rng.random_range(0.0..2.0 * PI);
272
+ let phase_y = rng.random_range(0.0..2.0 * PI);
273
+
274
+ let easing_function = EasingFunction::random(&mut rng);
275
+
276
+ let pauses_enabled = allow_pauses.unwrap_or(distance > 500.0);
277
+ let pause_points = if pauses_enabled {
278
+ calculate_pause_points(distance, &mut rng)
279
+ } else {
280
+ vec![]
281
+ };
282
+ let mut pause_idx = 0;
283
+
284
+ let base_step_time = if distance < 100.0 { 6.0 } else { 8.0 };
285
+ let steps = (movement_duration as f64 / base_step_time).ceil() as u64;
286
+
287
+ for i in 1..=steps {
288
+ let t_linear = i as f64 / steps as f64;
289
+
290
+ if pause_idx < pause_points.len() {
291
+ let pause_threshold = pause_points[pause_idx];
292
+ if t_linear >= pause_threshold && t_linear < pause_threshold + 0.05 {
293
+ let current_pos = cubic_bezier(easing_function.apply(t_linear), start, p1, p2, end);
294
+ apply_pause_with_drift(&mut enigo, current_pos, &mut rng)?;
295
+ pause_idx += 1;
296
+ }
297
+ }
298
+
299
+ let jitter_factor = rng.random_range(0.95..1.05);
300
+ let t_eased = easing_function.apply(t_linear * jitter_factor);
301
+
302
+ let mut point = cubic_bezier(t_eased, start, p1, p2, end);
303
+
304
+ let speed_factor = if distance < 100.0 { 0.5 } else if distance > 500.0 { 1.5 } else { 1.0 };
305
+ let tremor_mag = if overshoot || should_mistake {
306
+ rng.random_range(2.5..4.0)
307
+ } else {
308
+ rng.random_range(1.0..2.0)
309
+ };
310
+
311
+ let noise = calculate_tremor(t_linear, tremor_mag, phase_x, phase_y, speed_factor);
312
+
313
+ point.x += noise.x;
314
+ point.y += noise.y;
315
+
316
+ let _ = enigo.move_mouse(point.x as i32, point.y as i32, Coordinate::Abs);
317
+
318
+ let step_delay = rng.random_range(6..=12);
319
+ let micro_delay = if rng.random_bool(0.1) {
320
+ rng.random_range(10..=30)
321
+ } else {
322
+ 0
323
+ };
324
+
325
+ spin_sleep::sleep(Duration::from_millis(step_delay + micro_delay));
326
+ }
327
+
328
+ let _ = enigo.move_mouse(target_x as i32, target_y as i32, Coordinate::Abs);
329
+
330
+ apply_arrival_drift(&mut enigo, end, &mut rng)?;
331
+
332
+ Ok(())
333
+ }
334
+
335
+ #[pymodule]
336
+ fn rust_mouse(m: &Bound<'_, PyModule>) -> PyResult<()> {
337
+ m.add_function(wrap_pyfunction!(move_mouse_human, m)?)?;
338
+ Ok(())
339
+ }