Use global poll for UpowerBattery
This commit is contained in:
+7
-7
@@ -48,7 +48,7 @@ impl WaitContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Widget {
|
pub trait Widget {
|
||||||
fn wait(&self, ctx: &mut WaitContext);
|
fn wait(&mut self, ctx: &mut WaitContext);
|
||||||
fn enter(&mut self);
|
fn enter(&mut self);
|
||||||
fn leave(&mut self);
|
fn leave(&mut self);
|
||||||
fn size(&self) -> (u32, u32);
|
fn size(&self) -> (u32, u32);
|
||||||
@@ -81,8 +81,8 @@ impl VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for VerticalLayout {
|
impl Widget for VerticalLayout {
|
||||||
fn wait(&self, ctx: &mut WaitContext) {
|
fn wait(&mut self, ctx: &mut WaitContext) {
|
||||||
for child in &self.children {
|
for child in &mut self.children {
|
||||||
child.wait(ctx);
|
child.wait(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,8 +192,8 @@ impl HorizontalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for HorizontalLayout {
|
impl Widget for HorizontalLayout {
|
||||||
fn wait(&self, ctx: &mut WaitContext) {
|
fn wait(&mut self, ctx: &mut WaitContext) {
|
||||||
for child in &self.children {
|
for child in &mut self.children {
|
||||||
child.wait(ctx);
|
child.wait(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,7 +309,7 @@ impl Margin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Margin {
|
impl Widget for Margin {
|
||||||
fn wait(&self, ctx: &mut WaitContext) {
|
fn wait(&mut self, ctx: &mut WaitContext) {
|
||||||
self.child.wait(ctx)
|
self.child.wait(ctx)
|
||||||
}
|
}
|
||||||
fn enter(&mut self) {
|
fn enter(&mut self) {
|
||||||
@@ -386,7 +386,7 @@ impl Fixed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Fixed {
|
impl Widget for Fixed {
|
||||||
fn wait(&self, ctx: &mut WaitContext) {
|
fn wait(&mut self, ctx: &mut WaitContext) {
|
||||||
self.child.wait(ctx)
|
self.child.wait(ctx)
|
||||||
}
|
}
|
||||||
fn enter(&mut self) {
|
fn enter(&mut self) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
||||||
|
use crate::widget::WaitContext;
|
||||||
|
|
||||||
use alsa::mixer::{Mixer, Selem, SelemChannelId, SelemId};
|
use alsa::mixer::{Mixer, Selem, SelemChannelId, SelemId};
|
||||||
|
|
||||||
@@ -83,6 +84,7 @@ impl Alsa {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BarWidgetImpl for Alsa {
|
impl BarWidgetImpl for Alsa {
|
||||||
|
fn wait(&mut self, _: &mut WaitContext) {}
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"volume"
|
"volume"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::cmd::Cmd;
|
use crate::cmd::Cmd;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
||||||
|
use crate::widget::WaitContext;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -502,6 +503,7 @@ impl PulseAudio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BarWidgetImpl for PulseAudio {
|
impl BarWidgetImpl for PulseAudio {
|
||||||
|
fn wait(&mut self, _: &mut WaitContext) {}
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"volume"
|
"volume"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
||||||
|
use crate::widget::WaitContext;
|
||||||
|
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
@@ -93,6 +94,7 @@ impl Backlight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BarWidgetImpl for Backlight {
|
impl BarWidgetImpl for Backlight {
|
||||||
|
fn wait(&mut self, _: &mut WaitContext) {}
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"backlight"
|
"backlight"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, W
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
pub trait BarWidgetImpl {
|
pub trait BarWidgetImpl {
|
||||||
|
fn wait(&mut self, ctx: &mut WaitContext);
|
||||||
fn name(&self) -> &str;
|
fn name(&self) -> &str;
|
||||||
fn value(&self) -> f32;
|
fn value(&self) -> f32;
|
||||||
fn color(&self) -> Color;
|
fn color(&self) -> Color;
|
||||||
@@ -61,13 +62,14 @@ impl BarWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for BarWidget {
|
impl Widget for BarWidget {
|
||||||
fn wait(&self, _: &mut WaitContext) {}
|
fn wait(&mut self, ctx: &mut WaitContext) {
|
||||||
|
self.bar_impl.wait(ctx);
|
||||||
|
}
|
||||||
fn enter(&mut self) {}
|
fn enter(&mut self) {}
|
||||||
fn leave(&mut self) {}
|
fn leave(&mut self) {}
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
(self.length, self.font_size)
|
(self.length, self.font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(
|
fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut DrawContext,
|
ctx: &mut DrawContext,
|
||||||
|
|||||||
+69
-54
@@ -1,10 +1,12 @@
|
|||||||
use crate::cmd::Cmd;
|
use crate::cmd::Cmd;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
||||||
|
use crate::widget::WaitContext;
|
||||||
|
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
|
||||||
|
use nix::poll::{PollFd, PollFlags};
|
||||||
|
|
||||||
use dbus;
|
use dbus;
|
||||||
|
|
||||||
@@ -35,14 +37,27 @@ fn get_upower_property(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UpowerBattery {
|
// The widget is created on a different thread than where it will be used, so
|
||||||
device_path: String,
|
// we need it to be Send. However, dbus::Connection has a void*, so it's not
|
||||||
inner: Arc<Mutex<UpowerBatteryInner>>,
|
// auto-derived. So, we make a small wrapper where we make it Send.
|
||||||
|
struct DbusConnection(dbus::Connection);
|
||||||
|
|
||||||
|
impl std::convert::AsRef<dbus::Connection> for DbusConnection {
|
||||||
|
fn as_ref(&self) -> &dbus::Connection {
|
||||||
|
return &self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UpowerBatteryInner {
|
unsafe impl Send for DbusConnection {}
|
||||||
|
|
||||||
|
pub struct UpowerBattery {
|
||||||
|
device_path: String,
|
||||||
|
sender: Sender<Cmd>,
|
||||||
|
dirty: Arc<Mutex<bool>>,
|
||||||
state: UpowerBatteryState,
|
state: UpowerBatteryState,
|
||||||
capacity: f64,
|
capacity: f64,
|
||||||
|
con: DbusConnection,
|
||||||
|
watch: dbus::Watch,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UpowerBatteryState {
|
enum UpowerBatteryState {
|
||||||
@@ -55,12 +70,26 @@ enum UpowerBatteryState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UpowerBattery {
|
impl UpowerBattery {
|
||||||
pub fn from_device(device: &str) -> Result<Self, ::std::io::Error> {
|
pub fn from_device(dirty: Arc<Mutex<bool>>, sender: Sender<Cmd>, device: &str) -> Result<Self, ::std::io::Error> {
|
||||||
|
let con = dbus::Connection::get_private(dbus::BusType::System)
|
||||||
|
.map_err(|_| ::std::io::Error::new(
|
||||||
|
::std::io::ErrorKind::Other,
|
||||||
|
"unable to open dbus",
|
||||||
|
))?;
|
||||||
let device_path = format!("/org/freedesktop/UPower/devices/battery_{}", device);
|
let device_path = format!("/org/freedesktop/UPower/devices/battery_{}", device);
|
||||||
let con = dbus::Connection::get_private(dbus::BusType::System).map_err(|_| {
|
|
||||||
::std::io::Error::new(::std::io::ErrorKind::Other, "could not get dbus connection")
|
|
||||||
})?;
|
|
||||||
|
|
||||||
|
let rule = format!(
|
||||||
|
"type='signal',\
|
||||||
|
path='{}',\
|
||||||
|
interface='org.freedesktop.DBus.Properties',\
|
||||||
|
member='PropertiesChanged'",
|
||||||
|
&device_path
|
||||||
|
);
|
||||||
|
con.add_match(&rule)
|
||||||
|
.map_err(|_| ::std::io::Error::new(
|
||||||
|
::std::io::ErrorKind::Other,
|
||||||
|
"unable to add match rule to dbus connection",
|
||||||
|
))?;
|
||||||
let upower_type: dbus::arg::Variant<u32> =
|
let upower_type: dbus::arg::Variant<u32> =
|
||||||
match get_upower_property(&con, &device_path, "Type")?.get1() {
|
match get_upower_property(&con, &device_path, "Type")?.get1() {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
@@ -111,12 +140,22 @@ impl UpowerBattery {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let fds = con.watch_fds();
|
||||||
|
if fds.len() != 1 {
|
||||||
|
return Err(::std::io::Error::new(
|
||||||
|
::std::io::ErrorKind::Other,
|
||||||
|
"expected 1 watch fd from dbus",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(UpowerBattery {
|
Ok(UpowerBattery {
|
||||||
device_path,
|
device_path,
|
||||||
inner: Arc::new(Mutex::new(UpowerBatteryInner {
|
con: DbusConnection(con),
|
||||||
|
dirty,
|
||||||
|
sender,
|
||||||
capacity: capacity,
|
capacity: capacity,
|
||||||
state: state,
|
state: state,
|
||||||
})),
|
watch: fds[0],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,36 +165,21 @@ impl UpowerBattery {
|
|||||||
sender: Sender<Cmd>,
|
sender: Sender<Cmd>,
|
||||||
) -> Result<Box<BarWidget>, ::std::io::Error> {
|
) -> Result<Box<BarWidget>, ::std::io::Error> {
|
||||||
BarWidget::new(font_size, length, move |dirty| {
|
BarWidget::new(font_size, length, move |dirty| {
|
||||||
let d = UpowerBattery::from_device("BAT0")?;
|
let d = UpowerBattery::from_device(dirty, sender, "BAT0")?;
|
||||||
let path = d.device_path.clone();
|
Ok(Box::new(d))
|
||||||
let inner = d.inner.clone();
|
})
|
||||||
let _ = thread::Builder::new()
|
}
|
||||||
.name("battery_monitor".to_string())
|
}
|
||||||
.spawn(move || {
|
|
||||||
let con = dbus::Connection::get_private(dbus::BusType::System)
|
|
||||||
.expect("Failed to establish D-Bus connection.");
|
|
||||||
let rule = format!(
|
|
||||||
"type='signal',\
|
|
||||||
path='{}',\
|
|
||||||
interface='org.freedesktop.DBus.Properties',\
|
|
||||||
member='PropertiesChanged'",
|
|
||||||
path
|
|
||||||
);
|
|
||||||
|
|
||||||
// First we're going to get an (irrelevant) NameAcquired event.
|
impl BarWidgetImpl for UpowerBattery {
|
||||||
con.incoming(10_000).next();
|
fn wait(&mut self, ctx: &mut WaitContext) {
|
||||||
|
for _ in self.con.as_ref().watch_handle(self.watch.fd(), dbus::WatchEvent::Readable as u32) {
|
||||||
con.add_match(&rule)
|
let capacity = get_upower_property(self.con.as_ref(), &self.device_path, "Percentage")
|
||||||
.expect("Failed to add D-Bus match rule.");
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if con.incoming(10_000).next().is_some() {
|
|
||||||
let capacity = get_upower_property(&con, &path, "Percentage")
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get1::<dbus::arg::Variant<f64>>()
|
.get1::<dbus::arg::Variant<f64>>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let state = match get_upower_property(&con, &path, "State")
|
let state = match get_upower_property(self.con.as_ref(), &self.device_path, "State")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get1::<dbus::arg::Variant<u32>>()
|
.get1::<dbus::arg::Variant<u32>>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -169,33 +193,24 @@ impl UpowerBattery {
|
|||||||
6 => UpowerBatteryState::Discharging,
|
6 => UpowerBatteryState::Discharging,
|
||||||
_ => UpowerBatteryState::Unknown,
|
_ => UpowerBatteryState::Unknown,
|
||||||
};
|
};
|
||||||
let mut inner = inner.lock().unwrap();
|
self.state = state;
|
||||||
inner.state = state;
|
self.capacity = capacity;
|
||||||
inner.capacity = capacity;
|
*self.dirty.lock().unwrap() = true;
|
||||||
*dirty.lock().unwrap() = true;
|
self.sender.send(Cmd::Draw).unwrap();
|
||||||
sender.send(Cmd::Draw).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(Box::new(d))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BarWidgetImpl for UpowerBattery {
|
ctx.fds.push(PollFd::new(self.watch.fd(), PollFlags::POLLIN));
|
||||||
|
}
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"battery"
|
"battery"
|
||||||
}
|
}
|
||||||
fn value(&self) -> f32 {
|
fn value(&self) -> f32 {
|
||||||
let inner = self.inner.lock().unwrap();
|
(self.capacity as f32) / 100.0
|
||||||
(inner.capacity as f32) / 100.0
|
|
||||||
}
|
}
|
||||||
fn color(&self) -> Color {
|
fn color(&self) -> Color {
|
||||||
let inner = self.inner.lock().unwrap();
|
match self.state {
|
||||||
match inner.state {
|
|
||||||
UpowerBatteryState::Discharging | UpowerBatteryState::Unknown => {
|
UpowerBatteryState::Discharging | UpowerBatteryState::Unknown => {
|
||||||
if inner.capacity > 10.0 {
|
if self.capacity > 10.0 {
|
||||||
Color::new(1.0, 1.0, 1.0, 1.0)
|
Color::new(1.0, 1.0, 1.0, 1.0)
|
||||||
} else {
|
} else {
|
||||||
Color::new(1.0, 0.5, 0.0, 1.0)
|
Color::new(1.0, 0.5, 0.0, 1.0)
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ impl Calendar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Calendar {
|
impl Widget for Calendar {
|
||||||
fn wait(&self, _: &mut WaitContext) {}
|
fn wait(&mut self, _: &mut WaitContext) {}
|
||||||
fn enter(&mut self) {}
|
fn enter(&mut self) {}
|
||||||
fn leave(&mut self) {}
|
fn leave(&mut self) {}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ impl Clock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Clock {
|
impl Widget for Clock {
|
||||||
fn wait(&self, ctx: &mut WaitContext) {
|
fn wait(&mut self, ctx: &mut WaitContext) {
|
||||||
let target = (self.cur_time + Duration::seconds(60))
|
let target = (self.cur_time + Duration::seconds(60))
|
||||||
.with_second(0)
|
.with_second(0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ impl Date {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Date {
|
impl Widget for Date {
|
||||||
fn wait(&self, _: &mut WaitContext) {}
|
fn wait(&mut self, _: &mut WaitContext) {}
|
||||||
fn enter(&mut self) {}
|
fn enter(&mut self) {}
|
||||||
fn leave(&mut self) {}
|
fn leave(&mut self) {}
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ fn wlcopy(s: &str) -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Launcher {
|
impl Widget for Launcher {
|
||||||
fn wait(&self, _: &mut WaitContext) {}
|
fn wait(&mut self, _: &mut WaitContext) {}
|
||||||
fn enter(&mut self) {}
|
fn enter(&mut self) {}
|
||||||
fn leave(&mut self) {
|
fn leave(&mut self) {
|
||||||
self.input = "".to_string();
|
self.input = "".to_string();
|
||||||
|
|||||||
Reference in New Issue
Block a user