RCC: add tray enable/disable, move app settings to page

This commit is contained in:
Luke D. Jones
2023-07-03 15:02:25 +12:00
parent 98dec6403c
commit 14d043bbc3
13 changed files with 152 additions and 73 deletions

View File

@@ -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.

View File

@@ -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),
};
}
}
}

View File

@@ -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,

View File

@@ -47,6 +47,7 @@ pub const SHOW_GUI: u8 = 2;
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum Page {
AppSettings,
System,
AuraEffects,
AnimeMatrix,

View File

@@ -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,
)?));

View 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);
});
});
})
});
}
}

View File

@@ -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::*;

View File

@@ -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);

View File

@@ -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,
}
}
}

View File

@@ -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
}

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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();