mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-01-22 17:33:19 +01:00
Enable system tray status for dGPU and actions
This commit is contained in:
77
Cargo.lock
generated
77
Cargo.lock
generated
@@ -116,22 +116,22 @@ version = "1.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28"
|
checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"concurrent-queue",
|
"concurrent-queue 1.2.4",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-executor"
|
name = "async-executor"
|
||||||
version = "1.4.1"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
|
checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-lock",
|
||||||
"async-task",
|
"async-task",
|
||||||
"concurrent-queue",
|
"concurrent-queue 2.0.0",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"once_cell",
|
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"async-lock",
|
"async-lock",
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"concurrent-queue",
|
"concurrent-queue 1.2.4",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
@@ -399,9 +399,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "calloop"
|
name = "calloop"
|
||||||
version = "0.10.1"
|
version = "0.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a22a6a8f622f797120d452c630b0ab12e1331a1a753e2039ce7868d4ac77b4ee"
|
checksum = "595eb0438b3c6d262395fe30e6de9a61beb57ea56290b00a07f227fe6e20cbf2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"nix 0.24.2",
|
"nix 0.24.2",
|
||||||
@@ -412,9 +412,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.74"
|
version = "1.0.76"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574"
|
checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cesu8"
|
name = "cesu8"
|
||||||
@@ -532,6 +532,15 @@ dependencies = [
|
|||||||
"cache-padded",
|
"cache-padded",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "concurrent-queue"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.3"
|
version = "0.9.3"
|
||||||
@@ -603,6 +612,15 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossfont"
|
name = "crossfont"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -1786,9 +1804,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memmap2"
|
name = "memmap2"
|
||||||
version = "0.5.7"
|
version = "0.5.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498"
|
checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -2086,12 +2104,6 @@ dependencies = [
|
|||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "padlock"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c10569378a1dacd9f30dbe7ae49e054d2c45dc2f8ee49899903e09c3924e8b6f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango"
|
name = "pango"
|
||||||
version = "0.15.10"
|
version = "0.15.10"
|
||||||
@@ -2411,7 +2423,6 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
"tray-item",
|
|
||||||
"zbus",
|
"zbus",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2794,7 +2805,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "supergfxctl"
|
name = "supergfxctl"
|
||||||
version = "5.0.2"
|
version = "5.0.2"
|
||||||
source = "git+https://gitlab.com/asus-linux/supergfxctl.git#3ee8fdfaa1cc79d0fe116cbd67269603e4e7bafe"
|
source = "git+https://gitlab.com/asus-linux/supergfxctl.git#fa022efb54b752a3672a64c640bd7aebeb842e05"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"logind-zbus",
|
"logind-zbus",
|
||||||
@@ -3029,24 +3040,6 @@ dependencies = [
|
|||||||
"once_cell",
|
"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]]
|
[[package]]
|
||||||
name = "ttf-parser"
|
name = "ttf-parser"
|
||||||
version = "0.17.1"
|
version = "0.17.1"
|
||||||
@@ -3138,9 +3131,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version-compare"
|
name = "version-compare"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
|
checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
@@ -3332,9 +3325,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webbrowser"
|
name = "webbrowser"
|
||||||
version = "0.8.1"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f7aa8c655ad0b020787afb0b8f0656b2cfbef3452d619ea930e6b1aa1c5c1e9"
|
checksum = "2a0cc7962b5aaa0dfcebaeef0161eec6edf5f4606c12e6777fd7d392f52033a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jni",
|
"jni",
|
||||||
"ndk-context",
|
"ndk-context",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ version = "4.5.1"
|
|||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
async-trait = "^0.1"
|
async-trait = "^0.1"
|
||||||
tokio = { version = "^1.21.2", features = ["macros", "rt-multi-thread", "time"]}
|
tokio = { version = "^1.21.2", features = ["macros", "rt-multi-thread", "time", "sync"]}
|
||||||
concat-idents = "^1.1"
|
concat-idents = "^1.1"
|
||||||
dirs = "^4.0"
|
dirs = "^4.0"
|
||||||
smol = "^1.2"
|
smol = "^1.2"
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ impl Config {
|
|||||||
pub fn read(&mut self) {
|
pub fn read(&mut self) {
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.open(&CONFIG_PATH)
|
.open(CONFIG_PATH)
|
||||||
.unwrap_or_else(|err| panic!("Error reading {}: {}", CONFIG_PATH, err));
|
.unwrap_or_else(|err| panic!("Error reading {}: {}", CONFIG_PATH, err));
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
if let Ok(l) = file.read_to_string(&mut buf) {
|
if let Ok(l) = file.read_to_string(&mut buf) {
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ impl LedSupportFile {
|
|||||||
let mut loaded = false;
|
let mut loaded = false;
|
||||||
let mut data = LedSupportFile::default();
|
let mut data = LedSupportFile::default();
|
||||||
// Load user configs first so they are first to be checked
|
// Load user configs first so they are first to be checked
|
||||||
if let Ok(mut file) = OpenOptions::new().read(true).open(&ASUS_LED_MODE_USER_CONF) {
|
if let Ok(mut file) = OpenOptions::new().read(true).open(ASUS_LED_MODE_USER_CONF) {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
if let Ok(l) = file.read_to_string(&mut buf) {
|
if let Ok(l) = file.read_to_string(&mut buf) {
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
@@ -107,7 +107,7 @@ impl LedSupportFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Load and append the default LED support data
|
// Load and append the default LED support data
|
||||||
if let Ok(mut file) = OpenOptions::new().read(true).open(&ASUS_LED_MODE_CONF) {
|
if let Ok(mut file) = OpenOptions::new().read(true).open(ASUS_LED_MODE_CONF) {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
if let Ok(l) = file.read_to_string(&mut buf) {
|
if let Ok(l) = file.read_to_string(&mut buf) {
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ egui = { git = "https://github.com/flukejones/egui" }
|
|||||||
eframe= { 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"] }
|
#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
|
libappindicator = "0.7" # Tray icon
|
||||||
gtk = "0.15"
|
gtk = "0.15"
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
use std::{
|
use std::{
|
||||||
f64::consts::PI,
|
f64::consts::PI,
|
||||||
|
io::Write,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, AtomicU8, Ordering},
|
atomic::{AtomicBool, AtomicU8, Ordering},
|
||||||
mpsc::Receiver,
|
mpsc::Receiver,
|
||||||
Arc,
|
Arc,
|
||||||
},
|
},
|
||||||
time::{Duration, Instant}, io::Write,
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use egui::{Button, RichText};
|
use egui::{Button, RichText};
|
||||||
use rog_platform::supported::SupportedFunctions;
|
use rog_platform::supported::SupportedFunctions;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config, error::Result, page_states::PageDataStates, tray::TrayToApp, Page,
|
config::Config, error::Result, get_ipc_file, page_states::PageDataStates, tray::TrayToApp,
|
||||||
RogDbusClientBlocking, get_ipc_file, SHOW_GUI,
|
Page, RogDbusClientBlocking, SHOW_GUI,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct RogApp<'a> {
|
pub struct RogApp<'a> {
|
||||||
@@ -108,13 +109,13 @@ impl<'a> RogApp<'a> {
|
|||||||
|
|
||||||
fn check_app_cmds(&mut self, _ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
fn check_app_cmds(&mut self, _ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
let Self { app_cmd, .. } = self;
|
let Self { app_cmd, .. } = self;
|
||||||
|
|
||||||
if let Ok(cmd) = app_cmd.try_recv() {
|
if let Ok(cmd) = app_cmd.try_recv() {
|
||||||
match cmd {
|
match cmd {
|
||||||
TrayToApp::Open => {
|
TrayToApp::Open => {
|
||||||
dbg!();
|
dbg!();
|
||||||
get_ipc_file().unwrap().write_all(&[SHOW_GUI]).ok();
|
get_ipc_file().unwrap().write_all(&[SHOW_GUI]).ok();
|
||||||
},
|
}
|
||||||
TrayToApp::Quit => _frame.close(),
|
TrayToApp::Quit => _frame.close(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +127,7 @@ impl<'a> eframe::App for RogApp<'a> {
|
|||||||
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
||||||
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
|
||||||
self.check_app_cmds(ctx, frame);
|
self.check_app_cmds(ctx, frame);
|
||||||
|
|
||||||
let Self {
|
let Self {
|
||||||
supported,
|
supported,
|
||||||
asus_dbus: dbus,
|
asus_dbus: dbus,
|
||||||
|
|||||||
@@ -6,17 +6,18 @@ use std::{
|
|||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
//use log::{error, info, warn};
|
//use log::{error, info, warn};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::{error::Error, notify::EnabledNotifications};
|
||||||
|
|
||||||
const CFG_DIR: &str = "rog";
|
const CFG_DIR: &str = "rog";
|
||||||
const CFG_FILE_NAME: &str = "rog-control-center.cfg";
|
const CFG_FILE_NAME: &str = "rog-control-center.cfg";
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub run_in_background: bool,
|
pub run_in_background: bool,
|
||||||
pub startup_in_background: bool,
|
pub startup_in_background: bool,
|
||||||
pub enable_notifications: bool,
|
pub enable_notifications: bool,
|
||||||
|
pub enabled_notifications: EnabledNotifications,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@@ -25,6 +26,7 @@ impl Default for Config {
|
|||||||
run_in_background: true,
|
run_in_background: true,
|
||||||
startup_in_background: false,
|
startup_in_background: false,
|
||||||
enable_notifications: true,
|
enable_notifications: true,
|
||||||
|
enabled_notifications: EnabledNotifications::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +67,7 @@ impl Config {
|
|||||||
Err(Error::ConfigLoadFail)
|
Err(Error::ConfigLoadFail)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(&self) -> Result<(), Error> {
|
pub fn save(&mut self, enabled_notifications: &EnabledNotifications) -> Result<(), Error> {
|
||||||
let mut path = if let Some(dir) = dirs::config_dir() {
|
let mut path = if let Some(dir) = dirs::config_dir() {
|
||||||
dir
|
dir
|
||||||
} else {
|
} else {
|
||||||
@@ -85,6 +87,7 @@ impl Config {
|
|||||||
.truncate(true)
|
.truncate(true)
|
||||||
.open(&path)?;
|
.open(&path)?;
|
||||||
|
|
||||||
|
self.enabled_notifications = enabled_notifications.clone();
|
||||||
let t = toml::to_string_pretty(&self).unwrap();
|
let t = toml::to_string_pretty(&self).unwrap();
|
||||||
file.write_all(t.as_bytes())?;
|
file.write_all(t.as_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ pub mod notify;
|
|||||||
pub mod page_states;
|
pub mod page_states;
|
||||||
pub mod pages;
|
pub mod pages;
|
||||||
pub mod startup_error;
|
pub mod startup_error;
|
||||||
pub mod widgets;
|
|
||||||
pub mod tray;
|
pub mod tray;
|
||||||
|
pub mod widgets;
|
||||||
|
|
||||||
#[cfg(feature = "mocking")]
|
#[cfg(feature = "mocking")]
|
||||||
pub use mocking::RogDbusClientBlocking;
|
pub use mocking::RogDbusClientBlocking;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use eframe::{IconData, NativeOptions};
|
use eframe::{IconData, NativeOptions};
|
||||||
use log::{error, LevelFilter};
|
use log::{error, LevelFilter};
|
||||||
use rog_aura::layouts::KeyLayout;
|
use rog_aura::layouts::KeyLayout;
|
||||||
|
use rog_control_center::notify::EnabledNotifications;
|
||||||
use rog_control_center::tray::{AppToTray, TrayToApp};
|
use rog_control_center::tray::{AppToTray, TrayToApp};
|
||||||
use rog_control_center::{
|
use rog_control_center::{
|
||||||
config::Config, error::Result, get_ipc_file, notify::start_notifications, on_tmp_dir_exists,
|
config::Config, error::Result, get_ipc_file, notify::start_notifications, on_tmp_dir_exists,
|
||||||
@@ -39,10 +40,6 @@ fn main() -> Result<()> {
|
|||||||
// Enter the runtime so that `tokio::spawn` is available immediately.
|
// Enter the runtime so that `tokio::spawn` is available immediately.
|
||||||
let _enter = rt.enter();
|
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 {
|
let native_options = eframe::NativeOptions {
|
||||||
vsync: true,
|
vsync: true,
|
||||||
decorated: true,
|
decorated: true,
|
||||||
@@ -64,14 +61,32 @@ fn main() -> Result<()> {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let supported = match dbus.proxies().supported().supported_functions() {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => {
|
||||||
|
eframe::run_native(
|
||||||
|
"ROG Control Center",
|
||||||
|
native_options.clone(),
|
||||||
|
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
|
||||||
|
);
|
||||||
|
SupportedFunctions::default()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let (send, recv) = channel();
|
||||||
|
let update_tray = Arc::new(Mutex::new(send));
|
||||||
|
let app_cmd = Arc::new(init_tray(supported.clone(), recv));
|
||||||
|
|
||||||
// Startup
|
// Startup
|
||||||
let mut config = Config::load()?;
|
let mut config = Config::load()?;
|
||||||
let mut start_closed = config.startup_in_background;
|
let mut start_closed = config.startup_in_background;
|
||||||
|
|
||||||
if config.startup_in_background {
|
if config.startup_in_background {
|
||||||
config.run_in_background = true;
|
config.run_in_background = true;
|
||||||
config.save()?;
|
let tmp = config.enabled_notifications.clone(); // ends up being a double clone, oh well.
|
||||||
|
config.save(&tmp)?;
|
||||||
}
|
}
|
||||||
|
let enabled_notifications = EnabledNotifications::tokio_mutex(&config);
|
||||||
|
|
||||||
// Find and load a matching layout for laptop
|
// Find and load a matching layout for laptop
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
@@ -109,11 +124,11 @@ fn main() -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let states = setup_page_state_and_notifs(
|
let states = setup_page_state_and_notifs(
|
||||||
layout.clone(),
|
layout,
|
||||||
&config,
|
|
||||||
native_options.clone(),
|
|
||||||
&dbus,
|
&dbus,
|
||||||
|
enabled_notifications,
|
||||||
update_tray,
|
update_tray,
|
||||||
|
&supported,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@@ -147,10 +162,10 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
fn setup_page_state_and_notifs(
|
fn setup_page_state_and_notifs(
|
||||||
keyboard_layout: KeyLayout,
|
keyboard_layout: KeyLayout,
|
||||||
config: &Config,
|
|
||||||
native_options: NativeOptions,
|
|
||||||
dbus: &RogDbusClientBlocking,
|
dbus: &RogDbusClientBlocking,
|
||||||
|
enabled_notifications: Arc<Mutex<EnabledNotifications>>,
|
||||||
update_tray: Arc<Mutex<Sender<AppToTray>>>,
|
update_tray: Arc<Mutex<Sender<AppToTray>>>,
|
||||||
|
supported: &SupportedFunctions,
|
||||||
) -> Result<PageDataStates> {
|
) -> Result<PageDataStates> {
|
||||||
// Cheap method to alert to notifications rather than spinning a thread for each
|
// Cheap method to alert to notifications rather than spinning a thread for each
|
||||||
// This is quite different when done in a retained mode app
|
// This is quite different when done in a retained mode app
|
||||||
@@ -160,7 +175,6 @@ fn setup_page_state_and_notifs(
|
|||||||
let anime_notified = Arc::new(AtomicBool::new(false));
|
let anime_notified = Arc::new(AtomicBool::new(false));
|
||||||
let profiles_notified = Arc::new(AtomicBool::new(false));
|
let profiles_notified = Arc::new(AtomicBool::new(false));
|
||||||
let fans_notified = Arc::new(AtomicBool::new(false));
|
let fans_notified = Arc::new(AtomicBool::new(false));
|
||||||
let notifs_enabled = Arc::new(AtomicBool::new(config.enable_notifications));
|
|
||||||
|
|
||||||
start_notifications(
|
start_notifications(
|
||||||
charge_notified.clone(),
|
charge_notified.clone(),
|
||||||
@@ -169,33 +183,21 @@ fn setup_page_state_and_notifs(
|
|||||||
anime_notified.clone(),
|
anime_notified.clone(),
|
||||||
profiles_notified.clone(),
|
profiles_notified.clone(),
|
||||||
fans_notified.clone(),
|
fans_notified.clone(),
|
||||||
notifs_enabled.clone(),
|
enabled_notifications.clone(),
|
||||||
update_tray,
|
update_tray,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let supported = match dbus.proxies().supported().supported_functions() {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(e) => {
|
|
||||||
eframe::run_native(
|
|
||||||
"ROG Control Center",
|
|
||||||
native_options,
|
|
||||||
Box::new(move |_| Box::new(AppErrorShow::new(e.to_string()))),
|
|
||||||
);
|
|
||||||
SupportedFunctions::default()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
PageDataStates::new(
|
PageDataStates::new(
|
||||||
keyboard_layout,
|
keyboard_layout,
|
||||||
notifs_enabled.clone(),
|
enabled_notifications,
|
||||||
charge_notified.clone(),
|
charge_notified,
|
||||||
bios_notified.clone(),
|
bios_notified,
|
||||||
aura_notified.clone(),
|
aura_notified,
|
||||||
anime_notified.clone(),
|
anime_notified,
|
||||||
profiles_notified.clone(),
|
profiles_notified,
|
||||||
fans_notified.clone(),
|
fans_notified,
|
||||||
&supported,
|
supported,
|
||||||
&dbus,
|
dbus,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,71 @@
|
|||||||
use crate::{error::Result, tray::AppToTray};
|
use crate::{config::Config, error::Result, tray::AppToTray};
|
||||||
use notify_rust::{Hint, Notification, NotificationHandle};
|
use notify_rust::{Hint, Notification, NotificationHandle, Urgency};
|
||||||
use rog_dbus::{
|
use rog_dbus::{
|
||||||
zbus_anime::AnimeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy,
|
zbus_anime::AnimeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy,
|
||||||
zbus_power::PowerProxy, zbus_profile::ProfileProxy,
|
zbus_power::PowerProxy, zbus_profile::ProfileProxy,
|
||||||
};
|
};
|
||||||
use rog_platform::platform::GpuMode;
|
use rog_platform::platform::GpuMode;
|
||||||
use rog_profiles::Profile;
|
use rog_profiles::Profile;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
|
process::Command,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
mpsc::Sender,
|
mpsc::Sender,
|
||||||
Arc, Mutex,
|
Arc, Mutex,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use supergfxctl::pci_device::GfxPower;
|
use supergfxctl::{pci_device::GfxPower, zbus_proxy::DaemonProxy as SuperProxy};
|
||||||
use zbus::export::futures_util::{future, StreamExt};
|
use zbus::export::futures_util::{future, StreamExt};
|
||||||
|
|
||||||
const NOTIF_HEADER: &str = "ROG Control";
|
const NOTIF_HEADER: &str = "ROG Control";
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct EnabledNotifications {
|
||||||
|
pub receive_notify_post_boot_sound: bool,
|
||||||
|
pub receive_notify_panel_od: bool,
|
||||||
|
pub receive_notify_dgpu_disable: bool,
|
||||||
|
pub receive_notify_egpu_enable: bool,
|
||||||
|
pub receive_notify_gpu_mux_mode: bool,
|
||||||
|
pub receive_notify_charge_control_end_threshold: bool,
|
||||||
|
pub receive_notify_mains_online: bool,
|
||||||
|
pub receive_notify_profile: bool,
|
||||||
|
pub receive_notify_led: bool,
|
||||||
|
/// Anime
|
||||||
|
pub receive_power_states: bool,
|
||||||
|
pub receive_notify_gfx: bool,
|
||||||
|
pub receive_notify_gfx_status: bool,
|
||||||
|
pub all_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EnabledNotifications {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
receive_notify_post_boot_sound: false,
|
||||||
|
receive_notify_panel_od: true,
|
||||||
|
receive_notify_dgpu_disable: true,
|
||||||
|
receive_notify_egpu_enable: true,
|
||||||
|
receive_notify_gpu_mux_mode: true,
|
||||||
|
receive_notify_charge_control_end_threshold: true,
|
||||||
|
receive_notify_mains_online: false,
|
||||||
|
receive_notify_profile: true,
|
||||||
|
receive_notify_led: false,
|
||||||
|
receive_power_states: false,
|
||||||
|
receive_notify_gfx: false,
|
||||||
|
receive_notify_gfx_status: false,
|
||||||
|
all_enabled: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnabledNotifications {
|
||||||
|
pub fn tokio_mutex(config: &Config) -> Arc<Mutex<Self>> {
|
||||||
|
Arc::new(Mutex::new(config.enabled_notifications.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! notify {
|
macro_rules! notify {
|
||||||
($notifier:expr, $last_notif:ident) => {
|
($notifier:expr, $last_notif:ident) => {
|
||||||
if let Some(notif) = $last_notif.take() {
|
if let Some(notif) = $last_notif.take() {
|
||||||
@@ -46,19 +93,19 @@ macro_rules! recv_notif {
|
|||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
let proxy = $proxy::new(&conn).await.unwrap();
|
let proxy = $proxy::new(&conn).await.unwrap();
|
||||||
if let Ok(p) = proxy.$signal().await {
|
if let Ok(mut p) = proxy.$signal().await {
|
||||||
p.for_each(|e| {
|
while let Some(e) = p.next().await {
|
||||||
if let Ok(out) = e.args() {
|
if let Ok(out) = e.args() {
|
||||||
if notifs_enabled1.load(Ordering::SeqCst) {
|
if let Ok(config) = notifs_enabled1.lock() {
|
||||||
if let Ok(ref mut lock) = last_notif.try_lock() {
|
if config.all_enabled && config.$signal {
|
||||||
notify!($notifier($msg, &out$(.$out_arg)+()), lock);
|
if let Ok(ref mut lock) = last_notif.try_lock() {
|
||||||
|
notify!($notifier($msg, &out$(.$out_arg)+()), lock);
|
||||||
|
}
|
||||||
|
notified.store(true, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notified.store(true, Ordering::SeqCst);
|
|
||||||
}
|
}
|
||||||
future::ready(())
|
}
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -73,8 +120,8 @@ pub fn start_notifications(
|
|||||||
anime_notified: Arc<AtomicBool>,
|
anime_notified: Arc<AtomicBool>,
|
||||||
profiles_notified: Arc<AtomicBool>,
|
profiles_notified: Arc<AtomicBool>,
|
||||||
_fans_notified: Arc<AtomicBool>,
|
_fans_notified: Arc<AtomicBool>,
|
||||||
notifs_enabled: Arc<AtomicBool>,
|
enabled_notifications: Arc<Mutex<EnabledNotifications>>,
|
||||||
update_tray: Arc<Mutex<Sender<AppToTray>>>,
|
update_tray: Arc<std::sync::Mutex<Sender<AppToTray>>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let last_notification: SharedHandle = Arc::new(Mutex::new(None));
|
let last_notification: SharedHandle = Arc::new(Mutex::new(None));
|
||||||
|
|
||||||
@@ -84,7 +131,7 @@ pub fn start_notifications(
|
|||||||
receive_notify_post_boot_sound,
|
receive_notify_post_boot_sound,
|
||||||
bios_notified,
|
bios_notified,
|
||||||
last_notification,
|
last_notification,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
[on],
|
[on],
|
||||||
"BIOS Post sound",
|
"BIOS Post sound",
|
||||||
do_notification
|
do_notification
|
||||||
@@ -95,7 +142,7 @@ pub fn start_notifications(
|
|||||||
receive_notify_panel_od,
|
receive_notify_panel_od,
|
||||||
bios_notified,
|
bios_notified,
|
||||||
last_notification,
|
last_notification,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
[overdrive],
|
[overdrive],
|
||||||
"Panel Overdrive enabled:",
|
"Panel Overdrive enabled:",
|
||||||
do_notification
|
do_notification
|
||||||
@@ -106,7 +153,7 @@ pub fn start_notifications(
|
|||||||
receive_notify_dgpu_disable,
|
receive_notify_dgpu_disable,
|
||||||
bios_notified,
|
bios_notified,
|
||||||
last_notification,
|
last_notification,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
[disable],
|
[disable],
|
||||||
"BIOS dGPU disabled",
|
"BIOS dGPU disabled",
|
||||||
do_notification
|
do_notification
|
||||||
@@ -117,7 +164,7 @@ pub fn start_notifications(
|
|||||||
receive_notify_egpu_enable,
|
receive_notify_egpu_enable,
|
||||||
bios_notified,
|
bios_notified,
|
||||||
last_notification,
|
last_notification,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
[enable],
|
[enable],
|
||||||
"BIOS eGPU enabled",
|
"BIOS eGPU enabled",
|
||||||
do_notification
|
do_notification
|
||||||
@@ -128,10 +175,10 @@ pub fn start_notifications(
|
|||||||
receive_notify_gpu_mux_mode,
|
receive_notify_gpu_mux_mode,
|
||||||
bios_notified,
|
bios_notified,
|
||||||
last_notification,
|
last_notification,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
[mode],
|
[mode],
|
||||||
"BIOS GPU MUX mode (reboot required)",
|
"Reboot required. BIOS GPU MUX mode set to",
|
||||||
mux_notification
|
do_mux_notification
|
||||||
);
|
);
|
||||||
|
|
||||||
// Charge notif
|
// Charge notif
|
||||||
@@ -140,7 +187,7 @@ pub fn start_notifications(
|
|||||||
receive_notify_charge_control_end_threshold,
|
receive_notify_charge_control_end_threshold,
|
||||||
charge_notified,
|
charge_notified,
|
||||||
last_notification,
|
last_notification,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
[limit],
|
[limit],
|
||||||
"Battery charge limit changed to",
|
"Battery charge limit changed to",
|
||||||
do_notification
|
do_notification
|
||||||
@@ -151,7 +198,7 @@ pub fn start_notifications(
|
|||||||
receive_notify_mains_online,
|
receive_notify_mains_online,
|
||||||
bios_notified,
|
bios_notified,
|
||||||
last_notification,
|
last_notification,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
[on],
|
[on],
|
||||||
"AC Power power is",
|
"AC Power power is",
|
||||||
ac_power_notification
|
ac_power_notification
|
||||||
@@ -163,7 +210,7 @@ pub fn start_notifications(
|
|||||||
receive_notify_profile,
|
receive_notify_profile,
|
||||||
profiles_notified,
|
profiles_notified,
|
||||||
last_notification,
|
last_notification,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
[profile],
|
[profile],
|
||||||
"Profile changed to",
|
"Profile changed to",
|
||||||
do_thermal_notif
|
do_thermal_notif
|
||||||
@@ -176,7 +223,7 @@ pub fn start_notifications(
|
|||||||
receive_notify_led,
|
receive_notify_led,
|
||||||
aura_notified,
|
aura_notified,
|
||||||
last_notification,
|
last_notification,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
[data mode_name],
|
[data mode_name],
|
||||||
"Keyboard LED mode changed to",
|
"Keyboard LED mode changed to",
|
||||||
do_notification
|
do_notification
|
||||||
@@ -206,40 +253,73 @@ pub fn start_notifications(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
let notifs_enabled1 = notifs_enabled.clone();
|
recv_notif!(
|
||||||
let last_notif = last_notification.clone();
|
SuperProxy,
|
||||||
|
receive_notify_gfx,
|
||||||
|
bios_notified,
|
||||||
|
last_notification,
|
||||||
|
enabled_notifications,
|
||||||
|
[mode],
|
||||||
|
"Gfx mode changed to",
|
||||||
|
do_notification
|
||||||
|
);
|
||||||
|
|
||||||
|
// recv_notif!(
|
||||||
|
// SuperProxy,
|
||||||
|
// receive_notify_action,
|
||||||
|
// bios_notified,
|
||||||
|
// last_gfx_action_notif,
|
||||||
|
// enabled_notifications,
|
||||||
|
// [action],
|
||||||
|
// "Gfx mode change requires",
|
||||||
|
// do_gfx_action_notif
|
||||||
|
// );
|
||||||
|
|
||||||
let bios_notified1 = bios_notified.clone();
|
let bios_notified1 = bios_notified.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let conn = zbus::Connection::system().await.unwrap();
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
let proxy = supergfxctl::zbus_proxy::DaemonProxy::new(&conn)
|
let proxy = SuperProxy::new(&conn).await.unwrap();
|
||||||
.await
|
if let Ok(mut p) = proxy.receive_notify_action().await {
|
||||||
.unwrap();
|
while let Some(e) = p.next().await {
|
||||||
if let Ok(p) = proxy.receive_notify_gfx_status().await {
|
|
||||||
p.for_each(|e| {
|
|
||||||
if let Ok(out) = e.args() {
|
if let Ok(out) = e.args() {
|
||||||
if notifs_enabled1.load(Ordering::SeqCst) {
|
let action = out.action();
|
||||||
let status = out.status();
|
do_gfx_action_notif("Gfx mode change requires", &format!("{action:?}",))
|
||||||
if *status != GfxPower::Unknown {
|
.unwrap();
|
||||||
// Required check because status cycles through active/unknown/suspended
|
}
|
||||||
if let Ok(ref mut lock) = last_notif.try_lock() {
|
}
|
||||||
notify!(
|
bios_notified1.store(true, Ordering::SeqCst);
|
||||||
do_notification(
|
};
|
||||||
"dGPU status changed:",
|
});
|
||||||
&format!("{status:?}",)
|
|
||||||
),
|
let notifs_enabled1 = enabled_notifications;
|
||||||
lock
|
let last_notif = last_notification;
|
||||||
);
|
let bios_notified1 = bios_notified;
|
||||||
if let Ok(lock) = update_tray.try_lock() {
|
tokio::spawn(async move {
|
||||||
lock.send(AppToTray::DgpuStatus(*status)).ok();
|
let conn = zbus::Connection::system().await.unwrap();
|
||||||
|
let proxy = SuperProxy::new(&conn).await.unwrap();
|
||||||
|
if let Ok(mut p) = proxy.receive_notify_gfx_status().await {
|
||||||
|
while let Some(e) = p.next().await {
|
||||||
|
if let Ok(out) = e.args() {
|
||||||
|
let status = out.status();
|
||||||
|
if *status != GfxPower::Unknown {
|
||||||
|
if let Ok(config) = notifs_enabled1.lock() {
|
||||||
|
if config.all_enabled && config.receive_notify_gfx_status {
|
||||||
|
// Required check because status cycles through active/unknown/suspended
|
||||||
|
if let Ok(ref mut lock) = last_notif.try_lock() {
|
||||||
|
notify!(
|
||||||
|
do_gpu_status_notif("dGPU status changed:", status),
|
||||||
|
lock
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Ok(lock) = update_tray.try_lock() {
|
||||||
|
lock.send(AppToTray::DgpuStatus(*status)).ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bios_notified1.store(true, Ordering::SeqCst);
|
}
|
||||||
future::ready(())
|
bios_notified1.store(true, Ordering::SeqCst);
|
||||||
})
|
|
||||||
.await;
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -278,11 +358,6 @@ fn ac_power_notification(message: &str, on: &bool) -> Result<NotificationHandle>
|
|||||||
Ok(base_notification(message, &data).show()?)
|
Ok(base_notification(message, &data).show()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Actual GpuMode unused as data is never correct until switched by reboot
|
|
||||||
fn mux_notification(message: &str, _: &GpuMode) -> Result<NotificationHandle> {
|
|
||||||
Ok(base_notification(message, &"").show()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_thermal_notif(message: &str, profile: &Profile) -> Result<NotificationHandle> {
|
fn do_thermal_notif(message: &str, profile: &Profile) -> Result<NotificationHandle> {
|
||||||
let icon = match profile {
|
let icon = match profile {
|
||||||
Profile::Balanced => "asus_notif_yellow",
|
Profile::Balanced => "asus_notif_yellow",
|
||||||
@@ -293,3 +368,49 @@ fn do_thermal_notif(message: &str, profile: &Profile) -> Result<NotificationHand
|
|||||||
let mut notif = base_notification(message, &profile.to_uppercase());
|
let mut notif = base_notification(message, &profile.to_uppercase());
|
||||||
Ok(notif.icon(icon).show()?)
|
Ok(notif.icon(icon).show()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn do_gpu_status_notif(message: &str, data: &GfxPower) -> Result<NotificationHandle> {
|
||||||
|
// eww
|
||||||
|
let mut notif = base_notification(message, &<&str>::from(data).to_string());
|
||||||
|
let icon = match data {
|
||||||
|
GfxPower::Active => "asus_notif_red",
|
||||||
|
GfxPower::Suspended => "asus_notif_blue",
|
||||||
|
GfxPower::Off => "asus_notif_green",
|
||||||
|
GfxPower::AsusDisabled => "asus_notif_white",
|
||||||
|
GfxPower::AsusMuxDiscreet => "asus_notif_red",
|
||||||
|
GfxPower::Unknown => "gpu-integrated",
|
||||||
|
};
|
||||||
|
notif.icon(icon);
|
||||||
|
Ok(Notification::show(¬if)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_gfx_action_notif<T>(message: &str, data: &T) -> Result<()>
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
{
|
||||||
|
let mut notif = base_notification(message, data);
|
||||||
|
notif.action("gnome-session-quit", "Logout");
|
||||||
|
notif.urgency(Urgency::Critical);
|
||||||
|
notif.timeout(3000);
|
||||||
|
notif.icon("dialog-warning");
|
||||||
|
notif.hint(Hint::Transient(true));
|
||||||
|
let handle = notif.show()?;
|
||||||
|
handle.wait_for_action(|id| {
|
||||||
|
if id == "gnome-session-quit" {
|
||||||
|
let mut cmd = Command::new("gnome-session-quit");
|
||||||
|
cmd.spawn().ok();
|
||||||
|
} else if id == "__closed" {
|
||||||
|
// TODO: cancel the switching
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Actual GpuMode unused as data is never correct until switched by reboot
|
||||||
|
fn do_mux_notification(message: &str, _: &GpuMode) -> Result<NotificationHandle> {
|
||||||
|
let mut notif = base_notification(message, &"");
|
||||||
|
notif.urgency(Urgency::Critical);
|
||||||
|
notif.icon("system-reboot-symbolic");
|
||||||
|
notif.hint(Hint::Transient(true));
|
||||||
|
Ok(notif.show()?)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::{
|
|||||||
collections::{BTreeMap, HashSet},
|
collections::{BTreeMap, HashSet},
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
Arc,
|
Arc, Mutex,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ use rog_aura::{layouts::KeyLayout, usb::AuraPowerDev, AuraEffect, AuraModeNum};
|
|||||||
use rog_platform::{platform::GpuMode, supported::SupportedFunctions};
|
use rog_platform::{platform::GpuMode, supported::SupportedFunctions};
|
||||||
use rog_profiles::{fan_curve_set::FanCurveSet, FanCurvePU, Profile};
|
use rog_profiles::{fan_curve_set::FanCurveSet, FanCurvePU, Profile};
|
||||||
|
|
||||||
use crate::{error::Result, RogDbusClientBlocking};
|
use crate::{error::Result, notify::EnabledNotifications, RogDbusClientBlocking};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BiosState {
|
pub struct BiosState {
|
||||||
@@ -249,7 +249,7 @@ impl AnimeState {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PageDataStates {
|
pub struct PageDataStates {
|
||||||
pub keyboard_layout: KeyLayout,
|
pub keyboard_layout: KeyLayout,
|
||||||
pub notifs_enabled: Arc<AtomicBool>,
|
pub enabled_notifications: Arc<Mutex<EnabledNotifications>>,
|
||||||
pub was_notified: Arc<AtomicBool>,
|
pub was_notified: Arc<AtomicBool>,
|
||||||
/// Because much of the app state here is the same as `RogBiosSupportedFunctions`
|
/// Because much of the app state here is the same as `RogBiosSupportedFunctions`
|
||||||
/// we can re-use that structure.
|
/// we can re-use that structure.
|
||||||
@@ -266,7 +266,7 @@ pub struct PageDataStates {
|
|||||||
impl PageDataStates {
|
impl PageDataStates {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
keyboard_layout: KeyLayout,
|
keyboard_layout: KeyLayout,
|
||||||
notifs_enabled: Arc<AtomicBool>,
|
enabled_notifications: Arc<Mutex<EnabledNotifications>>,
|
||||||
charge_notified: Arc<AtomicBool>,
|
charge_notified: Arc<AtomicBool>,
|
||||||
bios_notified: Arc<AtomicBool>,
|
bios_notified: Arc<AtomicBool>,
|
||||||
aura_notified: Arc<AtomicBool>,
|
aura_notified: Arc<AtomicBool>,
|
||||||
@@ -278,7 +278,7 @@ impl PageDataStates {
|
|||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
keyboard_layout,
|
keyboard_layout,
|
||||||
notifs_enabled,
|
enabled_notifications,
|
||||||
was_notified: charge_notified,
|
was_notified: charge_notified,
|
||||||
charge_limit: dbus.proxies().charge().charge_control_end_threshold()?,
|
charge_limit: dbus.proxies().charge().charge_control_end_threshold()?,
|
||||||
bios: BiosState::new(bios_notified, supported, dbus)?,
|
bios: BiosState::new(bios_notified, supported, dbus)?,
|
||||||
@@ -335,7 +335,7 @@ impl Default for PageDataStates {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
keyboard_layout: KeyLayout::ga401_layout(),
|
keyboard_layout: KeyLayout::ga401_layout(),
|
||||||
notifs_enabled: Default::default(),
|
enabled_notifications: Default::default(),
|
||||||
was_notified: Default::default(),
|
was_notified: Default::default(),
|
||||||
bios: BiosState {
|
bios: BiosState {
|
||||||
was_notified: Default::default(),
|
was_notified: Default::default(),
|
||||||
|
|||||||
@@ -25,25 +25,23 @@ impl<'a> RogApp<'a> {
|
|||||||
.min_col_width(rect.width() / 2.0)
|
.min_col_width(rect.width() / 2.0)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
/******************************************************/
|
/******************************************************/
|
||||||
ui.vertical(|ui| {
|
|
||||||
ui.separator();
|
|
||||||
app_settings(config, states, ui);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
if supported.platform_profile.platform_profile {
|
if supported.platform_profile.platform_profile {
|
||||||
platform_profile(states, dbus, ui);
|
platform_profile(states, dbus, ui);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
ui.separator();
|
||||||
|
aura_power_group(supported, states, dbus, ui);
|
||||||
|
});
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
|
|
||||||
/******************************************************/
|
/******************************************************/
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
aura_power_group(supported, states, dbus, ui);
|
app_settings(config, states, ui);
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
rog_bios_group(supported, states, dbus, ui);
|
rog_bios_group(supported, states, dbus, ui);
|
||||||
|
|||||||
@@ -2,17 +2,23 @@
|
|||||||
//! commands over an MPSC channel.
|
//! commands over an MPSC channel.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
io::Write,
|
||||||
sync::{
|
sync::{
|
||||||
mpsc::{channel, Receiver},
|
mpsc::{channel, Receiver},
|
||||||
Arc, Mutex,
|
Arc, Mutex,
|
||||||
},
|
},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
io::Write,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use supergfxctl::pci_device::GfxPower;
|
use gtk::{gio::Icon, prelude::*, MenuItem};
|
||||||
use tray_item::TrayItem;
|
use rog_platform::{platform::GpuMode, supported::SupportedFunctions};
|
||||||
use crate::{SHOW_GUI, get_ipc_file};
|
|
||||||
|
use crate::{error::Result, get_ipc_file, SHOW_GUI};
|
||||||
|
use libappindicator::{AppIndicator, AppIndicatorStatus};
|
||||||
|
use supergfxctl::pci_device::{GfxMode, GfxPower};
|
||||||
|
|
||||||
|
const TRAY_APP_ICON: &str = "rog-control-center";
|
||||||
|
const TRAY_LABEL: &str = "ROG Control Center";
|
||||||
|
|
||||||
pub enum AppToTray {
|
pub enum AppToTray {
|
||||||
DgpuStatus(GfxPower),
|
DgpuStatus(GfxPower),
|
||||||
@@ -23,26 +29,214 @@ pub enum TrayToApp {
|
|||||||
Quit,
|
Quit,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_tray(recv_command: Receiver<AppToTray>) -> Receiver<TrayToApp> {
|
pub struct RadioGroup(Vec<gtk::RadioMenuItem>);
|
||||||
|
|
||||||
|
impl RadioGroup {
|
||||||
|
/// Add new radio menu item. `set_no_show_all()` is true until added to menu
|
||||||
|
/// to prevent teh callback from running
|
||||||
|
pub fn new<F>(first_label: &str, cb: F) -> Self
|
||||||
|
where
|
||||||
|
F: Fn(>k::RadioMenuItem) + Send + 'static,
|
||||||
|
{
|
||||||
|
let item = gtk::RadioMenuItem::with_label(first_label);
|
||||||
|
item.set_active(false);
|
||||||
|
item.set_no_show_all(true);
|
||||||
|
item.connect_activate(move |this| {
|
||||||
|
if this.is_active() && !this.is_no_show_all() {
|
||||||
|
cb(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Self(vec![item])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add new radio menu item. `set_no_show_all()` is true until added to menu
|
||||||
|
/// to prevent teh callback from running
|
||||||
|
pub fn add<F>(&mut self, label: &str, cb: F)
|
||||||
|
where
|
||||||
|
F: Fn(>k::RadioMenuItem) + Send + 'static,
|
||||||
|
{
|
||||||
|
debug_assert!(!self.0.is_empty());
|
||||||
|
let group = self.0[0].group();
|
||||||
|
|
||||||
|
let item = gtk::RadioMenuItem::with_label_from_widget(&group[0], Some(label));
|
||||||
|
item.set_active(false);
|
||||||
|
item.set_no_show_all(true);
|
||||||
|
item.connect_activate(move |this| {
|
||||||
|
if this.is_active() && !this.is_no_show_all() {
|
||||||
|
cb(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.0.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ROGTray {
|
||||||
|
tray: AppIndicator,
|
||||||
|
menu: gtk::Menu,
|
||||||
|
items: Vec<MenuItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ROGTray {
|
||||||
|
pub fn new() -> Result<Self> {
|
||||||
|
let mut rog_tray = Self {
|
||||||
|
tray: AppIndicator::new(TRAY_LABEL, TRAY_APP_ICON),
|
||||||
|
menu: gtk::Menu::new(),
|
||||||
|
items: Vec::new(),
|
||||||
|
};
|
||||||
|
// rog_tray.set_icon(TRAY_APP_ICON);
|
||||||
|
|
||||||
|
rog_tray.add_icon_menu_item("Open app", "asus_notif_red", move || {
|
||||||
|
get_ipc_file().unwrap().write_all(&[SHOW_GUI]).ok();
|
||||||
|
});
|
||||||
|
|
||||||
|
rog_tray.add_inactive_label("----");
|
||||||
|
|
||||||
|
Ok(rog_tray)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_icon(&mut self, icon: &str) {
|
||||||
|
self.tray.set_icon(icon);
|
||||||
|
self.tray.set_status(AppIndicatorStatus::Active);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a non-interactive label
|
||||||
|
fn add_inactive_label(&mut self, label: &str) {
|
||||||
|
let item = gtk::MenuItem::with_label(label);
|
||||||
|
item.set_sensitive(false);
|
||||||
|
self.menu.append(&item);
|
||||||
|
self.menu.show_all();
|
||||||
|
self.tray.set_menu(&mut self.menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_radio_sub_menu(&mut self, header_label: &str, active_label: &str, sub_menu: RadioGroup) {
|
||||||
|
let header_item = gtk::MenuItem::with_label(header_label);
|
||||||
|
header_item.show_all();
|
||||||
|
self.menu.add(&header_item);
|
||||||
|
|
||||||
|
let menu = gtk::Menu::new();
|
||||||
|
for item in sub_menu.0.iter() {
|
||||||
|
item.set_active(item.label().unwrap() == active_label);
|
||||||
|
item.set_no_show_all(false);
|
||||||
|
item.show_all();
|
||||||
|
menu.add(item);
|
||||||
|
}
|
||||||
|
menu.show_all();
|
||||||
|
header_item.set_submenu(Some(&menu));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_menu_item<F>(&mut self, label: &str, cb: F)
|
||||||
|
where
|
||||||
|
F: Fn() + Send + 'static,
|
||||||
|
{
|
||||||
|
let item = gtk::MenuItem::with_label(label);
|
||||||
|
self.items.push(item);
|
||||||
|
let item = self.items.last().unwrap();
|
||||||
|
item.connect_activate(move |_| {
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
self.menu.append(item);
|
||||||
|
self.menu.show_all();
|
||||||
|
self.tray.set_menu(&mut self.menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a menu item with an icon to the right
|
||||||
|
fn add_icon_menu_item<F>(&mut self, label: &str, icon: &str, cb: F)
|
||||||
|
where
|
||||||
|
F: Fn() + Send + 'static,
|
||||||
|
{
|
||||||
|
let g_box = gtk::Box::new(gtk::Orientation::Horizontal, 6);
|
||||||
|
let icon = gtk::Image::from_gicon(&Icon::for_string(icon).unwrap(), gtk::IconSize::Menu);
|
||||||
|
let label = gtk::Label::new(Some(label));
|
||||||
|
let menu_item = gtk::MenuItem::new();
|
||||||
|
g_box.add(&icon);
|
||||||
|
g_box.add(&label);
|
||||||
|
|
||||||
|
menu_item.add(&g_box);
|
||||||
|
menu_item.show_all();
|
||||||
|
|
||||||
|
self.items.push(menu_item);
|
||||||
|
let item = self.items.last().unwrap();
|
||||||
|
item.connect_activate(move |_| {
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
self.menu.append(item);
|
||||||
|
self.menu.show_all();
|
||||||
|
self.tray.set_menu(&mut self.menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_status(&mut self, status: AppIndicatorStatus) {
|
||||||
|
self.tray.set_status(status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_gpu_menu(supported: &SupportedFunctions, tray: &mut ROGTray) {
|
||||||
|
let conn = zbus::blocking::Connection::system().unwrap();
|
||||||
|
let gfx_dbus = supergfxctl::zbus_proxy::DaemonProxyBlocking::new(&conn).unwrap();
|
||||||
|
|
||||||
|
let mode = gfx_dbus.mode().unwrap();
|
||||||
|
let mut gpu_menu = RadioGroup::new("Integrated", move |_| {
|
||||||
|
let mode = gfx_dbus.mode().unwrap();
|
||||||
|
if mode != GfxMode::Integrated {
|
||||||
|
gfx_dbus.set_mode(&GfxMode::Integrated).unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let gfx_dbus = supergfxctl::zbus_proxy::DaemonProxyBlocking::new(&conn).unwrap();
|
||||||
|
gpu_menu.add("Hybrid", move |_| {
|
||||||
|
let mode = gfx_dbus.mode().unwrap();
|
||||||
|
if mode != GfxMode::Hybrid {
|
||||||
|
gfx_dbus.set_mode(&GfxMode::Hybrid).unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if supported.rog_bios_ctrl.gpu_mux {
|
||||||
|
let gfx_dbus = rog_dbus::zbus_platform::RogBiosProxyBlocking::new(&conn).unwrap();
|
||||||
|
gpu_menu.add("Ultimate (Reboot required)", move |_| {
|
||||||
|
let mode = gfx_dbus.gpu_mux_mode().unwrap();
|
||||||
|
if mode != GpuMode::Discrete {
|
||||||
|
gfx_dbus.set_gpu_mux_mode(GpuMode::Discrete).unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if supported.rog_bios_ctrl.egpu_enable {
|
||||||
|
let gfx_dbus = supergfxctl::zbus_proxy::DaemonProxyBlocking::new(&conn).unwrap();
|
||||||
|
gpu_menu.add("eGPU", move |_| {
|
||||||
|
let mode = gfx_dbus.mode().unwrap();
|
||||||
|
if mode != GfxMode::Egpu {
|
||||||
|
gfx_dbus.set_mode(&GfxMode::Egpu).unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let active = match mode {
|
||||||
|
GfxMode::AsusMuxDiscreet => "Discreet".to_string(),
|
||||||
|
_ => mode.to_string(),
|
||||||
|
};
|
||||||
|
tray.add_radio_sub_menu("GPU Mode", active.as_str(), gpu_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_tray(
|
||||||
|
supported: SupportedFunctions,
|
||||||
|
recv_command: Receiver<AppToTray>,
|
||||||
|
) -> Receiver<TrayToApp> {
|
||||||
let (send, recv) = channel();
|
let (send, recv) = channel();
|
||||||
let send = Arc::new(Mutex::new(send));
|
let _send = Arc::new(Mutex::new(send));
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
gtk::init().unwrap(); // Make this the main thread for gtk
|
gtk::init().unwrap(); // Make this the main thread for gtk
|
||||||
|
|
||||||
let mut tray = TrayItem::new("ROG Control Center", "rog-control-center").unwrap();
|
let mut tray = ROGTray::new().unwrap();
|
||||||
|
|
||||||
tray.add_menu_item("Open app", move || {
|
init_gpu_menu(&supported, &mut tray);
|
||||||
get_ipc_file().unwrap().write_all(&[SHOW_GUI]).ok();
|
// let s1 = send.clone();
|
||||||
})
|
// tray.add_menu_item("Quit", move || {
|
||||||
.ok();
|
// let lock = s1.lock().unwrap();
|
||||||
|
// lock.send(TrayToApp::Quit).ok();
|
||||||
let s1 = send.clone();
|
// })
|
||||||
tray.add_menu_item("Quit", move || {
|
// .ok();
|
||||||
let lock = s1.lock().unwrap();
|
|
||||||
lock.send(TrayToApp::Quit).ok();
|
//***********************************
|
||||||
})
|
// finally do
|
||||||
.ok();
|
tray.tray.set_menu(&mut tray.menu);
|
||||||
|
//***********************************
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Ok(command) = recv_command.try_recv() {
|
if let Ok(command) = recv_command.try_recv() {
|
||||||
@@ -55,8 +249,7 @@ pub fn init_tray(recv_command: Receiver<AppToTray>) -> Receiver<TrayToApp> {
|
|||||||
GfxPower::AsusDisabled => tray.set_icon("asus_notif_white"),
|
GfxPower::AsusDisabled => tray.set_icon("asus_notif_white"),
|
||||||
GfxPower::AsusMuxDiscreet => tray.set_icon("asus_notif_red"),
|
GfxPower::AsusMuxDiscreet => tray.set_icon("asus_notif_red"),
|
||||||
GfxPower::Unknown => tray.set_icon("gpu-integrated"),
|
GfxPower::Unknown => tray.set_icon("gpu-integrated"),
|
||||||
}
|
};
|
||||||
.ok();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use std::sync::atomic::Ordering;
|
|
||||||
|
|
||||||
use egui::Ui;
|
use egui::Ui;
|
||||||
|
|
||||||
use crate::{config::Config, page_states::PageDataStates};
|
use crate::{config::Config, page_states::PageDataStates};
|
||||||
@@ -8,6 +6,12 @@ pub fn app_settings(config: &mut Config, states: &mut PageDataStates, ui: &mut U
|
|||||||
ui.heading("ROG GUI Settings");
|
ui.heading("ROG GUI Settings");
|
||||||
// ui.label("Options are incomplete. Awake + Boot should work");
|
// ui.label("Options are incomplete. Awake + Boot should work");
|
||||||
|
|
||||||
|
let mut enabled_notifications = if let Ok(lock) = states.enabled_notifications.lock() {
|
||||||
|
lock.clone()
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
if ui
|
if ui
|
||||||
.checkbox(&mut config.run_in_background, "Run in Background")
|
.checkbox(&mut config.run_in_background, "Run in Background")
|
||||||
.clicked()
|
.clicked()
|
||||||
@@ -15,17 +19,70 @@ pub fn app_settings(config: &mut Config, states: &mut PageDataStates, ui: &mut U
|
|||||||
.checkbox(&mut config.startup_in_background, "Startup Hidden")
|
.checkbox(&mut config.startup_in_background, "Startup Hidden")
|
||||||
.clicked()
|
.clicked()
|
||||||
|| ui
|
|| ui
|
||||||
.checkbox(&mut config.enable_notifications, "Enable Notifications")
|
.checkbox(
|
||||||
|
&mut enabled_notifications.all_enabled,
|
||||||
|
"Enable Notifications",
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
|| ui
|
||||||
|
.checkbox(
|
||||||
|
&mut enabled_notifications.receive_notify_gfx_status,
|
||||||
|
"Enable dGPU status notification",
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
|| ui
|
||||||
|
.checkbox(
|
||||||
|
&mut enabled_notifications.receive_notify_dgpu_disable,
|
||||||
|
"Enable dGPU disablement notification",
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
|| ui
|
||||||
|
.checkbox(
|
||||||
|
&mut enabled_notifications.receive_notify_egpu_enable,
|
||||||
|
"Enable eGPU enablement notification",
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
|| ui
|
||||||
|
.checkbox(
|
||||||
|
&mut enabled_notifications.receive_notify_mains_online,
|
||||||
|
"Enable mains (AC) power notification",
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
|| ui
|
||||||
|
.checkbox(
|
||||||
|
&mut enabled_notifications.receive_notify_charge_control_end_threshold,
|
||||||
|
"Enable charge threshold notification",
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
|| ui
|
||||||
|
.checkbox(
|
||||||
|
&mut enabled_notifications.receive_notify_profile,
|
||||||
|
"Enable profile change notification",
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
|| ui
|
||||||
|
.checkbox(
|
||||||
|
&mut enabled_notifications.receive_notify_panel_od,
|
||||||
|
"Enable panel overdrive notification",
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
|| ui
|
||||||
|
.checkbox(
|
||||||
|
&mut enabled_notifications.receive_notify_post_boot_sound,
|
||||||
|
"Enable BIOS post sound notification",
|
||||||
|
)
|
||||||
.clicked()
|
.clicked()
|
||||||
{
|
{
|
||||||
states
|
if let Ok(mut lock) = states.enabled_notifications.lock() {
|
||||||
.notifs_enabled
|
// Replace inner content before save
|
||||||
.store(config.enable_notifications, Ordering::SeqCst);
|
*lock = enabled_notifications;
|
||||||
config
|
|
||||||
.save()
|
config
|
||||||
.map_err(|err| {
|
.save(&lock)
|
||||||
states.error = Some(err.to_string());
|
.map_err(|err| {
|
||||||
})
|
states.error = Some(err.to_string());
|
||||||
.ok();
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ pub fn write_attr_u8_array(device: &mut Device, attr: &str, values: &[u8]) -> Re
|
|||||||
let tmp: String = values.iter().map(|v| format!("{} ", v)).collect();
|
let tmp: String = values.iter().map(|v| format!("{} ", v)).collect();
|
||||||
let tmp = tmp.trim();
|
let tmp = tmp.trim();
|
||||||
device
|
device
|
||||||
.set_attribute_value(attr, &tmp)
|
.set_attribute_value(attr, tmp)
|
||||||
.map_err(|e| PlatformError::IoPath(attr.into(), e))
|
.map_err(|e| PlatformError::IoPath(attr.into(), e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user