shotgun_ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 843c3ccc8ae2090623976c3d8561be3842d2ce26af5e105c6667de0e85d73992
4
+ data.tar.gz: 70079ea8b4c5d108722ccde7387b4221614973612150c7ce4580390bad663eb5
5
+ SHA512:
6
+ metadata.gz: 4c0d5a3a4ff75bdec530dbe994faf12180f85894f84797e04fa93546fa464afd193da555f77ac1cfa61cd862ba6128dd915ec7bb0c06f695bd249d85113d419a
7
+ data.tar.gz: c12e2df1282b5b19c8f07cc9f0b1f947e7cf802b150a83f22ed34db78b6f48a97b01419c1942c159044a7cde6e3c20800638f1448f162d92b484ed7851b549d4
@@ -0,0 +1,410 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 3
4
+
5
+ [[package]]
6
+ name = "adler32"
7
+ version = "1.2.0"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
10
+
11
+ [[package]]
12
+ name = "aho-corasick"
13
+ version = "0.7.20"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
16
+ dependencies = [
17
+ "memchr",
18
+ ]
19
+
20
+ [[package]]
21
+ name = "autocfg"
22
+ version = "1.1.0"
23
+ source = "registry+https://github.com/rust-lang/crates.io-index"
24
+ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
25
+
26
+ [[package]]
27
+ name = "bindgen"
28
+ version = "0.60.1"
29
+ source = "registry+https://github.com/rust-lang/crates.io-index"
30
+ checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6"
31
+ dependencies = [
32
+ "bitflags",
33
+ "cexpr",
34
+ "clang-sys",
35
+ "lazy_static",
36
+ "lazycell",
37
+ "peeking_take_while",
38
+ "proc-macro2",
39
+ "quote",
40
+ "regex",
41
+ "rustc-hash",
42
+ "shlex",
43
+ ]
44
+
45
+ [[package]]
46
+ name = "bitflags"
47
+ version = "1.3.2"
48
+ source = "registry+https://github.com/rust-lang/crates.io-index"
49
+ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
50
+
51
+ [[package]]
52
+ name = "bytemuck"
53
+ version = "1.13.1"
54
+ source = "registry+https://github.com/rust-lang/crates.io-index"
55
+ checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
56
+
57
+ [[package]]
58
+ name = "byteorder"
59
+ version = "1.4.3"
60
+ source = "registry+https://github.com/rust-lang/crates.io-index"
61
+ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
62
+
63
+ [[package]]
64
+ name = "cexpr"
65
+ version = "0.6.0"
66
+ source = "registry+https://github.com/rust-lang/crates.io-index"
67
+ checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
68
+ dependencies = [
69
+ "nom",
70
+ ]
71
+
72
+ [[package]]
73
+ name = "cfg-if"
74
+ version = "1.0.0"
75
+ source = "registry+https://github.com/rust-lang/crates.io-index"
76
+ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
77
+
78
+ [[package]]
79
+ name = "clang-sys"
80
+ version = "1.6.1"
81
+ source = "registry+https://github.com/rust-lang/crates.io-index"
82
+ checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
83
+ dependencies = [
84
+ "glob",
85
+ "libc",
86
+ "libloading",
87
+ ]
88
+
89
+ [[package]]
90
+ name = "color_quant"
91
+ version = "1.1.0"
92
+ source = "registry+https://github.com/rust-lang/crates.io-index"
93
+ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
94
+
95
+ [[package]]
96
+ name = "crc32fast"
97
+ version = "1.3.2"
98
+ source = "registry+https://github.com/rust-lang/crates.io-index"
99
+ checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
100
+ dependencies = [
101
+ "cfg-if",
102
+ ]
103
+
104
+ [[package]]
105
+ name = "deflate"
106
+ version = "0.8.6"
107
+ source = "registry+https://github.com/rust-lang/crates.io-index"
108
+ checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
109
+ dependencies = [
110
+ "adler32",
111
+ "byteorder",
112
+ ]
113
+
114
+ [[package]]
115
+ name = "getopts"
116
+ version = "0.2.21"
117
+ source = "registry+https://github.com/rust-lang/crates.io-index"
118
+ checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
119
+ dependencies = [
120
+ "unicode-width",
121
+ ]
122
+
123
+ [[package]]
124
+ name = "glob"
125
+ version = "0.3.1"
126
+ source = "registry+https://github.com/rust-lang/crates.io-index"
127
+ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
128
+
129
+ [[package]]
130
+ name = "image"
131
+ version = "0.23.14"
132
+ source = "registry+https://github.com/rust-lang/crates.io-index"
133
+ checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
134
+ dependencies = [
135
+ "bytemuck",
136
+ "byteorder",
137
+ "color_quant",
138
+ "num-iter",
139
+ "num-rational",
140
+ "num-traits",
141
+ "png",
142
+ ]
143
+
144
+ [[package]]
145
+ name = "lazy_static"
146
+ version = "1.4.0"
147
+ source = "registry+https://github.com/rust-lang/crates.io-index"
148
+ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
149
+
150
+ [[package]]
151
+ name = "lazycell"
152
+ version = "1.3.0"
153
+ source = "registry+https://github.com/rust-lang/crates.io-index"
154
+ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
155
+
156
+ [[package]]
157
+ name = "libc"
158
+ version = "0.2.140"
159
+ source = "registry+https://github.com/rust-lang/crates.io-index"
160
+ checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
161
+
162
+ [[package]]
163
+ name = "libloading"
164
+ version = "0.7.4"
165
+ source = "registry+https://github.com/rust-lang/crates.io-index"
166
+ checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
167
+ dependencies = [
168
+ "cfg-if",
169
+ "winapi",
170
+ ]
171
+
172
+ [[package]]
173
+ name = "memchr"
174
+ version = "2.5.0"
175
+ source = "registry+https://github.com/rust-lang/crates.io-index"
176
+ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
177
+
178
+ [[package]]
179
+ name = "minimal-lexical"
180
+ version = "0.2.1"
181
+ source = "registry+https://github.com/rust-lang/crates.io-index"
182
+ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
183
+
184
+ [[package]]
185
+ name = "miniz_oxide"
186
+ version = "0.3.7"
187
+ source = "registry+https://github.com/rust-lang/crates.io-index"
188
+ checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
189
+ dependencies = [
190
+ "adler32",
191
+ ]
192
+
193
+ [[package]]
194
+ name = "nom"
195
+ version = "7.1.3"
196
+ source = "registry+https://github.com/rust-lang/crates.io-index"
197
+ checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
198
+ dependencies = [
199
+ "memchr",
200
+ "minimal-lexical",
201
+ ]
202
+
203
+ [[package]]
204
+ name = "num-integer"
205
+ version = "0.1.45"
206
+ source = "registry+https://github.com/rust-lang/crates.io-index"
207
+ checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
208
+ dependencies = [
209
+ "autocfg",
210
+ "num-traits",
211
+ ]
212
+
213
+ [[package]]
214
+ name = "num-iter"
215
+ version = "0.1.43"
216
+ source = "registry+https://github.com/rust-lang/crates.io-index"
217
+ checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
218
+ dependencies = [
219
+ "autocfg",
220
+ "num-integer",
221
+ "num-traits",
222
+ ]
223
+
224
+ [[package]]
225
+ name = "num-rational"
226
+ version = "0.3.2"
227
+ source = "registry+https://github.com/rust-lang/crates.io-index"
228
+ checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
229
+ dependencies = [
230
+ "autocfg",
231
+ "num-integer",
232
+ "num-traits",
233
+ ]
234
+
235
+ [[package]]
236
+ name = "num-traits"
237
+ version = "0.2.15"
238
+ source = "registry+https://github.com/rust-lang/crates.io-index"
239
+ checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
240
+ dependencies = [
241
+ "autocfg",
242
+ ]
243
+
244
+ [[package]]
245
+ name = "peeking_take_while"
246
+ version = "0.1.2"
247
+ source = "registry+https://github.com/rust-lang/crates.io-index"
248
+ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
249
+
250
+ [[package]]
251
+ name = "pkg-config"
252
+ version = "0.3.26"
253
+ source = "registry+https://github.com/rust-lang/crates.io-index"
254
+ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
255
+
256
+ [[package]]
257
+ name = "png"
258
+ version = "0.16.8"
259
+ source = "registry+https://github.com/rust-lang/crates.io-index"
260
+ checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
261
+ dependencies = [
262
+ "bitflags",
263
+ "crc32fast",
264
+ "deflate",
265
+ "miniz_oxide",
266
+ ]
267
+
268
+ [[package]]
269
+ name = "proc-macro2"
270
+ version = "1.0.54"
271
+ source = "registry+https://github.com/rust-lang/crates.io-index"
272
+ checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534"
273
+ dependencies = [
274
+ "unicode-ident",
275
+ ]
276
+
277
+ [[package]]
278
+ name = "quote"
279
+ version = "1.0.26"
280
+ source = "registry+https://github.com/rust-lang/crates.io-index"
281
+ checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
282
+ dependencies = [
283
+ "proc-macro2",
284
+ ]
285
+
286
+ [[package]]
287
+ name = "rb-sys"
288
+ version = "0.9.70"
289
+ source = "registry+https://github.com/rust-lang/crates.io-index"
290
+ checksum = "dd532ce4ab93abcabd4b92d0eb1df5c02f64d3624b713e2bcf6a4186847f2c65"
291
+ dependencies = [
292
+ "rb-sys-build",
293
+ ]
294
+
295
+ [[package]]
296
+ name = "rb-sys-build"
297
+ version = "0.9.70"
298
+ source = "registry+https://github.com/rust-lang/crates.io-index"
299
+ checksum = "6959d6f87715ddb2854d833039aa22b06bbab3c3d63bb1df22e6da198e8390c5"
300
+ dependencies = [
301
+ "bindgen",
302
+ "lazy_static",
303
+ "proc-macro2",
304
+ "quote",
305
+ "regex",
306
+ "shell-words",
307
+ "syn",
308
+ ]
309
+
310
+ [[package]]
311
+ name = "regex"
312
+ version = "1.7.3"
313
+ source = "registry+https://github.com/rust-lang/crates.io-index"
314
+ checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
315
+ dependencies = [
316
+ "aho-corasick",
317
+ "memchr",
318
+ "regex-syntax",
319
+ ]
320
+
321
+ [[package]]
322
+ name = "regex-syntax"
323
+ version = "0.6.29"
324
+ source = "registry+https://github.com/rust-lang/crates.io-index"
325
+ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
326
+
327
+ [[package]]
328
+ name = "rustc-hash"
329
+ version = "1.1.0"
330
+ source = "registry+https://github.com/rust-lang/crates.io-index"
331
+ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
332
+
333
+ [[package]]
334
+ name = "shell-words"
335
+ version = "1.1.0"
336
+ source = "registry+https://github.com/rust-lang/crates.io-index"
337
+ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
338
+
339
+ [[package]]
340
+ name = "shlex"
341
+ version = "1.1.0"
342
+ source = "registry+https://github.com/rust-lang/crates.io-index"
343
+ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
344
+
345
+ [[package]]
346
+ name = "shotgun_ruby"
347
+ version = "0.1.0"
348
+ dependencies = [
349
+ "getopts",
350
+ "image",
351
+ "libc",
352
+ "num-traits",
353
+ "rb-sys",
354
+ "x11",
355
+ ]
356
+
357
+ [[package]]
358
+ name = "syn"
359
+ version = "1.0.109"
360
+ source = "registry+https://github.com/rust-lang/crates.io-index"
361
+ checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
362
+ dependencies = [
363
+ "proc-macro2",
364
+ "quote",
365
+ "unicode-ident",
366
+ ]
367
+
368
+ [[package]]
369
+ name = "unicode-ident"
370
+ version = "1.0.8"
371
+ source = "registry+https://github.com/rust-lang/crates.io-index"
372
+ checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
373
+
374
+ [[package]]
375
+ name = "unicode-width"
376
+ version = "0.1.10"
377
+ source = "registry+https://github.com/rust-lang/crates.io-index"
378
+ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
379
+
380
+ [[package]]
381
+ name = "winapi"
382
+ version = "0.3.9"
383
+ source = "registry+https://github.com/rust-lang/crates.io-index"
384
+ checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
385
+ dependencies = [
386
+ "winapi-i686-pc-windows-gnu",
387
+ "winapi-x86_64-pc-windows-gnu",
388
+ ]
389
+
390
+ [[package]]
391
+ name = "winapi-i686-pc-windows-gnu"
392
+ version = "0.4.0"
393
+ source = "registry+https://github.com/rust-lang/crates.io-index"
394
+ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
395
+
396
+ [[package]]
397
+ name = "winapi-x86_64-pc-windows-gnu"
398
+ version = "0.4.0"
399
+ source = "registry+https://github.com/rust-lang/crates.io-index"
400
+ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
401
+
402
+ [[package]]
403
+ name = "x11"
404
+ version = "2.21.0"
405
+ source = "registry+https://github.com/rust-lang/crates.io-index"
406
+ checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e"
407
+ dependencies = [
408
+ "libc",
409
+ "pkg-config",
410
+ ]
@@ -0,0 +1,27 @@
1
+ [package]
2
+ name = "shotgun_ruby"
3
+ version = "0.1.0"
4
+ edition = "2018"
5
+
6
+ [dependencies]
7
+ rb-sys = { version = "0.9.68", features = ["global-allocator"] }
8
+
9
+ getopts = "0.2"
10
+ libc = "0.2"
11
+ num-traits = "0.2"
12
+
13
+ [dependencies.image]
14
+ default-features = false
15
+ version = "0.23"
16
+ features = ["png", "pnm"]
17
+
18
+ [dependencies.x11]
19
+ version = "2.18"
20
+ features = ["xlib", "xrandr"]
21
+
22
+
23
+ [lib]
24
+ crate-type = ["cdylib"]
25
+
26
+ [features]
27
+ test-feature = []
@@ -0,0 +1,34 @@
1
+ # Use local rb_sys gem (only needed for developing in this repo)
2
+ $LOAD_PATH.unshift(File.expand_path("../../../../gem/lib", __dir__))
3
+
4
+ # We need to require mkmf *first* this since `rake-compiler` injects code here for cross compilation
5
+ require "mkmf"
6
+ require "rb_sys/mkmf"
7
+
8
+ create_rust_makefile("shotgun_ruby/shotgun_ruby") do |r|
9
+ # Create debug builds in dev. Make sure that release gems are compiled with
10
+ # `RB_SYS_CARGO_PROFILE=release` (optional)
11
+ r.profile = ENV.fetch("RB_SYS_CARGO_PROFILE", :dev).to_sym
12
+
13
+ # Can be overridden with `RB_SYS_CARGO_FEATURES` env var (optional)
14
+ r.features = ["test-feature"]
15
+
16
+ # You can add whatever env vars you want to the env hash (optional)
17
+ r.env = {"FOO" => "BAR"}
18
+
19
+ # If your Cargo.toml is in a different directory, you can specify it here (optional)
20
+ r.ext_dir = "."
21
+
22
+ # Extra flags to pass to the $RUSTFLAGS environment variable (optional)
23
+ r.extra_rustflags << "--cfg=some_nested_config_var_for_crate"
24
+
25
+ # Force a rust toolchain to be installed via rustup (optional)
26
+ # You can also set the env var `RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN=true`
27
+ r.force_install_rust_toolchain = false
28
+
29
+ # Extra args to pass to the `cargo rustc` command (optional)
30
+ r.extra_cargo_args << "--quiet"
31
+
32
+ # Extra args to pass to the `rustc` command (optional)
33
+ r.extra_rustc_args = []
34
+ end
@@ -0,0 +1,101 @@
1
+ use rb_sys::*;
2
+ use std::ffi::{CStr, CString};
3
+ use std::os::raw::c_long;
4
+
5
+ use std::fs::File;
6
+ use std::path::Path;
7
+ use x11::xlib;
8
+
9
+
10
+ mod util;
11
+ mod xwrap;
12
+ use crate::xwrap::Display;
13
+
14
+ fn print_type_of<T>(_: &T) {
15
+ println!("{}", std::any::type_name::<T>())
16
+ }
17
+
18
+ unsafe extern "C" fn take_screenshot(_klass: RubyValue, mut winid: RubyValue, mut filepath: RubyValue) -> RubyValue {
19
+
20
+ let window_id = CStr::from_ptr(rb_string_value_cstr(&mut winid)).to_str().unwrap();
21
+ let path = CStr::from_ptr(rb_string_value_cstr(&mut filepath)).to_str().unwrap();
22
+
23
+ let display = match Display::open(None) {
24
+ Some(d) => d,
25
+ None => {
26
+ eprintln!("Failed to open display");
27
+ return 1;
28
+ }
29
+ };
30
+
31
+ let window = match util::parse_int::<xlib::Window>(&window_id){
32
+ Ok(r) => r,
33
+ Err(_) => {
34
+ eprintln!("Window ID is not a valid integer");
35
+ eprintln!("Accepted values are decimal, hex (0x*), octal (0o*) and binary (0b*)");
36
+ return 1;
37
+ }
38
+ };
39
+
40
+ let output_ext = "pam";
41
+ let output_format = image::ImageOutputFormat::Pnm(image::pnm::PNMSubtype::ArbitraryMap);
42
+
43
+ let window_rect = display.get_window_rect(window);
44
+ let sel = util::Rect {
45
+ x: 0,
46
+ y: 0,
47
+ w: window_rect.w,
48
+ h: window_rect.h,
49
+ };
50
+
51
+ let image = match display.get_image(window, sel, xwrap::ALL_PLANES, xlib::ZPixmap) {
52
+ Some(i) => i,
53
+ None => {
54
+ eprintln!("Failed to get image from X");
55
+ return 1;
56
+ }
57
+ };
58
+
59
+ let image = match image.into_image_buffer() {
60
+ Some(i) => image::DynamicImage::ImageRgba8(i),
61
+ None => {
62
+ eprintln!(
63
+ "Failed to convert captured framebuffer, only 24/32 \
64
+ bit (A)RGB8 is supported"
65
+ );
66
+ return 1;
67
+ }
68
+ };
69
+
70
+ match File::create(&Path::new(&path)) {
71
+ Ok(mut f) => image
72
+ .write_to(&mut f, output_format)
73
+ .expect("Writing to file failed"),
74
+ Err(e) => {
75
+ eprintln!("Failed to create {}: {}", path, e);
76
+ return 1;
77
+ }
78
+ }
79
+
80
+ let output = CString::new(path).unwrap();
81
+ let size = path.len() as c_long;
82
+
83
+ rb_utf8_str_new(output.as_ptr(), size)
84
+ }
85
+
86
+
87
+ #[allow(non_snake_case)]
88
+ #[no_mangle]
89
+ extern "C" fn Init_shotgun_ruby() {
90
+ let name = CString::new("ShotgunRuby").unwrap();
91
+ let function_name = CString::new("screenshot").unwrap();
92
+
93
+ unsafe {
94
+ let klass = rb_define_module(name.as_ptr());
95
+ let callback = std::mem::transmute::<
96
+ unsafe extern "C" fn(RubyValue, RubyValue, RubyValue) -> RubyValue,
97
+ unsafe extern "C" fn() -> RubyValue,
98
+ >(take_screenshot);
99
+ rb_define_module_function(klass, function_name.as_ptr(), Some(callback), 2);
100
+ }
101
+ }
@@ -0,0 +1,51 @@
1
+ use std::cmp;
2
+
3
+ #[derive(Copy, Clone, Debug)]
4
+ pub struct Rect {
5
+ pub x: i32,
6
+ pub y: i32,
7
+ pub w: i32,
8
+ pub h: i32,
9
+ }
10
+
11
+ #[derive(Copy, Clone, Debug)]
12
+ pub struct Point {
13
+ pub x: i32,
14
+ pub y: i32,
15
+ }
16
+
17
+ impl Rect {
18
+ pub fn intersection(&self, other: Rect) -> Option<Rect> {
19
+ let ix = cmp::max(self.x, other.x);
20
+ let iy = cmp::max(self.y, other.y);
21
+ let iw = cmp::min(self.x + self.w, other.x + other.w) - ix;
22
+ let ih = cmp::min(self.y + self.h, other.y + other.h) - iy;
23
+
24
+ if iw > 0 && ih > 0 {
25
+ Some(Rect {
26
+ x: ix,
27
+ y: iy,
28
+ w: iw,
29
+ h: ih,
30
+ })
31
+ } else {
32
+ None
33
+ }
34
+ }
35
+
36
+ pub fn contains(&self, pos: Point) -> bool {
37
+ pos.x >= self.x && pos.x < self.x + self.w && pos.y >= self.y && pos.y < self.y + self.h
38
+ }
39
+ }
40
+
41
+ pub fn parse_int<T: num_traits::Num>(string: &str) -> Result<T, T::FromStrRadixErr> {
42
+ if string.len() < 2 {
43
+ return T::from_str_radix(string, 10);
44
+ }
45
+ match &string[..2] {
46
+ "0x" | "0X" => T::from_str_radix(&string[2..], 16),
47
+ "0o" | "0O" => T::from_str_radix(&string[2..], 8),
48
+ "0b" | "0B" => T::from_str_radix(&string[2..], 2),
49
+ _ => T::from_str_radix(string, 10),
50
+ }
51
+ }
@@ -0,0 +1,327 @@
1
+ // This Source Code Form is subject to the terms of the Mozilla Public
2
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ use std::ffi;
6
+ use std::mem;
7
+ use std::os::raw;
8
+ use std::ptr;
9
+ use std::slice;
10
+
11
+ use image::Pixel;
12
+ use image::Rgba;
13
+ use image::RgbaImage;
14
+ use libc;
15
+ use x11::xlib;
16
+ use x11::xrandr;
17
+
18
+ use crate::util;
19
+
20
+ pub const ALL_PLANES: libc::c_ulong = !0;
21
+
22
+ pub struct Display {
23
+ handle: *mut xlib::Display,
24
+ }
25
+
26
+ pub struct Image {
27
+ handle: *mut xlib::XImage,
28
+ }
29
+
30
+ pub struct ScreenRectIter<'a> {
31
+ dpy: &'a Display,
32
+ res: *mut xrandr::XRRScreenResources,
33
+ crtcs: &'a [xrandr::RRCrtc],
34
+ i: usize,
35
+ }
36
+
37
+ impl Display {
38
+ pub fn open(name: Option<ffi::CString>) -> Option<Display> {
39
+ unsafe {
40
+ let name = match name {
41
+ None => ptr::null(),
42
+ Some(cstr) => cstr.as_ptr(),
43
+ };
44
+ let d = xlib::XOpenDisplay(name);
45
+
46
+ if d.is_null() {
47
+ return None;
48
+ }
49
+
50
+ Some(Display { handle: d })
51
+ }
52
+ }
53
+
54
+ pub fn get_default_root(&self) -> xlib::Window {
55
+ unsafe { xlib::XDefaultRootWindow(self.handle) }
56
+ }
57
+
58
+ pub fn get_window_rect(&self, window: xlib::Window) -> util::Rect {
59
+ unsafe {
60
+ let mut attrs = mem::MaybeUninit::uninit();
61
+ xlib::XGetWindowAttributes(self.handle, window, attrs.as_mut_ptr());
62
+ let attrs = attrs.assume_init();
63
+
64
+ let mut root = 0;
65
+ let mut parent = 0;
66
+ let mut children: *mut xlib::Window = ptr::null_mut();
67
+ let mut nchildren = 0;
68
+ xlib::XQueryTree(
69
+ self.handle,
70
+ window,
71
+ &mut root,
72
+ &mut parent,
73
+ &mut children,
74
+ &mut nchildren,
75
+ );
76
+ if !children.is_null() {
77
+ xlib::XFree(children as *mut raw::c_void);
78
+ }
79
+
80
+ let mut x = attrs.x;
81
+ let mut y = attrs.y;
82
+
83
+ if parent != 0 {
84
+ let mut child = 0;
85
+ xlib::XTranslateCoordinates(
86
+ self.handle,
87
+ parent,
88
+ root,
89
+ attrs.x,
90
+ attrs.y,
91
+ &mut x,
92
+ &mut y,
93
+ &mut child,
94
+ );
95
+ }
96
+
97
+ util::Rect {
98
+ x: x,
99
+ y: y,
100
+ w: attrs.width,
101
+ h: attrs.height,
102
+ }
103
+ }
104
+ }
105
+
106
+ pub fn get_image(
107
+ &self,
108
+ window: xlib::Window,
109
+ rect: util::Rect,
110
+ plane_mask: libc::c_ulong,
111
+ format: libc::c_int,
112
+ ) -> Option<Image> {
113
+ unsafe {
114
+ let image = xlib::XGetImage(
115
+ self.handle,
116
+ window,
117
+ rect.x,
118
+ rect.y,
119
+ rect.w as libc::c_uint,
120
+ rect.h as libc::c_uint,
121
+ plane_mask,
122
+ format,
123
+ );
124
+
125
+ if image.is_null() {
126
+ return None;
127
+ }
128
+
129
+ Some(Image::from_raw_ximage(image))
130
+ }
131
+ }
132
+
133
+ pub fn get_screen_rects(&self, root: xlib::Window) -> Option<ScreenRectIter<'_>> {
134
+ unsafe {
135
+ let xrr_res = xrandr::XRRGetScreenResourcesCurrent(self.handle, root);
136
+
137
+ if xrr_res.is_null() {
138
+ return None;
139
+ }
140
+
141
+ Some(ScreenRectIter {
142
+ dpy: &self,
143
+ res: xrr_res,
144
+ crtcs: slice::from_raw_parts((*xrr_res).crtcs, (*xrr_res).ncrtc as usize),
145
+ i: 0,
146
+ })
147
+ }
148
+ }
149
+
150
+ pub fn get_cursor_position(&self, window: xlib::Window) -> Option<util::Point> {
151
+ let mut x = 0;
152
+ let mut y = 0;
153
+
154
+ unsafe {
155
+ if xlib::XQueryPointer(
156
+ self.handle,
157
+ window,
158
+ &mut 0,
159
+ &mut 0,
160
+ &mut x,
161
+ &mut y,
162
+ &mut 0,
163
+ &mut 0,
164
+ &mut 0,
165
+ ) == 0
166
+ {
167
+ return None;
168
+ }
169
+ }
170
+
171
+ Some(util::Point { x, y })
172
+ }
173
+ }
174
+
175
+ impl Drop for Display {
176
+ fn drop(&mut self) {
177
+ unsafe {
178
+ xlib::XCloseDisplay(self.handle);
179
+ }
180
+ }
181
+ }
182
+
183
+ impl Image {
184
+ pub fn from_raw_ximage(ximage: *mut xlib::XImage) -> Image {
185
+ Image { handle: ximage }
186
+ }
187
+
188
+ pub fn into_image_buffer(&self) -> Option<RgbaImage> {
189
+ unsafe {
190
+ // Extract values from the XImage into our own scope
191
+ macro_rules! get {
192
+ ($($a:ident),+) => ($(let $a = (*self.handle).$a;)+);
193
+ }
194
+ get!(
195
+ width,
196
+ height,
197
+ byte_order,
198
+ depth,
199
+ bytes_per_line,
200
+ bits_per_pixel,
201
+ red_mask,
202
+ green_mask,
203
+ blue_mask
204
+ );
205
+
206
+ // Pixel size
207
+ let stride = match (depth, bits_per_pixel) {
208
+ (24, 24) => 3,
209
+ (24, 32) | (32, 32) => 4,
210
+ _ => return None,
211
+ };
212
+
213
+ // Compute subpixel offsets into each pixel according the the bitmasks X gives us
214
+ // Only 8 bit, byte-aligned values are supported
215
+ // Truncate masks to the lower 32 bits as that is the maximum pixel size
216
+ macro_rules! channel_offset {
217
+ ($mask:expr) => {
218
+ match (byte_order, $mask & 0xFFFFFFFF) {
219
+ (0, 0xFF) | (1, 0xFF000000) => 0,
220
+ (0, 0xFF00) | (1, 0xFF0000) => 1,
221
+ (0, 0xFF0000) | (1, 0xFF00) => 2,
222
+ (0, 0xFF000000) | (1, 0xFF) => 3,
223
+ _ => return None,
224
+ }
225
+ };
226
+ }
227
+ let red_offset = channel_offset!(red_mask);
228
+ let green_offset = channel_offset!(green_mask);
229
+ let blue_offset = channel_offset!(blue_mask);
230
+ let alpha_offset = channel_offset!(!(red_mask | green_mask | blue_mask));
231
+
232
+ // Wrap the pixel buffer into a slice
233
+ let size = (bytes_per_line * height) as usize;
234
+ let data = slice::from_raw_parts((*self.handle).data as *const u8, size);
235
+
236
+ // Finally, generate the image object
237
+ Some(RgbaImage::from_fn(width as u32, height as u32, |x, y| {
238
+ macro_rules! subpixel {
239
+ ($channel_offset:ident) => {
240
+ data[(y * bytes_per_line as u32 + x * stride as u32 + $channel_offset)
241
+ as usize]
242
+ };
243
+ }
244
+ Rgba::from_channels(
245
+ subpixel!(red_offset),
246
+ subpixel!(green_offset),
247
+ subpixel!(blue_offset),
248
+ // Make the alpha channel fully opaque if none is provided
249
+ if depth == 24 {
250
+ 0xFF
251
+ } else {
252
+ subpixel!(alpha_offset)
253
+ },
254
+ )
255
+ }))
256
+ }
257
+ }
258
+ }
259
+
260
+ impl Drop for Image {
261
+ fn drop(&mut self) {
262
+ unsafe {
263
+ xlib::XDestroyImage(self.handle);
264
+ }
265
+ }
266
+ }
267
+
268
+ impl<'a> Iterator for ScreenRectIter<'a> {
269
+ type Item = util::Rect;
270
+
271
+ fn next(&mut self) -> Option<Self::Item> {
272
+ if self.i >= self.crtcs.len() {
273
+ return None;
274
+ }
275
+
276
+ unsafe {
277
+ // TODO Handle failure here?
278
+ let crtc = xrandr::XRRGetCrtcInfo((*self.dpy).handle, self.res, self.crtcs[self.i]);
279
+ let x = (*crtc).x;
280
+ let y = (*crtc).y;
281
+ let w = (*crtc).width;
282
+ let h = (*crtc).height;
283
+ xrandr::XRRFreeCrtcInfo(crtc);
284
+
285
+ self.i += 1;
286
+
287
+ //Some((w as i32, h as i32, x as i32, y as i32))
288
+ Some(util::Rect {
289
+ x: x,
290
+ y: y,
291
+ w: w as i32,
292
+ h: h as i32,
293
+ })
294
+ }
295
+ }
296
+ }
297
+
298
+ impl<'a> Drop for ScreenRectIter<'a> {
299
+ fn drop(&mut self) {
300
+ unsafe {
301
+ xrandr::XRRFreeScreenResources(self.res);
302
+ }
303
+ }
304
+ }
305
+
306
+ pub fn parse_geometry(g: ffi::CString) -> util::Rect {
307
+ unsafe {
308
+ let mut x = 0;
309
+ let mut y = 0;
310
+ let mut w = 0;
311
+ let mut h = 0;
312
+ xlib::XParseGeometry(
313
+ g.as_ptr() as *const raw::c_char,
314
+ &mut x,
315
+ &mut y,
316
+ &mut w,
317
+ &mut h,
318
+ );
319
+
320
+ util::Rect {
321
+ x: x,
322
+ y: y,
323
+ w: w as i32,
324
+ h: h as i32,
325
+ }
326
+ }
327
+ }
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ RUBY_VERSION =~ /(\d+\.\d+)/
5
+ require "shotgun_ruby/#{$1}/shotgun_ruby"
6
+ rescue LoadError
7
+ require "shotgun_ruby/shotgun_ruby"
8
+ end
9
+
10
+ module ShotgunRuby
11
+ class Error < StandardError; end
12
+ # Your code goes here...
13
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shotgun_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jonas Moesicke
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-04-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A ruby gem adaptation of the shotgun screenshot tool for linux. Creates
14
+ a .pam screenshots at a given path and returns the location.
15
+ email:
16
+ - jmoesicke@clustermarket.com
17
+ executables: []
18
+ extensions:
19
+ - ext/shotgun_ruby/extconf.rb
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ext/shotgun_ruby/Cargo.lock
23
+ - ext/shotgun_ruby/Cargo.toml
24
+ - ext/shotgun_ruby/extconf.rb
25
+ - ext/shotgun_ruby/src/lib.rs
26
+ - ext/shotgun_ruby/src/util.rs
27
+ - ext/shotgun_ruby/src/xwrap.rs
28
+ - lib/shotgun_ruby.rb
29
+ homepage: https://github.com/jm591/shotgun_ruby
30
+ licenses: []
31
+ metadata: {}
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.3.0
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubygems_version: 3.4.8
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Rust Screenshot Tool
51
+ test_files: []