I think I've got status fetching down; need to test on something with an actual battery

This commit is contained in:
2022-05-04 15:13:34 +02:00
parent 048d3dd700
commit 2d5ed69245
2 changed files with 74 additions and 17 deletions

View File

@@ -74,7 +74,7 @@ impl Surface {
"WattBar".to_owned(), "WattBar".to_owned(),
); );
layer_surface.set_size(32, 32); layer_surface.set_size(1900, 3);
layer_surface.set_anchor(zwlr_layer_surface_v1::Anchor::Bottom); layer_surface.set_anchor(zwlr_layer_surface_v1::Anchor::Bottom);
layer_surface.set_exclusive_zone(3); layer_surface.set_exclusive_zone(3);
let next_render_event = Rc::new(Cell::new(None)); let next_render_event = Rc::new(Cell::new(None));
@@ -130,6 +130,9 @@ impl Surface {
} }
fn draw(&mut self) { fn draw(&mut self) {
if self.dimensions.0 == 0 || self.dimensions.1 == 0 {
return;
}
let stride = 4 * self.dimensions.0 as i32; let stride = 4 * self.dimensions.0 as i32;
let width = self.dimensions.0 as i32; let width = self.dimensions.0 as i32;
let height = self.dimensions.1 as i32; let height = self.dimensions.1 as i32;
@@ -215,9 +218,11 @@ fn main() -> anyhow::Result<()> {
let mut event_loop = calloop::EventLoop::<()>::try_new().expect("Failed to start event loop"); let mut event_loop = calloop::EventLoop::<()>::try_new().expect("Failed to start event loop");
let surfaces_handle = Rc::clone(&surfaces); let surfaces_handle = Rc::clone(&surfaces);
let power_state_handle = Arc::clone(&app_state.display_status);
event_loop.handle().insert_source( event_loop.handle().insert_source(
upower_channel, upower_channel,
move |_, _, _| { move |_, _, _| {
eprintln!("Power state: {:?}", &*power_state_handle.read().unwrap());
for (_, surface) in surfaces_handle.borrow_mut().iter() { for (_, surface) in surfaces_handle.borrow_mut().iter() {
if surface.next_render_event.get().is_none() { if surface.next_render_event.get().is_none() {
surface.next_render_event.set(Some(RenderEvent::DataChanged)); surface.next_render_event.set(Some(RenderEvent::DataChanged));
@@ -226,6 +231,7 @@ fn main() -> anyhow::Result<()> {
} }
).unwrap(); ).unwrap();
WaylandSource::new(queue) WaylandSource::new(queue)
.quick_insert(event_loop.handle()) .quick_insert(event_loop.handle())
.unwrap(); .unwrap();

View File

@@ -1,3 +1,4 @@
use std::collections::HashMap;
use crate::PowerState; use crate::PowerState;
use std::sync::mpsc::SyncSender; use std::sync::mpsc::SyncSender;
use std::sync::{ use std::sync::{
@@ -7,7 +8,9 @@ use std::sync::{
use upower_dbus; use upower_dbus;
use calloop::channel::Sender as CalloopSender; use calloop::channel::Sender as CalloopSender;
use upower_dbus::BatteryState;
use zbus; use zbus;
use zbus::zvariant::OwnedValue;
pub struct PowerReporter { pub struct PowerReporter {
pub sender: CalloopSender<()>, pub sender: CalloopSender<()>,
@@ -37,19 +40,67 @@ pub fn spawn_upower(reporter: PowerReporter) -> anyhow::Result<()> {
start_receive.recv()? start_receive.recv()?
} }
fn upower_update(reporter: &PowerReporter, properties: &HashMap<String, OwnedValue>) {
{
let mut status = reporter.status.write().unwrap();
let battery_state = upower_dbus::BatteryState::try_from(properties["State"].clone()).unwrap();
let charging = match battery_state {
// fully enumerate the options in case a new one is added.
BatteryState::Charging |
BatteryState::FullyCharged |
BatteryState::PendingCharge => true,
BatteryState::Empty |
BatteryState::Discharging |
BatteryState::PendingDischarge |
BatteryState::Unknown => false,
};
*status = Some(PowerState {
level: f64::try_from(&properties["Percentage"]).unwrap() as f32 / 100.0,
charging,
time_remaining: if charging {
i64::try_from(&properties["TimeToFull"]).unwrap()
} else {
i64::try_from(&properties["TimeToEmpty"]).unwrap()
} as f32
})
}
// Notify listeners
reporter.sender.send(()).ok();
}
fn upower_run( fn upower_run(
reporter: PowerReporter, reporter: PowerReporter,
start_send: &SyncSender<anyhow::Result<()>>, start_send: &SyncSender<anyhow::Result<()>>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let dbus = zbus::blocking::Connection::system()?; let dbus = zbus::blocking::Connection::system()?;
let display_device_path = upower_dbus::UPowerProxyBlocking::new(&dbus)?.get_display_device()?; let display_device_path = upower_dbus::UPowerProxyBlocking::new(&dbus)?.get_display_device()?;
let display_proxy = zbus::blocking::fdo::PropertiesProxy::builder(&dbus) let display_proxy : zbus::blocking::fdo::PropertiesProxy = zbus::blocking::fdo::PropertiesProxy::builder(&dbus)
.destination("org.freedesktop.UPower")? .destination("org.freedesktop.UPower")?
.path(display_device_path)? .path(display_device_path)?
.cache_properties(zbus::CacheProperties::No) .cache_properties(zbus::CacheProperties::No)
.build()?; .build()?;
let mut prop_changed_iterator = display_proxy.receive_properties_changed()?;
let device_interface_name = zbus::names::InterfaceName::from_static_str("org.freedesktop.UPower.Device").unwrap();
let mut properties: HashMap<String, OwnedValue> = display_proxy.get_all(device_interface_name.clone())?;
upower_update(&reporter, &properties);
start_send.send(Ok(())).unwrap(); start_send.send(Ok(())).unwrap();
for signal in prop_changed_iterator {
let args = signal.args().expect("Invalid signal arguments");
if args.interface_name != device_interface_name {
continue
}
for (name, value) in args.changed_properties {
properties.get_mut(name).map(|vp| *vp = value.into());
}
// Update reporter
upower_update(&reporter, &properties);
}
// TODO: actually watch for events // TODO: actually watch for events
Ok(()) Ok(())