mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
RCC: add tray enable/disable, move app settings to page
This commit is contained in:
@@ -5,7 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
## [v4.7.0-RC1]
|
||||
## [v4.7.0-RC2]
|
||||
### Added
|
||||
- Support for FX507Z LED modes
|
||||
- Support for GL503V LED modes
|
||||
@@ -31,6 +31,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Prevent the multiple notifications from a profile change from occuring (too many functions with side effects!)
|
||||
- Apply keyboard brightness when setting a mode
|
||||
- Update GL503 led config
|
||||
- Rog Control Center:
|
||||
- Added option to enable/disable system tray
|
||||
- Added button to fully quit app (exits from background)
|
||||
- Moved application settings to new page
|
||||
### BREAKING
|
||||
- All Anime related DBUS methods/notifs are changed
|
||||
- All dbus interfaces that handled an enum have now been forced to use the enum as String type, not uint or similar, this unfortunately breaks a heap of stuff but has the benefit of allowing asusctl to use crates to generate a typescript (or other) binding to the types being used by zbus for the proxies. The implication here is that there will be an eventual tighter integration with the gnome extension and maybe KDE also.
|
||||
|
||||
@@ -127,13 +127,12 @@ impl eframe::App for RogApp {
|
||||
self.aura_page(&mut states, ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
self.top_bar(&mut states, ctx, frame);
|
||||
self.side_panel(ctx);
|
||||
}
|
||||
|
||||
let page = self.page;
|
||||
|
||||
self.top_bar(ctx, frame);
|
||||
self.side_panel(ctx);
|
||||
|
||||
let mut was_error = false;
|
||||
|
||||
if let Ok(mut states) = states.try_lock() {
|
||||
@@ -163,16 +162,13 @@ impl eframe::App for RogApp {
|
||||
|
||||
if !was_error {
|
||||
if let Ok(mut states) = states.try_lock() {
|
||||
if page == Page::System {
|
||||
self.system_page(&mut states, ctx);
|
||||
} else if page == Page::AuraEffects {
|
||||
self.aura_page(&mut states, ctx);
|
||||
// TODO: Anime page is not complete
|
||||
// } else if page == Page::AnimeMatrix {
|
||||
// self.anime_page(ctx);
|
||||
} else if page == Page::FanCurves {
|
||||
self.fan_curve_page(&mut states, ctx);
|
||||
}
|
||||
match page {
|
||||
Page::AppSettings => self.app_settings_page(&mut states, ctx),
|
||||
Page::System => self.system_page(&mut states, ctx),
|
||||
Page::AuraEffects => self.aura_page(&mut states, ctx),
|
||||
Page::AnimeMatrix => todo!(),
|
||||
Page::FanCurves => self.fan_curve_page(&mut states, ctx),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ const CFG_FILE_NAME: &str = "rog-control-center.cfg";
|
||||
pub struct Config {
|
||||
pub run_in_background: bool,
|
||||
pub startup_in_background: bool,
|
||||
pub enable_tray_icon: bool,
|
||||
pub ac_command: String,
|
||||
pub bat_command: String,
|
||||
pub enable_notifications: bool,
|
||||
@@ -28,6 +29,7 @@ impl Default for Config {
|
||||
run_in_background: true,
|
||||
startup_in_background: false,
|
||||
enable_notifications: true,
|
||||
enable_tray_icon: true,
|
||||
dark_mode: true,
|
||||
enabled_notifications: EnabledNotifications::default(),
|
||||
ac_command: String::new(),
|
||||
@@ -74,6 +76,9 @@ impl Config {
|
||||
} else if let Ok(data) = toml::from_str::<Config>(&buf) {
|
||||
info!("Loaded config file {path:?}");
|
||||
return Ok(data);
|
||||
} else if let Ok(data) = toml::from_str::<Config461>(&buf) {
|
||||
info!("Loaded old v4.6.1 config file {path:?}");
|
||||
return Ok(data.into());
|
||||
} else if let Ok(data) = toml::from_str::<Config460>(&buf) {
|
||||
info!("Loaded old v4.6.0 config file {path:?}");
|
||||
return Ok(data.into());
|
||||
@@ -127,6 +132,7 @@ impl From<Config455> for Config {
|
||||
Self {
|
||||
run_in_background: c.run_in_background,
|
||||
startup_in_background: c.startup_in_background,
|
||||
enable_tray_icon: true,
|
||||
enable_notifications: c.enable_notifications,
|
||||
enabled_notifications: c.enabled_notifications,
|
||||
dark_mode: true,
|
||||
@@ -151,6 +157,34 @@ impl From<Config460> for Config {
|
||||
Self {
|
||||
run_in_background: c.run_in_background,
|
||||
startup_in_background: c.startup_in_background,
|
||||
enable_tray_icon: true,
|
||||
ac_command: c.ac_command,
|
||||
bat_command: c.bat_command,
|
||||
dark_mode: true,
|
||||
enable_notifications: c.enable_notifications,
|
||||
enabled_notifications: c.enabled_notifications,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Config461 {
|
||||
pub run_in_background: bool,
|
||||
pub startup_in_background: bool,
|
||||
pub ac_command: String,
|
||||
pub bat_command: String,
|
||||
pub enable_notifications: bool,
|
||||
pub dark_mode: bool,
|
||||
// This field must be last
|
||||
pub enabled_notifications: EnabledNotifications,
|
||||
}
|
||||
|
||||
impl From<Config461> for Config {
|
||||
fn from(c: Config461) -> Self {
|
||||
Self {
|
||||
run_in_background: c.run_in_background,
|
||||
startup_in_background: c.startup_in_background,
|
||||
enable_tray_icon: true,
|
||||
ac_command: c.ac_command,
|
||||
bat_command: c.bat_command,
|
||||
dark_mode: true,
|
||||
|
||||
@@ -47,6 +47,7 @@ pub const SHOW_GUI: u8 = 2;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Page {
|
||||
AppSettings,
|
||||
System,
|
||||
AuraEffects,
|
||||
AnimeMatrix,
|
||||
|
||||
@@ -189,7 +189,9 @@ fn main() -> Result<()> {
|
||||
&supported,
|
||||
)?;
|
||||
|
||||
init_tray(supported, states.clone());
|
||||
if config.enable_tray_icon {
|
||||
init_tray(supported, states.clone());
|
||||
}
|
||||
|
||||
let mut bg_check_spawned = false;
|
||||
loop {
|
||||
@@ -210,35 +212,32 @@ fn main() -> Result<()> {
|
||||
bg_check_spawned = false;
|
||||
}
|
||||
|
||||
if !config.run_in_background || cli_parsed.board_name.is_some() || cli_parsed.layout_viewing
|
||||
{
|
||||
break;
|
||||
if let Ok(lock) = states.try_lock() {
|
||||
if !lock.run_in_bg || cli_parsed.board_name.is_some() || cli_parsed.layout_viewing {
|
||||
break;
|
||||
}
|
||||
|
||||
if lock.run_in_bg && running_in_bg.load(Ordering::Acquire) && !bg_check_spawned {
|
||||
let running_in_bg = running_in_bg.clone();
|
||||
thread::spawn(move || {
|
||||
let mut buf = [0u8; 4];
|
||||
// blocks until it is read, typically the read will happen after a second
|
||||
// process writes to the IPC (so there is data to actually read)
|
||||
loop {
|
||||
if get_ipc_file().unwrap().read(&mut buf).is_ok() && buf[0] == SHOW_GUI {
|
||||
running_in_bg.store(false, Ordering::Release);
|
||||
debug!("Wait thread got from tray {buf:#?}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
bg_check_spawned = true;
|
||||
}
|
||||
}
|
||||
|
||||
if config.run_in_background && running_in_bg.load(Ordering::Acquire) && !bg_check_spawned {
|
||||
let running_in_bg = running_in_bg.clone();
|
||||
thread::spawn(move || {
|
||||
let mut buf = [0u8; 4];
|
||||
// blocks until it is read, typically the read will happen after a second
|
||||
// process writes to the IPC (so there is data to actually read)
|
||||
loop {
|
||||
if get_ipc_file().unwrap().read(&mut buf).is_ok() && buf[0] == SHOW_GUI {
|
||||
running_in_bg.store(false, Ordering::Release);
|
||||
debug!("Wait thread got from tray {buf:#?}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
bg_check_spawned = true;
|
||||
}
|
||||
// Prevent hogging CPU
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
}
|
||||
|
||||
// loop {
|
||||
// // This is just a blocker to idle and ensure the reator reacts
|
||||
// sleep(Duration::from_millis(1000)).await;
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -255,6 +254,8 @@ fn setup_page_state_and_notifs(
|
||||
keyboard_layout,
|
||||
keyboard_layouts,
|
||||
enabled_notifications.clone(),
|
||||
config.enable_tray_icon,
|
||||
config.run_in_background,
|
||||
supported,
|
||||
)?));
|
||||
|
||||
|
||||
24
rog-control-center/src/pages/app_settings.rs
Normal file
24
rog-control-center/src/pages/app_settings.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::system_state::SystemState;
|
||||
use crate::widgets::app_settings;
|
||||
use crate::RogApp;
|
||||
|
||||
impl RogApp {
|
||||
pub fn app_settings_page(&mut self, states: &mut SystemState, ctx: &egui::Context) {
|
||||
let Self { config, .. } = self;
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||
ui.spacing_mut().item_spacing = egui::vec2(8.0, 10.0);
|
||||
let rect = ui.available_rect_before_wrap();
|
||||
egui::Grid::new("grid_of_bits")
|
||||
.min_col_width(rect.width() / 2.0)
|
||||
.show(ui, |ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.separator();
|
||||
app_settings(config, states, ui);
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
mod anime_page;
|
||||
mod app_settings;
|
||||
mod aura_page;
|
||||
mod fan_curve_page;
|
||||
mod system_page;
|
||||
|
||||
pub use anime_page::*;
|
||||
pub use app_settings::*;
|
||||
pub use aura_page::*;
|
||||
pub use fan_curve_page::*;
|
||||
pub use system_page::*;
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
use crate::system_state::SystemState;
|
||||
use crate::widgets::{
|
||||
anime_power_group, app_settings, aura_power_group, platform_profile, rog_bios_group,
|
||||
};
|
||||
use crate::widgets::{anime_power_group, aura_power_group, platform_profile, rog_bios_group};
|
||||
use crate::RogApp;
|
||||
|
||||
impl RogApp {
|
||||
pub fn system_page(&mut self, states: &mut SystemState, ctx: &egui::Context) {
|
||||
let Self {
|
||||
config, supported, ..
|
||||
} = self;
|
||||
let Self { supported, .. } = self;
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("Base settings");
|
||||
ui.heading("Laptop settings");
|
||||
|
||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||
ui.spacing_mut().item_spacing = egui::vec2(8.0, 10.0);
|
||||
@@ -31,10 +27,6 @@ impl RogApp {
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
ui.vertical(|ui| {
|
||||
ui.separator();
|
||||
app_settings(config, states, ui);
|
||||
});
|
||||
ui.vertical(|ui| {
|
||||
ui.separator();
|
||||
rog_bios_group(supported, states, ui);
|
||||
|
||||
@@ -316,6 +316,8 @@ pub struct SystemState {
|
||||
pub app_should_update: bool,
|
||||
pub asus_dbus: RogDbusClientBlocking<'static>,
|
||||
pub gfx_dbus: GfxProxyBlocking<'static>,
|
||||
pub tray_enabled: bool,
|
||||
pub run_in_bg: bool,
|
||||
}
|
||||
|
||||
impl SystemState {
|
||||
@@ -326,6 +328,8 @@ impl SystemState {
|
||||
keyboard_layout: KeyLayout,
|
||||
keyboard_layouts: Vec<PathBuf>,
|
||||
enabled_notifications: Arc<Mutex<EnabledNotifications>>,
|
||||
tray_enabled: bool,
|
||||
run_in_bg: bool,
|
||||
supported: &SupportedFunctions,
|
||||
) -> Result<Self> {
|
||||
let (asus_dbus, conn) = RogDbusClientBlocking::new()?;
|
||||
@@ -390,6 +394,8 @@ impl SystemState {
|
||||
app_should_update: true,
|
||||
asus_dbus,
|
||||
gfx_dbus,
|
||||
tray_enabled,
|
||||
run_in_bg,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -449,6 +455,8 @@ impl Default for SystemState {
|
||||
app_should_update: true,
|
||||
asus_dbus,
|
||||
gfx_dbus,
|
||||
tray_enabled: true,
|
||||
run_in_bg: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
//! commands over an MPSC channel.
|
||||
|
||||
use std::io::Write;
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -29,11 +28,6 @@ pub enum AppToTray {
|
||||
DgpuStatus(GfxPower),
|
||||
}
|
||||
|
||||
pub enum TrayToApp {
|
||||
Open,
|
||||
Quit,
|
||||
}
|
||||
|
||||
pub struct RadioGroup(Vec<gtk::RadioMenuItem>);
|
||||
|
||||
impl RadioGroup {
|
||||
@@ -418,13 +412,8 @@ impl ROGTray {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_tray(
|
||||
supported: SupportedFunctions,
|
||||
states: Arc<Mutex<SystemState>>,
|
||||
) -> Receiver<TrayToApp> {
|
||||
let (send, recv) = channel();
|
||||
let _send = Arc::new(Mutex::new(send));
|
||||
|
||||
/// The tray is controlled somewhat by `Arc<Mutex<SystemState>>`
|
||||
pub fn init_tray(supported: SupportedFunctions, states: Arc<Mutex<SystemState>>) {
|
||||
std::thread::spawn(move || {
|
||||
let gtk_init = gtk::init().map_err(|e| {
|
||||
error!("ROGTray: gtk init {e}");
|
||||
@@ -538,6 +527,4 @@ pub fn init_tray(
|
||||
trace!("Tray loop ticked");
|
||||
}
|
||||
});
|
||||
|
||||
recv
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ use crate::config::Config;
|
||||
use crate::system_state::SystemState;
|
||||
|
||||
pub fn app_settings(config: &mut Config, states: &mut SystemState, ui: &mut Ui) {
|
||||
ui.heading("ROG GUI Settings");
|
||||
// ui.label("Options are incomplete. Awake + Boot should work");
|
||||
ui.heading("App Settings");
|
||||
|
||||
let mut enabled_notifications = if let Ok(lock) = states.enabled_notifications.lock() {
|
||||
lock.clone()
|
||||
@@ -15,8 +14,14 @@ pub fn app_settings(config: &mut Config, states: &mut SystemState, ui: &mut Ui)
|
||||
|
||||
ui.label("Application settings");
|
||||
let app_changed = ui
|
||||
.checkbox(&mut config.run_in_background, "Run in Background")
|
||||
.checkbox(
|
||||
&mut config.enable_tray_icon,
|
||||
"Enable Tray Icon (restart required)",
|
||||
)
|
||||
.clicked()
|
||||
|| ui
|
||||
.checkbox(&mut config.run_in_background, "Run in Background")
|
||||
.clicked()
|
||||
|| ui
|
||||
.checkbox(&mut config.startup_in_background, "Startup Hidden")
|
||||
.clicked()
|
||||
@@ -27,6 +32,10 @@ pub fn app_settings(config: &mut Config, states: &mut SystemState, ui: &mut Ui)
|
||||
)
|
||||
.clicked();
|
||||
|
||||
// if ui.button("Quit").clicked() {
|
||||
// states.run_in_bg = false;
|
||||
// }
|
||||
|
||||
ui.label("Notification settings");
|
||||
let notif_changed = ui
|
||||
.checkbox(
|
||||
@@ -100,6 +109,9 @@ pub fn app_settings(config: &mut Config, states: &mut SystemState, ui: &mut Ui)
|
||||
states.error = Some(err.to_string());
|
||||
})
|
||||
.ok();
|
||||
|
||||
states.tray_enabled = config.enable_tray_icon;
|
||||
states.run_in_bg = config.run_in_background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,14 @@ impl RogApp {
|
||||
// }
|
||||
// }
|
||||
|
||||
ui.separator();
|
||||
if ui
|
||||
.selectable_value(page, Page::AppSettings, "App Settings")
|
||||
.clicked()
|
||||
{
|
||||
*page = Page::AppSettings;
|
||||
}
|
||||
|
||||
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 0.0;
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
use egui::{vec2, Align2, FontId, Id, Sense};
|
||||
|
||||
use crate::system_state::SystemState;
|
||||
use crate::{RogApp, VERSION};
|
||||
|
||||
impl RogApp {
|
||||
pub fn top_bar(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
|
||||
pub fn top_bar(
|
||||
&mut self,
|
||||
states: &mut SystemState,
|
||||
ctx: &egui::Context,
|
||||
frame: &mut eframe::Frame,
|
||||
) {
|
||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||
// The top panel is often a good place for a menu bar:
|
||||
egui::menu::bar(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
self.dark_light_mode_buttons(ui);
|
||||
egui::warn_if_debug_build(ui);
|
||||
if ui.button("Quit app").clicked() {
|
||||
states.run_in_bg = false;
|
||||
frame.close();
|
||||
}
|
||||
});
|
||||
|
||||
// Drag area
|
||||
@@ -35,9 +45,9 @@ impl RogApp {
|
||||
);
|
||||
// // Add the close button:
|
||||
// let close_response = ui.put(
|
||||
// Rect::from_min_size(titlebar_rect.right_top(),
|
||||
// Vec2::splat(height)),
|
||||
// Button::new(RichText::new("❌").size(height -
|
||||
// egui::Rect::from_min_size(titlebar_rect.right_top(),
|
||||
// egui::Vec2::splat(height)),
|
||||
// egui::Button::new(egui::RichText::new("❌").size(height -
|
||||
// 4.0)).frame(false), );
|
||||
// if close_response.clicked() {
|
||||
// frame.close();
|
||||
|
||||
Reference in New Issue
Block a user