From 519f6bd46b21049613adc7ee5a46bcd16be1d13e Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 18 Apr 2024 13:48:23 +1200 Subject: [PATCH] Cleanup notifs, sys state, ac/bat commands --- rog-anime/src/diagonal.rs | 2 +- rog-aura/data/aura_support.ron | 2 +- rog-control-center/src/config.rs | 11 +- rog-control-center/src/lib.rs | 3 +- rog-control-center/src/main.rs | 31 +- rog-control-center/src/system_state.rs | 91 ---- rog-control-center/src/tray.rs | 44 +- rog-control-center/src/ui/mod.rs | 4 +- rog-control-center/src/update_and_notify.rs | 442 ------------------ .../translations/en/rog-control-center.po | 2 +- 10 files changed, 33 insertions(+), 599 deletions(-) delete mode 100644 rog-control-center/src/system_state.rs delete mode 100644 rog-control-center/src/update_and_notify.rs diff --git a/rog-anime/src/diagonal.rs b/rog-anime/src/diagonal.rs index 2e6527b0..b9758d65 100644 --- a/rog-anime/src/diagonal.rs +++ b/rog-anime/src/diagonal.rs @@ -9,7 +9,7 @@ use crate::AnimeType; /// Mostly intended to be used with ASUS gifs, but can be used for other /// purposes (like images) -#[derive(Debug, Clone)] +#[allow(dead_code)] pub struct AnimeDiagonal(AnimeType, Vec>, Option); impl AnimeDiagonal { diff --git a/rog-aura/data/aura_support.ron b/rog-aura/data/aura_support.ron index 55888bd6..45a413f1 100644 --- a/rog-aura/data/aura_support.ron +++ b/rog-aura/data/aura_support.ron @@ -702,7 +702,7 @@ power_zones: [Keyboard], ), ( - board_name: "GU605M", + device_name: "GU605M", product_id: "", layout_name: "ga401q", basic_modes: [Static, Breathe, Strobe, Rainbow, Pulse], diff --git a/rog-control-center/src/config.rs b/rog-control-center/src/config.rs index 7a39b40b..8494160a 100644 --- a/rog-control-center/src/config.rs +++ b/rog-control-center/src/config.rs @@ -3,7 +3,7 @@ use std::fs::create_dir; use config_traits::{StdConfig, StdConfigLoad1}; use serde_derive::{Deserialize, Serialize}; -use crate::update_and_notify::EnabledNotifications; +use crate::notify::EnabledNotifications; const CFG_DIR: &str = "rog"; const CFG_FILE_NAME: &str = "rog-control-center.cfg"; @@ -15,14 +15,13 @@ pub struct Config { pub enable_tray_icon: bool, pub ac_command: String, pub bat_command: String, - pub enable_notifications: bool, pub dark_mode: bool, // intended for use with devices like the ROG Ally pub start_fullscreen: bool, pub fullscreen_width: u32, pub fullscreen_height: u32, // This field must be last - pub enabled_notifications: EnabledNotifications, + pub notifications: EnabledNotifications, } impl Default for Config { @@ -30,13 +29,12 @@ impl Default for Config { Self { run_in_background: true, startup_in_background: false, - enable_notifications: true, enable_tray_icon: true, dark_mode: true, start_fullscreen: false, fullscreen_width: 1920, fullscreen_height: 1080, - enabled_notifications: EnabledNotifications::default(), + notifications: EnabledNotifications::default(), ac_command: String::new(), bat_command: String::new(), } @@ -94,8 +92,7 @@ impl From for Config { start_fullscreen: false, fullscreen_width: 1920, fullscreen_height: 1080, - enable_notifications: c.enable_notifications, - enabled_notifications: c.enabled_notifications, + notifications: c.enabled_notifications, } } } diff --git a/rog-control-center/src/lib.rs b/rog-control-center/src/lib.rs index cc663c5d..4cce391a 100644 --- a/rog-control-center/src/lib.rs +++ b/rog-control-center/src/lib.rs @@ -17,11 +17,10 @@ pub mod config; pub mod error; #[cfg(feature = "mocking")] pub mod mocking; -pub mod system_state; +pub mod notify; pub mod tray; pub mod types; pub mod ui; -pub mod update_and_notify; use nix::sys::stat; use nix::unistd; diff --git a/rog-control-center/src/main.rs b/rog-control-center/src/main.rs index 3787831b..163b1079 100644 --- a/rog-control-center/src/main.rs +++ b/rog-control-center/src/main.rs @@ -14,11 +14,10 @@ use log::{info, LevelFilter}; use rog_control_center::cli_options::CliStart; use rog_control_center::config::Config; use rog_control_center::error::Result; +use rog_control_center::notify::start_notifications; use rog_control_center::slint::ComponentHandle; -use rog_control_center::system_state::SystemState; use rog_control_center::tray::init_tray; use rog_control_center::ui::setup_window; -use rog_control_center::update_and_notify::{start_notifications, EnabledNotifications}; use rog_control_center::{ get_ipc_file, on_tmp_dir_exists, print_versions, MainWindow, QUIT_APP, SHOWING_GUI, SHOW_GUI, }; @@ -102,7 +101,7 @@ async fn main() -> Result<()> { } if is_rog_ally { - config.enable_notifications = false; + config.notifications.enabled = false; config.enable_tray_icon = false; config.run_in_background = false; config.startup_in_background = false; @@ -115,16 +114,12 @@ async fn main() -> Result<()> { } config.write(); - let enabled_notifications = EnabledNotifications::tokio_mutex(&config); - - // TODO: config mutex to share config in various places - let states = setup_page_state_and_notifs(&enabled_notifications, &config).await?; - let enable_tray_icon = config.enable_tray_icon; let startup_in_background = config.startup_in_background; let config = Arc::new(Mutex::new(config)); + start_notifications(config.clone())?; if enable_tray_icon { - init_tray(supported_properties, states.clone(), config.clone()); + init_tray(supported_properties, config.clone()); } thread_local! { pub static UI: std::cell::RefCell> = Default::default()}; @@ -216,24 +211,6 @@ async fn main() -> Result<()> { Ok(()) } -async fn setup_page_state_and_notifs( - enabled_notifications: &Arc>, - config: &Config, -) -> Result>> { - let page_states = Arc::new(Mutex::new( - SystemState::new( - enabled_notifications.clone(), - config.enable_tray_icon, - config.run_in_background, - ) - .await?, - )); - - start_notifications(config, &page_states, enabled_notifications)?; - - Ok(page_states) -} - // /// 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); diff --git a/rog-control-center/src/system_state.rs b/rog-control-center/src/system_state.rs deleted file mode 100644 index a6aecc9d..00000000 --- a/rog-control-center/src/system_state.rs +++ /dev/null @@ -1,91 +0,0 @@ -use std::sync::{Arc, Mutex}; - -use log::error; -use supergfxctl::pci_device::{GfxMode, GfxPower}; -#[cfg(not(feature = "mocking"))] -use supergfxctl::zbus_proxy::DaemonProxy as GfxProxy; -use zbus::Connection; - -use crate::error::Result; -#[cfg(feature = "mocking")] -use crate::mocking::DaemonProxyBlocking as GfxProxyBlocking; -use crate::update_and_notify::EnabledNotifications; - -#[derive(Clone, Debug)] -pub struct GfxState { - pub has_supergfx: bool, - pub mode: GfxMode, - pub power_status: GfxPower, -} - -impl GfxState { - pub async fn new(dbus: &GfxProxy<'_>) -> Result { - Ok(Self { - has_supergfx: dbus.mode().await.is_ok(), - mode: dbus.mode().await.unwrap_or(GfxMode::None), - power_status: dbus.power().await.unwrap_or(GfxPower::Unknown), - }) - } -} - -impl Default for GfxState { - fn default() -> Self { - Self { - has_supergfx: false, - mode: GfxMode::None, - power_status: GfxPower::Unknown, - } - } -} - -/// State stored from system daemons. This is shared with: tray, zbus -/// notifications thread and the GUI app thread. -pub struct SystemState { - pub enabled_notifications: Arc>, - pub gfx_state: GfxState, - pub error: Option, - /// Specific field for the tray only so that we can know when it does need - /// update. The tray should set this to false when done. - pub tray_should_update: bool, - pub app_should_update: bool, - pub tray_enabled: bool, - pub run_in_bg: bool, -} - -impl SystemState { - /// Creates self, including the relevant dbus connections and proixies for - /// internal use - pub async fn new( - enabled_notifications: Arc>, - tray_enabled: bool, - run_in_bg: bool, - ) -> Result { - let conn = Connection::system().await?; - - let gfx_dbus = GfxProxy::builder(&conn) - .destination(":org.supergfxctl.Daemon")? - .build() - .await - .expect("Couldn't connect to supergfxd"); - Ok(Self { - enabled_notifications, - gfx_state: GfxState::new(&gfx_dbus) - .await - .map_err(|e| { - let e = format!("Could not get supergfxd state: {e}"); - error!("{e}"); - }) - .unwrap_or_default(), - error: None, - tray_should_update: true, - app_should_update: true, - tray_enabled, - run_in_bg, - }) - } - - pub fn set_notified(&mut self) { - self.tray_should_update = true; - self.app_should_update = true; - } -} diff --git a/rog-control-center/src/tray.rs b/rog-control-center/src/tray.rs index baa30273..f9f682ce 100644 --- a/rog-control-center/src/tray.rs +++ b/rog-control-center/src/tray.rs @@ -17,7 +17,6 @@ use supergfxctl::zbus_proxy::DaemonProxyBlocking as GfxProxy; use versions::Versioning; use crate::config::Config; -use crate::system_state::SystemState; use crate::{get_ipc_file, QUIT_APP, SHOW_GUI}; const TRAY_LABEL: &str = "ROG Control Center"; @@ -88,13 +87,17 @@ fn do_action(event: TrayEvent) { } } -fn set_tray_icon_and_tip(lock: &SystemState, tray: &TrayIcon, supergfx_active: bool) { +fn set_tray_icon_and_tip( + mode: GfxMode, + power: GfxPower, + tray: &mut TrayIcon, + supergfx_active: bool, +) { if let Some(icons) = ICONS.get() { - let gpu_status = lock.gfx_state.power_status; - match gpu_status { + match power { GfxPower::Suspended => tray.set_icon(Some(icons.rog_blue.clone())), GfxPower::Off => { - if lock.gfx_state.mode == GfxMode::Vfio { + if mode == GfxMode::Vfio { tray.set_icon(Some(icons.rog_red.clone())) } else { tray.set_icon(Some(icons.rog_green.clone())) @@ -113,24 +116,16 @@ fn set_tray_icon_and_tip(lock: &SystemState, tray: &TrayIcon, superg } }; - let current_gpu_mode = lock.gfx_state.mode; - - tray.set_tooltip(format!( - "ROG: gpu mode = {current_gpu_mode:?}, gpu power = {gpu_status:?}" - )); + tray.set_tooltip(format!("ROG: gpu mode = {mode:?}, gpu power = {power:?}")); } } /// The tray is controlled somewhat by `Arc>` -pub fn init_tray( - _supported_properties: Vec, - states: Arc>, - config: Arc>, -) { +pub fn init_tray(_supported_properties: Vec, config: Arc>) { std::thread::spawn(move || { let rog_red = read_icon(&PathBuf::from("asus_notif_red.png")); - if let Ok(tray) = TrayIconBuilder::::new() + if let Ok(mut tray) = TrayIconBuilder::::new() .with_icon(rog_red.clone()) .with_tooltip(TRAY_LABEL) .with_menu(build_menu()) @@ -170,15 +165,14 @@ pub fn init_tray( info!("Started ROGTray"); loop { - if let Ok(mut lock) = states.lock() { - if lock.tray_should_update { - set_tray_icon_and_tip(&lock, &tray, supergfx_active); - lock.tray_should_update = false; - if let Ok(lock) = config.try_lock() { - if !lock.enable_tray_icon { - return; - } - } + if let Ok(lock) = config.try_lock() { + if !lock.enable_tray_icon { + return; + } + } + if let Ok(mode) = gfx_proxy.mode() { + if let Ok(power) = gfx_proxy.power() { + set_tray_icon_and_tip(mode, power, &mut tray, supergfx_active); } } sleep(Duration::from_millis(50)); diff --git a/rog-control-center/src/ui/mod.rs b/rog-control-center/src/ui/mod.rs index 45bfcda5..63f52bf8 100644 --- a/rog-control-center/src/ui/mod.rs +++ b/rog-control-center/src/ui/mod.rs @@ -166,7 +166,7 @@ pub fn setup_app_settings_page(ui: &MainWindow, config: Arc>) { let config_copy = config.clone(); global.on_set_enable_notifications(move |enable| { if let Ok(mut lock) = config_copy.try_lock() { - lock.enable_notifications = enable; + lock.notifications.enabled = enable; lock.write(); } }); @@ -175,6 +175,6 @@ pub fn setup_app_settings_page(ui: &MainWindow, config: Arc>) { global.set_run_in_background(lock.run_in_background); global.set_startup_in_background(lock.startup_in_background); global.set_enable_tray_icon(lock.enable_tray_icon); - global.set_enable_notifications(lock.enable_notifications); + global.set_enable_notifications(lock.notifications.enabled); } } diff --git a/rog-control-center/src/update_and_notify.rs b/rog-control-center/src/update_and_notify.rs deleted file mode 100644 index 5418d049..00000000 --- a/rog-control-center/src/update_and_notify.rs +++ /dev/null @@ -1,442 +0,0 @@ -//! `update_and_notify` is responsible for both notifications *and* updating -//! stored statuses about the system state. This is done through either direct, -//! intoify, zbus notifications or similar methods. -//! -//! This module very much functions like a stand-alone app on its own thread. - -use std::fmt::Display; -use std::process::Command; -use std::sync::{Arc, Mutex}; -use std::time::Duration; - -use log::{error, info, trace, warn}; -use notify_rust::{Hint, Notification, NotificationHandle, Urgency}; -use rog_dbus::zbus_platform::PlatformProxy; -use rog_platform::platform::GpuMode; -use serde::{Deserialize, Serialize}; -use supergfxctl::actions::UserActionRequired as GfxUserAction; -use supergfxctl::pci_device::{GfxMode, GfxPower}; -use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy; -use tokio::time::sleep; -use zbus::export::futures_util::StreamExt; - -use crate::config::Config; -use crate::error::Result; -use crate::system_state::SystemState; - -const NOTIF_HEADER: &str = "ROG Control"; - -static mut POWER_AC_CMD: Option = None; -static mut POWER_BAT_CMD: Option = None; - -#[derive(Debug, Default, Clone, Deserialize, Serialize)] -#[serde(default)] -pub struct EnabledNotifications { - pub receive_power_states: bool, - pub receive_notify_gfx: bool, - pub receive_notify_gfx_status: bool, -} - -impl EnabledNotifications { - pub fn tokio_mutex(config: &Config) -> Arc> { - Arc::new(Mutex::new(config.enabled_notifications.clone())) - } -} - -fn gpu_to_gfx(value: GpuMode) -> GfxMode { - match value { - GpuMode::Optimus => GfxMode::Hybrid, - GpuMode::Integrated => GfxMode::Integrated, - GpuMode::Egpu => GfxMode::AsusEgpu, - GpuMode::Vfio => GfxMode::Vfio, - GpuMode::Ultimate => GfxMode::AsusMuxDgpu, - GpuMode::Error => GfxMode::None, - GpuMode::NotSupported => GfxMode::None, - } -} - -// TODO: drop the macro and use generics plus closure -macro_rules! recv_notif { - ($proxy:ident, - $signal:ident, - $last_notif:ident, - $notif_enabled:ident, - $page_states:ident, - ($($args: tt)*), - ($($out_arg:tt)+), - $msg:literal, - $notifier:ident) => { - - let notifs_enabled1 = $notif_enabled.clone(); - let page_states1 = $page_states.clone(); - - tokio::spawn(async move { - let conn = zbus::Connection::system().await.map_err(|e| { - log::error!("zbus signal: {}: {e}", stringify!($signal)); - e - }).unwrap(); - let proxy = $proxy::builder(&conn).build().await.map_err(|e| { - log::error!("zbus signal: {}: {e}", stringify!($signal)); - e - }).unwrap(); - if let Ok(mut p) = proxy.$signal().await { - info!("Started zbus signal thread: {}", stringify!($signal)); - while let Some(e) = p.next().await { - if let Ok(out) = e.args() { - if let Ok(config) = notifs_enabled1.lock() { - if config.$signal { - trace!("zbus signal {}", stringify!($signal)); - $notifier($msg, &out.$($out_arg)+()).ok(); - } - } - if let Ok(mut lock) = page_states1.lock() { - lock.$($args)+ = *out.$($out_arg)+(); - lock.set_notified(); - } - } - sleep(Duration::from_millis(500)).await; - } - }; - }); - }; -} - -pub fn start_notifications( - config: &Config, - page_states: &Arc>, - enabled_notifications: &Arc>, -) -> Result<()> { - // Setup the AC/BAT commands that will run on poweer status change - unsafe { - let prog: Vec<&str> = config.ac_command.split_whitespace().collect(); - if prog.len() > 1 { - let mut cmd = Command::new(prog[0]); - - for arg in prog.iter().skip(1) { - cmd.arg(*arg); - } - POWER_AC_CMD = Some(cmd); - } - } - unsafe { - let prog: Vec<&str> = config.bat_command.split_whitespace().collect(); - if prog.len() > 1 { - let mut cmd = Command::new(prog[0]); - - for arg in prog.iter().skip(1) { - cmd.arg(*arg); - } - POWER_BAT_CMD = Some(cmd); - } - } - - let page_states1 = page_states.clone(); - tokio::spawn(async move { - let conn = zbus::Connection::system() - .await - .map_err(|e| { - error!("zbus signal: receive_notify_gpu_mux_mode: {e}"); - e - }) - .unwrap(); - let proxy = PlatformProxy::new(&conn) - .await - .map_err(|e| { - error!("zbus signal: receive_notify_gpu_mux_mode: {e}"); - e - }) - .unwrap(); - - let mut actual_mux_mode = GpuMode::Error; - if let Ok(mode) = proxy.gpu_mux_mode().await { - actual_mux_mode = GpuMode::from(mode); - } - - info!("Started zbus signal thread: receive_notify_gpu_mux_mode"); - while let Some(e) = proxy.receive_gpu_mux_mode_changed().await.next().await { - if let Ok(out) = e.get().await { - let mode = GpuMode::from(out); - if mode == actual_mux_mode { - continue; - } - if let Ok(mut lock) = page_states1.lock() { - lock.gfx_state.mode = gpu_to_gfx(mode); - lock.set_notified(); - } - do_mux_notification("Reboot required. BIOS GPU MUX mode set to", &mode).ok(); - } - } - }); - - use supergfxctl::pci_device::Device; - let dev = Device::find().unwrap_or_default(); - let mut found_dgpu = false; // just for logging - for dev in dev { - if dev.is_dgpu() { - let notifs_enabled1 = enabled_notifications.clone(); - let page_states1 = page_states.clone(); - // Plain old thread is perfectly fine since most of this is potentially blocking - tokio::spawn(async move { - let mut last_status = GfxPower::Unknown; - loop { - if let Ok(status) = dev.get_runtime_status() { - if status != GfxPower::Unknown && status != last_status { - if let Ok(config) = notifs_enabled1.lock() { - if config.receive_notify_gfx_status { - // Required check because status cycles through - // active/unknown/suspended - do_gpu_status_notif("dGPU status changed:", &status).ok(); - } - } - if let Ok(mut lock) = page_states1.lock() { - lock.set_notified(); - } - } - if let Ok(mut lock) = page_states1.lock() { - lock.gfx_state.power_status = status; - } - last_status = status; - } - sleep(Duration::from_millis(500)).await; - } - }); - found_dgpu = true; - break; - } - } - if !found_dgpu { - warn!("Did not find a dGPU on this system, dGPU status won't be avilable"); - } - - let page_states1 = page_states.clone(); - let enabled_notifications1 = enabled_notifications.clone(); - tokio::spawn(async move { - let conn = zbus::Connection::system() - .await - .map_err(|e| { - error!("zbus signal: receive_notify_action: {e}"); - e - }) - .unwrap(); - let proxy = SuperProxy::builder(&conn) - .build() - .await - .map_err(|e| { - error!("zbus signal: receive_notify_action: {e}"); - e - }) - .unwrap(); - - if let Ok(mode) = proxy.mode().await { - if let Ok(mut lock) = page_states1.lock() { - lock.gfx_state.mode = mode; - lock.gfx_state.has_supergfx = true; - } - } else { - info!("supergfxd not running or not responding"); - return; - } - - let page_states2 = page_states1.clone(); - recv_notif!( - SuperProxy, - receive_notify_gfx, - last_notification, - enabled_notifications1, - page_states2, - (gfx_state.mode), - (mode), - "Gfx mode changed to", - do_notification - ); - - if let Ok(mut p) = proxy.receive_notify_action().await { - info!("Started zbus signal thread: receive_notify_action"); - while let Some(e) = p.next().await { - if let Ok(out) = e.args() { - let action = out.action(); - let mode = if let Ok(lock) = page_states1.lock() { - convert_gfx_mode(lock.gfx_state.mode) - } else { - GpuMode::Error - }; - match action { - supergfxctl::actions::UserActionRequired::Reboot => { - do_mux_notification("Graphics mode change requires reboot", &mode) - } - _ => do_gfx_action_notif(<&str>::from(action), *action, mode), - } - .map_err(|e| { - error!("zbus signal: do_gfx_action_notif: {e}"); - e - }) - .ok(); - } - } - }; - }); - - Ok(()) -} - -fn convert_gfx_mode(gfx: GfxMode) -> GpuMode { - match gfx { - GfxMode::Hybrid => GpuMode::Optimus, - GfxMode::Integrated => GpuMode::Integrated, - GfxMode::NvidiaNoModeset => GpuMode::Optimus, - GfxMode::Vfio => GpuMode::Vfio, - GfxMode::AsusEgpu => GpuMode::Egpu, - GfxMode::AsusMuxDgpu => GpuMode::Ultimate, - GfxMode::None => GpuMode::Error, - } -} - -fn base_notification(message: &str, data: &T) -> Notification -where - T: Display, -{ - let mut notif = Notification::new(); - - notif - .summary(NOTIF_HEADER) - .body(&format!("{message} {data}")) - .timeout(-1) - //.hint(Hint::Resident(true)) - .hint(Hint::Category("device".into())); - - notif -} - -fn do_notification(message: &str, data: &T) -> Result -where - T: Display, -{ - Ok(base_notification(message, data).show()?) -} - -// TODO: -fn _ac_power_notification(message: &str, on: &bool) -> Result { - let data = if *on { - unsafe { - if let Some(cmd) = POWER_AC_CMD.as_mut() { - if let Err(e) = cmd.spawn() { - error!("AC power command error: {e}"); - } - } - } - "plugged".to_owned() - } else { - unsafe { - if let Some(cmd) = POWER_BAT_CMD.as_mut() { - if let Err(e) = cmd.spawn() { - error!("Battery power command error: {e}"); - } - } - } - "unplugged".to_owned() - }; - Ok(base_notification(message, &data).show()?) -} - -fn do_gpu_status_notif(message: &str, data: &GfxPower) -> Result { - // eww - let mut notif = base_notification(message, &<&str>::from(data).to_owned()); - let icon = match data { - GfxPower::Suspended => "asus_notif_blue", - GfxPower::Off => "asus_notif_green", - GfxPower::AsusDisabled => "asus_notif_white", - GfxPower::AsusMuxDiscreet | GfxPower::Active => "asus_notif_red", - GfxPower::Unknown => "gpu-integrated", - }; - notif.icon(icon); - Ok(Notification::show(¬if)?) -} - -fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> Result<()> { - if matches!(action, GfxUserAction::Reboot) { - do_mux_notification("Graphics mode change requires reboot", &mode).ok(); - return Ok(()); - } - - let mut notif = Notification::new(); - notif - .summary(NOTIF_HEADER) - .body(&format!("Changing to {mode}. {message}")) - .timeout(2000) - //.hint(Hint::Resident(true)) - .hint(Hint::Category("device".into())) - .urgency(Urgency::Critical) - .timeout(-1) - .icon("dialog-warning") - .hint(Hint::Transient(true)); - - if matches!(action, GfxUserAction::Logout) { - notif.action("gfx-mode-session-action", "Logout"); - let handle = notif.show()?; - if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") { - if desktop.to_lowercase() == "gnome" { - handle.wait_for_action(|id| { - if id == "gfx-mode-session-action" { - let mut cmd = Command::new("gnome-session-quit"); - cmd.spawn().ok(); - } else if id == "__closed" { - // TODO: cancel the switching - } - }); - } else if desktop.to_lowercase() == "kde" { - handle.wait_for_action(|id| { - if id == "gfx-mode-session-action" { - let mut cmd = Command::new("qdbus"); - cmd.args(["org.kde.ksmserver", "/KSMServer", "logout", "1", "0", "0"]); - cmd.spawn().ok(); - } else if id == "__closed" { - // TODO: cancel the switching - } - }); - } else { - // todo: handle alternatives - } - } - } else { - notif.show()?; - } - Ok(()) -} - -/// Actual `GpuMode` unused as data is never correct until switched by reboot -fn do_mux_notification(message: &str, m: &GpuMode) -> Result<()> { - let mut notif = base_notification(message, &m.to_string()); - notif - .action("gfx-mode-session-action", "Reboot") - .urgency(Urgency::Critical) - .icon("system-reboot-symbolic") - .hint(Hint::Transient(true)); - let handle = notif.show()?; - - std::thread::spawn(|| { - if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") { - if desktop.to_lowercase() == "gnome" { - handle.wait_for_action(|id| { - if id == "gfx-mode-session-action" { - let mut cmd = Command::new("gnome-session-quit"); - cmd.arg("--reboot"); - cmd.spawn().ok(); - } else if id == "__closed" { - // TODO: cancel the switching - } - }); - } else if desktop.to_lowercase() == "kde" { - handle.wait_for_action(|id| { - if id == "gfx-mode-session-action" { - let mut cmd = Command::new("qdbus"); - cmd.args(["org.kde.ksmserver", "/KSMServer", "logout", "1", "1", "0"]); - cmd.spawn().ok(); - } else if id == "__closed" { - // TODO: cancel the switching - } - }); - } - } - }); - Ok(()) -} diff --git a/rog-control-center/translations/en/rog-control-center.po b/rog-control-center/translations/en/rog-control-center.po index 27947d01..70f69168 100644 --- a/rog-control-center/translations/en/rog-control-center.po +++ b/rog-control-center/translations/en/rog-control-center.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2024-04-17 09:39+0000\n" +"POT-Creation-Date: 2024-04-18 01:47+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n"