feat: add power setttings page, with power profiles
This commit is contained in:
parent
71c776e0f7
commit
1b3d00ebfc
6 changed files with 255 additions and 2 deletions
|
|
@ -11,10 +11,11 @@ use crate::pages::desktop::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::pages::input::{self};
|
use crate::pages::input::{self};
|
||||||
use crate::pages::{self, display, sound, system, time};
|
use crate::pages::{self, display, power, sound, system, time};
|
||||||
use crate::subscription::desktop_files;
|
use crate::subscription::desktop_files;
|
||||||
use crate::widget::{page_title, search_header};
|
use crate::widget::{page_title, search_header};
|
||||||
use crate::PageCommands;
|
use crate::PageCommands;
|
||||||
|
use cosmic::app::command::message;
|
||||||
use cosmic::app::DbusActivationMessage;
|
use cosmic::app::DbusActivationMessage;
|
||||||
use cosmic::iced::futures::SinkExt;
|
use cosmic::iced::futures::SinkExt;
|
||||||
use cosmic::iced::Subscription;
|
use cosmic::iced::Subscription;
|
||||||
|
|
@ -63,7 +64,7 @@ impl SettingsApp {
|
||||||
PageCommands::Keyboard => self.pages.page_id::<input::keyboard::Page>(),
|
PageCommands::Keyboard => self.pages.page_id::<input::keyboard::Page>(),
|
||||||
PageCommands::Mouse => self.pages.page_id::<input::mouse::Page>(),
|
PageCommands::Mouse => self.pages.page_id::<input::mouse::Page>(),
|
||||||
PageCommands::Network => None,
|
PageCommands::Network => None,
|
||||||
PageCommands::Power => None,
|
PageCommands::Power => self.pages.page_id::<power::Page>(),
|
||||||
PageCommands::RegionLanguage => self.pages.page_id::<time::region::Page>(),
|
PageCommands::RegionLanguage => self.pages.page_id::<time::region::Page>(),
|
||||||
PageCommands::Sound => self.pages.page_id::<sound::Page>(),
|
PageCommands::Sound => self.pages.page_id::<sound::Page>(),
|
||||||
PageCommands::Time => self.pages.page_id::<time::Page>(),
|
PageCommands::Time => self.pages.page_id::<time::Page>(),
|
||||||
|
|
@ -129,6 +130,7 @@ impl cosmic::Application for SettingsApp {
|
||||||
app.insert_page::<sound::Page>();
|
app.insert_page::<sound::Page>();
|
||||||
app.insert_page::<system::Page>();
|
app.insert_page::<system::Page>();
|
||||||
app.insert_page::<time::Page>();
|
app.insert_page::<time::Page>();
|
||||||
|
app.insert_page::<power::Page>();
|
||||||
|
|
||||||
let active_id = match flags.subcommand {
|
let active_id = match flags.subcommand {
|
||||||
Some(p) => app.subcommand_to_page(&p),
|
Some(p) => app.subcommand_to_page(&p),
|
||||||
|
|
@ -365,6 +367,10 @@ impl cosmic::Application for SettingsApp {
|
||||||
return page.update(message).map(cosmic::app::Message::App);
|
return page.update(message).map(cosmic::app::Message::App);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate::pages::Message::Power(message) => {
|
||||||
|
page::update!(self.pages, message, power::Page)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Message::PanelConfig(config) if config.name.to_lowercase().contains("panel") => {
|
Message::PanelConfig(config) if config.name.to_lowercase().contains("panel") => {
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,14 @@ pub mod networking;
|
||||||
pub mod sound;
|
pub mod sound;
|
||||||
pub mod system;
|
pub mod system;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
|
pub mod power;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
About(system::about::Message),
|
About(system::about::Message),
|
||||||
Appearance(desktop::appearance::Message),
|
Appearance(desktop::appearance::Message),
|
||||||
DateAndTime(time::date::Message),
|
DateAndTime(time::date::Message),
|
||||||
|
Power(power::Message),
|
||||||
Desktop(desktop::Message),
|
Desktop(desktop::Message),
|
||||||
DesktopWallpaper(desktop::wallpaper::Message),
|
DesktopWallpaper(desktop::wallpaper::Message),
|
||||||
DesktopWorkspaces(desktop::workspaces::Message),
|
DesktopWorkspaces(desktop::workspaces::Message),
|
||||||
|
|
|
||||||
108
cosmic-settings/src/pages/power/backend/mod.rs
Normal file
108
cosmic-settings/src/pages/power/backend/mod.rs
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
use zbus::Connection;
|
||||||
|
mod s76powerdaemon;
|
||||||
|
|
||||||
|
// Get backend, if exist s76powerdaemon preferred. If not exist power profiles deamon preferred.
|
||||||
|
async fn get_power_daemon<'a>() -> Result<s76powerdaemon::PowerDaemonProxy<'a>, ()> {
|
||||||
|
let connection = match Connection::system().await {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(e) => {
|
||||||
|
println!("[Cosmic Settings] zbus connection failed. {e}");
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match s76powerdaemon::PowerDaemonProxy::new(&connection).await {
|
||||||
|
Ok(d) => Ok(d),
|
||||||
|
Err(e) => {
|
||||||
|
println!("[S76PowerDaemon] Power daemon proxy can't created. Is it installed? {e}");
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum PowerProfile {
|
||||||
|
Performance,
|
||||||
|
Balanced,
|
||||||
|
Battery,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PowerProfile {
|
||||||
|
fn from_string(s: &str) -> PowerProfile {
|
||||||
|
match s {
|
||||||
|
"Performance" => Self::Performance,
|
||||||
|
"Battery" => Self::Battery,
|
||||||
|
_ => Self::Balanced,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn title(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Performance => fl!("power-profiles", "performance"),
|
||||||
|
Self::Balanced => fl!("power-profiles", "balanced"),
|
||||||
|
Self::Battery => fl!("power-profiles", "battery"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn description(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Performance => fl!("power-profiles", "performance-desc"),
|
||||||
|
Self::Balanced => fl!("power-profiles", "balanced-desc"),
|
||||||
|
Self::Battery => fl!("power-profiles", "battery-desc"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_power_profile(profile: PowerProfile) {
|
||||||
|
let daemon = match get_power_daemon().await {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(e) => {
|
||||||
|
println!("[Cosmic Settings] Problem while setting power profile.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match profile {
|
||||||
|
PowerProfile::Performance => match daemon.performance().await {
|
||||||
|
Ok(x) => println!("[Cosmic Settings] Performance mode activated."),
|
||||||
|
Err(e) => println!("{e}"),
|
||||||
|
},
|
||||||
|
PowerProfile::Balanced => match daemon.balanced().await {
|
||||||
|
Ok(x) => println!("[Cosmic Settings] Balanced mode activated."),
|
||||||
|
Err(e) => println!("{e}"),
|
||||||
|
},
|
||||||
|
PowerProfile::Battery => match daemon.battery().await {
|
||||||
|
Ok(x) => println!("[Cosmic Settings] Battery mode activated."),
|
||||||
|
Err(e) => println!("{e}"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_power_profiles() -> Vec<PowerProfile> {
|
||||||
|
vec![
|
||||||
|
PowerProfile::Performance,
|
||||||
|
PowerProfile::Balanced,
|
||||||
|
PowerProfile::Battery,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_current_power_profile() -> PowerProfile {
|
||||||
|
let daemon = match get_power_daemon().await {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(e) => {
|
||||||
|
println!("[Cosmic Settings] Problem while setting power profile.");
|
||||||
|
//Default
|
||||||
|
return PowerProfile::Balanced;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match daemon.get_profile().await {
|
||||||
|
Ok(p) => PowerProfile::from_string(p.as_str()),
|
||||||
|
//Default
|
||||||
|
Err(_) => {
|
||||||
|
println!("[Cosmic Settings] Problem while setting power profile.");
|
||||||
|
//Default
|
||||||
|
PowerProfile::Balanced
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
cosmic-settings/src/pages/power/backend/s76powerdaemon.rs
Normal file
41
cosmic-settings/src/pages/power/backend/s76powerdaemon.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
use zbus::proxy;
|
||||||
|
|
||||||
|
#[proxy(
|
||||||
|
interface = "com.system76.PowerDaemon",
|
||||||
|
default_path = "/com/system76/PowerDaemon",
|
||||||
|
assume_defaults = true
|
||||||
|
)]
|
||||||
|
pub trait PowerDaemon {
|
||||||
|
fn balanced(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
fn battery(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
fn get_charge_profiles(
|
||||||
|
&self,
|
||||||
|
) -> zbus::Result<Vec<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>>;
|
||||||
|
|
||||||
|
fn get_charge_thresholds(&self) -> zbus::Result<(u8, u8)>;
|
||||||
|
|
||||||
|
fn get_default_graphics(&self) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
fn get_external_displays_require_dgpu(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
|
fn get_graphics(&self) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
fn get_graphics_power(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
|
fn get_profile(&self) -> zbus::Result<String>;
|
||||||
|
|
||||||
|
fn get_switchable(&self) -> zbus::Result<bool>;
|
||||||
|
|
||||||
|
fn performance(&self) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
fn set_charge_thresholds(&self, thresholds: &(u8, u8)) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
fn set_graphics(&self, vendor: &str) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
fn set_graphics_power(&self, power: bool) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
#[zbus(signal)]
|
||||||
|
fn hot_plug_detect(&self, port: u64) -> zbus::Result<()>;
|
||||||
|
}
|
||||||
83
cosmic-settings/src/pages/power/mod.rs
Normal file
83
cosmic-settings/src/pages/power/mod.rs
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
use cosmic_settings_page::{self as page, section, Section};
|
||||||
|
use backend::PowerProfile;
|
||||||
|
use cosmic::iced::widget;
|
||||||
|
use cosmic::{widget::settings, Apply};
|
||||||
|
use slotmap::SlotMap;
|
||||||
|
|
||||||
|
pub mod backend;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Page;
|
||||||
|
|
||||||
|
impl page::Page<crate::pages::Message> for Page {
|
||||||
|
fn info(&self) -> page::Info {
|
||||||
|
page::Info::new("power", "battery-symbolic")
|
||||||
|
.title(fl!("power"))
|
||||||
|
.description(fl!("power", "desc"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn content(
|
||||||
|
&self,
|
||||||
|
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
|
||||||
|
) -> Option<page::Content> {
|
||||||
|
Some(vec![sections.insert(profiles())])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Message {
|
||||||
|
PowerProfileChange(PowerProfile),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Page {
|
||||||
|
pub fn update(&mut self, message: Message) {
|
||||||
|
let runtime = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
match message {
|
||||||
|
Message::PowerProfileChange(p) => runtime.block_on(backend::set_power_profile(p)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn profiles() -> Section<crate::pages::Message> {
|
||||||
|
Section::default()
|
||||||
|
.title(fl!("power-profiles"))
|
||||||
|
.descriptions(vec![fl!("power", "desc").into()])
|
||||||
|
.view::<Page>(|_binder, page, section| {
|
||||||
|
let runtime = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
|
||||||
|
let profiles = backend::get_power_profiles();
|
||||||
|
|
||||||
|
let current_profile = runtime.block_on(backend::get_current_power_profile());
|
||||||
|
|
||||||
|
let mut section = settings::view_section(§ion.title);
|
||||||
|
|
||||||
|
let mut widgets = Vec::new();
|
||||||
|
|
||||||
|
for profile in profiles {
|
||||||
|
let selected = if current_profile == profile {
|
||||||
|
Some(true)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let widget = widget::Radio::new("", true, selected, |_| {
|
||||||
|
Message::PowerProfileChange(profile.clone())
|
||||||
|
});
|
||||||
|
let item = settings::item::builder(profile.title())
|
||||||
|
.description(profile.description())
|
||||||
|
.control(widget);
|
||||||
|
widgets.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for item in widgets {
|
||||||
|
section = section.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
section
|
||||||
|
.apply(cosmic::Element::from)
|
||||||
|
.map(crate::pages::Message::Power)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||||
|
|
@ -431,3 +431,16 @@ switch-to-next-workspace = Switch to next workspace
|
||||||
switch-to-prev-workspace = Switch to prev workspace
|
switch-to-prev-workspace = Switch to prev workspace
|
||||||
open-application-library = Open Application Library
|
open-application-library = Open Application Library
|
||||||
open-workspaces-view = Open Workspaces Overview
|
open-workspaces-view = Open Workspaces Overview
|
||||||
|
|
||||||
|
## Power
|
||||||
|
|
||||||
|
power = Power
|
||||||
|
.desc = Manage power settings
|
||||||
|
|
||||||
|
power-profiles = Power Profiles
|
||||||
|
.performance = Performance Mode
|
||||||
|
.balanced = Balanced Mode
|
||||||
|
.battery = Power Save Mode
|
||||||
|
.performance-desc = Maximum performance but high power consumption.
|
||||||
|
.balanced-desc = Balanced performance and power consumption.
|
||||||
|
.battery-desc = Low performance but low power consumption.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue