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(),
|
"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;
|
||||||
@@ -165,14 +168,14 @@ fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
// Spawn upower watcher
|
// Spawn upower watcher
|
||||||
let upower_channel = {
|
let upower_channel = {
|
||||||
let (sender, channel) = calloop::channel::channel();
|
let (sender, channel) = calloop::channel::channel();
|
||||||
let reporter = upower::PowerReporter {
|
let reporter = upower::PowerReporter {
|
||||||
sender,
|
sender,
|
||||||
status: Arc::clone(&app_state.display_status),
|
status: Arc::clone(&app_state.display_status),
|
||||||
};
|
};
|
||||||
|
|
||||||
upower::spawn_upower(reporter)?;
|
upower::spawn_upower(reporter)?;
|
||||||
channel
|
channel
|
||||||
};
|
};
|
||||||
|
|
||||||
let (env, display, queue) =
|
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 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 |_, _, _| {
|
||||||
for (_, surface) in surfaces_handle.borrow_mut().iter() {
|
eprintln!("Power state: {:?}", &*power_state_handle.read().unwrap());
|
||||||
if surface.next_render_event.get().is_none() {
|
for (_, surface) in surfaces_handle.borrow_mut().iter() {
|
||||||
surface.next_render_event.set(Some(RenderEvent::DataChanged));
|
if surface.next_render_event.get().is_none() {
|
||||||
}
|
surface.next_render_event.set(Some(RenderEvent::DataChanged));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
|
|
||||||
WaylandSource::new(queue)
|
WaylandSource::new(queue)
|
||||||
.quick_insert(event_loop.handle())
|
.quick_insert(event_loop.handle())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
|||||||
Reference in New Issue
Block a user