I think I've got status fetching down; need to test on something with an actual battery
This commit is contained in:
38
src/main.rs
38
src/main.rs
@@ -74,7 +74,7 @@ impl Surface {
|
||||
"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_exclusive_zone(3);
|
||||
let next_render_event = Rc::new(Cell::new(None));
|
||||
@@ -130,6 +130,9 @@ impl Surface {
|
||||
}
|
||||
|
||||
fn draw(&mut self) {
|
||||
if self.dimensions.0 == 0 || self.dimensions.1 == 0 {
|
||||
return;
|
||||
}
|
||||
let stride = 4 * self.dimensions.0 as i32;
|
||||
let width = self.dimensions.0 as i32;
|
||||
let height = self.dimensions.1 as i32;
|
||||
@@ -165,14 +168,14 @@ fn main() -> anyhow::Result<()> {
|
||||
|
||||
// Spawn upower watcher
|
||||
let upower_channel = {
|
||||
let (sender, channel) = calloop::channel::channel();
|
||||
let reporter = upower::PowerReporter {
|
||||
sender,
|
||||
status: Arc::clone(&app_state.display_status),
|
||||
};
|
||||
let (sender, channel) = calloop::channel::channel();
|
||||
let reporter = upower::PowerReporter {
|
||||
sender,
|
||||
status: Arc::clone(&app_state.display_status),
|
||||
};
|
||||
|
||||
upower::spawn_upower(reporter)?;
|
||||
channel
|
||||
upower::spawn_upower(reporter)?;
|
||||
channel
|
||||
};
|
||||
|
||||
let (env, display, queue) =
|
||||
@@ -215,17 +218,20 @@ fn main() -> anyhow::Result<()> {
|
||||
let mut event_loop = calloop::EventLoop::<()>::try_new().expect("Failed to start event loop");
|
||||
|
||||
let surfaces_handle = Rc::clone(&surfaces);
|
||||
let power_state_handle = Arc::clone(&app_state.display_status);
|
||||
event_loop.handle().insert_source(
|
||||
upower_channel,
|
||||
move |_, _, _| {
|
||||
for (_, surface) in surfaces_handle.borrow_mut().iter() {
|
||||
if surface.next_render_event.get().is_none() {
|
||||
surface.next_render_event.set(Some(RenderEvent::DataChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
upower_channel,
|
||||
move |_, _, _| {
|
||||
eprintln!("Power state: {:?}", &*power_state_handle.read().unwrap());
|
||||
for (_, surface) in surfaces_handle.borrow_mut().iter() {
|
||||
if surface.next_render_event.get().is_none() {
|
||||
surface.next_render_event.set(Some(RenderEvent::DataChanged));
|
||||
}
|
||||
}
|
||||
}
|
||||
).unwrap();
|
||||
|
||||
|
||||
WaylandSource::new(queue)
|
||||
.quick_insert(event_loop.handle())
|
||||
.unwrap();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::PowerState;
|
||||
use std::sync::mpsc::SyncSender;
|
||||
use std::sync::{
|
||||
@@ -7,7 +8,9 @@ use std::sync::{
|
||||
use upower_dbus;
|
||||
|
||||
use calloop::channel::Sender as CalloopSender;
|
||||
use upower_dbus::BatteryState;
|
||||
use zbus;
|
||||
use zbus::zvariant::OwnedValue;
|
||||
|
||||
pub struct PowerReporter {
|
||||
pub sender: CalloopSender<()>,
|
||||
@@ -37,19 +40,67 @@ pub fn spawn_upower(reporter: PowerReporter) -> anyhow::Result<()> {
|
||||
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(
|
||||
reporter: PowerReporter,
|
||||
start_send: &SyncSender<anyhow::Result<()>>,
|
||||
) -> anyhow::Result<()> {
|
||||
let dbus = zbus::blocking::Connection::system()?;
|
||||
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")?
|
||||
.path(display_device_path)?
|
||||
.cache_properties(zbus::CacheProperties::No)
|
||||
.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();
|
||||
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
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user