diff --git a/rog-control-center/src/cli_options.rs b/rog-control-center/src/cli_options.rs index d7bde2d4..b3fc9b4f 100644 --- a/rog-control-center/src/cli_options.rs +++ b/rog-control-center/src/cli_options.rs @@ -14,6 +14,8 @@ pub struct CliStart { pub windowed: bool, #[options(help = "show program version number")] pub version: bool, + #[options(help = "start in background (UI closed)")] + pub background: bool, #[options( meta = "", help = "set board name for testing, this will make ROGCC show only the keyboard page" diff --git a/rog-control-center/src/config.rs b/rog-control-center/src/config.rs index ef8207f2..24a090d2 100644 --- a/rog-control-center/src/config.rs +++ b/rog-control-center/src/config.rs @@ -13,6 +13,10 @@ pub struct Config { pub run_in_background: bool, pub startup_in_background: bool, pub enable_tray_icon: bool, + #[serde(default)] + pub enable_autostart: bool, + #[serde(default)] + pub autostart_in_background: bool, pub ac_command: String, pub bat_command: String, pub dark_mode: bool, @@ -30,6 +34,8 @@ impl Default for Config { run_in_background: true, startup_in_background: false, enable_tray_icon: true, + enable_autostart: false, + autostart_in_background: false, dark_mode: true, start_fullscreen: false, fullscreen_width: 1920, @@ -86,6 +92,8 @@ impl From for Config { run_in_background: c.run_in_background, startup_in_background: c.startup_in_background, enable_tray_icon: true, + enable_autostart: false, + autostart_in_background: false, ac_command: c.ac_command, bat_command: c.bat_command, dark_mode: true, @@ -96,3 +104,96 @@ impl From for Config { } } } + +pub fn update_autostart(enable: bool, in_background: bool) { + let autostart_dir = match dirs::config_dir() { + Some(mut p) => { + p.push("autostart"); + p + } + None => { + log::error!("Could not find config directory for autostart"); + return; + } + }; + + let desktop_file = autostart_dir.join("rog-control-center.desktop"); + + if enable { + if !autostart_dir.exists() { + if let Err(e) = std::fs::create_dir_all(&autostart_dir) { + log::error!("Failed to create autostart directory: {e}"); + return; + } + } + + let exec_cmd = if in_background { + "rog-control-center --background" + } else { + "rog-control-center" + }; + + let content = format!("[Desktop Entry]\n\ + Version=1.0\n\ + Type=Application\n\ + Name=ROG Control Center\n\ + Comment=Make your ASUS ROG Laptop go Brrrrr!\n\ + Categories=Settings;\n\ + Icon=rog-control-center\n\ + Exec={}\n\ + Terminal=false\n", exec_cmd); + + if let Err(e) = std::fs::write(&desktop_file, content) { + log::error!("Failed to write autostart desktop file: {e}"); + } else { + log::info!("Created autostart entry at {:?}", desktop_file); + } + } else { + if desktop_file.exists() { + if let Err(e) = std::fs::remove_file(&desktop_file) { + log::error!("Failed to remove autostart desktop file: {e}"); + } else { + log::info!("Removed autostart entry at {:?}", desktop_file); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_update_autostart() { + let path = dirs::config_dir().map(|mut p| { + p.push("autostart"); + p.push("rog-control-center.desktop"); + p + }); + + if let Some(path) = path { + // Backup existing file if any + let backup = if path.exists() { + Some(std::fs::read_to_string(&path).unwrap()) + } else { + None + }; + + // Test enabling + update_autostart(true, true); + assert!(path.exists()); + let content = std::fs::read_to_string(&path).unwrap(); + assert!(content.contains("Name=ROG Control Center")); + assert!(content.contains("Exec=rog-control-center --background")); + + // Test disabling + update_autostart(false, false); + assert!(!path.exists()); + + // Restore backup if any + if let Some(ref backup_content) = backup { + std::fs::write(&path, backup_content).ok(); + } + } + } +} diff --git a/rog-control-center/src/main.rs b/rog-control-center/src/main.rs index 2e72d48a..2a0cacaf 100644 --- a/rog-control-center/src/main.rs +++ b/rog-control-center/src/main.rs @@ -161,12 +161,14 @@ async fn main() -> Result<()> { config.run_in_background = false; config.startup_in_background = false; config.start_fullscreen = true; + config.enable_autostart = false; } config.write(); + rog_control_center::config::update_autostart(config.enable_autostart, config.autostart_in_background); let enable_tray_icon = config.enable_tray_icon; - let startup_in_background = config.startup_in_background; + let startup_in_background = cli_parsed.background || config.startup_in_background; let config = Arc::new(Mutex::new(config)); start_notifications(config.clone(), &rt)?; diff --git a/rog-control-center/src/ui/mod.rs b/rog-control-center/src/ui/mod.rs index b0d0b10c..0228439b 100644 --- a/rog-control-center/src/ui/mod.rs +++ b/rog-control-center/src/ui/mod.rs @@ -211,11 +211,31 @@ pub fn setup_app_settings_page(ui: &MainWindow, config: Arc>) { lock.write(); } }); + let config_copy = config.clone(); + global.on_set_enable_autostart(move |enable| { + if let Ok(mut lock) = config_copy.try_lock() { + lock.enable_autostart = enable; + let in_bg = lock.autostart_in_background; + lock.write(); + super::config::update_autostart(enable, in_bg); + } + }); + let config_copy = config.clone(); + global.on_set_autostart_in_background(move |enable| { + if let Ok(mut lock) = config_copy.try_lock() { + lock.autostart_in_background = enable; + let autostart = lock.enable_autostart; + lock.write(); + super::config::update_autostart(autostart, enable); + } + }); if let Ok(lock) = config.try_lock() { 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_dgpu_notifications(lock.notifications.enabled); + global.set_enable_autostart(lock.enable_autostart); + global.set_autostart_in_background(lock.autostart_in_background); } } diff --git a/rog-control-center/ui/pages/app_settings.slint b/rog-control-center/ui/pages/app_settings.slint index 95919868..aec89e9f 100644 --- a/rog-control-center/ui/pages/app_settings.slint +++ b/rog-control-center/ui/pages/app_settings.slint @@ -10,6 +10,10 @@ export global AppSettingsPageData { callback set_enable_tray_icon(bool); in-out property enable_dgpu_notifications; callback set_enable_dgpu_notifications(bool); + in-out property enable_autostart; + callback set_enable_autostart(bool); + in-out property autostart_in_background; + callback set_autostart_in_background(bool); } export component PageAppSettings inherits VerticalLayout { @@ -51,6 +55,25 @@ export component PageAppSettings inherits VerticalLayout { } } + SystemToggle { + text: @tr("Start app on system startup"); + checked <=> AppSettingsPageData.enable_autostart; + toggled => { + AppSettingsPageData.set_enable_autostart(AppSettingsPageData.enable_autostart) + } + } + + if AppSettingsPageData.enable_autostart : HorizontalLayout { + padding-left: 20px; + SystemToggle { + text: @tr("Start in background on startup"); + checked <=> AppSettingsPageData.autostart_in_background; + toggled => { + AppSettingsPageData.set_autostart_in_background(AppSettingsPageData.autostart_in_background) + } + } + } + Text { color: Palette.accent-background; text: " WIP: some features like notifications are not complete";