Add suspend timer

This commit is contained in:
Ian Douglas Scott 2024-10-25 11:33:11 -07:00
parent 9907afc859
commit b384ea9fa2
2 changed files with 60 additions and 10 deletions

View file

@ -5,12 +5,18 @@ use serde::{Deserialize, Serialize};
pub struct CosmicIdleConfig { pub struct CosmicIdleConfig {
/// Screen off idle time, in ms /// Screen off idle time, in ms
pub screen_off_time: Option<u32>, pub screen_off_time: Option<u32>,
/// Suspend idle time when on battery, in ms
pub suspend_on_battery_time: Option<u32>,
/// Suspend idle time when on ac, in ms
pub suspend_on_ac_time: Option<u32>,
} }
impl Default for CosmicIdleConfig { impl Default for CosmicIdleConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
screen_off_time: Some(10 * 60 * 1000), screen_off_time: Some(10 * 60 * 1000),
suspend_on_battery_time: Some(20 * 60 * 1000),
suspend_on_ac_time: Some(20 * 60 * 1000),
} }
} }
} }

View file

@ -6,7 +6,10 @@ use cosmic_config::{calloop::ConfigWatchSource, CosmicConfigEntry};
use cosmic_idle_config::CosmicIdleConfig; use cosmic_idle_config::CosmicIdleConfig;
use futures_lite::stream::StreamExt; use futures_lite::stream::StreamExt;
use keyframe::{ease, functions::EaseInOut}; use keyframe::{ease, functions::EaseInOut};
use std::time::{Duration, Instant}; use std::{
process::Command,
time::{Duration, Instant},
};
use upower_dbus::UPowerProxy; use upower_dbus::UPowerProxy;
use wayland_client::{ use wayland_client::{
delegate_noop, delegate_noop,
@ -137,11 +140,13 @@ struct State {
inner: StateInner, inner: StateInner,
outputs: Vec<Output>, outputs: Vec<Output>,
conf: CosmicIdleConfig, conf: CosmicIdleConfig,
idle_notification: Option<ext_idle_notification_v1::ExtIdleNotificationV1>, screen_off_idle_notification: Option<ext_idle_notification_v1::ExtIdleNotificationV1>,
suspend_idle_notification: Option<ext_idle_notification_v1::ExtIdleNotificationV1>,
on_battery: bool,
} }
impl State { impl State {
fn update_idle(&mut self, is_idle: bool) { fn update_screen_off_idle(&mut self, is_idle: bool) {
for output in &mut self.outputs { for output in &mut self.outputs {
if is_idle { if is_idle {
output.fade_surface = Some(FadeBlackSurface::new(&self.inner, &output.output)); output.fade_surface = Some(FadeBlackSurface::new(&self.inner, &output.output));
@ -152,24 +157,57 @@ impl State {
} }
} }
fn update_suspend_idle(&mut self, is_idle: bool) {
if is_idle {
// TODO: Make command configurable
match Command::new("systemctl").arg("suspend").status() {
Ok(status) if status.success() => {}
Ok(status) => {
log::error!("suspend command failed with exit status {}", status)
}
Err(err) => log::error!("failed to run suspend command: {}", err),
}
}
}
fn recreate_notification(&mut self) { fn recreate_notification(&mut self) {
if let Some(idle_notification) = self.idle_notification.take() { if let Some(idle_notification) = self.screen_off_idle_notification.take() {
idle_notification.destroy();
}
if let Some(idle_notification) = self.suspend_idle_notification.take() {
idle_notification.destroy(); idle_notification.destroy();
} }
if let Some(time) = self.conf.screen_off_time { if let Some(time) = self.conf.screen_off_time {
self.idle_notification = Some(self.inner.idle_notifier.get_idle_notification( self.screen_off_idle_notification =
Some(self.inner.idle_notifier.get_idle_notification(
time,
&self.inner.seat,
&self.inner.qh,
(),
));
}
let suspend_time = if self.on_battery {
self.conf.suspend_on_battery_time
} else {
self.conf.suspend_on_ac_time
};
if let Some(time) = suspend_time {
self.suspend_idle_notification = Some(self.inner.idle_notifier.get_idle_notification(
time, time,
&self.inner.seat, &self.inner.seat,
&self.inner.qh, &self.inner.qh,
(), (),
)); ));
} }
self.update_idle(false); self.update_screen_off_idle(false);
self.update_suspend_idle(false);
} }
fn handle_event(&mut self, event: Event) { fn handle_event(&mut self, event: Event) {
match event { match event {
Event::OnBattery(_value) => {} Event::OnBattery(value) => {
self.on_battery = value;
}
} }
} }
} }
@ -251,9 +289,11 @@ fn main() {
seat, seat,
qh, qh,
}, },
idle_notification: None, screen_off_idle_notification: None,
suspend_idle_notification: None,
outputs, outputs,
conf, conf,
on_battery: false,
}; };
state.recreate_notification(); state.recreate_notification();
@ -339,7 +379,7 @@ impl Dispatch<wl_registry::WlRegistry, GlobalListContents> for State {
impl Dispatch<ext_idle_notification_v1::ExtIdleNotificationV1, ()> for State { impl Dispatch<ext_idle_notification_v1::ExtIdleNotificationV1, ()> for State {
fn event( fn event(
state: &mut Self, state: &mut Self,
_: &ext_idle_notification_v1::ExtIdleNotificationV1, notification: &ext_idle_notification_v1::ExtIdleNotificationV1,
event: ext_idle_notification_v1::Event, event: ext_idle_notification_v1::Event,
_: &(), _: &(),
_: &Connection, _: &Connection,
@ -350,7 +390,11 @@ impl Dispatch<ext_idle_notification_v1::ExtIdleNotificationV1, ()> for State {
ext_idle_notification_v1::Event::Resumed => false, ext_idle_notification_v1::Event::Resumed => false,
_ => unreachable!(), _ => unreachable!(),
}; };
state.update_idle(is_idle); if state.screen_off_idle_notification.as_ref() == Some(notification) {
state.update_screen_off_idle(is_idle);
} else if state.suspend_idle_notification.as_ref() == Some(notification) {
state.update_suspend_idle(is_idle);
}
} }
} }