mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Advanced Aura feature
Groundwork for 'advanced' aura modes Add single zone + Doom light flash Fix mocking for ROGCC Better prepare & change to mapping of keyboard layouts to models and functions Refactor and begin using new key layout stuff Enable first arg to rogcc to set layout in mocking feature mode Complete refactor of key layouts, and to RON serde
This commit is contained in:
@@ -6,6 +6,7 @@ authors = ["Luke D. Jones <luke@ljones.dev>"]
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
#default = ["mocking"]
|
||||
mocking = []
|
||||
|
||||
[dependencies]
|
||||
@@ -23,6 +24,7 @@ rog_profiles = { path = "../rog-profiles" }
|
||||
rog_platform = { path = "../rog-platform" }
|
||||
supergfxctl = { git = "https://gitlab.com/asus-linux/supergfxctl.git", default-features = false }
|
||||
|
||||
gumdrop.workspace = true
|
||||
log.workspace = true
|
||||
env_logger.workspace = true
|
||||
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use std::{
|
||||
f64::consts::PI,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicU8, Ordering},
|
||||
Arc, Mutex,
|
||||
},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use std::f64::consts::PI;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use egui::{Button, RichText};
|
||||
use rog_aura::layouts::KeyLayout;
|
||||
use rog_platform::supported::SupportedFunctions;
|
||||
|
||||
use crate::{
|
||||
config::Config, error::Result, system_state::SystemState, Page, RogDbusClientBlocking,
|
||||
};
|
||||
use crate::config::Config;
|
||||
use crate::error::Result;
|
||||
use crate::system_state::SystemState;
|
||||
use crate::{Page, RogDbusClientBlocking};
|
||||
|
||||
pub struct RogApp {
|
||||
pub page: Page,
|
||||
@@ -103,8 +101,9 @@ impl RogApp {
|
||||
}
|
||||
|
||||
impl eframe::App for RogApp {
|
||||
/// Called each time the UI needs repainting, which may be many times per second.
|
||||
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
|
||||
/// Called each time the UI needs repainting, which may be many times per
|
||||
/// second. Put your widgets into a `SidePanel`, `TopPanel`,
|
||||
/// `CentralPanel`, `Window` or `Area`.
|
||||
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
|
||||
let states = self.states.clone();
|
||||
|
||||
@@ -115,6 +114,21 @@ impl eframe::App for RogApp {
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcut typical display stuff
|
||||
if let Ok(mut states) = states.try_lock() {
|
||||
let layout_testing = states.aura_creation.layout_testing.clone();
|
||||
if let Some(path) = &layout_testing {
|
||||
let modified = path.metadata().unwrap().modified().unwrap();
|
||||
if states.aura_creation.layout_last_modified < modified {
|
||||
states.aura_creation.layout_last_modified = modified;
|
||||
// time to reload the config
|
||||
states.aura_creation.keyboard_layout = KeyLayout::from_file(path).unwrap();
|
||||
}
|
||||
self.aura_page(&mut states, ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let page = self.page;
|
||||
|
||||
self.top_bar(ctx, frame);
|
||||
@@ -146,6 +160,7 @@ impl eframe::App for RogApp {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if !was_error {
|
||||
if let Ok(mut states) = states.try_lock() {
|
||||
if page == Page::System {
|
||||
|
||||
19
rog-control-center/src/cli_options.rs
Normal file
19
rog-control-center/src/cli_options.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use gumdrop::Options;
|
||||
|
||||
#[derive(Default, Options)]
|
||||
pub struct CliStart {
|
||||
#[options(help_flag, help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(help = "show program version number")]
|
||||
pub version: bool,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "set board name for testing, this will make ROGCC show only the keyboard page"
|
||||
)]
|
||||
pub board_name: Option<String>,
|
||||
#[options(
|
||||
help = "put ROGCC in layout viewing mode - this is helpful for finding existing layouts \
|
||||
that might match your laptop"
|
||||
)]
|
||||
pub layout_viewing: bool,
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::fs::{create_dir, OpenOptions};
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use log::{error, info, warn};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{
|
||||
fs::{create_dir, OpenOptions},
|
||||
io::{Read, Write},
|
||||
};
|
||||
|
||||
use crate::{error::Error, update_and_notify::EnabledNotifications};
|
||||
use crate::error::Error;
|
||||
use crate::update_and_notify::EnabledNotifications;
|
||||
|
||||
const CFG_DIR: &str = "rog";
|
||||
const CFG_FILE_NAME: &str = "rog-control-center.cfg";
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
pub mod app;
|
||||
use std::{
|
||||
fs::{remove_dir_all, File, OpenOptions},
|
||||
io::{Read, Write},
|
||||
process::exit,
|
||||
thread::sleep,
|
||||
time::Duration,
|
||||
};
|
||||
use std::fs::{remove_dir_all, File, OpenOptions};
|
||||
use std::io::{Read, Write};
|
||||
use std::process::exit;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
|
||||
pub use app::RogApp;
|
||||
|
||||
pub mod cli_options;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
#[cfg(feature = "mocking")]
|
||||
@@ -22,12 +21,12 @@ pub mod widgets;
|
||||
|
||||
#[cfg(feature = "mocking")]
|
||||
pub use mocking::RogDbusClientBlocking;
|
||||
use nix::sys::stat;
|
||||
use nix::unistd;
|
||||
#[cfg(not(feature = "mocking"))]
|
||||
pub use rog_dbus::RogDbusClientBlocking;
|
||||
|
||||
use nix::{sys::stat, unistd};
|
||||
use tempfile::TempDir;
|
||||
//use log::{error, info, warn};
|
||||
// use log::{error, info, warn};
|
||||
|
||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
use std::env::args;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use eframe::{IconData, NativeOptions};
|
||||
use log::{error, info};
|
||||
use gumdrop::Options;
|
||||
use log::{error, info, warn};
|
||||
use rog_aura::aura_detection::{LaptopLedData, LedSupportFile};
|
||||
use rog_aura::layouts::KeyLayout;
|
||||
use rog_control_center::cli_options::CliStart;
|
||||
use rog_control_center::config::Config;
|
||||
use rog_control_center::error::Result;
|
||||
use rog_control_center::startup_error::AppErrorShow;
|
||||
use rog_control_center::system_state::SystemState;
|
||||
use rog_control_center::tray::init_tray;
|
||||
use rog_control_center::update_and_notify::EnabledNotifications;
|
||||
use rog_control_center::update_and_notify::{start_notifications, EnabledNotifications};
|
||||
use rog_control_center::{
|
||||
config::Config, error::Result, get_ipc_file, on_tmp_dir_exists, print_versions,
|
||||
startup_error::AppErrorShow, system_state::SystemState, update_and_notify::start_notifications,
|
||||
RogApp, RogDbusClientBlocking, SHOWING_GUI, SHOW_GUI,
|
||||
get_ipc_file, on_tmp_dir_exists, print_versions, RogApp, RogDbusClientBlocking, SHOWING_GUI,
|
||||
SHOW_GUI,
|
||||
};
|
||||
use rog_platform::supported::SupportedFunctions;
|
||||
use std::sync::Mutex;
|
||||
use std::{
|
||||
fs::OpenOptions,
|
||||
io::{Read, Write},
|
||||
path::PathBuf,
|
||||
sync::Arc,
|
||||
};
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
#[cfg(not(feature = "mocking"))]
|
||||
@@ -26,7 +31,19 @@ const BOARD_NAME: &str = "/sys/class/dmi/id/board_name";
|
||||
const APP_ICON_PATH: &str = "/usr/share/icons/hicolor/512x512/apps/rog-control-center.png";
|
||||
|
||||
fn main() -> Result<()> {
|
||||
print_versions();
|
||||
let args: Vec<String> = args().skip(1).collect();
|
||||
|
||||
let parsed = match CliStart::parse_args_default(&args) {
|
||||
Ok(p) => p,
|
||||
Err(err) => {
|
||||
panic!("source {}", err);
|
||||
}
|
||||
};
|
||||
|
||||
if do_cli_help(&parsed) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut logger = env_logger::Builder::new();
|
||||
logger
|
||||
.parse_default_env()
|
||||
@@ -43,8 +60,8 @@ fn main() -> Result<()> {
|
||||
vsync: true,
|
||||
decorated: true,
|
||||
transparent: false,
|
||||
min_window_size: Some(egui::vec2(840.0, 600.0)),
|
||||
max_window_size: Some(egui::vec2(840.0, 600.0)),
|
||||
min_window_size: Some(egui::vec2(900.0, 600.0)),
|
||||
max_window_size: Some(egui::vec2(900.0, 600.0)),
|
||||
run_and_return: true,
|
||||
icon_data: Some(load_icon()),
|
||||
..Default::default()
|
||||
@@ -88,25 +105,66 @@ fn main() -> Result<()> {
|
||||
.read(true)
|
||||
.open(PathBuf::from(BOARD_NAME))
|
||||
.map_err(|e| {
|
||||
println!("{BOARD_NAME}, {e}");
|
||||
println!("DOH! {BOARD_NAME}, {e}");
|
||||
e
|
||||
})?;
|
||||
let mut board_name = String::new();
|
||||
file.read_to_string(&mut board_name)?;
|
||||
|
||||
#[cfg(feature = "mocking")]
|
||||
{
|
||||
board_name = "gl504".to_string();
|
||||
let mut led_support = LaptopLedData::get_data();
|
||||
|
||||
let mut path = PathBuf::from(DATA_DIR);
|
||||
let mut layout_name = None;
|
||||
let mut layouts = Vec::new();
|
||||
if parsed.board_name.is_some() || parsed.layout_viewing {
|
||||
path.pop();
|
||||
path.push("rog-aura");
|
||||
path.push("data");
|
||||
layouts = KeyLayout::layout_files(path.to_owned()).unwrap();
|
||||
|
||||
if let Some(name) = &parsed.board_name {
|
||||
if let Some(modes) = LedSupportFile::load_from_config() {
|
||||
if let Some(data) = modes.matcher(name) {
|
||||
led_support = data;
|
||||
}
|
||||
}
|
||||
board_name = name.to_owned();
|
||||
for layout in &layouts {
|
||||
if layout
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.contains(&led_support.layout_name.to_lowercase())
|
||||
{
|
||||
layout_name = Some(layout.to_owned());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
board_name = "GQ401QM".to_string()
|
||||
};
|
||||
|
||||
if parsed.layout_viewing {
|
||||
layout_name = Some(layouts[0].clone());
|
||||
board_name = layouts[0]
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.split_once('_')
|
||||
.unwrap()
|
||||
.0
|
||||
.to_owned();
|
||||
led_support.layout_name = board_name.clone();
|
||||
}
|
||||
}
|
||||
|
||||
let layout = KeyLayout::find_layout(board_name.as_str(), PathBuf::from(DATA_DIR))
|
||||
let layout = KeyLayout::find_layout(led_support, path)
|
||||
.map_err(|e| {
|
||||
println!("{BOARD_NAME}, {e}");
|
||||
println!("DERP! , {e}");
|
||||
})
|
||||
.unwrap_or_else(|_| KeyLayout::ga401_layout());
|
||||
.unwrap_or_else(|_| {
|
||||
warn!("Did not find a keyboard layout matching {board_name}");
|
||||
KeyLayout::default_layout()
|
||||
});
|
||||
|
||||
// tmp-dir must live to the end of program life
|
||||
let _tmp_dir = match tempfile::Builder::new()
|
||||
@@ -118,7 +176,14 @@ fn main() -> Result<()> {
|
||||
Err(_) => on_tmp_dir_exists().unwrap(),
|
||||
};
|
||||
|
||||
let states = setup_page_state_and_notifs(layout, enabled_notifications, &config, &supported)?;
|
||||
let states = setup_page_state_and_notifs(
|
||||
layout_name,
|
||||
layout,
|
||||
layouts,
|
||||
enabled_notifications,
|
||||
&config,
|
||||
&supported,
|
||||
)?;
|
||||
|
||||
init_tray(supported, states.clone());
|
||||
|
||||
@@ -128,7 +193,7 @@ fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
let config = Config::load()?;
|
||||
if !config.run_in_background {
|
||||
if !config.run_in_background || parsed.board_name.is_some() || parsed.layout_viewing {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -151,13 +216,17 @@ fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
fn setup_page_state_and_notifs(
|
||||
layout_testing: Option<PathBuf>,
|
||||
keyboard_layout: KeyLayout,
|
||||
keyboard_layouts: Vec<PathBuf>,
|
||||
enabled_notifications: Arc<Mutex<EnabledNotifications>>,
|
||||
config: &Config,
|
||||
supported: &SupportedFunctions,
|
||||
) -> Result<Arc<Mutex<SystemState>>> {
|
||||
let page_states = Arc::new(Mutex::new(SystemState::new(
|
||||
layout_testing,
|
||||
keyboard_layout,
|
||||
keyboard_layouts,
|
||||
enabled_notifications.clone(),
|
||||
supported,
|
||||
)?));
|
||||
@@ -216,3 +285,31 @@ fn load_icon() -> IconData {
|
||||
rgba,
|
||||
}
|
||||
}
|
||||
|
||||
fn do_cli_help(parsed: &CliStart) -> bool {
|
||||
if parsed.help {
|
||||
println!("{}", CliStart::usage());
|
||||
println!();
|
||||
if let Some(cmdlist) = CliStart::command_list() {
|
||||
let commands: Vec<String> = cmdlist.lines().map(|s| s.to_owned()).collect();
|
||||
for command in commands.iter() {
|
||||
println!("{}", command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if parsed.version {
|
||||
print_versions();
|
||||
println!();
|
||||
}
|
||||
|
||||
parsed.help
|
||||
}
|
||||
|
||||
pub fn get_layout_path(path: &Path, layout_name: &str) -> PathBuf {
|
||||
let mut data_path = PathBuf::from(path);
|
||||
let layout_file = format!("{}_US.ron", layout_name);
|
||||
data_path.push("layouts");
|
||||
data_path.push(layout_file);
|
||||
data_path
|
||||
}
|
||||
|
||||
@@ -1,35 +1,48 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use rog_aura::{
|
||||
usb::{AuraDev19b6, AuraDevice, AuraPowerDev},
|
||||
AuraEffect, AuraModeNum, AuraZone,
|
||||
};
|
||||
use rog_profiles::fan_curve_set::{CurveData, FanCurveSet};
|
||||
use rog_supported::{
|
||||
AnimeSupportedFunctions, ChargeSupportedFunctions, LedSupportedFunctions,
|
||||
use rog_aura::usb::{AuraDev19b6, AuraDevice, AuraPowerDev};
|
||||
use rog_aura::{AuraEffect, AuraModeNum, AuraZone};
|
||||
use rog_platform::platform::GpuMode;
|
||||
use rog_platform::supported::{
|
||||
AdvancedAura, AnimeSupportedFunctions, ChargeSupportedFunctions, LedSupportedFunctions,
|
||||
PlatformProfileFunctions, RogBiosSupportedFunctions, SupportedFunctions,
|
||||
};
|
||||
use rog_profiles::fan_curve_set::{CurveData, FanCurveSet};
|
||||
use supergfxctl::pci_device::{GfxMode, GfxPower};
|
||||
|
||||
use crate::error::Result;
|
||||
|
||||
const NOPE: &'static str = "";
|
||||
const NOPE: &str = "";
|
||||
|
||||
pub struct RogDbusClientBlocking<'a> {
|
||||
#[derive(Default)]
|
||||
pub struct DaemonProxyBlocking<'a> {
|
||||
_phantom: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Default for RogDbusClientBlocking<'a> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
impl<'a> DaemonProxyBlocking<'a> {
|
||||
pub fn new(_c: &bool) -> Result<Self> {
|
||||
Ok(Self { _phantom: NOPE })
|
||||
}
|
||||
|
||||
pub fn mode(&self) -> Result<GfxMode> {
|
||||
Ok(GfxMode::None)
|
||||
}
|
||||
|
||||
pub fn power(&self) -> Result<GfxPower> {
|
||||
Ok(GfxPower::Suspended)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RogDbusClientBlocking<'a> {
|
||||
_phantom: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> RogDbusClientBlocking<'a> {
|
||||
pub fn new() -> Result<(Self, bool)> {
|
||||
Ok((Self { _phantom: NOPE }, true))
|
||||
}
|
||||
|
||||
pub fn proxies(&self) -> Proxies {
|
||||
Proxies
|
||||
}
|
||||
@@ -40,18 +53,23 @@ impl Proxies {
|
||||
pub fn rog_bios(&self) -> Bios {
|
||||
Bios
|
||||
}
|
||||
|
||||
pub fn profile(&self) -> Profile {
|
||||
Profile
|
||||
}
|
||||
|
||||
pub fn led(&self) -> Led {
|
||||
Led
|
||||
}
|
||||
|
||||
pub fn anime(&self) -> Anime {
|
||||
Anime
|
||||
}
|
||||
|
||||
pub fn charge(&self) -> Profile {
|
||||
Profile
|
||||
}
|
||||
|
||||
pub fn supported(&self) -> Supported {
|
||||
Supported
|
||||
}
|
||||
@@ -62,18 +80,23 @@ impl Bios {
|
||||
pub fn post_boot_sound(&self) -> Result<i16> {
|
||||
Ok(1)
|
||||
}
|
||||
pub fn gpu_mux_mode(&self) -> Result<i16> {
|
||||
Ok(1)
|
||||
|
||||
pub fn gpu_mux_mode(&self) -> Result<GpuMode> {
|
||||
Ok(GpuMode::Optimus)
|
||||
}
|
||||
pub fn panel_od(&self) -> Result<i16> {
|
||||
Ok(1)
|
||||
|
||||
pub fn panel_od(&self) -> Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn set_post_boot_sound(&self, _b: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
pub fn set_gpu_mux_mode(&self, _b: bool) -> Result<()> {
|
||||
|
||||
pub fn set_gpu_mux_mode(&self, _b: GpuMode) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_panel_od(&self, _b: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
@@ -88,15 +111,18 @@ impl Profile {
|
||||
rog_profiles::Profile::Quiet,
|
||||
])
|
||||
}
|
||||
|
||||
pub fn active_profile(&self) -> Result<rog_profiles::Profile> {
|
||||
Ok(rog_profiles::Profile::Performance)
|
||||
}
|
||||
|
||||
pub fn enabled_fan_profiles(&self) -> Result<Vec<rog_profiles::Profile>> {
|
||||
Ok(vec![
|
||||
rog_profiles::Profile::Performance,
|
||||
rog_profiles::Profile::Balanced,
|
||||
])
|
||||
}
|
||||
|
||||
pub fn fan_curve_data(&self, _p: rog_profiles::Profile) -> Result<FanCurveSet> {
|
||||
let mut curve = FanCurveSet::default();
|
||||
curve.cpu.pwm = [30, 40, 60, 100, 140, 180, 200, 250];
|
||||
@@ -105,21 +131,34 @@ impl Profile {
|
||||
curve.gpu.temp = [20, 30, 40, 50, 70, 80, 90, 100];
|
||||
Ok(curve)
|
||||
}
|
||||
|
||||
pub fn set_fan_curve(&self, _p: rog_profiles::Profile, _c: CurveData) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_fan_curve_enabled(&self, _p: rog_profiles::Profile, _b: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
pub fn limit(&self) -> Result<i16> {
|
||||
|
||||
pub fn charge_control_end_threshold(&self) -> Result<u8> {
|
||||
Ok(66)
|
||||
}
|
||||
pub fn set_limit(&self, _l: u8) -> Result<()> {
|
||||
|
||||
pub fn set_charge_control_end_threshold(&self, _l: u8) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_active_profile(&self, _p: rog_profiles::Profile) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mains_online(&self) -> Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn reset_profile_curves(&self, _p: rog_profiles::Profile) -> Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Led;
|
||||
@@ -139,12 +178,15 @@ impl Led {
|
||||
data.insert(AuraModeNum::Pulse, AuraEffect::default());
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn led_mode(&self) -> Result<AuraModeNum> {
|
||||
Ok(AuraModeNum::Rainbow)
|
||||
}
|
||||
|
||||
pub fn led_brightness(&self) -> Result<i16> {
|
||||
Ok(1)
|
||||
}
|
||||
|
||||
pub fn leds_enabled(&self) -> Result<AuraPowerDev> {
|
||||
Ok(AuraPowerDev {
|
||||
tuf: vec![],
|
||||
@@ -157,9 +199,11 @@ impl Led {
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_leds_power(&self, _a: AuraPowerDev, _b: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_led_mode(&self, _a: &AuraEffect) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
@@ -170,12 +214,15 @@ impl Anime {
|
||||
pub fn boot_enabled(&self) -> Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn awake_enabled(&self) -> Result<bool> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn set_on_off(&self, _b: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_boot_on_off(&self, _b: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
@@ -194,16 +241,16 @@ impl Supported {
|
||||
fan_curves: true,
|
||||
},
|
||||
keyboard_led: LedSupportedFunctions {
|
||||
prod_id: AuraDevice::X19B6,
|
||||
brightness_set: true,
|
||||
stock_led_modes: vec![
|
||||
dev_id: AuraDevice::X19B6,
|
||||
brightness: true,
|
||||
basic_modes: vec![
|
||||
AuraModeNum::Rain,
|
||||
AuraModeNum::Rainbow,
|
||||
AuraModeNum::Star,
|
||||
AuraModeNum::Static,
|
||||
AuraModeNum::Strobe,
|
||||
],
|
||||
multizone_led_mode: vec![
|
||||
basic_zones: vec![
|
||||
AuraZone::Key1,
|
||||
AuraZone::Key2,
|
||||
AuraZone::Key3,
|
||||
@@ -212,12 +259,12 @@ impl Supported {
|
||||
AuraZone::BarRight,
|
||||
AuraZone::Logo,
|
||||
],
|
||||
per_key_led_mode: true,
|
||||
advanced_type: AdvancedAura::PerKey,
|
||||
},
|
||||
rog_bios_ctrl: RogBiosSupportedFunctions {
|
||||
post_sound: true,
|
||||
dedicated_gfx: true,
|
||||
panel_od: true,
|
||||
gpu_mux: true,
|
||||
panel_overdrive: true,
|
||||
dgpu_disable: true,
|
||||
egpu_enable: true,
|
||||
},
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use std::{sync::atomic::Ordering, time::Duration};
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::time::Duration;
|
||||
|
||||
use egui::Color32;
|
||||
use rog_aura::{AuraEffect, AuraModeNum};
|
||||
|
||||
use crate::{
|
||||
system_state::SystemState,
|
||||
widgets::{aura_modes_group, keyboard},
|
||||
RogApp,
|
||||
};
|
||||
use crate::system_state::SystemState;
|
||||
use crate::widgets::{aura_modes_group, keyboard};
|
||||
use crate::RogApp;
|
||||
|
||||
impl RogApp {
|
||||
pub fn aura_page(&mut self, states: &mut SystemState, ctx: &egui::Context) {
|
||||
let Self {
|
||||
supported,
|
||||
oscillator1,
|
||||
oscillator2,
|
||||
oscillator3,
|
||||
@@ -70,9 +68,13 @@ impl RogApp {
|
||||
|
||||
// TODO: animation of colour changes/periods/blending
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
aura_modes_group(supported, states, oscillator_freq, ui);
|
||||
|
||||
keyboard(ui, &states.keyboard_layout, &mut states.aura, colour);
|
||||
aura_modes_group(states, oscillator_freq, ui);
|
||||
keyboard(
|
||||
ui,
|
||||
&states.aura_creation.keyboard_layout,
|
||||
&mut states.aura,
|
||||
colour,
|
||||
);
|
||||
});
|
||||
|
||||
// Only do repaint request if on this page
|
||||
|
||||
@@ -1,28 +1,37 @@
|
||||
use crate::{
|
||||
system_state::{FanCurvesState, ProfilesState, SystemState},
|
||||
widgets::fan_graphs,
|
||||
RogApp, RogDbusClientBlocking,
|
||||
};
|
||||
use egui::Ui;
|
||||
use rog_platform::supported::SupportedFunctions;
|
||||
use rog_profiles::Profile;
|
||||
|
||||
use crate::system_state::{FanCurvesState, ProfilesState, SystemState};
|
||||
use crate::widgets::fan_graphs;
|
||||
use crate::{RogApp, RogDbusClientBlocking};
|
||||
|
||||
impl RogApp {
|
||||
pub fn fan_curve_page(&mut self, states: &mut SystemState, ctx: &egui::Context) {
|
||||
let Self { supported, .. } = self;
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("Custom fan curves");
|
||||
ui.label("A fan curve is only active when the related profile is active and the curve is enabled");
|
||||
ui.label(
|
||||
"A fan curve is only active when the related profile is active and the curve is \
|
||||
enabled",
|
||||
);
|
||||
Self::fan_curve(
|
||||
supported,
|
||||
&mut states.profiles,
|
||||
&mut states.fan_curves,
|
||||
&states.asus_dbus, &mut states.error,
|
||||
&states.asus_dbus,
|
||||
&mut states.error,
|
||||
ui,
|
||||
);
|
||||
|
||||
fan_graphs(supported, &mut states.fan_curves, &states.asus_dbus, &mut states.error, ui);
|
||||
fan_graphs(
|
||||
supported,
|
||||
&mut states.fan_curves,
|
||||
&states.asus_dbus,
|
||||
&mut states.error,
|
||||
ui,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use crate::{
|
||||
system_state::SystemState,
|
||||
widgets::{
|
||||
anime_power_group, app_settings, aura_power_group, platform_profile, rog_bios_group,
|
||||
},
|
||||
RogApp,
|
||||
use crate::system_state::SystemState;
|
||||
use crate::widgets::{
|
||||
anime_power_group, app_settings, 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) {
|
||||
@@ -21,7 +19,6 @@ impl RogApp {
|
||||
egui::Grid::new("grid_of_bits")
|
||||
.min_col_width(rect.width() / 2.0)
|
||||
.show(ui, |ui| {
|
||||
/******************************************************/
|
||||
ui.vertical(|ui| {
|
||||
ui.separator();
|
||||
if supported.platform_profile.platform_profile {
|
||||
@@ -34,7 +31,6 @@ impl RogApp {
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
/******************************************************/
|
||||
ui.vertical(|ui| {
|
||||
ui.separator();
|
||||
app_settings(config, states, ui);
|
||||
@@ -45,7 +41,6 @@ impl RogApp {
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
/******************************************************/
|
||||
ui.vertical(|ui| {
|
||||
ui.separator();
|
||||
if supported.anime_ctrl.0 {
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
use std::{
|
||||
collections::{BTreeMap, HashSet},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::SystemTime;
|
||||
|
||||
use egui::Vec2;
|
||||
use rog_aura::{layouts::KeyLayout, usb::AuraPowerDev, AuraEffect, AuraModeNum};
|
||||
use rog_platform::{platform::GpuMode, supported::SupportedFunctions};
|
||||
use rog_profiles::{fan_curve_set::FanCurveSet, FanCurvePU, Profile};
|
||||
use supergfxctl::{
|
||||
pci_device::{GfxMode, GfxPower},
|
||||
zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking,
|
||||
};
|
||||
|
||||
use crate::{error::Result, update_and_notify::EnabledNotifications, RogDbusClientBlocking};
|
||||
use log::error;
|
||||
use rog_aura::layouts::KeyLayout;
|
||||
use rog_aura::usb::AuraPowerDev;
|
||||
use rog_aura::{AuraEffect, AuraModeNum};
|
||||
use rog_platform::platform::GpuMode;
|
||||
use rog_platform::supported::SupportedFunctions;
|
||||
use rog_profiles::fan_curve_set::FanCurveSet;
|
||||
use rog_profiles::{FanCurvePU, Profile};
|
||||
use supergfxctl::pci_device::{GfxMode, GfxPower};
|
||||
#[cfg(not(feature = "mocking"))]
|
||||
use supergfxctl::zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking;
|
||||
|
||||
use crate::error::Result;
|
||||
#[cfg(feature = "mocking")]
|
||||
use crate::mocking::DaemonProxyBlocking as GfxProxyBlocking;
|
||||
use crate::update_and_notify::EnabledNotifications;
|
||||
use crate::RogDbusClientBlocking;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct BiosState {
|
||||
@@ -149,25 +156,21 @@ pub struct AuraState {
|
||||
}
|
||||
|
||||
impl AuraState {
|
||||
pub fn new(supported: &SupportedFunctions, dbus: &RogDbusClientBlocking<'_>) -> Result<Self> {
|
||||
pub fn new(layout: &KeyLayout, dbus: &RogDbusClientBlocking<'_>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
current_mode: if !supported.keyboard_led.stock_led_modes.is_empty() {
|
||||
current_mode: if !layout.basic_modes().is_empty() {
|
||||
dbus.proxies().led().led_mode().unwrap_or_default()
|
||||
} else {
|
||||
AuraModeNum::Static
|
||||
},
|
||||
|
||||
modes: if !supported.keyboard_led.stock_led_modes.is_empty() {
|
||||
modes: if !layout.basic_modes().is_empty() {
|
||||
dbus.proxies().led().led_modes().unwrap_or_default()
|
||||
} else {
|
||||
BTreeMap::new()
|
||||
},
|
||||
enabled: dbus.proxies().led().leds_enabled().unwrap_or_default(),
|
||||
bright: if !supported.keyboard_led.brightness_set {
|
||||
dbus.proxies().led().led_brightness().unwrap_or_default()
|
||||
} else {
|
||||
2
|
||||
},
|
||||
bright: dbus.proxies().led().led_brightness().unwrap_or_default(),
|
||||
wave_red: [0u8; 22],
|
||||
wave_green: [0u8; 22],
|
||||
wave_blue: [0u8; 22],
|
||||
@@ -259,13 +262,42 @@ impl PowerState {
|
||||
}
|
||||
}
|
||||
|
||||
/// State stored from system daemons. This is shared with: tray, zbus notifications thread
|
||||
/// and the GUI app thread.
|
||||
pub struct SystemState {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AuraCreation {
|
||||
/// Specifically for testing the development of keyboard layouts (combined
|
||||
/// with `--layout-name` CLI option)
|
||||
pub layout_testing: Option<PathBuf>,
|
||||
pub layout_last_modified: SystemTime,
|
||||
pub keyboard_layout: KeyLayout,
|
||||
pub keyboard_layouts: Vec<PathBuf>,
|
||||
/// current index in to `self.keyboard_layouts`
|
||||
pub keyboard_layout_index: usize,
|
||||
}
|
||||
|
||||
impl AuraCreation {
|
||||
pub fn new(
|
||||
layout_testing: Option<PathBuf>,
|
||||
keyboard_layout: KeyLayout,
|
||||
keyboard_layouts: Vec<PathBuf>,
|
||||
) -> Self {
|
||||
Self {
|
||||
layout_testing,
|
||||
layout_last_modified: SystemTime::now(),
|
||||
keyboard_layout,
|
||||
keyboard_layouts,
|
||||
keyboard_layout_index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State stored from system daemons. This is shared with: tray, zbus
|
||||
/// notifications thread and the GUI app thread.
|
||||
pub struct SystemState {
|
||||
pub aura_creation: AuraCreation,
|
||||
//--
|
||||
pub enabled_notifications: Arc<Mutex<EnabledNotifications>>,
|
||||
/// Because much of the app state here is the same as `RogBiosSupportedFunctions`
|
||||
/// we can re-use that structure.
|
||||
/// Because much of the app state here is the same as
|
||||
/// `RogBiosSupportedFunctions` we can re-use that structure.
|
||||
pub bios: BiosState,
|
||||
pub aura: AuraState,
|
||||
pub anime: AnimeState,
|
||||
@@ -274,8 +306,8 @@ pub struct SystemState {
|
||||
pub gfx_state: GfxState,
|
||||
pub power_state: PowerState,
|
||||
pub error: Option<String>,
|
||||
/// 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.
|
||||
/// 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 asus_dbus: RogDbusClientBlocking<'static>,
|
||||
@@ -283,17 +315,28 @@ pub struct SystemState {
|
||||
}
|
||||
|
||||
impl SystemState {
|
||||
/// Creates self, including the relevant dbus connections and proixies for internal use
|
||||
/// Creates self, including the relevant dbus connections and proixies for
|
||||
/// internal use
|
||||
pub fn new(
|
||||
layout_testing: Option<PathBuf>,
|
||||
keyboard_layout: KeyLayout,
|
||||
keyboard_layouts: Vec<PathBuf>,
|
||||
enabled_notifications: Arc<Mutex<EnabledNotifications>>,
|
||||
supported: &SupportedFunctions,
|
||||
) -> Result<Self> {
|
||||
let (asus_dbus, conn) = RogDbusClientBlocking::new()?;
|
||||
let mut error = None;
|
||||
let gfx_dbus = GfxProxyBlocking::new(&conn).expect("Couldn't connect to supergfxd");
|
||||
let aura = AuraState::new(&keyboard_layout, &asus_dbus)
|
||||
.map_err(|e| {
|
||||
let e = format!("Could not get AuraState state: {e}");
|
||||
error!("{e}");
|
||||
error = Some(e);
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(Self {
|
||||
keyboard_layout,
|
||||
aura_creation: AuraCreation::new(layout_testing, keyboard_layout, keyboard_layouts),
|
||||
enabled_notifications,
|
||||
power_state: PowerState::new(supported, &asus_dbus)
|
||||
.map_err(|e| {
|
||||
@@ -309,13 +352,7 @@ impl SystemState {
|
||||
error = Some(e);
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
aura: AuraState::new(supported, &asus_dbus)
|
||||
.map_err(|e| {
|
||||
let e = format!("Could not get AuraState state: {e}");
|
||||
error!("{e}");
|
||||
error = Some(e);
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
aura,
|
||||
anime: AnimeState::new(supported, &asus_dbus)
|
||||
.map_err(|e| {
|
||||
let e = format!("Could not get AanimeState state: {e}");
|
||||
@@ -364,7 +401,13 @@ impl Default for SystemState {
|
||||
let gfx_dbus = GfxProxyBlocking::new(&conn).expect("Couldn't connect to supergfxd");
|
||||
|
||||
Self {
|
||||
keyboard_layout: KeyLayout::ga401_layout(),
|
||||
aura_creation: AuraCreation {
|
||||
layout_testing: None,
|
||||
layout_last_modified: SystemTime::now(),
|
||||
keyboard_layout: KeyLayout::default_layout(),
|
||||
keyboard_layouts: Default::default(),
|
||||
keyboard_layout_index: 0,
|
||||
},
|
||||
enabled_notifications: Default::default(),
|
||||
bios: BiosState {
|
||||
post_sound: Default::default(),
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
//! A seld-contained tray icon with menus. The control of app<->tray is done via
|
||||
//! commands over an MPSC channel.
|
||||
|
||||
use std::{
|
||||
io::Write,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc::{channel, Receiver},
|
||||
Arc, Mutex,
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
use std::io::Write;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use gtk::{gio::Icon, prelude::*};
|
||||
use rog_dbus::zbus_platform::RogBiosProxyBlocking;
|
||||
use rog_platform::{platform::GpuMode, supported::SupportedFunctions};
|
||||
|
||||
use crate::{error::Result, get_ipc_file, system_state::SystemState, SHOW_GUI};
|
||||
use gtk::gio::Icon;
|
||||
use gtk::prelude::*;
|
||||
use libappindicator::{AppIndicator, AppIndicatorStatus};
|
||||
use supergfxctl::{
|
||||
pci_device::{GfxMode, GfxPower},
|
||||
zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking,
|
||||
};
|
||||
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use rog_dbus::zbus_platform::RogBiosProxyBlocking;
|
||||
use rog_platform::platform::GpuMode;
|
||||
use rog_platform::supported::SupportedFunctions;
|
||||
use supergfxctl::pci_device::{GfxMode, GfxPower};
|
||||
use supergfxctl::zbus_proxy::DaemonProxyBlocking as GfxProxyBlocking;
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::system_state::SystemState;
|
||||
use crate::{get_ipc_file, SHOW_GUI};
|
||||
|
||||
const TRAY_APP_ICON: &str = "rog-control-center";
|
||||
const TRAY_LABEL: &str = "ROG Control Center";
|
||||
@@ -433,7 +430,8 @@ impl ROGTray {
|
||||
debug!("ROGTray: cleared self");
|
||||
}
|
||||
|
||||
/// Reset GTK menu to internal state, this can be called after clearing and rebuilding the menu too.
|
||||
/// Reset GTK menu to internal state, this can be called after clearing and
|
||||
/// rebuilding the menu too.
|
||||
fn menu_update(&mut self) {
|
||||
self.tray.set_menu(&mut self.menu);
|
||||
self.set_icon(self.icon);
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
//! `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.
|
||||
//! `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.
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::process::Command;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::{config::Config, error::Result, system_state::SystemState};
|
||||
use log::{error, info, trace, warn};
|
||||
use notify_rust::{Hint, Notification, NotificationHandle, Urgency};
|
||||
use rog_dbus::{
|
||||
zbus_anime::AnimeProxy, zbus_led::LedProxy, zbus_platform::RogBiosProxy,
|
||||
zbus_power::PowerProxy, zbus_profile::ProfileProxy,
|
||||
};
|
||||
use rog_dbus::zbus_anime::AnimeProxy;
|
||||
use rog_dbus::zbus_led::LedProxy;
|
||||
use rog_dbus::zbus_platform::RogBiosProxy;
|
||||
use rog_dbus::zbus_power::PowerProxy;
|
||||
use rog_dbus::zbus_profile::ProfileProxy;
|
||||
use rog_platform::platform::GpuMode;
|
||||
use rog_profiles::Profile;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
fmt::Display,
|
||||
process::Command,
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
use supergfxctl::{pci_device::GfxPower, zbus_proxy::DaemonProxy as SuperProxy};
|
||||
use supergfxctl::pci_device::GfxPower;
|
||||
use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy;
|
||||
use tokio::time::sleep;
|
||||
use zbus::export::futures_util::{future, 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<Command> = None;
|
||||
@@ -356,7 +360,8 @@ pub fn start_notifications(
|
||||
if status != GfxPower::Unknown && status != last_status {
|
||||
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
|
||||
// Required check because status cycles through
|
||||
// active/unknown/suspended
|
||||
if let Ok(ref mut lock) = last_notif.lock() {
|
||||
notify!(
|
||||
do_gpu_status_notif(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use egui::Ui;
|
||||
|
||||
use crate::{config::Config, system_state::SystemState};
|
||||
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");
|
||||
|
||||
@@ -1,42 +1,41 @@
|
||||
use std::sync::{
|
||||
atomic::{AtomicU8, Ordering},
|
||||
Arc,
|
||||
};
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use egui::{RichText, Ui};
|
||||
use rog_aura::layouts::KeyLayout;
|
||||
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour, Speed};
|
||||
use rog_platform::supported::SupportedFunctions;
|
||||
|
||||
use crate::system_state::{AuraState, SystemState};
|
||||
|
||||
pub fn aura_modes_group(
|
||||
supported: &SupportedFunctions,
|
||||
states: &mut SystemState,
|
||||
freq: &mut Arc<AtomicU8>,
|
||||
ui: &mut Ui,
|
||||
) {
|
||||
pub fn aura_modes_group(states: &mut SystemState, freq: &mut Arc<AtomicU8>, ui: &mut Ui) {
|
||||
let mut changed = false;
|
||||
let mut selected = states.aura.current_mode;
|
||||
let allowed = AuraEffect::allowed_parameters(selected);
|
||||
|
||||
let has_keyzones = supported
|
||||
.keyboard_led
|
||||
.multizone_led_mode
|
||||
let SystemState { aura_creation, .. } = states;
|
||||
|
||||
let has_keyzones = aura_creation
|
||||
.keyboard_layout
|
||||
.basic_zones()
|
||||
.contains(&AuraZone::Key2);
|
||||
let has_logo = supported
|
||||
.keyboard_led
|
||||
.multizone_led_mode
|
||||
let has_logo = aura_creation
|
||||
.keyboard_layout
|
||||
.basic_zones()
|
||||
.contains(&AuraZone::Logo);
|
||||
let has_lightbar = supported
|
||||
.keyboard_led
|
||||
.multizone_led_mode
|
||||
let has_lightbar = aura_creation
|
||||
.keyboard_layout
|
||||
.basic_zones()
|
||||
.contains(&AuraZone::BarLeft)
|
||||
|| supported
|
||||
.keyboard_led
|
||||
.multizone_led_mode
|
||||
|| aura_creation
|
||||
.keyboard_layout
|
||||
.basic_zones()
|
||||
.contains(&AuraZone::BarRight);
|
||||
|
||||
ui.heading("Aura modes");
|
||||
if let Some(p) = aura_creation.layout_testing.as_ref() {
|
||||
ui.heading(format!("{p:?}"));
|
||||
} else {
|
||||
ui.heading("Aura modes");
|
||||
}
|
||||
let mut item = |a: AuraModeNum, ui: &mut Ui| {
|
||||
if ui
|
||||
.selectable_value(&mut selected, a, format!("{:?}", a))
|
||||
@@ -168,7 +167,7 @@ pub fn aura_modes_group(
|
||||
ui.separator();
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
|
||||
if ui.add(egui::Button::new("Cancel")).clicked() {
|
||||
match AuraState::new(supported, &states.asus_dbus) {
|
||||
match AuraState::new(&aura_creation.keyboard_layout, &states.asus_dbus) {
|
||||
Ok(a) => states.aura.modes = a.modes,
|
||||
Err(e) => states.error = Some(e.to_string()),
|
||||
}
|
||||
@@ -177,6 +176,32 @@ pub fn aura_modes_group(
|
||||
if ui.add(egui::Button::new("Apply")).clicked() {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if aura_creation.layout_testing.is_some() {
|
||||
if ui.add(egui::Button::new("Next layout")).clicked() {
|
||||
if aura_creation.keyboard_layout_index < aura_creation.keyboard_layouts.len() - 1 {
|
||||
aura_creation.keyboard_layout_index += 1;
|
||||
}
|
||||
aura_creation.layout_testing = Some(
|
||||
aura_creation.keyboard_layouts[aura_creation.keyboard_layout_index].clone(),
|
||||
);
|
||||
aura_creation.keyboard_layout =
|
||||
KeyLayout::from_file(aura_creation.layout_testing.as_ref().unwrap().as_path())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if ui.add(egui::Button::new("Prev layout")).clicked() {
|
||||
if aura_creation.keyboard_layout_index > 0 {
|
||||
aura_creation.keyboard_layout_index -= 1;
|
||||
}
|
||||
aura_creation.layout_testing = Some(
|
||||
aura_creation.keyboard_layouts[aura_creation.keyboard_layout_index].clone(),
|
||||
);
|
||||
aura_creation.keyboard_layout =
|
||||
KeyLayout::from_file(aura_creation.layout_testing.as_ref().unwrap().as_path())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// egui::TopBottomPanel::bottom("error_bar")
|
||||
@@ -185,8 +210,8 @@ pub fn aura_modes_group(
|
||||
// ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
|
||||
// if ui.add(egui::Button::new("Cancel")).clicked() {
|
||||
// let notif = states.aura.was_notified.clone();
|
||||
// states.aura.modes = AuraState::new(notif, supported, dbus).modes;
|
||||
// }
|
||||
// states.aura.modes = AuraState::new(notif, supported,
|
||||
// dbus).modes; }
|
||||
|
||||
// if ui.add(egui::Button::new("Apply")).clicked() {
|
||||
// changed = true;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use egui::{RichText, Ui};
|
||||
use rog_aura::{
|
||||
usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev},
|
||||
AuraZone,
|
||||
};
|
||||
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev};
|
||||
use rog_aura::AuraZone;
|
||||
use rog_platform::supported::SupportedFunctions;
|
||||
|
||||
use crate::system_state::SystemState;
|
||||
@@ -10,7 +8,7 @@ use crate::system_state::SystemState;
|
||||
pub fn aura_power_group(supported: &SupportedFunctions, states: &mut SystemState, ui: &mut Ui) {
|
||||
ui.heading("LED settings");
|
||||
|
||||
match supported.keyboard_led.prod_id {
|
||||
match supported.keyboard_led.dev_id {
|
||||
AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866 => {
|
||||
aura_power1(supported, states, ui);
|
||||
}
|
||||
@@ -26,7 +24,7 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
|
||||
let mut sleep = enabled_states.x1866.contains(&AuraDev1866::Sleep);
|
||||
let mut keyboard = enabled_states.x1866.contains(&AuraDev1866::Keyboard);
|
||||
let mut lightbar = enabled_states.x1866.contains(&AuraDev1866::Lightbar);
|
||||
if supported.keyboard_led.prod_id == AuraDevice::Tuf {
|
||||
if supported.keyboard_led.dev_id == AuraDevice::Tuf {
|
||||
boot = enabled_states.tuf.contains(&AuraDevTuf::Boot);
|
||||
sleep = enabled_states.tuf.contains(&AuraDevTuf::Sleep);
|
||||
keyboard = enabled_states.tuf.contains(&AuraDevTuf::Awake);
|
||||
@@ -63,7 +61,7 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
|
||||
if ui.toggle_value(&mut keyboard, "Keyboard").changed() {
|
||||
changed = true;
|
||||
}
|
||||
if !supported.keyboard_led.multizone_led_mode.is_empty()
|
||||
if !supported.keyboard_led.basic_zones.is_empty()
|
||||
&& ui.toggle_value(&mut lightbar, "Lightbar").changed()
|
||||
{
|
||||
changed = true;
|
||||
@@ -84,8 +82,8 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
|
||||
// ))
|
||||
// .changed()
|
||||
// {
|
||||
// let bright = LedBrightness::from(states.aura.bright as u32);
|
||||
// dbus.proxies()
|
||||
// let bright = LedBrightness::from(states.aura.bright as
|
||||
// u32); dbus.proxies()
|
||||
// .led()
|
||||
// .set_brightness(bright)
|
||||
// .map_err(|err| {
|
||||
@@ -98,7 +96,7 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
|
||||
});
|
||||
|
||||
if changed {
|
||||
if supported.keyboard_led.prod_id == AuraDevice::Tuf {
|
||||
if supported.keyboard_led.dev_id == AuraDevice::Tuf {
|
||||
let mut enabled = Vec::new();
|
||||
let mut disabled = Vec::new();
|
||||
|
||||
@@ -174,7 +172,7 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
|
||||
modify_x1866(boot, AuraDev1866::Boot);
|
||||
modify_x1866(sleep, AuraDev1866::Sleep);
|
||||
modify_x1866(keyboard, AuraDev1866::Keyboard);
|
||||
if !supported.keyboard_led.multizone_led_mode.is_empty() {
|
||||
if !supported.keyboard_led.basic_zones.is_empty() {
|
||||
modify_x1866(lightbar, AuraDev1866::Lightbar);
|
||||
}
|
||||
|
||||
@@ -203,17 +201,14 @@ fn aura_power1(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
|
||||
|
||||
fn aura_power2(supported: &SupportedFunctions, states: &mut SystemState, ui: &mut Ui) {
|
||||
let enabled_states = &mut states.aura.enabled;
|
||||
let has_logo = supported
|
||||
.keyboard_led
|
||||
.multizone_led_mode
|
||||
.contains(&AuraZone::Logo);
|
||||
let has_logo = supported.keyboard_led.basic_zones.contains(&AuraZone::Logo);
|
||||
let has_lightbar = supported
|
||||
.keyboard_led
|
||||
.multizone_led_mode
|
||||
.basic_zones
|
||||
.contains(&AuraZone::BarLeft)
|
||||
|| supported
|
||||
.keyboard_led
|
||||
.multizone_led_mode
|
||||
.basic_zones
|
||||
.contains(&AuraZone::BarRight);
|
||||
|
||||
let boot_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeBar);
|
||||
@@ -294,18 +289,14 @@ fn aura_power2(supported: &SupportedFunctions, states: &mut SystemState, ui: &mu
|
||||
modify(*boot_keyb, AuraDev19b6::BootKeyb);
|
||||
modify(*sleep_keyb, AuraDev19b6::SleepKeyb);
|
||||
modify(*awake_keyb, AuraDev19b6::AwakeKeyb);
|
||||
if supported
|
||||
.keyboard_led
|
||||
.multizone_led_mode
|
||||
.contains(&AuraZone::Logo)
|
||||
{
|
||||
if supported.keyboard_led.basic_zones.contains(&AuraZone::Logo) {
|
||||
modify(*boot_logo, AuraDev19b6::BootLogo);
|
||||
modify(*sleep_logo, AuraDev19b6::SleepLogo);
|
||||
modify(*awake_logo, AuraDev19b6::AwakeLogo);
|
||||
}
|
||||
if supported
|
||||
.keyboard_led
|
||||
.multizone_led_mode
|
||||
.basic_zones
|
||||
.contains(&AuraZone::BarLeft)
|
||||
{
|
||||
modify(*boot_bar, AuraDev19b6::AwakeBar);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use egui::{plot::Points, Ui};
|
||||
use egui::plot::Points;
|
||||
use egui::Ui;
|
||||
use rog_platform::supported::SupportedFunctions;
|
||||
use rog_profiles::{FanCurvePU, Profile};
|
||||
|
||||
use crate::{system_state::FanCurvesState, RogDbusClientBlocking};
|
||||
use crate::system_state::FanCurvesState;
|
||||
use crate::RogDbusClientBlocking;
|
||||
|
||||
pub fn fan_graphs(
|
||||
supported: &SupportedFunctions,
|
||||
|
||||
@@ -1,59 +1,152 @@
|
||||
use egui::{Align, Color32, Vec2};
|
||||
use rog_aura::{keys::KeyShape, layouts::KeyLayout, AuraModeNum};
|
||||
use egui::{Color32, Pos2};
|
||||
use rog_aura::advanced::LedCode;
|
||||
use rog_aura::layouts::{KeyLayout, KeyShape};
|
||||
use rog_aura::{AdvancedAuraType, AuraModeNum};
|
||||
|
||||
use crate::system_state::AuraState;
|
||||
|
||||
const SCALE: f32 = 2.0;
|
||||
|
||||
// TODO:
|
||||
// - Multizone: draw regions? While iterating keys check if located in one of
|
||||
// the 4 regions and mark
|
||||
// - Tab for advanced effects
|
||||
// - Keys need to select colour themselves
|
||||
|
||||
pub fn keyboard(
|
||||
ui: &mut egui::Ui,
|
||||
keyboard_layout: &KeyLayout,
|
||||
states: &mut AuraState,
|
||||
mut colour: Color32,
|
||||
colour: Color32,
|
||||
) {
|
||||
let mut key_colour = colour;
|
||||
let mut input_colour = colour;
|
||||
let (keyboard_is_multizoned, keyboard_width, keyboard_is_per_key) =
|
||||
match keyboard_layout.advanced_type() {
|
||||
AdvancedAuraType::PerKey => (false, 0.0, true),
|
||||
AdvancedAuraType::None => (false, keyboard_layout.max_width(), false),
|
||||
AdvancedAuraType::Zoned(zones) => {
|
||||
let width = if let Some(row) = keyboard_layout.rows_ref().get(2) {
|
||||
row.width() as f32
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
(!zones.contains(&LedCode::SingleZone), width, false)
|
||||
}
|
||||
};
|
||||
let mut start_pos = None;
|
||||
|
||||
let y = ui.spacing().interact_size.y;
|
||||
let this_size = ui.available_size();
|
||||
let keys_width = keyboard_layout.max_width() * SCALE * y;
|
||||
let keys_height = keyboard_layout.max_height() * SCALE * y;
|
||||
let x_start = (this_size.x - keys_width) / SCALE;
|
||||
let y_start = (this_size.y - keys_height) / SCALE;
|
||||
|
||||
ui.spacing_mut().item_spacing = egui::vec2(0.0, 0.0);
|
||||
let mut arrows_done = false;
|
||||
let mut rog_done = false;
|
||||
blank(ui, 0.0, y_start / y);
|
||||
// Need to exclude the lightbar row if there is one
|
||||
let mut keyboard_height = 0.0;
|
||||
for row in keyboard_layout.rows() {
|
||||
ui.horizontal_top(|ui| {
|
||||
blank(ui, x_start / y, 0.0);
|
||||
for (i, key) in row.row().enumerate() {
|
||||
if !key.0.is_lightbar_zone() && i == 0 {
|
||||
keyboard_height += row.height() as f32 * SCALE;
|
||||
}
|
||||
if states.current_mode == AuraModeNum::Rainbow {
|
||||
colour = Color32::from_rgb(
|
||||
key_colour = Color32::from_rgb(
|
||||
(states.wave_red[i] as u32 * 255 / 100) as u8,
|
||||
(states.wave_green[i] as u32 * 255 / 100) as u8,
|
||||
(states.wave_blue[i] as u32 * 255 / 100) as u8,
|
||||
);
|
||||
}
|
||||
// your boat
|
||||
let height = if rog_done {
|
||||
row.height()
|
||||
} else {
|
||||
// Use the first item (always a blank) to stand off the row
|
||||
rog_done = true;
|
||||
1.2
|
||||
};
|
||||
let shape = KeyShape::from(key);
|
||||
if (keyboard_is_multizoned && !key.0.is_lightbar_zone())
|
||||
&& states.current_mode == AuraModeNum::Rainbow
|
||||
{
|
||||
input_colour = key_colour;
|
||||
key_colour = Color32::TRANSPARENT;
|
||||
}
|
||||
|
||||
let label = <&str>::from(key);
|
||||
if shape.is_arrow_cluster() {
|
||||
if !arrows_done {
|
||||
arrow_cluster(ui, colour);
|
||||
arrows_done = true;
|
||||
let label = <&str>::from(key.0);
|
||||
let mut shape = key.1.clone();
|
||||
shape.scale(SCALE);
|
||||
|
||||
match shape {
|
||||
KeyShape::Led {
|
||||
width,
|
||||
height,
|
||||
pad_left,
|
||||
pad_right,
|
||||
pad_top,
|
||||
pad_bottom,
|
||||
} => {
|
||||
let (pos, response) = key_shape(
|
||||
ui, key_colour, width, height, pad_left, pad_right, pad_top, pad_bottom,
|
||||
);
|
||||
if start_pos.is_none() {
|
||||
start_pos = Some(pos);
|
||||
} else if let Some(old_pos) = start_pos.as_mut() {
|
||||
if !key.0.is_lightbar_zone() {
|
||||
if pos.x < old_pos.x {
|
||||
old_pos.x = pos.x;
|
||||
}
|
||||
if pos.y < old_pos.y {
|
||||
old_pos.y = pos.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
if response.on_hover_text(label).clicked() && keyboard_is_per_key {
|
||||
// TODO: set an effect on the LedCode
|
||||
}
|
||||
}
|
||||
KeyShape::Blank { width, height } => {
|
||||
blank(ui, width, height);
|
||||
}
|
||||
} else if shape.is_blank() || shape.is_spacer() {
|
||||
blank(ui, shape.width(), height);
|
||||
} else if shape.is_group() {
|
||||
key_group(ui, colour, shape.width(), height).on_hover_text(label);
|
||||
} else {
|
||||
key_shape(ui, colour, shape.width(), height).on_hover_text(label);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if keyboard_is_multizoned {
|
||||
let zone_width = keyboard_width * SCALE / 4.0 - 0.1;
|
||||
for n in 0..4 {
|
||||
if states.current_mode == AuraModeNum::Rainbow {
|
||||
input_colour = Color32::from_rgba_unmultiplied(
|
||||
(states.wave_red[n] as u32 * 255 / 100) as u8,
|
||||
(states.wave_green[n] as u32 * 255 / 100) as u8,
|
||||
(states.wave_blue[n] as u32 * 255 / 100) as u8,
|
||||
70,
|
||||
);
|
||||
}
|
||||
if let Some(mut pos) = start_pos {
|
||||
pos.x += n as f32 * zone_width * y;
|
||||
let response = zone_shape(ui, input_colour, pos, zone_width, keyboard_height);
|
||||
let label = format!("Zone {}", 1 + n);
|
||||
if response.on_hover_text(label).clicked() {
|
||||
// TODO: set an effect on the zone
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn key_shape(ui: &mut egui::Ui, colour: Color32, ux: f32, uy: f32) -> egui::Response {
|
||||
let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0 * ux, 2.0 * uy);
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn key_shape(
|
||||
ui: &mut egui::Ui,
|
||||
colour: Color32,
|
||||
width: f32,
|
||||
height: f32,
|
||||
pad_left: f32,
|
||||
pad_right: f32,
|
||||
pad_top: f32,
|
||||
pad_bottom: f32,
|
||||
) -> (egui::Pos2, egui::Response) {
|
||||
// First, get some space
|
||||
let y = ui.spacing().interact_size.y;
|
||||
let desired_size = y * egui::vec2(width + pad_left + pad_right, height + pad_top + pad_bottom);
|
||||
let (mut rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click());
|
||||
rect = rect.shrink(3.0);
|
||||
// rect = rect.shrink(3.0);
|
||||
if response.clicked() {
|
||||
response.mark_changed();
|
||||
}
|
||||
@@ -62,62 +155,56 @@ fn key_shape(ui: &mut egui::Ui, colour: Color32, ux: f32, uy: f32) -> egui::Resp
|
||||
});
|
||||
|
||||
if ui.is_rect_visible(rect) {
|
||||
// Now set the actual visible rect
|
||||
let visuals = ui.style().interact_selectable(&response, true);
|
||||
let rect = rect.expand(visuals.expansion);
|
||||
let size = y * egui::vec2(width, height);
|
||||
rect.set_width(size.x);
|
||||
rect.set_height(size.y);
|
||||
let center = Pos2::new(
|
||||
rect.center().x + pad_left * y,
|
||||
rect.center().y + pad_top * y,
|
||||
);
|
||||
rect.set_center(center);
|
||||
// let rect = rect.expand(visuals.expansion);
|
||||
ui.painter().rect(rect, 0.1, colour, visuals.fg_stroke);
|
||||
}
|
||||
|
||||
(rect.left_top(), response)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn zone_shape(
|
||||
ui: &mut egui::Ui,
|
||||
mut colour: Color32,
|
||||
pos: Pos2,
|
||||
width: f32,
|
||||
height: f32,
|
||||
) -> egui::Response {
|
||||
// First, get some space
|
||||
let y = ui.spacing().interact_size.y;
|
||||
let desired_size = y * egui::vec2(width, height);
|
||||
let rect = egui::Rect::from_min_size(pos, desired_size);
|
||||
let mut response = ui.allocate_rect(rect, egui::Sense::click());
|
||||
// rect = rect.shrink(3.0);
|
||||
if response.clicked() {
|
||||
response.mark_changed();
|
||||
}
|
||||
response.widget_info(|| {
|
||||
egui::WidgetInfo::selected(egui::WidgetType::Checkbox, response.clicked(), "")
|
||||
});
|
||||
|
||||
if ui.is_rect_visible(rect) {
|
||||
// Now set the actual visible rect
|
||||
let visuals = ui.style().interact_selectable(&response, true);
|
||||
// let rect = rect.expand(visuals.expansion);
|
||||
colour[3] = 20;
|
||||
ui.painter().rect(rect, 0.1, colour, visuals.fg_stroke);
|
||||
}
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
fn key_group(ui: &mut egui::Ui, colour: Color32, ux: f32, uy: f32) -> egui::Response {
|
||||
let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0 * ux, 2.0 * uy);
|
||||
let (mut rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click());
|
||||
rect = rect.shrink2(Vec2::new(3.0, 3.0));
|
||||
if response.clicked() {
|
||||
response.mark_changed();
|
||||
}
|
||||
response.widget_info(|| {
|
||||
egui::WidgetInfo::selected(egui::WidgetType::Checkbox, response.clicked(), "")
|
||||
});
|
||||
|
||||
if ui.is_rect_visible(rect) {
|
||||
let visuals = ui.style().interact_selectable(&response, true);
|
||||
let rect = rect.expand(visuals.expansion);
|
||||
let mut stroke = visuals.fg_stroke;
|
||||
stroke.color = visuals.bg_fill;
|
||||
ui.painter().rect(rect, 0.1, colour, stroke);
|
||||
}
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
fn blank(ui: &mut egui::Ui, ux: f32, uy: f32) {
|
||||
let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0 * ux, 2.0 * uy);
|
||||
let desired_size = ui.spacing().interact_size.y * egui::vec2(ux, uy);
|
||||
ui.allocate_exact_size(desired_size, egui::Sense::click());
|
||||
}
|
||||
|
||||
/// Draws entire arrow cluster block. This is visibly different to the split-arrows.
|
||||
fn arrow_cluster(ui: &mut egui::Ui, colour: Color32) {
|
||||
let height = 0.7;
|
||||
let space = KeyShape::ArrowSpacer;
|
||||
let shape = KeyShape::Arrow;
|
||||
ui.horizontal_top(|ui| {
|
||||
ui.with_layout(egui::Layout::top_down(Align::LEFT), |ui| {
|
||||
blank(ui, space.width(), height);
|
||||
ui.horizontal(|ui| {
|
||||
blank(ui, KeyShape::RowEndSpacer.width(), height);
|
||||
blank(ui, KeyShape::RowEndSpacer.width(), height);
|
||||
key_shape(ui, colour, shape.width(), height).on_hover_text("Left");
|
||||
});
|
||||
});
|
||||
ui.with_layout(egui::Layout::top_down(Align::LEFT), |ui| {
|
||||
key_shape(ui, colour, shape.width(), height).on_hover_text("Up");
|
||||
key_shape(ui, colour, shape.width(), height).on_hover_text("Down");
|
||||
});
|
||||
ui.with_layout(egui::Layout::top_down(Align::LEFT), |ui| {
|
||||
blank(ui, space.width(), height);
|
||||
key_shape(ui, colour, shape.width(), height).on_hover_text("Right");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use crate::system_state::SystemState;
|
||||
use egui::Ui;
|
||||
use rog_platform::{platform::GpuMode, supported::SupportedFunctions};
|
||||
use rog_platform::platform::GpuMode;
|
||||
use rog_platform::supported::SupportedFunctions;
|
||||
use rog_profiles::Profile;
|
||||
|
||||
use crate::system_state::SystemState;
|
||||
|
||||
pub fn platform_profile(states: &mut SystemState, ui: &mut Ui) {
|
||||
ui.heading("Platform profile");
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ impl RogApp {
|
||||
}
|
||||
}
|
||||
|
||||
if !self.supported.keyboard_led.stock_led_modes.is_empty() {
|
||||
if !self.supported.keyboard_led.basic_modes.is_empty() {
|
||||
ui.separator();
|
||||
if ui
|
||||
.selectable_value(page, Page::AuraEffects, "Keyboard Aura")
|
||||
|
||||
@@ -12,7 +12,6 @@ impl RogApp {
|
||||
egui::warn_if_debug_build(ui);
|
||||
});
|
||||
|
||||
/***********************************************************/
|
||||
// Drag area
|
||||
let text_color = ctx.style().visuals.text_color();
|
||||
let mut titlebar_rect = ui.available_rect_before_wrap();
|
||||
@@ -23,8 +22,9 @@ impl RogApp {
|
||||
{
|
||||
frame.drag_window();
|
||||
}
|
||||
/***********************************************************/
|
||||
|
||||
let height = titlebar_rect.height();
|
||||
|
||||
// Paint the title:
|
||||
ui.painter().text(
|
||||
titlebar_rect.right_top() + vec2(0.0, height / 2.0),
|
||||
@@ -35,9 +35,10 @@ 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 - 4.0)).frame(false),
|
||||
// );
|
||||
// Rect::from_min_size(titlebar_rect.right_top(),
|
||||
// Vec2::splat(height)),
|
||||
// Button::new(RichText::new("❌").size(height -
|
||||
// 4.0)).frame(false), );
|
||||
// if close_response.clicked() {
|
||||
// frame.close();
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user