battery: Trigger dgpu refresh on toggle

This commit is contained in:
Victoria Brekenfeld 2025-08-29 19:30:42 +02:00 committed by Ashley Wulber
parent 8fc0733f73
commit 94646f0124
2 changed files with 28 additions and 5 deletions

View file

@ -81,6 +81,7 @@ struct CosmicBatteryApplet {
battery_percent: f64, battery_percent: f64,
on_battery: bool, on_battery: bool,
gpus: HashMap<PathBuf, GPUData>, gpus: HashMap<PathBuf, GPUData>,
update_trigger: Option<UnboundedSender<()>>,
time_remaining: Duration, time_remaining: Duration,
max_kbd_brightness: Option<i32>, max_kbd_brightness: Option<i32>,
kbd_brightness: Option<i32>, kbd_brightness: Option<i32>,
@ -180,6 +181,7 @@ enum Message {
SetChargingLimit(chain::Toggler, bool), SetChargingLimit(chain::Toggler, bool),
KeyboardBacklight(KeyboardBacklightUpdate), KeyboardBacklight(KeyboardBacklightUpdate),
UpowerDevice(DeviceDbusEvent), UpowerDevice(DeviceDbusEvent),
GpuInit(UnboundedSender<()>),
GpuOn(PathBuf, String, Option<Vec<Entry>>), GpuOn(PathBuf, String, Option<Vec<Entry>>),
GpuOff(PathBuf), GpuOff(PathBuf),
ToggleGpuApps(PathBuf), ToggleGpuApps(PathBuf),
@ -338,6 +340,9 @@ impl cosmic::Application for CosmicBatteryApplet {
if let Some(tx) = self.power_profile_sender.as_ref() { if let Some(tx) = self.power_profile_sender.as_ref() {
let _ = tx.send(PowerProfileRequest::Get); let _ = tx.send(PowerProfileRequest::Get);
} }
if let Some(tx) = self.update_trigger.as_ref() {
let _ = tx.send(());
}
let mut tasks = vec![get_popup(popup_settings)]; let mut tasks = vec![get_popup(popup_settings)];
// Try again every time a popup is opened // Try again every time a popup is opened
if self.charging_limit.is_none() { if self.charging_limit.is_none() {
@ -424,6 +429,9 @@ impl cosmic::Application for CosmicBatteryApplet {
tokio::spawn(cosmic::process::spawn(cmd)); tokio::spawn(cosmic::process::spawn(cmd));
} }
}, },
Message::GpuInit(tx) => {
self.update_trigger = Some(tx);
}
Message::GpuOn(path, name, app_list) => { Message::GpuOn(path, name, app_list) => {
let toggled = self let toggled = self
.gpus .gpus
@ -845,6 +853,7 @@ impl cosmic::Application for CosmicBatteryApplet {
PowerProfileUpdate::Error(e) => Message::Errored(e), // TODO: handle error PowerProfileUpdate::Error(e) => Message::Errored(e), // TODO: handle error
}), }),
dgpu_subscription(0).map(|event| match event { dgpu_subscription(0).map(|event| match event {
GpuUpdate::Init(tx) => Message::GpuInit(tx),
GpuUpdate::On(path, name, list) => Message::GpuOn(path, name, list), GpuUpdate::On(path, name, list) => Message::GpuOn(path, name, list),
GpuUpdate::Off(path) => Message::GpuOff(path), GpuUpdate::Off(path) => Message::GpuOff(path),
}), }),

View file

@ -19,6 +19,7 @@ use drm::control::Device as ControlDevice;
use futures::{FutureExt, SinkExt}; use futures::{FutureExt, SinkExt};
use tokio::{ use tokio::{
io::unix::AsyncFd, io::unix::AsyncFd,
sync::mpsc::{self, UnboundedReceiver, UnboundedSender},
task::spawn_blocking, task::spawn_blocking,
time::{self, Interval}, time::{self, Interval},
}; };
@ -396,12 +397,13 @@ pub fn dgpu_subscription<I: 'static + Hash + Copy + Send + Sync + Debug>(
#[derive(Debug)] #[derive(Debug)]
pub enum State { pub enum State {
Ready, Ready,
Waiting(GpuMonitor), Waiting(GpuMonitor, UnboundedReceiver<()>),
Finished, Finished,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum GpuUpdate { pub enum GpuUpdate {
Init(UnboundedSender<()>),
Off(PathBuf), Off(PathBuf),
On(PathBuf, String, Option<Vec<Entry>>), On(PathBuf, String, Option<Vec<Entry>>),
} }
@ -412,10 +414,17 @@ async fn start_listening(
) -> State { ) -> State {
match state { match state {
State::Ready => match GpuMonitor::new().await { State::Ready => match GpuMonitor::new().await {
Some(monitor) => State::Waiting(monitor), Some(monitor) => {
let (tx, rx) = mpsc::unbounded_channel();
if output.send(GpuUpdate::Init(tx)).await.is_err() {
State::Finished
} else {
State::Waiting(monitor, rx)
}
}
None => State::Finished, None => State::Finished,
}, },
State::Waiting(mut monitor) => { State::Waiting(mut monitor, mut trigger) => {
let select_all = futures::future::select_all( let select_all = futures::future::select_all(
monitor monitor
.gpus .gpus
@ -503,7 +512,7 @@ async fn start_listening(
i = select_all => { i = select_all => {
let gpu = &mut monitor.gpus[i]; let gpu = &mut monitor.gpus[i];
if gpu.path == monitor.primary_gpu { if gpu.path == monitor.primary_gpu {
return State::Waiting(monitor); return State::Waiting(monitor, trigger);
} }
trace!("Polling gpu {}", gpu.path.display()); trace!("Polling gpu {}", gpu.path.display());
@ -529,9 +538,14 @@ async fn start_listening(
return State::Finished; return State::Finished;
} }
} }
_ = trigger.recv() => {
for gpu in &mut monitor.gpus {
gpu.interval.reset_immediately();
}
}
}; };
State::Waiting(monitor) State::Waiting(monitor, trigger)
} }
State::Finished => iced::futures::future::pending().await, State::Finished => iced::futures::future::pending().await,
} }