diff --git a/Cargo.lock b/Cargo.lock index 51da3381..b03103fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,6 +45,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" + [[package]] name = "arboard" version = "3.2.0" @@ -229,6 +235,30 @@ dependencies = [ "syn", ] +[[package]] +name = "atk" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd" +dependencies = [ + "atk-sys", + "bitflags", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "atomic-waker" version = "1.0.0" @@ -266,9 +296,9 @@ checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block" @@ -343,6 +373,30 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" +[[package]] +name = "cairo-rs" +version = "0.15.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c76ee391b03d35510d9fa917357c7f1855bd9a6659c95a1b392e33f49b3369bc" +dependencies = [ + "bitflags", + "cairo-sys-rs", + "glib", + "libc", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + [[package]] name = "calloop" version = "0.10.1" @@ -368,6 +422,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cfg-expr" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa" +dependencies = [ + "smallvec", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -867,9 +930,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", @@ -927,6 +990,16 @@ dependencies = [ "instant", ] +[[package]] +name = "field-offset" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92" +dependencies = [ + "memoffset", + "rustc_version", +] + [[package]] name = "flate2" version = "1.0.24" @@ -1025,12 +1098,32 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "futures-channel" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +dependencies = [ + "futures-core", +] + [[package]] name = "futures-core" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +[[package]] +name = "futures-executor" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.25" @@ -1078,6 +1171,65 @@ dependencies = [ "slab", ] +[[package]] +name = "gdk" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a" +dependencies = [ + "bitflags", + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + [[package]] name = "generic-array" version = "0.14.6" @@ -1121,6 +1273,36 @@ dependencies = [ "weezl", ] +[[package]] +name = "gio" +version = "0.15.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68fdbc90312d462781a395f7a16d96a2b379bb6ef8cd6310a2df272771c4283b" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-io", + "gio-sys", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + [[package]] name = "gl_generator" version = "0.14.0" @@ -1141,6 +1323,51 @@ dependencies = [ "serde", ] +[[package]] +name = "glib" +version = "0.15.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64" +dependencies = [ + "anyhow", + "heck 0.4.0", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" +dependencies = [ + "libc", + "system-deps", +] + [[package]] name = "glow" version = "0.11.2" @@ -1218,6 +1445,72 @@ dependencies = [ "gl_generator", ] +[[package]] +name = "gobject-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e3004a2d5d6d8b5057d2b57b3712c9529b62e82c77f25c1fecde1fd5c23bd0" +dependencies = [ + "atk", + "bitflags", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "once_cell", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f518afe90c23fba585b2d7697856f9e6a7bbc62f65588035e66f6afb01a2e9" +dependencies = [ + "anyhow", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "gumdrop" version = "0.8.1" @@ -1247,6 +1540,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1365,6 +1664,30 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "libappindicator" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2d3cb96d092b4824cb306c9e544c856a4cb6210c1081945187f7f1924b47e8" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b3b6681973cea8cc3bce7391e6d7d5502720b80a581c9a95c9cbaf592826aa" +dependencies = [ + "gtk-sys", + "libloading", + "once_cell", +] + [[package]] name = "libc" version = "0.2.137" @@ -1589,19 +1912,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "nix" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945" -dependencies = [ - "bitflags", - "cc", - "cfg-if", - "libc", - "memoffset", -] - [[package]] name = "nix" version = "0.24.2" @@ -1776,6 +2086,37 @@ dependencies = [ "ttf-parser", ] +[[package]] +name = "padlock" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c10569378a1dacd9f30dbe7ae49e054d2c45dc2f8ee49899903e09c3924e8b6f" + +[[package]] +name = "pango" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" +dependencies = [ + "bitflags", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "parking" version = "2.0.0" @@ -1811,6 +2152,16 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "pest" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a528564cc62c19a7acac4d81e01f39e53e25e17b934878f4c6d25cc2836e62f8" +dependencies = [ + "thiserror", + "ucd-trie", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -1888,6 +2239,30 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.47" @@ -2017,8 +2392,13 @@ dependencies = [ "dirs", "eframe", "egui", - "nix 0.20.2", + "env_logger", + "gtk", + "libappindicator", + "log", + "nix 0.25.0", "notify-rust", + "png_pong", "rog_anime", "rog_aura", "rog_dbus", @@ -2031,6 +2411,7 @@ dependencies = [ "tempfile", "tokio", "toml", + "tray-item", "zbus", ] @@ -2112,6 +2493,15 @@ dependencies = [ "libusb1-sys", ] +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver", +] + [[package]] name = "ryu" version = "1.0.11" @@ -2160,6 +2550,24 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.147" @@ -2377,7 +2785,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn", @@ -2420,6 +2828,19 @@ dependencies = [ "numtoa", ] +[[package]] +name = "system-deps" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" +dependencies = [ + "cfg-expr", + "heck 0.4.0", + "pkg-config", + "toml", + "version-compare", +] + [[package]] name = "tauri-winrt-notification" version = "0.1.0" @@ -2608,6 +3029,24 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tray-item" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0914b62e00e8f51241806cb9f9c4ea6b10c75d94cae02c89278de6f4b98c7d0f" +dependencies = [ + "cocoa", + "core-graphics", + "gtk", + "libappindicator", + "libc", + "objc", + "objc-foundation", + "objc_id", + "padlock", + "winapi", +] + [[package]] name = "ttf-parser" version = "0.17.1" @@ -2620,6 +3059,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "ucd-trie" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" + [[package]] name = "udev" version = "0.6.3" @@ -2691,6 +3136,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version-compare" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 3ef9e302..89bc2afc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ serde_json = "^1.0" toml = "^0.5.9" log = "^0.4" -env_logger = "^0.9" +env_logger = "^0.9.3" glam = { version = "^0.22", features = ["serde"] } gumdrop = "^0.8" diff --git a/rog-control-center/Cargo.toml b/rog-control-center/Cargo.toml index 797fe9b3..8f06ce75 100644 --- a/rog-control-center/Cargo.toml +++ b/rog-control-center/Cargo.toml @@ -12,6 +12,10 @@ egui = { git = "https://github.com/flukejones/egui" } eframe= { git = "https://github.com/flukejones/egui" } #eframe= { git = "https://github.com/emilk/egui", default-features = false, features = ["dark-light", "default_fonts", "wgpu"] } +tray-item = "0.7.1" +libappindicator = "0.7" # Tray icon +gtk = "0.15" + daemon = { path = "../daemon" } rog_anime = { path = "../rog-anime" } rog_dbus = { path = "../rog-dbus" } @@ -21,6 +25,9 @@ rog_platform = { path = "../rog-platform" } supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", default-features = false } #supergfxctl = { path = "../../supergfxctl", default-features = false } +log.workspace = true +env_logger.workspace = true + tokio.workspace = true serde.workspace = true toml.workspace = true @@ -30,5 +37,7 @@ zbus.workspace = true dirs.workspace = true notify-rust.workspace = true -nix = "^0.20.0" +png_pong.workspace = true + +nix = "^0.25" tempfile = "3.2.0" \ No newline at end of file diff --git a/rog-control-center/data/rog-control-center.png b/rog-control-center/data/rog-control-center.png index 71e7b176..958944bc 100644 Binary files a/rog-control-center/data/rog-control-center.png and b/rog-control-center/data/rog-control-center.png differ diff --git a/rog-control-center/src/app.rs b/rog-control-center/src/app.rs index 847364fe..51d71789 100644 --- a/rog-control-center/src/app.rs +++ b/rog-control-center/src/app.rs @@ -2,16 +2,18 @@ use std::{ f64::consts::PI, sync::{ atomic::{AtomicBool, AtomicU8, Ordering}, + mpsc::Receiver, Arc, }, - time::{Duration, Instant}, + time::{Duration, Instant}, io::Write, }; use egui::{Button, RichText}; use rog_platform::supported::SupportedFunctions; use crate::{ - config::Config, error::Result, page_states::PageDataStates, Page, RogDbusClientBlocking, + config::Config, error::Result, page_states::PageDataStates, tray::TrayToApp, Page, + RogDbusClientBlocking, get_ipc_file, SHOW_GUI, }; pub struct RogApp<'a> { @@ -29,6 +31,7 @@ pub struct RogApp<'a> { pub oscillator_freq: Arc, /// A toggle that toggles true/false when the oscillator reaches 0 pub oscillator_toggle: Arc, + pub app_cmd: Arc>, } impl<'a> RogApp<'a> { @@ -36,6 +39,7 @@ impl<'a> RogApp<'a> { pub fn new( config: Config, states: PageDataStates, + app_cmd: Arc>, _cc: &eframe::CreationContext<'_>, ) -> Result { let (dbus, _) = RogDbusClientBlocking::new()?; @@ -98,20 +102,38 @@ impl<'a> RogApp<'a> { oscillator3, oscillator_toggle, oscillator_freq, + app_cmd, }) } + + fn check_app_cmds(&mut self, _ctx: &egui::Context, _frame: &mut eframe::Frame) { + let Self { app_cmd, .. } = self; + + if let Ok(cmd) = app_cmd.try_recv() { + match cmd { + TrayToApp::Open => { + dbg!(); + get_ipc_file().unwrap().write_all(&[SHOW_GUI]).ok(); + }, + TrayToApp::Quit => _frame.close(), + } + } + } } impl<'a> eframe::App for RogApp<'a> { /// Called each time the UI needs repainting, which may be many times per second. /// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`. fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { + self.check_app_cmds(ctx, frame); + let Self { supported, asus_dbus: dbus, states, .. } = self; + states .refresh_if_notfied(supported, dbus) .map(|repaint| { diff --git a/rog-control-center/src/lib.rs b/rog-control-center/src/lib.rs index de4a5324..76c926db 100644 --- a/rog-control-center/src/lib.rs +++ b/rog-control-center/src/lib.rs @@ -18,6 +18,7 @@ pub mod page_states; pub mod pages; pub mod startup_error; pub mod widgets; +pub mod tray; #[cfg(feature = "mocking")] pub use mocking::RogDbusClientBlocking; @@ -96,7 +97,7 @@ pub fn get_ipc_file() -> Result { let tmp_dir = std::env::temp_dir().join("rog-gui"); let fifo_path = tmp_dir.join("ipc.pipe"); if let Err(e) = unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) { - if !matches!(e, nix::Error::Sys(nix::errno::Errno::EEXIST)) { + if !matches!(e, nix::errno::Errno::EEXIST) { return Err(e)?; } } diff --git a/rog-control-center/src/main.rs b/rog-control-center/src/main.rs index 232a4e7c..514a4a6f 100644 --- a/rog-control-center/src/main.rs +++ b/rog-control-center/src/main.rs @@ -1,34 +1,48 @@ -use eframe::NativeOptions; +use eframe::{IconData, NativeOptions}; +use log::{error, LevelFilter}; use rog_aura::layouts::KeyLayout; +use rog_control_center::tray::{AppToTray, TrayToApp}; use rog_control_center::{ config::Config, error::Result, get_ipc_file, notify::start_notifications, on_tmp_dir_exists, - page_states::PageDataStates, print_versions, startup_error::AppErrorShow, RogApp, - RogDbusClientBlocking, SHOWING_GUI, SHOW_GUI, + page_states::PageDataStates, print_versions, startup_error::AppErrorShow, tray::init_tray, + RogApp, RogDbusClientBlocking, SHOWING_GUI, SHOW_GUI, }; use rog_platform::supported::SupportedFunctions; -use tokio::runtime::Runtime; - +use std::sync::mpsc::{channel, Receiver, Sender}; +use std::sync::Mutex; use std::{ fs::OpenOptions, io::{Read, Write}, path::PathBuf, sync::{atomic::AtomicBool, Arc}, }; +use tokio::runtime::Runtime; #[cfg(not(feature = "mocking"))] const DATA_DIR: &str = "/usr/share/rog-gui/"; #[cfg(feature = "mocking")] const DATA_DIR: &str = env!("CARGO_MANIFEST_DIR"); const BOARD_NAME: &str = "/sys/class/dmi/id/board_name"; +const APP_ICON_PATH: &str = "/usr/share/icons/hicolor/512x512/apps/rog-control-center.png"; fn main() -> Result<()> { print_versions(); + let mut logger = env_logger::Builder::new(); + logger + .target(env_logger::Target::Stdout) + .format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())) + .filter(None, LevelFilter::Info) + .init(); // start tokio let rt = Runtime::new().expect("Unable to create Runtime"); // Enter the runtime so that `tokio::spawn` is available immediately. let _enter = rt.enter(); + let (send, recv) = channel(); + let update_tray = Arc::new(Mutex::new(send)); + let app_cmd = Arc::new(init_tray(recv)); + let native_options = eframe::NativeOptions { vsync: true, decorated: true, @@ -36,6 +50,7 @@ fn main() -> Result<()> { min_window_size: Some(egui::vec2(840.0, 600.0)), max_window_size: Some(egui::vec2(840.0, 600.0)), run_and_return: true, + icon_data: Some(load_icon()), ..Default::default() }; @@ -93,13 +108,18 @@ fn main() -> Result<()> { Err(_) => on_tmp_dir_exists().unwrap(), }; - let states = - setup_page_state_and_notifs(layout.clone(), &config, native_options.clone(), &dbus) - .unwrap(); + let states = setup_page_state_and_notifs( + layout.clone(), + &config, + native_options.clone(), + &dbus, + update_tray, + ) + .unwrap(); loop { if !start_closed { - start_app(states.clone(), native_options.clone())?; + start_app(states.clone(), native_options.clone(), app_cmd.clone())?; } let config = Config::load().unwrap(); @@ -130,6 +150,7 @@ fn setup_page_state_and_notifs( config: &Config, native_options: NativeOptions, dbus: &RogDbusClientBlocking, + update_tray: Arc>>, ) -> Result { // Cheap method to alert to notifications rather than spinning a thread for each // This is quite different when done in a retained mode app @@ -149,6 +170,7 @@ fn setup_page_state_and_notifs( profiles_notified.clone(), fans_notified.clone(), notifs_enabled.clone(), + update_tray, )?; let supported = match dbus.proxies().supported().supported_functions() { @@ -177,13 +199,57 @@ fn setup_page_state_and_notifs( ) } -fn start_app(states: PageDataStates, native_options: NativeOptions) -> Result<()> { +fn start_app( + states: PageDataStates, + native_options: NativeOptions, + app_cmd: Arc>, +) -> Result<()> { let mut ipc_file = get_ipc_file().unwrap(); ipc_file.write_all(&[SHOWING_GUI]).unwrap(); eframe::run_native( "ROG Control Center", native_options, - Box::new(move |cc| Box::new(RogApp::new(Config::load().unwrap(), states, cc).unwrap())), + Box::new(move |cc| { + Box::new(RogApp::new(Config::load().unwrap(), states, app_cmd, cc).unwrap()) + }), ); Ok(()) } + +/// Bah.. the icon dosn't work on wayland anyway, but we'll leave it in for now. +fn load_icon() -> IconData { + let path = PathBuf::from(APP_ICON_PATH); + let mut buf = Vec::new(); + let mut rgba = Vec::new(); + let mut height = 512; + let mut width = 512; + if path.exists() { + if let Ok(mut file) = OpenOptions::new() + .read(true) + .open(path) + .map_err(|e| error!("Error opening app icon: {e:?}")) + { + file.read_to_end(&mut buf) + .map_err(|e| error!("Error reading app icon: {e:?}")) + .ok(); + + let data = std::io::Cursor::new(buf); + let decoder = png_pong::Decoder::new(data).unwrap().into_steps(); + let png_pong::Step { raster, delay: _ } = decoder.last().unwrap().unwrap(); + + if let png_pong::PngRaster::Rgba8(ras) = raster { + rgba = ras.as_u8_slice().to_vec(); + width = ras.width(); + height = ras.height(); + } + } + } else { + error!("Missing {APP_ICON_PATH}") + } + + IconData { + height, + width, + rgba, + } +} diff --git a/rog-control-center/src/notify.rs b/rog-control-center/src/notify.rs index 0314901f..a6704d07 100644 --- a/rog-control-center/src/notify.rs +++ b/rog-control-center/src/notify.rs @@ -1,4 +1,4 @@ -use crate::error::Result; +use crate::{error::Result, tray::AppToTray}; use notify_rust::{Hint, Notification, NotificationHandle}; use rog_dbus::{ zbus_anime::AnimeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy, @@ -10,6 +10,7 @@ use std::{ fmt::Display, sync::{ atomic::{AtomicBool, Ordering}, + mpsc::Sender, Arc, Mutex, }, }; @@ -73,6 +74,7 @@ pub fn start_notifications( profiles_notified: Arc, _fans_notified: Arc, notifs_enabled: Arc, + update_tray: Arc>>, ) -> Result<()> { let last_notification: SharedHandle = Arc::new(Mutex::new(None)); @@ -227,6 +229,9 @@ pub fn start_notifications( ), lock ); + if let Ok(lock) = update_tray.try_lock() { + lock.send(AppToTray::DgpuStatus(*status)).ok(); + } } } }