screen layout detection

This commit is contained in:
Michael Zhang 2020-06-26 14:53:06 -05:00
parent 77393ca68c
commit 8dc13a1ad6
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
12 changed files with 328 additions and 74 deletions

135
Cargo.lock generated
View file

@ -20,11 +20,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "atty"
version = "0.2.14"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -53,13 +53,23 @@ name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chrono"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.33.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -206,6 +216,11 @@ dependencies = [
"rayon 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -218,7 +233,9 @@ dependencies = [
"anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)",
"leanshot_x11 0.2.0",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"png 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
"stderrlog 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -236,6 +253,14 @@ name = "libc"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lzw"
version = "0.10.0"
@ -308,6 +333,11 @@ dependencies = [
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "numtoa"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pkg-config"
version = "0.3.17"
@ -390,6 +420,19 @@ dependencies = [
"num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_termios"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
@ -400,6 +443,18 @@ name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "stderrlog"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.8.0"
@ -445,6 +500,25 @@ dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termion"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
"numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@ -471,6 +545,15 @@ dependencies = [
"syn 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tiff"
version = "0.5.0"
@ -481,6 +564,15 @@ dependencies = [
"miniz_oxide 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-segmentation"
version = "1.6.0"
@ -501,11 +593,24 @@ name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.8"
@ -520,6 +625,14 @@ name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@ -538,12 +651,13 @@ dependencies = [
"checksum adler32 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum anyhow 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum bytemuck 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37fa13df2292ecb479ec23aa06f4507928bef07839be9ef15281411076629431"
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
@ -560,8 +674,10 @@ dependencies = [
"checksum image 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d534e95ad8b9d5aa614322d02352b4f1bf962254adcf02ac6f2def8be18498e8"
"checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
"checksum jpeg-decoder 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5b47b4c4e017b01abdc5bcc126d2d1002e5a75bbe3ce73f9f4f311a916363704"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
"checksum memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8"
@ -571,6 +687,7 @@ dependencies = [
"checksum num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
"checksum num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
"checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
"checksum png 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63daf481fdd0defa2d1d2be15c674fbfa1b0fd71882c303a91f9a79b3252c359"
"checksum png 0.16.5 (registry+https://github.com/rust-lang/crates.io-index)" = "34ccdd66f6fe4b2433b07e4728e9a013e43233120427046e93ceb709c3a439bf"
@ -580,23 +697,33 @@ dependencies = [
"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
"checksum rayon 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "62f02856753d04e03e26929f820d0a0a337ebe71f849801eea335d464b349080"
"checksum rayon-core 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e92e15d89083484e11353891f1af602cc661426deb9564c298b270c726973280"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
"checksum stderrlog 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32e5ee9b90a5452c570a0b0ac1c99ae9498db7e56e33d74366de7f2a7add7f25"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7"
"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107"
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
"checksum syn 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6"
"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
"checksum termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c22cec9d8978d906be5ac94bceb5a010d885c626c4c8855721a4dbd20e3ac905"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08"
"checksum thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
"checksum tiff 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f3b8a87c4da944c3f27e5943289171ac71a6150a79ff6bacfff06d159dfff2f"
"checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum x11 2.18.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77ecd092546cb16f25783a5451538e73afc8d32e242648d54f4ae5459ba1e773"

View file

@ -24,4 +24,6 @@ structopt = "0.2"
anyhow = "1.0.31"
image = "0.23.5"
leanshot_x11 = { version = "0.2", path = "x11", optional = true, features = ["xlib"] }
leanshot_x11 = { version = "0.2", path = "x11", optional = true, features = ["xlib", "xinerama"] }
log = "0.4.8"
stderrlog = "0.4.3"

View file

@ -4,39 +4,34 @@
#[macro_use]
extern crate anyhow;
#[macro_use]
extern crate structopt;
extern crate leanshot_x11 as x11;
extern crate structopt;
mod options;
mod platform;
use anyhow::Result;
pub use crate::options::{Options, Region};
use crate::platform::{x11::X11, Platform};
pub use crate::platform::{x11::X11, Platform};
type Rectangle = x11::Rectangle;
/// The main capture routine
pub fn capture(opt: &Options) -> Result<()> {
let gui = X11::new()?;
let image = match opt.region {
Region::ActiveWindow => {
let window = gui.get_active_window()?;
let image = gui.capture_window(window);
}
Region::Fullscreen | Region::Selection => {
let mut image = gui.capture_full_screen()?;
if let Region::Fullscreen = opt.region {
let rect = gui.show_interactive_selection(image)?;
// TODO: crop the image
}
}
};
unimplemented!("leanshot::capture")
// imlib2::context_set_image(&capture);
// capture.save_image(&opt.outfile)?;
/// A region option
#[allow(missing_docs)]
pub enum Region {
Fullscreen,
ActiveWindow,
Selection,
}
impl Region {
/// Convert string to Region enum
// TODO: use FromStr trait
pub fn from_str(x: &str) -> Result<Self> {
match x {
"fullscreen" => Ok(Region::Fullscreen),
"window" => Ok(Region::ActiveWindow),
"select" | "selection" => Ok(Region::Selection),
_ => bail!("please choose a region from 'fullscreen', 'window', or 'select'"),
}
}
}

View file

@ -1,9 +1,49 @@
use std::path::PathBuf;
use anyhow::Result;
use leanshot::{capture, Options};
use leanshot::{Platform, Region, X11};
use structopt::StructOpt;
#[allow(missing_docs)]
pub fn main() -> Result<()> {
stderrlog::new().module(module_path!()).init().unwrap();
let opt = Options::from_args();
capture(&opt)
let gui = X11::new()?;
let screen_layout = gui.get_screen_layout()?;
println!("{:?}", screen_layout);
let image = match opt.region {
Region::ActiveWindow => {
let window = gui.get_active_window()?;
let image = gui.capture_window(window);
}
Region::Fullscreen | Region::Selection => {
let mut image = gui.capture_full_screen()?;
if let Region::Fullscreen = opt.region {
let rect = gui.show_interactive_selection(image)?;
// TODO: crop the image
}
}
};
unimplemented!("leanshot::capture")
}
/// Options for screenshot
#[derive(StructOpt)]
pub struct Options {
/// The region to select (fullscreen | window | select)
#[structopt(parse(try_from_str = "Region::from_str"))]
pub region: Region,
/// The file to save the screenshot to
#[structopt(short = "o", long = "out", parse(from_os_str))]
pub outfile: PathBuf,
/// Whether or not to also copy it to the clipboard
#[structopt(short = "c")]
pub clipboard: bool,
}

View file

@ -1,38 +0,0 @@
use std::path::PathBuf;
use anyhow::Result;
/// A region option
#[allow(missing_docs)]
pub enum Region {
Fullscreen,
ActiveWindow,
Selection,
}
/// Options for screenshot
#[derive(StructOpt)]
pub struct Options {
/// The region to select (fullscreen | window | select)
#[structopt(parse(try_from_str = "Region::from_str"))]
pub region: Region,
/// The file to save the screenshot to
#[structopt(short = "o", long = "out", parse(from_os_str))]
pub outfile: PathBuf,
/// Whether or not to also copy it to the clipboard
#[structopt(short = "c")]
pub clipboard: bool,
}
impl Region {
pub(self) fn from_str(x: &str) -> Result<Self> {
match x {
"fullscreen" => Ok(Region::Fullscreen),
"window" => Ok(Region::ActiveWindow),
"select" | "selection" => Ok(Region::Selection),
_ => bail!("please choose a region from 'fullscreen', 'window', or 'select'"),
}
}
}

View file

@ -1,21 +1,50 @@
#[cfg(feature = "x11")]
pub mod x11;
use std::collections::HashMap;
use std::hash::Hash;
use anyhow::Result;
use image::RgbaImage;
use crate::Rectangle;
#[derive(Debug)]
pub struct ScreenInfo {
pub width: u16,
pub height: u16,
pub x: i16,
pub y: i16,
}
/// Set of functions that all platforms must implement
pub trait Platform {
/// Type of window handles
type Window;
/// Type of images
type Image: Image;
/// Type of screen handles
type ScreenId: Hash;
/// Get a handle to the currently active window
fn get_active_window(&self) -> Result<Self::Window>;
/// Capture a specific window by handle
fn capture_window(&self, window: Self::Window) -> Result<Self::Image>;
/// Get the screen layout (list of screens, where they are)
fn get_screen_layout(&self) -> Result<HashMap<Self::ScreenId, ScreenInfo>>;
/// Capture full screen
fn capture_full_screen(&self) -> Result<Self::Image>;
/// Open the interactive selection interface
fn show_interactive_selection(&self, image: Self::Image) -> Result<Rectangle>;
}
/// Set of functions platform-specific images must implement
pub trait Image {
fn into_rgba_image(self) -> RgbaImage;
}

View file

@ -1,17 +1,26 @@
use std::collections::HashMap;
use anyhow::Result;
use image::RgbaImage;
use x11::xlib::{Display, Window};
use x11::{
xinerama::ScreensInfo,
xlib::{Display, Window},
};
use crate::platform::{Image as ImageT, Platform};
use crate::platform::{Image as ImageT, Platform, ScreenInfo};
use crate::Rectangle;
/// Interface to x11
pub struct X11 {
inner: Display,
}
impl X11 {
/// Create a new x11 instace
pub fn new() -> Result<Self> {
// TODO: configure connection string
let display = Display::connect(":0")?;
Ok(X11 { inner: display })
}
}
@ -19,6 +28,7 @@ impl X11 {
impl Platform for X11 {
type Window = Window;
type Image = Image;
type ScreenId = i32;
fn get_active_window(&self) -> Result<Self::Window> {
let (window, _) = self.inner.get_input_focus()?;
@ -35,6 +45,24 @@ impl Platform for X11 {
unimplemented!()
}
fn get_screen_layout(&self) -> Result<HashMap<Self::ScreenId, ScreenInfo>> {
let screens_info = ScreensInfo::query(&self.inner)?;
Ok(screens_info
.iter()
.map(|(num, screen)| {
(
num,
ScreenInfo {
x: screen.x,
y: screen.y,
width: screen.width as u16,
height: screen.height as u16,
},
)
})
.collect())
}
fn show_interactive_selection(&self, image: Self::Image) -> Result<Rectangle> {
let window = Window::create(&self.inner, None, Rectangle::new(0, 0, 500, 500))?;
window.map();

View file

@ -9,6 +9,7 @@ authors = ["Michael Zhang <failed.down@gmail.com>"]
default = []
xlib = ["x11/xlib"]
xrender = ["x11/xrender"]
xinerama = ["x11/xlib", "x11/xinerama"]
[dependencies]
libc = "0.2"

View file

@ -11,6 +11,9 @@ pub mod xlib;
#[cfg(feature = "xrender")]
pub mod xrender;
#[cfg(feature = "xinerama")]
pub mod xinerama;
mod errors;
mod rect;

3
x11/src/xinerama/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod screen_info;
pub use self::screen_info::ScreensInfo;

View file

@ -0,0 +1,64 @@
use x11::xinerama;
use crate::errors::Result;
use crate::xlib::Display;
pub struct ScreensInfo {
inner: *mut xinerama::XineramaScreenInfo,
heads: isize,
}
impl ScreensInfo {
pub fn query(display: &Display) -> Result<Self> {
let mut heads = 0;
let inner = unsafe { xinerama::XineramaQueryScreens(display.inner, &mut heads as *mut _) };
// TODO: check for error
Ok(ScreensInfo {
inner,
heads: heads as isize,
})
}
pub fn iter(&self) -> ScreenInfoIter {
ScreenInfoIter(self, 0)
}
}
impl Drop for ScreensInfo {
fn drop(&mut self) {
unsafe { x11::xlib::XFree(self.inner as *mut _) };
}
}
pub struct ScreenInfoIter<'a>(&'a ScreensInfo, isize);
pub struct ScreenInfo {
pub x: i16,
pub y: i16,
pub width: i16,
pub height: i16,
}
impl<'a> Iterator for ScreenInfoIter<'a> {
type Item = (i32, ScreenInfo);
fn next(&mut self) -> Option<Self::Item> {
if self.1 >= self.0.heads {
return None;
}
let screen = unsafe { self.0.inner.offset(self.1) };
self.1 += 1;
unsafe {
Some((
(*screen).screen_number as i32,
ScreenInfo {
x: (*screen).x_org as i16,
y: (*screen).y_org as i16,
width: (*screen).width as i16,
height: (*screen).height as i16,
},
))
}
}
}

View file

@ -11,7 +11,7 @@ use super::window::Window;
/// A connection to an X server.
pub struct Display {
inner: *mut xlib::Display,
pub(crate) inner: *mut xlib::Display,
}
pub struct Grab(pub(crate) *mut xlib::Display);