deskbot 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +5 -0
- data/Cargo.lock +238 -57
- data/README.md +37 -0
- data/ext/deskbot/Cargo.toml +5 -4
- data/ext/deskbot/src/bitmap.rs +3 -3
- data/ext/deskbot/src/lib.rs +6 -3
- data/ext/deskbot/src/listen.rs +195 -0
- data/lib/deskbot/event.rb +135 -0
- data/lib/deskbot/providers/autopilot.rb +1 -0
- data/lib/deskbot/screen.rb +12 -1
- data/lib/deskbot/version.rb +1 -1
- data/lib/deskbot.rb +1 -0
- metadata +5 -7
- data/sig/deskbot.rbs +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: da7d37a439362a3cb1a37ce6b4fcd61695934e37eb1a7f4fed655890b0951e76
|
|
4
|
+
data.tar.gz: b282f88eccf10ff28175950599ef2c8d6ea8493e9f64bbd2f25663319df555d8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6a0b040f9fb91fbf6432655fd678f7de9597543c18e0676de849f6a0640ca64dc0b5da239e2f6c8149202b36f3de9904cede8f863e17045f5d1825ec0c7c2e77
|
|
7
|
+
data.tar.gz: 79dc6bbadff2ffff4b5e74f90c50fa7c1bb531a78ee18757501c4ffe13b2c46bc43d32e781f59adf877e3ee72163472434567fb6e53f1cd37380326c71e190c3
|
data/CHANGELOG.md
CHANGED
data/Cargo.lock
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This file is automatically @generated by Cargo.
|
|
2
2
|
# It is not intended for manual editing.
|
|
3
|
-
version =
|
|
3
|
+
version = 4
|
|
4
4
|
|
|
5
5
|
[[package]]
|
|
6
6
|
name = "adler32"
|
|
@@ -30,7 +30,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
30
30
|
checksum = "3a2fd0359d0cd30b15419bcce7e6641a3cbe2046c612b3900216dc64bc989558"
|
|
31
31
|
dependencies = [
|
|
32
32
|
"cocoa",
|
|
33
|
-
"core-foundation",
|
|
33
|
+
"core-foundation 0.7.0",
|
|
34
34
|
"core-graphics",
|
|
35
35
|
"image",
|
|
36
36
|
"libc",
|
|
@@ -43,21 +43,19 @@ dependencies = [
|
|
|
43
43
|
|
|
44
44
|
[[package]]
|
|
45
45
|
name = "bindgen"
|
|
46
|
-
version = "0.
|
|
46
|
+
version = "0.72.1"
|
|
47
47
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
48
|
-
checksum = "
|
|
48
|
+
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
|
49
49
|
dependencies = [
|
|
50
50
|
"bitflags 2.5.0",
|
|
51
51
|
"cexpr",
|
|
52
52
|
"clang-sys",
|
|
53
53
|
"itertools",
|
|
54
|
-
"lazy_static",
|
|
55
|
-
"lazycell",
|
|
56
54
|
"proc-macro2 1.0.83",
|
|
57
55
|
"quote 1.0.36",
|
|
58
56
|
"regex",
|
|
59
57
|
"rustc-hash",
|
|
60
|
-
"shlex",
|
|
58
|
+
"shlex 1.3.0",
|
|
61
59
|
"syn 2.0.65",
|
|
62
60
|
]
|
|
63
61
|
|
|
@@ -140,7 +138,7 @@ checksum = "0c49e86fc36d5704151f5996b7b3795385f50ce09e3be0f47a0cfde869681cf8"
|
|
|
140
138
|
dependencies = [
|
|
141
139
|
"bitflags 1.3.2",
|
|
142
140
|
"block",
|
|
143
|
-
"core-foundation",
|
|
141
|
+
"core-foundation 0.7.0",
|
|
144
142
|
"core-graphics",
|
|
145
143
|
"foreign-types",
|
|
146
144
|
"libc",
|
|
@@ -159,7 +157,17 @@ version = "0.7.0"
|
|
|
159
157
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
160
158
|
checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
|
|
161
159
|
dependencies = [
|
|
162
|
-
"core-foundation-sys",
|
|
160
|
+
"core-foundation-sys 0.7.0",
|
|
161
|
+
"libc",
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
[[package]]
|
|
165
|
+
name = "core-foundation"
|
|
166
|
+
version = "0.9.4"
|
|
167
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
168
|
+
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
|
169
|
+
dependencies = [
|
|
170
|
+
"core-foundation-sys 0.8.7",
|
|
163
171
|
"libc",
|
|
164
172
|
]
|
|
165
173
|
|
|
@@ -169,6 +177,12 @@ version = "0.7.0"
|
|
|
169
177
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
170
178
|
checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
|
|
171
179
|
|
|
180
|
+
[[package]]
|
|
181
|
+
name = "core-foundation-sys"
|
|
182
|
+
version = "0.8.7"
|
|
183
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
184
|
+
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
|
185
|
+
|
|
172
186
|
[[package]]
|
|
173
187
|
name = "core-graphics"
|
|
174
188
|
version = "0.19.2"
|
|
@@ -176,7 +190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
176
190
|
checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923"
|
|
177
191
|
dependencies = [
|
|
178
192
|
"bitflags 1.3.2",
|
|
179
|
-
"core-foundation",
|
|
193
|
+
"core-foundation 0.7.0",
|
|
180
194
|
"foreign-types",
|
|
181
195
|
"libc",
|
|
182
196
|
]
|
|
@@ -230,11 +244,26 @@ name = "deskbot"
|
|
|
230
244
|
version = "0.1.0"
|
|
231
245
|
dependencies = [
|
|
232
246
|
"autopilot",
|
|
247
|
+
"device_query",
|
|
233
248
|
"image",
|
|
234
249
|
"magnus",
|
|
235
250
|
"opencv",
|
|
236
251
|
]
|
|
237
252
|
|
|
253
|
+
[[package]]
|
|
254
|
+
name = "device_query"
|
|
255
|
+
version = "4.0.1"
|
|
256
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
257
|
+
checksum = "d7331225604b9b097b41872d550134933d4be83465d70a2c4a132b929f99aaca"
|
|
258
|
+
dependencies = [
|
|
259
|
+
"macos-accessibility-client",
|
|
260
|
+
"pkg-config",
|
|
261
|
+
"readkey",
|
|
262
|
+
"readmouse",
|
|
263
|
+
"windows 0.48.0",
|
|
264
|
+
"x11",
|
|
265
|
+
]
|
|
266
|
+
|
|
238
267
|
[[package]]
|
|
239
268
|
name = "dunce"
|
|
240
269
|
version = "1.0.4"
|
|
@@ -348,12 +377,6 @@ version = "1.4.0"
|
|
|
348
377
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
349
378
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|
350
379
|
|
|
351
|
-
[[package]]
|
|
352
|
-
name = "lazycell"
|
|
353
|
-
version = "1.3.0"
|
|
354
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
355
|
-
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|
356
|
-
|
|
357
380
|
[[package]]
|
|
358
381
|
name = "libc"
|
|
359
382
|
version = "0.2.155"
|
|
@@ -367,7 +390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
367
390
|
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
|
368
391
|
dependencies = [
|
|
369
392
|
"cfg-if",
|
|
370
|
-
"windows-targets",
|
|
393
|
+
"windows-targets 0.52.5",
|
|
371
394
|
]
|
|
372
395
|
|
|
373
396
|
[[package]]
|
|
@@ -376,11 +399,21 @@ version = "0.10.0"
|
|
|
376
399
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
377
400
|
checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
|
|
378
401
|
|
|
402
|
+
[[package]]
|
|
403
|
+
name = "macos-accessibility-client"
|
|
404
|
+
version = "0.0.1"
|
|
405
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
406
|
+
checksum = "edf7710fbff50c24124331760978fb9086d6de6288dcdb38b25a97f8b1bdebbb"
|
|
407
|
+
dependencies = [
|
|
408
|
+
"core-foundation 0.9.4",
|
|
409
|
+
"core-foundation-sys 0.8.7",
|
|
410
|
+
]
|
|
411
|
+
|
|
379
412
|
[[package]]
|
|
380
413
|
name = "magnus"
|
|
381
|
-
version = "0.
|
|
414
|
+
version = "0.8.2"
|
|
382
415
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
383
|
-
checksum = "
|
|
416
|
+
checksum = "3b36a5b126bbe97eb0d02d07acfeb327036c6319fd816139a49824a83b7f9012"
|
|
384
417
|
dependencies = [
|
|
385
418
|
"magnus-macros",
|
|
386
419
|
"rb-sys",
|
|
@@ -390,9 +423,9 @@ dependencies = [
|
|
|
390
423
|
|
|
391
424
|
[[package]]
|
|
392
425
|
name = "magnus-macros"
|
|
393
|
-
version = "0.
|
|
426
|
+
version = "0.8.0"
|
|
394
427
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
395
|
-
checksum = "
|
|
428
|
+
checksum = "47607461fd8e1513cb4f2076c197d8092d921a1ea75bd08af97398f593751892"
|
|
396
429
|
dependencies = [
|
|
397
430
|
"proc-macro2 1.0.83",
|
|
398
431
|
"quote 1.0.36",
|
|
@@ -498,36 +531,37 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
|
|
498
531
|
|
|
499
532
|
[[package]]
|
|
500
533
|
name = "opencv"
|
|
501
|
-
version = "0.
|
|
534
|
+
version = "0.100.1"
|
|
502
535
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
503
|
-
checksum = "
|
|
536
|
+
checksum = "08cb1e12c6c3f533f6b1f2c573c73ea42e07e75c4891af6cea9679508fd61e1f"
|
|
504
537
|
dependencies = [
|
|
505
538
|
"cc",
|
|
506
539
|
"dunce",
|
|
507
540
|
"jobserver",
|
|
508
541
|
"libc",
|
|
509
542
|
"num-traits",
|
|
510
|
-
"once_cell",
|
|
511
543
|
"opencv-binding-generator",
|
|
512
544
|
"pkg-config",
|
|
513
545
|
"semver",
|
|
514
|
-
"shlex",
|
|
546
|
+
"shlex 2.0.1",
|
|
515
547
|
"vcpkg",
|
|
516
|
-
"windows",
|
|
548
|
+
"windows 0.62.2",
|
|
549
|
+
"winsplit",
|
|
517
550
|
]
|
|
518
551
|
|
|
519
552
|
[[package]]
|
|
520
553
|
name = "opencv-binding-generator"
|
|
521
|
-
version = "0.
|
|
554
|
+
version = "0.105.0"
|
|
522
555
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
523
|
-
checksum = "
|
|
556
|
+
checksum = "619e1ab8e9b95beb1eb7919ab34710027894db29428634f6680dfde15eb004f0"
|
|
524
557
|
dependencies = [
|
|
525
558
|
"clang",
|
|
526
559
|
"clang-sys",
|
|
527
560
|
"dunce",
|
|
528
|
-
"once_cell",
|
|
529
561
|
"percent-encoding",
|
|
530
562
|
"regex",
|
|
563
|
+
"semver",
|
|
564
|
+
"shlex 2.0.1",
|
|
531
565
|
]
|
|
532
566
|
|
|
533
567
|
[[package]]
|
|
@@ -659,18 +693,18 @@ dependencies = [
|
|
|
659
693
|
|
|
660
694
|
[[package]]
|
|
661
695
|
name = "rb-sys"
|
|
662
|
-
version = "0.9.
|
|
696
|
+
version = "0.9.130"
|
|
663
697
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
664
|
-
checksum = "
|
|
698
|
+
checksum = "02faf625bb10ba893e3ae620f19c9fb1b5f8fcae0fe4eb86bb3f2230fad75edb"
|
|
665
699
|
dependencies = [
|
|
666
700
|
"rb-sys-build",
|
|
667
701
|
]
|
|
668
702
|
|
|
669
703
|
[[package]]
|
|
670
704
|
name = "rb-sys-build"
|
|
671
|
-
version = "0.9.
|
|
705
|
+
version = "0.9.130"
|
|
672
706
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
673
|
-
checksum = "
|
|
707
|
+
checksum = "05be6f9c86fe5482808162826f6c047d093b3670582296c770de1d94f8066694"
|
|
674
708
|
dependencies = [
|
|
675
709
|
"bindgen",
|
|
676
710
|
"lazy_static",
|
|
@@ -683,9 +717,21 @@ dependencies = [
|
|
|
683
717
|
|
|
684
718
|
[[package]]
|
|
685
719
|
name = "rb-sys-env"
|
|
686
|
-
version = "0.
|
|
720
|
+
version = "0.2.3"
|
|
687
721
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
688
|
-
checksum = "
|
|
722
|
+
checksum = "cca7ad6a7e21e72151d56fe2495a259b5670e204c3adac41ee7ef676ea08117a"
|
|
723
|
+
|
|
724
|
+
[[package]]
|
|
725
|
+
name = "readkey"
|
|
726
|
+
version = "0.2.2"
|
|
727
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
728
|
+
checksum = "8a36870cefdfcff57edbc0fa62165f42dfd4e5a0d8965117c1ea84c5700e4450"
|
|
729
|
+
|
|
730
|
+
[[package]]
|
|
731
|
+
name = "readmouse"
|
|
732
|
+
version = "0.2.1"
|
|
733
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
734
|
+
checksum = "be105c72a1e6a5a1198acee3d5b506a15676b74a02ecd78060042a447f408d94"
|
|
689
735
|
|
|
690
736
|
[[package]]
|
|
691
737
|
name = "regex"
|
|
@@ -718,9 +764,9 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
|
|
718
764
|
|
|
719
765
|
[[package]]
|
|
720
766
|
name = "rustc-hash"
|
|
721
|
-
version = "
|
|
767
|
+
version = "2.1.3"
|
|
722
768
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
723
|
-
checksum = "
|
|
769
|
+
checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
|
|
724
770
|
|
|
725
771
|
[[package]]
|
|
726
772
|
name = "scoped_threadpool"
|
|
@@ -758,6 +804,12 @@ version = "1.3.0"
|
|
|
758
804
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
759
805
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|
760
806
|
|
|
807
|
+
[[package]]
|
|
808
|
+
name = "shlex"
|
|
809
|
+
version = "2.0.1"
|
|
810
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
811
|
+
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
|
812
|
+
|
|
761
813
|
[[package]]
|
|
762
814
|
name = "syn"
|
|
763
815
|
version = "0.15.44"
|
|
@@ -840,31 +892,63 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
|
840
892
|
|
|
841
893
|
[[package]]
|
|
842
894
|
name = "windows"
|
|
843
|
-
version = "0.
|
|
895
|
+
version = "0.48.0"
|
|
896
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
897
|
+
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
|
898
|
+
dependencies = [
|
|
899
|
+
"windows-targets 0.48.5",
|
|
900
|
+
]
|
|
901
|
+
|
|
902
|
+
[[package]]
|
|
903
|
+
name = "windows"
|
|
904
|
+
version = "0.62.2"
|
|
905
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
906
|
+
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
|
907
|
+
dependencies = [
|
|
908
|
+
"windows-collections",
|
|
909
|
+
"windows-core",
|
|
910
|
+
"windows-future",
|
|
911
|
+
"windows-numerics",
|
|
912
|
+
]
|
|
913
|
+
|
|
914
|
+
[[package]]
|
|
915
|
+
name = "windows-collections"
|
|
916
|
+
version = "0.3.2"
|
|
844
917
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
845
|
-
checksum = "
|
|
918
|
+
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
|
846
919
|
dependencies = [
|
|
847
920
|
"windows-core",
|
|
848
|
-
"windows-targets",
|
|
849
921
|
]
|
|
850
922
|
|
|
851
923
|
[[package]]
|
|
852
924
|
name = "windows-core"
|
|
853
|
-
version = "0.
|
|
925
|
+
version = "0.62.2"
|
|
854
926
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
855
|
-
checksum = "
|
|
927
|
+
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
|
856
928
|
dependencies = [
|
|
857
929
|
"windows-implement",
|
|
858
930
|
"windows-interface",
|
|
931
|
+
"windows-link",
|
|
859
932
|
"windows-result",
|
|
860
|
-
"windows-
|
|
933
|
+
"windows-strings",
|
|
934
|
+
]
|
|
935
|
+
|
|
936
|
+
[[package]]
|
|
937
|
+
name = "windows-future"
|
|
938
|
+
version = "0.3.2"
|
|
939
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
940
|
+
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
|
941
|
+
dependencies = [
|
|
942
|
+
"windows-core",
|
|
943
|
+
"windows-link",
|
|
944
|
+
"windows-threading",
|
|
861
945
|
]
|
|
862
946
|
|
|
863
947
|
[[package]]
|
|
864
948
|
name = "windows-implement"
|
|
865
|
-
version = "0.
|
|
949
|
+
version = "0.60.2"
|
|
866
950
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
867
|
-
checksum = "
|
|
951
|
+
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
|
868
952
|
dependencies = [
|
|
869
953
|
"proc-macro2 1.0.83",
|
|
870
954
|
"quote 1.0.36",
|
|
@@ -873,22 +957,62 @@ dependencies = [
|
|
|
873
957
|
|
|
874
958
|
[[package]]
|
|
875
959
|
name = "windows-interface"
|
|
876
|
-
version = "0.
|
|
960
|
+
version = "0.59.3"
|
|
877
961
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
878
|
-
checksum = "
|
|
962
|
+
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
|
879
963
|
dependencies = [
|
|
880
964
|
"proc-macro2 1.0.83",
|
|
881
965
|
"quote 1.0.36",
|
|
882
966
|
"syn 2.0.65",
|
|
883
967
|
]
|
|
884
968
|
|
|
969
|
+
[[package]]
|
|
970
|
+
name = "windows-link"
|
|
971
|
+
version = "0.2.1"
|
|
972
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
973
|
+
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
|
974
|
+
|
|
975
|
+
[[package]]
|
|
976
|
+
name = "windows-numerics"
|
|
977
|
+
version = "0.3.1"
|
|
978
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
979
|
+
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
|
980
|
+
dependencies = [
|
|
981
|
+
"windows-core",
|
|
982
|
+
"windows-link",
|
|
983
|
+
]
|
|
984
|
+
|
|
885
985
|
[[package]]
|
|
886
986
|
name = "windows-result"
|
|
887
|
-
version = "0.
|
|
987
|
+
version = "0.4.1"
|
|
988
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
989
|
+
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
|
990
|
+
dependencies = [
|
|
991
|
+
"windows-link",
|
|
992
|
+
]
|
|
993
|
+
|
|
994
|
+
[[package]]
|
|
995
|
+
name = "windows-strings"
|
|
996
|
+
version = "0.5.1"
|
|
997
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
998
|
+
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
|
999
|
+
dependencies = [
|
|
1000
|
+
"windows-link",
|
|
1001
|
+
]
|
|
1002
|
+
|
|
1003
|
+
[[package]]
|
|
1004
|
+
name = "windows-targets"
|
|
1005
|
+
version = "0.48.5"
|
|
888
1006
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
889
|
-
checksum = "
|
|
1007
|
+
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
|
890
1008
|
dependencies = [
|
|
891
|
-
"
|
|
1009
|
+
"windows_aarch64_gnullvm 0.48.5",
|
|
1010
|
+
"windows_aarch64_msvc 0.48.5",
|
|
1011
|
+
"windows_i686_gnu 0.48.5",
|
|
1012
|
+
"windows_i686_msvc 0.48.5",
|
|
1013
|
+
"windows_x86_64_gnu 0.48.5",
|
|
1014
|
+
"windows_x86_64_gnullvm 0.48.5",
|
|
1015
|
+
"windows_x86_64_msvc 0.48.5",
|
|
892
1016
|
]
|
|
893
1017
|
|
|
894
1018
|
[[package]]
|
|
@@ -897,28 +1021,55 @@ version = "0.52.5"
|
|
|
897
1021
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
898
1022
|
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
|
899
1023
|
dependencies = [
|
|
900
|
-
"windows_aarch64_gnullvm",
|
|
901
|
-
"windows_aarch64_msvc",
|
|
902
|
-
"windows_i686_gnu",
|
|
1024
|
+
"windows_aarch64_gnullvm 0.52.5",
|
|
1025
|
+
"windows_aarch64_msvc 0.52.5",
|
|
1026
|
+
"windows_i686_gnu 0.52.5",
|
|
903
1027
|
"windows_i686_gnullvm",
|
|
904
|
-
"windows_i686_msvc",
|
|
905
|
-
"windows_x86_64_gnu",
|
|
906
|
-
"windows_x86_64_gnullvm",
|
|
907
|
-
"windows_x86_64_msvc",
|
|
1028
|
+
"windows_i686_msvc 0.52.5",
|
|
1029
|
+
"windows_x86_64_gnu 0.52.5",
|
|
1030
|
+
"windows_x86_64_gnullvm 0.52.5",
|
|
1031
|
+
"windows_x86_64_msvc 0.52.5",
|
|
1032
|
+
]
|
|
1033
|
+
|
|
1034
|
+
[[package]]
|
|
1035
|
+
name = "windows-threading"
|
|
1036
|
+
version = "0.2.1"
|
|
1037
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1038
|
+
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
|
1039
|
+
dependencies = [
|
|
1040
|
+
"windows-link",
|
|
908
1041
|
]
|
|
909
1042
|
|
|
1043
|
+
[[package]]
|
|
1044
|
+
name = "windows_aarch64_gnullvm"
|
|
1045
|
+
version = "0.48.5"
|
|
1046
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1047
|
+
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|
1048
|
+
|
|
910
1049
|
[[package]]
|
|
911
1050
|
name = "windows_aarch64_gnullvm"
|
|
912
1051
|
version = "0.52.5"
|
|
913
1052
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
914
1053
|
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
|
915
1054
|
|
|
1055
|
+
[[package]]
|
|
1056
|
+
name = "windows_aarch64_msvc"
|
|
1057
|
+
version = "0.48.5"
|
|
1058
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1059
|
+
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|
1060
|
+
|
|
916
1061
|
[[package]]
|
|
917
1062
|
name = "windows_aarch64_msvc"
|
|
918
1063
|
version = "0.52.5"
|
|
919
1064
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
920
1065
|
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
|
921
1066
|
|
|
1067
|
+
[[package]]
|
|
1068
|
+
name = "windows_i686_gnu"
|
|
1069
|
+
version = "0.48.5"
|
|
1070
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1071
|
+
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|
1072
|
+
|
|
922
1073
|
[[package]]
|
|
923
1074
|
name = "windows_i686_gnu"
|
|
924
1075
|
version = "0.52.5"
|
|
@@ -931,30 +1082,60 @@ version = "0.52.5"
|
|
|
931
1082
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
932
1083
|
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
|
933
1084
|
|
|
1085
|
+
[[package]]
|
|
1086
|
+
name = "windows_i686_msvc"
|
|
1087
|
+
version = "0.48.5"
|
|
1088
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1089
|
+
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|
1090
|
+
|
|
934
1091
|
[[package]]
|
|
935
1092
|
name = "windows_i686_msvc"
|
|
936
1093
|
version = "0.52.5"
|
|
937
1094
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
938
1095
|
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
|
939
1096
|
|
|
1097
|
+
[[package]]
|
|
1098
|
+
name = "windows_x86_64_gnu"
|
|
1099
|
+
version = "0.48.5"
|
|
1100
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1101
|
+
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|
1102
|
+
|
|
940
1103
|
[[package]]
|
|
941
1104
|
name = "windows_x86_64_gnu"
|
|
942
1105
|
version = "0.52.5"
|
|
943
1106
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
944
1107
|
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
|
945
1108
|
|
|
1109
|
+
[[package]]
|
|
1110
|
+
name = "windows_x86_64_gnullvm"
|
|
1111
|
+
version = "0.48.5"
|
|
1112
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1113
|
+
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|
1114
|
+
|
|
946
1115
|
[[package]]
|
|
947
1116
|
name = "windows_x86_64_gnullvm"
|
|
948
1117
|
version = "0.52.5"
|
|
949
1118
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
950
1119
|
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
|
951
1120
|
|
|
1121
|
+
[[package]]
|
|
1122
|
+
name = "windows_x86_64_msvc"
|
|
1123
|
+
version = "0.48.5"
|
|
1124
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1125
|
+
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|
1126
|
+
|
|
952
1127
|
[[package]]
|
|
953
1128
|
name = "windows_x86_64_msvc"
|
|
954
1129
|
version = "0.52.5"
|
|
955
1130
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
956
1131
|
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
|
957
1132
|
|
|
1133
|
+
[[package]]
|
|
1134
|
+
name = "winsplit"
|
|
1135
|
+
version = "0.1.0"
|
|
1136
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1137
|
+
checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956"
|
|
1138
|
+
|
|
958
1139
|
[[package]]
|
|
959
1140
|
name = "x11"
|
|
960
1141
|
version = "2.21.0"
|
data/README.md
CHANGED
|
@@ -16,6 +16,9 @@ so I've rewritten matching templates to use
|
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
19
|
+
You will need to have installed [Rust](https://www.rust-lang.org/tools/install) and
|
|
20
|
+
[opencv](https://github.com/twistedfall/opencv-rust/blob/master/INSTALL.md)
|
|
21
|
+
|
|
19
22
|
Install the gem and add to the application's Gemfile by executing:
|
|
20
23
|
|
|
21
24
|
$ bundle add deskbot
|
|
@@ -215,6 +218,40 @@ bitmap.all_color([255, 255, 255, 0])
|
|
|
215
218
|
|
|
216
219
|
These will return `Deskbot::Point` objects with `x` and `y` attributes.
|
|
217
220
|
|
|
221
|
+
### Listening for device events
|
|
222
|
+
|
|
223
|
+
You can record device events (key presses, mouse button presses and mouse
|
|
224
|
+
movements) with a blocking `listen` loop. Each event is yielded:
|
|
225
|
+
|
|
226
|
+
- `Deskbot::Event::KeyDown`,
|
|
227
|
+
- `Deskbot::Event::KeyUp`
|
|
228
|
+
- `Deskbot::Event::MouseDown`
|
|
229
|
+
- `Deskbot::Event::MouseUp`
|
|
230
|
+
- `Deskbot::Event::MouseMove`
|
|
231
|
+
|
|
232
|
+
```ruby
|
|
233
|
+
Deskbot.screen.listen do |event|
|
|
234
|
+
case event
|
|
235
|
+
when Deskbot::Event::MouseMove
|
|
236
|
+
puts "mouse moved to #{event.x}, #{event.y}"
|
|
237
|
+
when Deskbot::Event::KeyDown
|
|
238
|
+
puts "key down: #{event.key}"
|
|
239
|
+
when Deskbot::Event::KeyUp
|
|
240
|
+
puts "key up: #{event.key}"
|
|
241
|
+
when Deskbot::Event::MouseDown
|
|
242
|
+
puts "button down: #{event.button}"
|
|
243
|
+
when Deskbot::Event::MouseUp
|
|
244
|
+
puts "button up: #{event.button}"
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Each event exposes only the fields relevant to it: key events have `key`, mouse
|
|
250
|
+
button events have `button`, and mouse movement events have `x`, `y` and
|
|
251
|
+
`coords`.
|
|
252
|
+
|
|
253
|
+
`listen` blocks the calling thread. Raising inside the block stops listening.
|
|
254
|
+
|
|
218
255
|
## Development
|
|
219
256
|
|
|
220
257
|
After checking out the repo, run `bin/setup` to install dependencies.
|
data/ext/deskbot/Cargo.toml
CHANGED
|
@@ -10,7 +10,8 @@ publish = false
|
|
|
10
10
|
crate-type = ["cdylib"]
|
|
11
11
|
|
|
12
12
|
[dependencies]
|
|
13
|
-
opencv = { version = "0.
|
|
14
|
-
magnus = { version = "0.
|
|
15
|
-
autopilot = { version = "0.4
|
|
16
|
-
|
|
13
|
+
opencv = { version = "0.100", features = ["clang-runtime"] }
|
|
14
|
+
magnus = { version = "0.8" }
|
|
15
|
+
autopilot = { version = "0.4" }
|
|
16
|
+
device_query = "4.0"
|
|
17
|
+
image = { version = "0.22" }
|
data/ext/deskbot/src/bitmap.rs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
extern crate autopilot;
|
|
2
2
|
|
|
3
3
|
use image::open;
|
|
4
|
-
use magnus::
|
|
4
|
+
use magnus::{Error, Ruby};
|
|
5
5
|
use std::collections::HashMap;
|
|
6
6
|
|
|
7
7
|
extern crate opencv;
|
|
@@ -22,8 +22,8 @@ impl Bitmap {
|
|
|
22
22
|
pub fn save(&self, path: String) -> Result<bool, magnus::Error> {
|
|
23
23
|
match self.0.image.save(path) {
|
|
24
24
|
Ok(_) => Ok(true),
|
|
25
|
-
Err(_) => Err(
|
|
26
|
-
|
|
25
|
+
Err(_) => Err(Error::new(
|
|
26
|
+
Ruby::get().unwrap().exception_runtime_error(),
|
|
27
27
|
"Could not save the image",
|
|
28
28
|
)),
|
|
29
29
|
}
|
data/ext/deskbot/src/lib.rs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
use magnus::{
|
|
1
|
+
use magnus::{function, method, prelude::*, Error, Ruby};
|
|
2
2
|
extern crate autopilot;
|
|
3
3
|
|
|
4
|
+
mod alert;
|
|
4
5
|
mod bitmap;
|
|
5
6
|
mod keys;
|
|
7
|
+
mod listen;
|
|
6
8
|
mod mouse;
|
|
7
9
|
mod screen;
|
|
8
|
-
mod alert;
|
|
9
10
|
|
|
10
11
|
#[magnus::init]
|
|
11
12
|
fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
@@ -28,6 +29,8 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
28
29
|
module.define_singleton_method("is_point_visible", function!(screen::is_point_visible, 2))?;
|
|
29
30
|
module.define_singleton_method("is_area_visible", function!(screen::is_rect_visible, 4))?;
|
|
30
31
|
|
|
32
|
+
module.define_singleton_method("listen", function!(listen::listen, 0))?;
|
|
33
|
+
|
|
31
34
|
module.define_singleton_method("alert", function!(alert::alert, 1))?;
|
|
32
35
|
|
|
33
36
|
module.define_singleton_method(
|
|
@@ -36,7 +39,7 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
|
36
39
|
)?;
|
|
37
40
|
module.define_singleton_method("capture_screen", function!(bitmap::capture_screen, 0))?;
|
|
38
41
|
|
|
39
|
-
let bitmap = module.define_class("Bitmap",
|
|
42
|
+
let bitmap = module.define_class("Bitmap", ruby.class_object())?;
|
|
40
43
|
bitmap.define_method("bounds", method!(bitmap::Bitmap::bounds, 0))?;
|
|
41
44
|
bitmap.define_method("find", method!(bitmap::Bitmap::find, 2))?;
|
|
42
45
|
bitmap.define_method("all", method!(bitmap::Bitmap::all, 2))?;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
use std::sync::{
|
|
2
|
+
mpsc::{self, Receiver, Sender},
|
|
3
|
+
Arc, Mutex, OnceLock,
|
|
4
|
+
};
|
|
5
|
+
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
6
|
+
|
|
7
|
+
use device_query::{
|
|
8
|
+
DeviceEvents, DeviceEventsHandler, Keycode, MouseButton, MousePosition,
|
|
9
|
+
};
|
|
10
|
+
use magnus::{Error, RHash, Ruby, Value};
|
|
11
|
+
|
|
12
|
+
/// An event captured from `device_query`, buffered until the Ruby listener
|
|
13
|
+
/// thread is ready to handle it.
|
|
14
|
+
enum RawEvent {
|
|
15
|
+
KeyDown(String),
|
|
16
|
+
KeyUp(String),
|
|
17
|
+
MouseDown(usize),
|
|
18
|
+
MouseUp(usize),
|
|
19
|
+
MouseMove(i64, i64),
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// A buffered event along with the wall-clock time (seconds since the Unix
|
|
23
|
+
/// epoch, as a float) at which it was captured by `device_query`.
|
|
24
|
+
type BufferedEvent = (f64, RawEvent);
|
|
25
|
+
|
|
26
|
+
/// Returns the current wall-clock time in seconds (with fractional precision)
|
|
27
|
+
/// since the Unix epoch.
|
|
28
|
+
fn now() -> f64 {
|
|
29
|
+
let duration = SystemTime::now()
|
|
30
|
+
.duration_since(UNIX_EPOCH)
|
|
31
|
+
.expect("system clock is set before the Unix epoch");
|
|
32
|
+
duration.as_secs() as f64 + f64::from(duration.subsec_nanos()) / 1_000_000_000.0
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// `device_query` only allows a single event loop to be initialised for the
|
|
36
|
+
/// lifetime of the process. The loop keeps polling in the background once it
|
|
37
|
+
/// has started, so we cache the first `DeviceEventsHandler` we manage to
|
|
38
|
+
/// create and reuse it for every `listen` call.
|
|
39
|
+
static HANDLER: OnceLock<Result<DeviceEventsHandler, String>> = OnceLock::new();
|
|
40
|
+
|
|
41
|
+
fn handler() -> Result<&'static DeviceEventsHandler, String> {
|
|
42
|
+
HANDLER.get_or_init(|| {
|
|
43
|
+
DeviceEventsHandler::new(Duration::from_millis(10))
|
|
44
|
+
.ok_or_else(|| "device event loop is already running".to_string())
|
|
45
|
+
})
|
|
46
|
+
.as_ref()
|
|
47
|
+
.map_err(|message| message.clone())
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// Converts a `Keycode`'s `Debug` variant name (e.g. `LControl`) into a
|
|
51
|
+
/// lowercase snake_case string (e.g. `l_control`).
|
|
52
|
+
fn keycode_to_name(keycode: Keycode) -> String {
|
|
53
|
+
let variant = format!("{keycode:?}");
|
|
54
|
+
let chars: Vec<char> = variant.chars().collect();
|
|
55
|
+
let mut name = String::with_capacity(variant.len());
|
|
56
|
+
|
|
57
|
+
for (index, character) in chars.iter().enumerate() {
|
|
58
|
+
if character.is_ascii_uppercase() {
|
|
59
|
+
let previous_is_upper = index > 0 && chars[index - 1].is_ascii_uppercase();
|
|
60
|
+
let next_is_lower =
|
|
61
|
+
index + 1 < chars.len() && chars[index + 1].is_ascii_lowercase();
|
|
62
|
+
|
|
63
|
+
if index > 0 && (next_is_lower || !previous_is_upper) {
|
|
64
|
+
name.push('_');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
name.push(character.to_ascii_lowercase());
|
|
68
|
+
} else {
|
|
69
|
+
name.push(*character);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
name
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// Turns a buffered event into a Ruby `Hash` describing it.
|
|
77
|
+
fn event_to_ruby(ruby: &Ruby, event: BufferedEvent) -> Result<RHash, Error> {
|
|
78
|
+
let (recorded_at, event) = event;
|
|
79
|
+
let hash = ruby.hash_new();
|
|
80
|
+
hash.aset("recorded_at", recorded_at)?;
|
|
81
|
+
|
|
82
|
+
match event {
|
|
83
|
+
RawEvent::KeyDown(key) => {
|
|
84
|
+
hash.aset("type", "key_down")?;
|
|
85
|
+
hash.aset("key", key)?;
|
|
86
|
+
}
|
|
87
|
+
RawEvent::KeyUp(key) => {
|
|
88
|
+
hash.aset("type", "key_up")?;
|
|
89
|
+
hash.aset("key", key)?;
|
|
90
|
+
}
|
|
91
|
+
RawEvent::MouseDown(button) => {
|
|
92
|
+
hash.aset("type", "mouse_down")?;
|
|
93
|
+
hash.aset("button", button as i64)?;
|
|
94
|
+
}
|
|
95
|
+
RawEvent::MouseUp(button) => {
|
|
96
|
+
hash.aset("type", "mouse_up")?;
|
|
97
|
+
hash.aset("button", button as i64)?;
|
|
98
|
+
}
|
|
99
|
+
RawEvent::MouseMove(x, y) => {
|
|
100
|
+
hash.aset("type", "mouse_move")?;
|
|
101
|
+
hash.aset("x", x)?;
|
|
102
|
+
hash.aset("y", y)?;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
Ok(hash)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Registers `device_query` callbacks that buffer events for the blocking
|
|
110
|
+
/// listener to drain. Each returned guard keeps its callback alive; dropping
|
|
111
|
+
/// them unregisters the callback.
|
|
112
|
+
#[allow(clippy::type_complexity)]
|
|
113
|
+
fn register_callbacks(
|
|
114
|
+
handler: &DeviceEventsHandler,
|
|
115
|
+
sender: &Sender<BufferedEvent>,
|
|
116
|
+
) -> (
|
|
117
|
+
device_query::CallbackGuard<impl Fn(&Keycode) + Send + Sync + 'static>,
|
|
118
|
+
device_query::CallbackGuard<impl Fn(&Keycode) + Send + Sync + 'static>,
|
|
119
|
+
device_query::CallbackGuard<impl Fn(&MouseButton) + Send + Sync + 'static>,
|
|
120
|
+
device_query::CallbackGuard<impl Fn(&MouseButton) + Send + Sync + 'static>,
|
|
121
|
+
device_query::CallbackGuard<impl Fn(&MousePosition) + Send + Sync + 'static>,
|
|
122
|
+
) {
|
|
123
|
+
let sender = Arc::new(Mutex::new(sender.clone()));
|
|
124
|
+
|
|
125
|
+
let key_down_sender = Arc::clone(&sender);
|
|
126
|
+
let key_down = handler.on_key_down(move |key: &Keycode| {
|
|
127
|
+
let _ = key_down_sender.lock().map(|sender| {
|
|
128
|
+
sender.send((now(), RawEvent::KeyDown(keycode_to_name(*key))))
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
let key_up_sender = Arc::clone(&sender);
|
|
133
|
+
let key_up = handler.on_key_up(move |key: &Keycode| {
|
|
134
|
+
let _ = key_up_sender.lock().map(|sender| {
|
|
135
|
+
sender.send((now(), RawEvent::KeyUp(keycode_to_name(*key))))
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
let mouse_down_sender = Arc::clone(&sender);
|
|
140
|
+
let mouse_down = handler.on_mouse_down(move |button: &MouseButton| {
|
|
141
|
+
let _ = mouse_down_sender
|
|
142
|
+
.lock()
|
|
143
|
+
.map(|sender| sender.send((now(), RawEvent::MouseDown(*button))));
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
let mouse_up_sender = Arc::clone(&sender);
|
|
147
|
+
let mouse_up = handler.on_mouse_up(move |button: &MouseButton| {
|
|
148
|
+
let _ = mouse_up_sender
|
|
149
|
+
.lock()
|
|
150
|
+
.map(|sender| sender.send((now(), RawEvent::MouseUp(*button))));
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
let mouse_move_sender = Arc::clone(&sender);
|
|
154
|
+
let mouse_move = handler.on_mouse_move(move |position: &MousePosition| {
|
|
155
|
+
let _ = mouse_move_sender.lock().map(|sender| {
|
|
156
|
+
sender.send((
|
|
157
|
+
now(),
|
|
158
|
+
RawEvent::MouseMove(position.0 as i64, position.1 as i64),
|
|
159
|
+
))
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
(key_down, key_up, mouse_down, mouse_up, mouse_move)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/// Blocks the calling Ruby thread, yielding a `Hash` describing each device
|
|
167
|
+
/// event (key down/up, mouse down/up/move) to the given block until it raises.
|
|
168
|
+
pub fn listen(ruby: &Ruby) -> Result<(), Error> {
|
|
169
|
+
if !ruby.block_given() {
|
|
170
|
+
return Err(Error::new(
|
|
171
|
+
ruby.exception_arg_error(),
|
|
172
|
+
"no block given",
|
|
173
|
+
));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let handler = handler().map_err(|message| {
|
|
177
|
+
Error::new(ruby.exception_arg_error(), message)
|
|
178
|
+
})?;
|
|
179
|
+
let (sender, receiver): (Sender<BufferedEvent>, Receiver<BufferedEvent>) = mpsc::channel();
|
|
180
|
+
|
|
181
|
+
let (_key_down, _key_up, _mouse_down, _mouse_up, _mouse_move) =
|
|
182
|
+
register_callbacks(handler, &sender);
|
|
183
|
+
|
|
184
|
+
loop {
|
|
185
|
+
let event = match receiver.recv() {
|
|
186
|
+
Ok(event) => event,
|
|
187
|
+
Err(_) => break,
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
let hash = event_to_ruby(ruby, event)?;
|
|
191
|
+
let _: Value = ruby.yield_value(hash)?;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
Ok(())
|
|
195
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deskbot
|
|
4
|
+
# Base class for the distinct device events yielded by {Screen#listen}.
|
|
5
|
+
#
|
|
6
|
+
# Listening yields an instance of one of the concrete subclasses, each of
|
|
7
|
+
# which exposes only the fields relevant to it:
|
|
8
|
+
#
|
|
9
|
+
# - {Event::KeyDown} / {Event::KeyUp} - expose `key`
|
|
10
|
+
# - {Event::MouseDown} / {Event::MouseUp} - expose `button`
|
|
11
|
+
# - {Event::MouseMove} - exposes `x`, `y` and `coords`
|
|
12
|
+
#
|
|
13
|
+
# Dispatch on the event's class rather than on a `type` value:
|
|
14
|
+
#
|
|
15
|
+
# Deskbot.screen.listen do |event|
|
|
16
|
+
# case event
|
|
17
|
+
# when Deskbot::Event::KeyDown then puts "pressed #{event.key}"
|
|
18
|
+
# when Deskbot::Event::KeyUp then puts "released #{event.key}"
|
|
19
|
+
# when Deskbot::Event::MouseDown then puts "button down: #{event.button}"
|
|
20
|
+
# when Deskbot::Event::MouseUp then puts "button up: #{event.button}"
|
|
21
|
+
# when Deskbot::Event::MouseMove then puts event.coords.inspect
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# Base `Event` is abstract and is never instantiated directly; use
|
|
26
|
+
# {Event.build} to turn a native payload into the matching subclass.
|
|
27
|
+
class Event
|
|
28
|
+
# The time the event was recorded. Every concrete event exposes it.
|
|
29
|
+
attr_reader :recorded_at
|
|
30
|
+
|
|
31
|
+
# Builds the concrete event described by the raw hash yielded by the native
|
|
32
|
+
# listener.
|
|
33
|
+
def self.build(payload)
|
|
34
|
+
subclass = {
|
|
35
|
+
"key_down" => Event::KeyDown,
|
|
36
|
+
"key_up" => Event::KeyUp,
|
|
37
|
+
"mouse_down" => Event::MouseDown,
|
|
38
|
+
"mouse_up" => Event::MouseUp,
|
|
39
|
+
"mouse_move" => Event::MouseMove
|
|
40
|
+
}[payload["type"]]
|
|
41
|
+
|
|
42
|
+
unless subclass
|
|
43
|
+
raise ArgumentError,
|
|
44
|
+
"unknown event type: #{payload["type"].inspect}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
subclass.build(payload)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Builds the recorded-at `Time` for an event from its native payload.
|
|
51
|
+
def self.recorded_at_from(payload)
|
|
52
|
+
Time.at(payload["recorded_at"])
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# A key was pressed down. Exposes the pressed {#key}.
|
|
56
|
+
class KeyDown < Event
|
|
57
|
+
attr_reader :key
|
|
58
|
+
|
|
59
|
+
def initialize(key:, recorded_at:)
|
|
60
|
+
@key = key.to_sym
|
|
61
|
+
@recorded_at = recorded_at
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.build(payload)
|
|
65
|
+
new(key: payload["key"], recorded_at: recorded_at_from(payload))
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# A key was released. Exposes the released {#key}.
|
|
70
|
+
class KeyUp < Event
|
|
71
|
+
attr_reader :key
|
|
72
|
+
|
|
73
|
+
def initialize(key:, recorded_at:)
|
|
74
|
+
@key = key.to_sym
|
|
75
|
+
@recorded_at = recorded_at
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.build(payload)
|
|
79
|
+
new(key: payload["key"], recorded_at: recorded_at_from(payload))
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# A mouse button was pressed down. Exposes the pressed {#button}.
|
|
84
|
+
class MouseDown < Event
|
|
85
|
+
attr_reader :button
|
|
86
|
+
|
|
87
|
+
def initialize(button:, recorded_at:)
|
|
88
|
+
@button = button
|
|
89
|
+
@recorded_at = recorded_at
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def self.build(payload)
|
|
93
|
+
new(button: payload["button"], recorded_at: recorded_at_from(payload))
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# A mouse button was released. Exposes the released {#button}.
|
|
98
|
+
class MouseUp < Event
|
|
99
|
+
attr_reader :button
|
|
100
|
+
|
|
101
|
+
def initialize(button:, recorded_at:)
|
|
102
|
+
@button = button
|
|
103
|
+
@recorded_at = recorded_at
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.build(payload)
|
|
107
|
+
new(button: payload["button"], recorded_at: recorded_at_from(payload))
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# The mouse moved to a new position. Exposes {#x}, {#y} and {#coords}.
|
|
112
|
+
class MouseMove < Event
|
|
113
|
+
attr_reader :x, :y
|
|
114
|
+
|
|
115
|
+
def initialize(x:, y:, recorded_at:) # rubocop:disable Naming/MethodParameterName
|
|
116
|
+
@x = x
|
|
117
|
+
@y = y
|
|
118
|
+
@recorded_at = recorded_at
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def self.build(payload)
|
|
122
|
+
new(
|
|
123
|
+
x: payload["x"],
|
|
124
|
+
y: payload["y"],
|
|
125
|
+
recorded_at: recorded_at_from(payload)
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Returns the mouse position as `[x, y]`.
|
|
130
|
+
def coords
|
|
131
|
+
[x, y]
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
data/lib/deskbot/screen.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Deskbot
|
|
4
|
-
class Screen
|
|
4
|
+
class Screen # rubocop:disable Metrics/ClassLength
|
|
5
5
|
# This is the API for any provider
|
|
6
6
|
|
|
7
7
|
def initialize(provider)
|
|
@@ -127,5 +127,16 @@ module Deskbot
|
|
|
127
127
|
|
|
128
128
|
Deskbot::Bitmap.new(bitmap)
|
|
129
129
|
end
|
|
130
|
+
|
|
131
|
+
# Blocks listening for device events (key down/up, mouse down/up/move),
|
|
132
|
+
# yielding each concrete event (a subclass of {Event}) to the block. Raises
|
|
133
|
+
# to stop listening.
|
|
134
|
+
def listen
|
|
135
|
+
raise ArgumentError, "a block is required" unless block_given?
|
|
136
|
+
|
|
137
|
+
@provider.listen do |payload|
|
|
138
|
+
yield Event.build(payload)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
130
141
|
end
|
|
131
142
|
end
|
data/lib/deskbot/version.rb
CHANGED
data/lib/deskbot.rb
CHANGED
|
@@ -12,6 +12,7 @@ require_relative "deskbot/point"
|
|
|
12
12
|
require_relative "deskbot/color"
|
|
13
13
|
require_relative "deskbot/size"
|
|
14
14
|
require_relative "deskbot/area"
|
|
15
|
+
require_relative "deskbot/event"
|
|
15
16
|
require_relative "deskbot/bitmap"
|
|
16
17
|
|
|
17
18
|
require "deskbot/providers/autopilot/bitmap"
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: deskbot
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nolan J Tait
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: dry-matcher
|
|
@@ -88,12 +87,14 @@ files:
|
|
|
88
87
|
- ext/deskbot/src/bitmap.rs
|
|
89
88
|
- ext/deskbot/src/keys.rs
|
|
90
89
|
- ext/deskbot/src/lib.rs
|
|
90
|
+
- ext/deskbot/src/listen.rs
|
|
91
91
|
- ext/deskbot/src/mouse.rs
|
|
92
92
|
- ext/deskbot/src/screen.rs
|
|
93
93
|
- lib/deskbot.rb
|
|
94
94
|
- lib/deskbot/area.rb
|
|
95
95
|
- lib/deskbot/bitmap.rb
|
|
96
96
|
- lib/deskbot/color.rb
|
|
97
|
+
- lib/deskbot/event.rb
|
|
97
98
|
- lib/deskbot/point.rb
|
|
98
99
|
- lib/deskbot/providers/autopilot.rb
|
|
99
100
|
- lib/deskbot/providers/autopilot/bitmap.rb
|
|
@@ -101,7 +102,6 @@ files:
|
|
|
101
102
|
- lib/deskbot/size.rb
|
|
102
103
|
- lib/deskbot/types.rb
|
|
103
104
|
- lib/deskbot/version.rb
|
|
104
|
-
- sig/deskbot.rbs
|
|
105
105
|
homepage: https://github.com/nolantait/desktbot
|
|
106
106
|
licenses:
|
|
107
107
|
- MIT
|
|
@@ -110,7 +110,6 @@ metadata:
|
|
|
110
110
|
source_code_uri: https://github.com/nolantait/desktbot
|
|
111
111
|
changelog_uri: https://github.com/nolantait/desktbot
|
|
112
112
|
rubygems_mfa_required: 'true'
|
|
113
|
-
post_install_message:
|
|
114
113
|
rdoc_options: []
|
|
115
114
|
require_paths:
|
|
116
115
|
- lib
|
|
@@ -125,8 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
125
124
|
- !ruby/object:Gem::Version
|
|
126
125
|
version: 3.3.11
|
|
127
126
|
requirements: []
|
|
128
|
-
rubygems_version:
|
|
129
|
-
signing_key:
|
|
127
|
+
rubygems_version: 4.0.16
|
|
130
128
|
specification_version: 4
|
|
131
129
|
summary: Ruby dekstop automation
|
|
132
130
|
test_files: []
|
data/sig/deskbot.rbs
DELETED