diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Cargo.lock | 997 | ||||
-rw-r--r-- | Cargo.toml | 10 | ||||
-rw-r--r-- | icon.svg | 138 | ||||
-rw-r--r-- | resources/exclam.png | bin | 0 -> 1631 bytes | |||
-rw-r--r-- | resources/ok.png | bin | 0 -> 1907 bytes | |||
-rw-r--r-- | src/error.rs | 27 | ||||
-rw-r--r-- | src/main.rs | 184 |
8 files changed, 1357 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..3545048 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,997 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "acpi-inhibitor" +version = "0.1.0" +dependencies = [ + "dialog", + "systray", + "tempfile", +] + +[[package]] +name = "aho-corasick" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" + +[[package]] +name = "atk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444daefa55f229af145ea58d77efd23725024ee1f6f3102743709aa6b18c663e" +dependencies = [ + "atk-sys", + "bitflags", + "glib", + "glib-sys", + "gobject-sys", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e552c1776737a4c80110d06b36d099f47c727335f9aaa5d942a72b6863a8ec6f" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.8", +] + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" + +[[package]] +name = "bindgen" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c85344eb535a31b62f0af37be84441ba9e7f0f4111eb0530f43d15e513fe57" +dependencies = [ + "bitflags", + "cexpr", + "cfg-if", + "clang-sys", + "clap", + "env_logger", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "which", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "blake2b_simd" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "cairo-rs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157049ba9618aa3a61c39d5d785102c04d3b1f40632a706c621a9aedc21e6084" +dependencies = [ + "bitflags", + "cairo-sys-rs", + "glib", + "glib-sys", + "gobject-sys", + "libc", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff65ba02cac715be836f63429ab00a767d48336efc5497c5637afb53b4f14d63" +dependencies = [ + "glib-sys", + "libc", + "pkg-config", +] + +[[package]] +name = "cc" +version = "1.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d" + +[[package]] +name = "cexpr" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "clang-sys" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "dialog" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736bab36d647d14c985725a57a4110a1182c6852104536cd42f1c97e96d29bf0" +dependencies = [ + "dirs", + "rpassword", +] + +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +dependencies = [ + "cfg-if", + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" +dependencies = [ + "cfg-if", + "libc", + "redox_users", + "winapi 0.3.8", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "futures-channel" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" + +[[package]] +name = "futures-executor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6" + +[[package]] +name = "futures-macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-task" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" + +[[package]] +name = "futures-util" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +dependencies = [ + "futures-core", + "futures-macro", + "futures-task", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "slab", +] + +[[package]] +name = "gdk" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbe5e8772fc0865c52460cdd7a59d7d47700f44d9809d1dd00eecceb769a7589" +dependencies = [ + "bitflags", + "cairo-rs", + "cairo-sys-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e248220c46b329b097d4b158d2717f8c688f16dd76d0399ace82b3e98062bdd7" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8991b060a9e9161bafd09bf4a202e6fd404f5b4dd1a08d53a1e84256fb34ab0" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", +] + +[[package]] +name = "gdk-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6adf679e91d1bff0c06860287f80403e7db54c2d2424dce0a470023b56c88fbb" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gio" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cd10f9415cce39b53f8024bf39a21f84f8157afa52da53837b102e585a296a5" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "lazy_static", + "libc", +] + +[[package]] +name = "gio-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fad225242b9eae7ec8a063bb86974aca56885014672375e5775dc0ea3533911" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", +] + +[[package]] +name = "glib" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40fb573a09841b6386ddf15fd4bc6655b4f5b106ca962f57ecaecde32a0061c0" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "glib-sys", + "gobject-sys", + "lazy_static", + "libc", +] + +[[package]] +name = "glib-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95856f3802f446c05feffa5e24859fe6a183a7cb849c8449afc35c86b1e316e2" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "gobject-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d1a804f62034eccf370006ccaef3708a71c31d561fee88564abe71177553d9" +dependencies = [ + "glib-sys", + "libc", + "pkg-config", +] + +[[package]] +name = "gtk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e1e8d70290239c668594002d1b174fcc7d7ef5d26670ee141490ede8facf8f" +dependencies = [ + "atk", + "bitflags", + "cairo-rs", + "cairo-sys-rs", + "cc", + "gdk", + "gdk-pixbuf", + "gdk-pixbuf-sys", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk-sys", + "lazy_static", + "libc", + "pango", + "pango-sys", +] + +[[package]] +name = "gtk-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53def660c7b48b00b510c81ef2d2fbd3c570f1527081d8d7947f471513e1a4c1" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", +] + +[[package]] +name = "hermit-abi" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" + +[[package]] +name = "libappindicator" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f31c50d55007b7c159531ad0301ab6fc3c65de3788ae8956ecbf9b890304059" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366238ec86fad8ffcf593078ff667f9852bf30836b38ebd1a70d3c9ddfec07a3" +dependencies = [ + "bindgen", + "gtk-sys", + "pkg-config", +] + +[[package]] +name = "libc" +version = "0.2.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" + +[[package]] +name = "libloading" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +dependencies = [ + "cc", + "winapi 0.3.8", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +dependencies = [ + "memchr", + "version_check", +] + +[[package]] +name = "pango" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9c6b728f1be8edb5f9f981420b651d5ea30bdb9de89f1f1262d0084a020577" +dependencies = [ + "bitflags", + "glib", + "glib-sys", + "gobject-sys", + "lazy_static", + "libc", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b93d84907b3cf0819bff8f13598ba72843bee579d5ebc2502e4b0367b4be7d" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" + +[[package]] +name = "proc-macro-hack" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" + +[[package]] +name = "proc-macro-nested" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" + +[[package]] +name = "proc-macro2" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" + +[[package]] +name = "redox_users" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" +dependencies = [ + "getrandom", + "redox_syscall", + "rust-argon2", +] + +[[package]] +name = "regex" +version = "1.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" + +[[package]] +name = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "rpassword" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37473170aedbe66ffa3ad3726939ba677d83c646ad4fd99e5b4bc38712f45ec" +dependencies = [ + "kernel32-sys", + "libc", + "winapi 0.2.8", +] + +[[package]] +name = "rust-argon2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" +dependencies = [ + "base64", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "systray" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d32363b257d5b4d444bb76a7d063663569544fd598cf4fd2f13bb5b0f2d8b5" +dependencies = [ + "glib", + "gtk", + "libappindicator", + "libc", + "log", + "winapi 0.3.8", +] + +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.8", +] + +[[package]] +name = "termcolor" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "which" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" +dependencies = [ + "libc", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a5aa342 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "acpi-inhibitor" +version = "0.1.0" +authors = ["Tom Smeding <tom.smeding@gmail.com>"] +edition = "2018" + +[dependencies] +"systray" = "0.4" +"dialog" = "0.3" +"tempfile" = "3.1" diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..1c86a6f --- /dev/null +++ b/icon.svg @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="200mm" + height="200mm" + viewBox="0 0 200 200" + version="1.1" + id="svg8" + inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)" + sodipodi:docname="icon.svg" + inkscape:export-filename="/home/tom/code/acpi-inhibitor/spark.png" + inkscape:export-xdpi="6.0959997" + inkscape:export-ydpi="6.0959997"> + <defs + id="defs2"> + <inkscape:path-effect + effect="mirror_symmetry" + start_point="105.30419,153.47626" + end_point="105.30419,208.80105" + center_point="105.30419,181.13865" + id="path-effect4526" + is_visible="true" + mode="free" + discard_orig_path="false" + fuse_paths="false" + oposite_fuse="false" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.49497475" + inkscape:cx="279.261" + inkscape:cy="304.39757" + inkscape:document-units="mm" + inkscape:current-layer="layer2" + showgrid="false" + fit-margin-top="5" + fit-margin-left="5" + fit-margin-right="5" + fit-margin-bottom="5" + inkscape:window-width="1916" + inkscape:window-height="1028" + inkscape:window-x="0" + inkscape:window-y="24" + inkscape:window-maximized="0" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-5.423512,-59.315461)" + style="display:inline"> + <circle + style="opacity:0.98999999;fill:none;fill-opacity:1;stroke:#ff1e1e;stroke-width:25;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path4518" + cx="105.42352" + cy="171.96426" + r="64.255951" /> + <path + style="fill:none;stroke:#ff1e1e;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 105.42351,69.910707 V 147.65983" + id="path4520" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + </g> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="spark" + style="display:inline"> + <path + transform="translate(-5.423512,-59.315461)" + style="display:inline;fill:#ffff2b;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 12.814623,203.96466 57.195676,-63.07561 64.411961,43.03039 63.61014,-37.2841 -63.34288,62.14017 -63.342873,-41.42677 z" + id="path4524" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccc" /> + </g> + <g + inkscape:groupmode="layer" + id="layer3" + inkscape:label="exclam" + style="display:none"> + <path + style="fill:#ffff2b;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 68.194927,19.325801 H 131.80507 L 100,138.09814 Z" + id="path847" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + style="opacity:0.98999999;fill:#ffff2b;fill-opacity:1;stroke:none;stroke-width:25;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path849" + sodipodi:type="arc" + sodipodi:cx="100" + sodipodi:cy="167.12585" + sodipodi:rx="21.648832" + sodipodi:ry="21.648832" + sodipodi:start="0" + sodipodi:end="6.2783507" + sodipodi:open="true" + d="m 121.64883,167.12585 a 21.648832,21.648832 0 0 1 -21.62266,21.64882 21.648832,21.648832 0 0 1 -21.674939,-21.59648 21.648832,21.648832 0 0 1 21.570271,-21.70103 21.648832,21.648832 0 0 1 21.727078,21.54403" /> + </g> + <g + inkscape:groupmode="layer" + id="layer4" + inkscape:label="ok" + style="display:none"> + <path + style="fill:none;stroke:#14ff14;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 16.570709,108.05928 63.075608,160.97865 178.53604,61.554386" + id="path853" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccc" /> + </g> +</svg> diff --git a/resources/exclam.png b/resources/exclam.png Binary files differnew file mode 100644 index 0000000..312b4a8 --- /dev/null +++ b/resources/exclam.png diff --git a/resources/ok.png b/resources/ok.png Binary files differnew file mode 100644 index 0000000..bd0390c --- /dev/null +++ b/resources/ok.png diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..f25bc5d --- /dev/null +++ b/src/error.rs @@ -0,0 +1,27 @@ +use std::io; + +pub trait IntoIOError { + fn ioerr(self) -> io::Error; + fn perror(self, parent: io::Error) -> io::Error; +} + +// This impl bound is taken directly from the io::Error::new function. +impl<E: Into<Box<dyn std::error::Error + Send + Sync>>> IntoIOError for E { + fn ioerr(self) -> io::Error { + io::Error::new(io::ErrorKind::Other, self) + } + + fn perror(self, parent: io::Error) -> io::Error { + io::Error::new(parent.kind(), format!("{}: {}", self.into(), parent)) + } +} + +pub trait IntoIOResult<T> { + fn iores(self) -> io::Result<T>; +} + +impl<T, E: IntoIOError> IntoIOResult<T> for Result<T, E> { + fn iores(self) -> io::Result<T> { + self.map_err(|e| e.ioerr()) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..7eb4a41 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,184 @@ +use std::fs; +use std::io; +use std::path::{Path, PathBuf}; +use std::process::{Command, Child, Stdio}; +use std::sync::{Mutex, Arc}; +use systray; +use dialog::{self, DialogBox}; +use tempfile::tempdir; +use crate::error::*; + +mod error; + +const ICON_EXCLAM_PNG: &[u8] = include_bytes!("../resources/exclam.png"); +const ICON_OK_PNG: &[u8] = include_bytes!("../resources/ok.png"); + +fn join(sep: &str, v: &[String]) -> String { + let mut res = String::new(); + let mut first = true; + for item in v { + if first { first = false; } + else { res.push_str(sep); } + res.push_str(item); + } + res +} + +struct State { + // Child is 'cat >/dev/null', with stdin piped. + // Close stdin to terminate. + inhibitor: Option<(Child, Vec<String>)>, + ok_path: String, + exclam_path: String, +} + +impl State { + fn new(ok_path: &str, exclam_path: &str) -> State { + State { + inhibitor: None, + ok_path: ok_path.to_string(), + exclam_path: exclam_path.to_string(), + } + } + + fn what_inhibited(&self) -> Option<&[String]> { + match &self.inhibitor { + Some((_, v)) => Some(v), + None => None, + } + } + + fn inhibit(&mut self, what: &[String]) -> io::Result<()> { + self.uninhibit()?; + + let mut whatarg = "--what=".to_string(); + whatarg.push_str(&join(":", what)); + + let child = Command::new("systemd-inhibit") + .arg(whatarg) + .arg("--who=Tom's acpi-inhibitor") + .arg("--why=User request") + .arg("cat") + .stdin(Stdio::piped()) + .stdout(Stdio::null()) + .spawn()?; + self.inhibitor = Some((child, what.to_vec())); + + Ok(()) + } + + fn uninhibit(&mut self) -> io::Result<()> { + if let Some((ch, _)) = &mut self.inhibitor { + // This automatically closes the child's stdin + ch.wait()?; + self.inhibitor = None; + } + + Ok(()) + } + + fn poll(&mut self) -> io::Result<()> { + if let Some((ch, _)) = &mut self.inhibitor { + if ch.try_wait()?.is_some() { + self.inhibitor = None; + } + } + + Ok(()) + } +} + +fn show_dialog(title: &str, body: &str) -> io::Result<()> { + dialog::Message::new(body).title(title).show() + .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{}", e))) +} + +fn status_message(state: &mut State) -> io::Result<String> { + state.poll()?; + + let mut msg; + match state.what_inhibited() { + Some(what) => { + msg = "Currently inhibiting: ".to_string(); + msg.push_str(&join(", ", what)); + } + None => { + msg = "Currently functioning normally (not inhibited)".to_string(); + } + } + + Ok(msg) +} + +fn update_icon(app: &mut systray::Application, state: &mut State) -> io::Result<()> { + match state.what_inhibited() { + Some(_) => app.set_icon_from_file(&state.exclam_path).iores(), + None => app.set_icon_from_file(&state.ok_path).iores(), + } +} + +fn materialise_icon(dir: &Path, fname: &str, bytes: &[u8]) -> io::Result<PathBuf> { + let mut pathbuf = dir.to_path_buf(); + pathbuf.push(fname); + fs::write(&pathbuf, bytes)?; + Ok(pathbuf) +} + +fn main() -> io::Result<()> { + let resources_dir = tempdir()?; + let resources_path = resources_dir.path(); + + let icon_ok_path = materialise_icon(&resources_path, "ok.png", ICON_OK_PNG)?; + let icon_exclam_path = materialise_icon(&resources_path, "exclam.png", ICON_EXCLAM_PNG)?; + + let mut app = systray::Application::new().iores()?; + + let state = Arc::new(Mutex::new(State::new( + icon_ok_path.to_str().unwrap(), + icon_exclam_path.to_str().unwrap() + ))); + + app.set_icon_from_file(icon_ok_path.to_str().unwrap()).iores()?; + + { + let state = state.clone(); + app.add_menu_item("Status", move |window| { + let mut state = state.as_ref().lock().unwrap(); + let msg = status_message(&mut state)?; + update_icon(window, &mut state)?; + show_dialog("acpi-inhibitor status", &msg) + }).iores()?; + } + + app.add_menu_separator().iores()?; + + macro_rules! switcher_menu { + ($label:expr, $keys:expr) => {{ + let state = state.clone(); + app.add_menu_item($label, move |mut window| { + let mut state = state.as_ref().lock().unwrap(); + let keys = $keys; + if state.what_inhibited() == Some(keys) { + state.uninhibit()?; + } else { + state.inhibit(keys)?; + } + update_icon(&mut window, &mut state)?; + Ok::<_, io::Error>(()) + }).iores()?; + }} + } + + switcher_menu!("Shutdown/sleep/idle", &["shutdown".to_string(), "sleep".to_string(), "idle".to_string()]); + + switcher_menu!("Lid switch", &["handle-lid-switch".to_string()]); + + app.add_menu_separator().iores()?; + + app.add_menu_item("Quit", |window| { + window.quit(); + Ok::<_, systray::Error>(()) + }).iores()?; + + app.wait_for_message().iores() +} |