Add "Power Savings" settings
This commit is contained in:
parent
bad0942ef7
commit
11666225d0
5 changed files with 187 additions and 1 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -1514,6 +1514,15 @@ dependencies = [
|
||||||
"zvariant 4.2.0",
|
"zvariant 4.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cosmic-idle-config"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/pop-os/cosmic-idle#f682e19f2105f7bb4b722b858bf747dcb60be2c0"
|
||||||
|
dependencies = [
|
||||||
|
"cosmic-config",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-panel-config"
|
name = "cosmic-panel-config"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -1586,6 +1595,7 @@ dependencies = [
|
||||||
"cosmic-comp-config",
|
"cosmic-comp-config",
|
||||||
"cosmic-config",
|
"cosmic-config",
|
||||||
"cosmic-dbus-networkmanager",
|
"cosmic-dbus-networkmanager",
|
||||||
|
"cosmic-idle-config",
|
||||||
"cosmic-panel-config",
|
"cosmic-panel-config",
|
||||||
"cosmic-randr",
|
"cosmic-randr",
|
||||||
"cosmic-randr-shell",
|
"cosmic-randr-shell",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ git = "https://github.com/pop-os/cosmic-bg"
|
||||||
[workspace.dependencies.cosmic-comp-config]
|
[workspace.dependencies.cosmic-comp-config]
|
||||||
git = "https://github.com/pop-os/cosmic-comp"
|
git = "https://github.com/pop-os/cosmic-comp"
|
||||||
|
|
||||||
|
[workspace.dependencies.cosmic-idle-config]
|
||||||
|
git = "https://github.com/pop-os/cosmic-idle"
|
||||||
|
|
||||||
[workspace.dependencies.cosmic-panel-config]
|
[workspace.dependencies.cosmic-panel-config]
|
||||||
git = "https://github.com/pop-os/cosmic-panel"
|
git = "https://github.com/pop-os/cosmic-panel"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ cosmic-bg-config.workspace = true
|
||||||
cosmic-comp-config = { workspace = true, optional = true }
|
cosmic-comp-config = { workspace = true, optional = true }
|
||||||
cosmic-config.workspace = true
|
cosmic-config.workspace = true
|
||||||
cosmic-dbus-networkmanager = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
|
cosmic-dbus-networkmanager = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
|
||||||
|
cosmic-idle-config.workspace = true
|
||||||
cosmic-panel-config = { workspace = true, optional = true }
|
cosmic-panel-config = { workspace = true, optional = true }
|
||||||
cosmic-randr-shell.workspace = true
|
cosmic-randr-shell.workspace = true
|
||||||
cosmic-randr = { workspace = true, optional = true }
|
cosmic-randr = { workspace = true, optional = true }
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,82 @@ use cosmic::iced_widget::{column, row};
|
||||||
use cosmic::widget::{self, radio, settings, text};
|
use cosmic::widget::{self, radio, settings, text};
|
||||||
use cosmic::Apply;
|
use cosmic::Apply;
|
||||||
use cosmic::Task;
|
use cosmic::Task;
|
||||||
|
use cosmic_config::{Config, CosmicConfigEntry};
|
||||||
|
use cosmic_idle_config::CosmicIdleConfig;
|
||||||
use cosmic_settings_page::{self as page, section, Section};
|
use cosmic_settings_page::{self as page, section, Section};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use slab::Slab;
|
use slab::Slab;
|
||||||
use slotmap::SlotMap;
|
use slotmap::SlotMap;
|
||||||
|
use std::iter;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
static SCREEN_OFF_TIMES: &[Duration] = &[
|
||||||
|
Duration::from_secs(2 * 60),
|
||||||
|
Duration::from_secs(5 * 60),
|
||||||
|
Duration::from_secs(10 * 60),
|
||||||
|
Duration::from_secs(15 * 60),
|
||||||
|
Duration::from_secs(30 * 60),
|
||||||
|
];
|
||||||
|
|
||||||
|
static SUSPEND_TIMES: &[Duration] = &[
|
||||||
|
Duration::from_secs(15 * 60),
|
||||||
|
Duration::from_secs(20 * 60),
|
||||||
|
Duration::from_secs(25 * 60),
|
||||||
|
Duration::from_secs(30 * 60),
|
||||||
|
Duration::from_secs(45 * 60),
|
||||||
|
Duration::from_secs(1 * 60 * 60),
|
||||||
|
Duration::from_secs(80 * 60),
|
||||||
|
Duration::from_secs(90 * 60),
|
||||||
|
Duration::from_secs(100 * 60),
|
||||||
|
Duration::from_secs(2 * 60 * 60),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn format_time(duration: Duration) -> String {
|
||||||
|
let m = duration.as_secs() / 60;
|
||||||
|
if m % 60 == 0 {
|
||||||
|
fl!("x-hours", number = (m / 60))
|
||||||
|
} else {
|
||||||
|
fl!("x-minutes", number = m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Page {
|
pub struct Page {
|
||||||
entity: page::Entity,
|
entity: page::Entity,
|
||||||
battery: Battery,
|
battery: Battery,
|
||||||
connected_devices: Vec<ConnectedDevice>,
|
connected_devices: Vec<ConnectedDevice>,
|
||||||
on_enter_handle: Option<cosmic::iced::task::Handle>,
|
on_enter_handle: Option<cosmic::iced::task::Handle>,
|
||||||
|
screen_off_labels: Vec<String>,
|
||||||
|
suspend_labels: Vec<String>,
|
||||||
|
idle_config: Config,
|
||||||
|
idle_conf: CosmicIdleConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Page {
|
||||||
|
fn default() -> Self {
|
||||||
|
let idle_config = Config::new("com.system76.CosmicIdle", 1).unwrap();
|
||||||
|
let idle_conf = CosmicIdleConfig::get_entry(&idle_config).unwrap_or_else(|(_, conf)| conf);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
entity: Default::default(),
|
||||||
|
battery: Default::default(),
|
||||||
|
connected_devices: Vec::new(),
|
||||||
|
on_enter_handle: None,
|
||||||
|
screen_off_labels: SCREEN_OFF_TIMES
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(format_time)
|
||||||
|
.chain(iter::once(fl!("never")))
|
||||||
|
.collect(),
|
||||||
|
suspend_labels: SUSPEND_TIMES
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(format_time)
|
||||||
|
.chain(iter::once(fl!("never")))
|
||||||
|
.collect(),
|
||||||
|
idle_config,
|
||||||
|
idle_conf,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl page::Page<crate::pages::Message> for Page {
|
impl page::Page<crate::pages::Message> for Page {
|
||||||
|
|
@ -41,6 +106,7 @@ impl page::Page<crate::pages::Message> for Page {
|
||||||
sections.insert(battery_info()),
|
sections.insert(battery_info()),
|
||||||
sections.insert(connected_devices()),
|
sections.insert(connected_devices()),
|
||||||
sections.insert(profiles()),
|
sections.insert(profiles()),
|
||||||
|
sections.insert(power_saving()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,6 +147,9 @@ pub enum Message {
|
||||||
PowerProfileChange(PowerProfile),
|
PowerProfileChange(PowerProfile),
|
||||||
UpdateBattery(Battery),
|
UpdateBattery(Battery),
|
||||||
UpdateConnectedDevices(Vec<ConnectedDevice>),
|
UpdateConnectedDevices(Vec<ConnectedDevice>),
|
||||||
|
ScreenOffTimeChange(Option<Duration>),
|
||||||
|
SuspendOnAcTimeChange(Option<Duration>),
|
||||||
|
SuspendOnBatteryTimeChange(Option<Duration>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Page {
|
impl Page {
|
||||||
|
|
@ -99,6 +168,30 @@ impl Page {
|
||||||
Message::UpdateConnectedDevices(connected_devices) => {
|
Message::UpdateConnectedDevices(connected_devices) => {
|
||||||
self.connected_devices = connected_devices;
|
self.connected_devices = connected_devices;
|
||||||
}
|
}
|
||||||
|
Message::ScreenOffTimeChange(time) => {
|
||||||
|
let time = time.map(|x| x.as_millis() as u32);
|
||||||
|
if let Err(err) = self.idle_conf.set_screen_off_time(&self.idle_config, time) {
|
||||||
|
tracing::error!("failed to set screen off time: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::SuspendOnAcTimeChange(time) => {
|
||||||
|
let time = time.map(|x| x.as_millis() as u32);
|
||||||
|
if let Err(err) = self
|
||||||
|
.idle_conf
|
||||||
|
.set_suspend_on_ac_time(&self.idle_config, time)
|
||||||
|
{
|
||||||
|
tracing::error!("failed to set suspend on ac time: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::SuspendOnBatteryTimeChange(time) => {
|
||||||
|
let time = time.map(|x| x.as_millis() as u32);
|
||||||
|
if let Err(err) = self
|
||||||
|
.idle_conf
|
||||||
|
.set_suspend_on_battery_time(&self.idle_config, time)
|
||||||
|
{
|
||||||
|
tracing::error!("failed to set suspend on battery time: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -259,4 +352,77 @@ fn profiles() -> Section<crate::pages::Message> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn power_saving_row<'a>(
|
||||||
|
label: &'a str,
|
||||||
|
labels: &'a [String],
|
||||||
|
selected_time: Option<Duration>,
|
||||||
|
times: &'static [Duration],
|
||||||
|
on_select: fn(Option<Duration>) -> Message,
|
||||||
|
) -> cosmic::Element<'a, Message> {
|
||||||
|
let selected = if let Some(time) = selected_time {
|
||||||
|
times.iter().position(|x| *x == time)
|
||||||
|
} else {
|
||||||
|
// "Never"
|
||||||
|
Some(times.len())
|
||||||
|
};
|
||||||
|
|
||||||
|
settings::item(
|
||||||
|
label,
|
||||||
|
widget::dropdown(labels, selected, move |i| on_select(times.get(i).copied())),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn power_saving() -> Section<crate::pages::Message> {
|
||||||
|
let mut descriptions = Slab::new();
|
||||||
|
|
||||||
|
let turn_off_screen_desc = descriptions.insert(fl!("power-saving", "turn-off-screen-after"));
|
||||||
|
let auto_suspend_ac_desc = descriptions.insert(fl!("power-saving", "auto-suspend-ac"));
|
||||||
|
let auto_suspend_battery_desc =
|
||||||
|
descriptions.insert(fl!("power-saving", "auto-suspend-battery"));
|
||||||
|
|
||||||
|
Section::default()
|
||||||
|
.title(fl!("power-saving"))
|
||||||
|
.descriptions(descriptions)
|
||||||
|
.view::<Page>(move |_binder, page, section| {
|
||||||
|
let screen_off_time = page
|
||||||
|
.idle_conf
|
||||||
|
.screen_off_time
|
||||||
|
.map(|t| Duration::from_millis(t.into()));
|
||||||
|
let suspend_on_ac_time = page
|
||||||
|
.idle_conf
|
||||||
|
.suspend_on_ac_time
|
||||||
|
.map(|t| Duration::from_millis(t.into()));
|
||||||
|
let suspend_on_battery_time = page
|
||||||
|
.idle_conf
|
||||||
|
.suspend_on_battery_time
|
||||||
|
.map(|t| Duration::from_millis(t.into()));
|
||||||
|
settings::section()
|
||||||
|
.title(§ion.title)
|
||||||
|
.add(power_saving_row(
|
||||||
|
§ion.descriptions[turn_off_screen_desc],
|
||||||
|
&page.screen_off_labels,
|
||||||
|
screen_off_time,
|
||||||
|
SCREEN_OFF_TIMES,
|
||||||
|
Message::ScreenOffTimeChange,
|
||||||
|
))
|
||||||
|
.add(power_saving_row(
|
||||||
|
§ion.descriptions[auto_suspend_ac_desc],
|
||||||
|
&page.suspend_labels,
|
||||||
|
suspend_on_ac_time,
|
||||||
|
SUSPEND_TIMES,
|
||||||
|
Message::SuspendOnAcTimeChange,
|
||||||
|
))
|
||||||
|
.add(power_saving_row(
|
||||||
|
§ion.descriptions[auto_suspend_battery_desc],
|
||||||
|
&page.suspend_labels,
|
||||||
|
suspend_on_battery_time,
|
||||||
|
SUSPEND_TIMES,
|
||||||
|
Message::SuspendOnBatteryTimeChange,
|
||||||
|
))
|
||||||
|
.apply(cosmic::Element::from)
|
||||||
|
.map(crate::pages::Message::Power)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
impl page::AutoBind<crate::pages::Message> for Page {}
|
impl page::AutoBind<crate::pages::Message> for Page {}
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,7 @@ x-hours = { $number ->
|
||||||
[1] 1 hour
|
[1] 1 hour
|
||||||
*[other] { $number } hours
|
*[other] { $number } hours
|
||||||
}
|
}
|
||||||
|
never = Never
|
||||||
|
|
||||||
## Desktop: Appearance
|
## Desktop: Appearance
|
||||||
|
|
||||||
|
|
@ -461,6 +462,11 @@ power-mode = Power Mode
|
||||||
.performance-desc = Peak performance and power usage.
|
.performance-desc = Peak performance and power usage.
|
||||||
.no-backend = Backend not found. Install system76-power or power-profiles-daemon.
|
.no-backend = Backend not found. Install system76-power or power-profiles-daemon.
|
||||||
|
|
||||||
|
power-saving = Power Savings Options
|
||||||
|
.turn-off-screen-after = Turn off the screen after
|
||||||
|
.auto-suspend-ac = Automatic suspend when plugged in
|
||||||
|
.auto-suspend-battery = Automatic on battery power
|
||||||
|
|
||||||
## Input
|
## Input
|
||||||
|
|
||||||
acceleration-desc = Automatically adjusts tracking sensitivity based on speed.
|
acceleration-desc = Automatically adjusts tracking sensitivity based on speed.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue