This commit is contained in:
Kenny Levinsen
2019-08-04 14:23:49 +02:00
parent 5cc4a6e740
commit beb6cb2f08
9 changed files with 181 additions and 131 deletions
+2 -6
View File
@@ -1,6 +1,6 @@
use crate::buffer::Buffer;
use crate::color::Color;
use crate::draw::{draw_bar, draw_text, draw_box, ROBOTO_REGULAR};
use crate::draw::{draw_bar, draw_box, draw_text, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl};
use std::fs::OpenOptions;
@@ -118,11 +118,7 @@ impl ModuleImpl for Backlight {
24,
self.brightness(),
)?;
draw_box(
&mut buf.subdimensions((128, 0, 432, 24))?,
&c,
(432, 24),
)?;
draw_box(&mut buf.subdimensions((128, 0, 432, 24))?, &c, (432, 24))?;
Ok(vec![buf.get_signed_bounds()])
}
+65 -35
View File
@@ -1,33 +1,45 @@
use crate::buffer::Buffer;
use crate::color::Color;
use crate::draw::{draw_bar, draw_text, draw_box, ROBOTO_REGULAR};
use crate::draw::{draw_bar, draw_box, draw_text, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl};
use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use std::thread;
use dbus;
use chrono::{DateTime, Local};
use dbus;
fn get_upower_property(con: &dbus::Connection, device_path: &str, property: &str) -> Result<dbus::Message, ::std::io::Error> {
fn get_upower_property(
con: &dbus::Connection,
device_path: &str,
property: &str,
) -> Result<dbus::Message, ::std::io::Error> {
let msg = dbus::Message::new_method_call(
"org.freedesktop.UPower",
device_path,
"org.freedesktop.DBus.Properties",
"Get",
).map_err(|_| ::std::io::Error::new(::std::io::ErrorKind::Other, "could not send make dbus method call"))?
.append2(
dbus::MessageItem::Str("org.freedesktop.UPower.Device".to_string()),
dbus::MessageItem::Str(property.to_string()),
);;
)
.map_err(|_| {
::std::io::Error::new(
::std::io::ErrorKind::Other,
"could not send make dbus method call",
)
})?
.append2(
dbus::MessageItem::Str("org.freedesktop.UPower.Device".to_string()),
dbus::MessageItem::Str(property.to_string()),
);;
con.send_with_reply_and_block(msg, 1000).map_err(|_| {::std::io::Error::new(::std::io::ErrorKind::Other, "could not send dbus message")})
con.send_with_reply_and_block(msg, 1000).map_err(|_| {
::std::io::Error::new(::std::io::ErrorKind::Other, "could not send dbus message")
})
}
pub struct UpowerBattery {
device_path: String,
inner: Arc<Mutex<UpowerBatteryInner>>
inner: Arc<Mutex<UpowerBatteryInner>>,
}
pub struct UpowerBatteryInner {
@@ -48,15 +60,20 @@ enum UpowerBatteryState {
impl UpowerBattery {
pub fn from_device(device: &str) -> Result<Self, ::std::io::Error> {
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 con = dbus::Connection::get_private(dbus::BusType::System).map_err(|_| {
::std::io::Error::new(::std::io::ErrorKind::Other, "could not get dbus connection")
})?;
let upower_type: dbus::arg::Variant<u32> = match get_upower_property(&con, &device_path, "Type")?.get1() {
Some(v) => v,
None => {
return Err(::std::io::Error::new(::std::io::ErrorKind::Other, "no such upower device"));
}
};
let upower_type: dbus::arg::Variant<u32> =
match get_upower_property(&con, &device_path, "Type")?.get1() {
Some(v) => v,
None => {
return Err(::std::io::Error::new(
::std::io::ErrorKind::Other,
"no such upower device",
));
}
};
// https://upower.freedesktop.org/docs/Device.html#Device:Type
if upower_type.0 != 2 {
@@ -66,13 +83,20 @@ impl UpowerBattery {
));
}
let capacity: f64 = match get_upower_property(&con, &device_path, "Percentage")?.get1::<dbus::arg::Variant<f64>>() {
let capacity: f64 = match get_upower_property(&con, &device_path, "Percentage")?
.get1::<dbus::arg::Variant<f64>>()
{
Some(v) => v.0,
None => {
return Err(::std::io::Error::new(::std::io::ErrorKind::Other, "no such upower device"));
return Err(::std::io::Error::new(
::std::io::ErrorKind::Other,
"no such upower device",
));
}
};
let state: UpowerBatteryState = match get_upower_property(&con, &device_path, "State")?.get1::<dbus::arg::Variant<u32>>() {
let state: UpowerBatteryState = match get_upower_property(&con, &device_path, "State")?
.get1::<dbus::arg::Variant<u32>>()
{
Some(v) => match v.0 {
1 => UpowerBatteryState::Charging,
2 => UpowerBatteryState::Discharging,
@@ -83,16 +107,19 @@ impl UpowerBattery {
_ => UpowerBatteryState::Unknown,
},
None => {
return Err(::std::io::Error::new(::std::io::ErrorKind::Other, "no such upower device"));
return Err(::std::io::Error::new(
::std::io::ErrorKind::Other,
"no such upower device",
));
}
};
Ok(UpowerBattery {
device_path,
inner: Arc::new(Mutex::new(UpowerBatteryInner{
inner: Arc::new(Mutex::new(UpowerBatteryInner {
capacity: capacity,
state: state,
dirty: true
dirty: true,
})),
})
}
@@ -120,8 +147,17 @@ impl UpowerBattery {
loop {
if con.incoming(10_000).next().is_some() {
let capacity = get_upower_property(&con, &path, "Percentage").unwrap().get1::<dbus::arg::Variant<f64>>().unwrap().0;
let state = match get_upower_property(&con, &path, "State").unwrap().get1::<dbus::arg::Variant<u32>>().unwrap().0 {
let capacity = get_upower_property(&con, &path, "Percentage")
.unwrap()
.get1::<dbus::arg::Variant<f64>>()
.unwrap()
.0;
let state = match get_upower_property(&con, &path, "State")
.unwrap()
.get1::<dbus::arg::Variant<u32>>()
.unwrap()
.0
{
1 => UpowerBatteryState::Charging,
2 => UpowerBatteryState::Discharging,
3 => UpowerBatteryState::Empty,
@@ -140,9 +176,7 @@ impl UpowerBattery {
});
Ok(d)
}
}
impl ModuleImpl for UpowerBattery {
@@ -171,11 +205,7 @@ impl ModuleImpl for UpowerBattery {
(inner.capacity as f32) / 100.0,
)?;
draw_box(
&mut buf.subdimensions((128, 0, 432, 24))?,
&c,
(432, 24),
)?;
draw_box(&mut buf.subdimensions((128, 0, 432, 24))?, &c, (432, 24))?;
Ok(vec![buf.get_signed_bounds()])
}
+25 -9
View File
@@ -38,14 +38,21 @@ impl<'a> Buffer<'a> {
}
}
pub fn subdimensions(&mut self, subdimensions: (u32, u32, u32, u32)) -> Result<Buffer, ::std::io::Error> {
pub fn subdimensions(
&mut self,
subdimensions: (u32, u32, u32, u32),
) -> Result<Buffer, ::std::io::Error> {
let bounds = self.get_bounds();
if subdimensions.0 + subdimensions.2 > bounds.2
|| subdimensions.1 + subdimensions.3 > bounds.3
{
return Err(::std::io::Error::new(::std::io::ErrorKind::Other, format!("cannot create subdimensions larger than buffer: {:?} > {:?}",
subdimensions, bounds
)));
return Err(::std::io::Error::new(
::std::io::ErrorKind::Other,
format!(
"cannot create subdimensions larger than buffer: {:?} > {:?}",
subdimensions, bounds
),
));
}
Ok(Buffer {
@@ -84,15 +91,24 @@ impl<'a> Buffer<'a> {
pub fn put(&mut self, pos: (u32, u32), c: &Color) -> Result<(), ::std::io::Error> {
let true_pos = if let Some(subdim) = self.subdimensions {
if pos.0 > subdim.2 || pos.1 > subdim.3 {
return Err(::std::io::Error::new(::std::io::ErrorKind::Other, format!("put({:?}) is not within subdimensions of buffer ({:?})",
pos, subdim)));
return Err(::std::io::Error::new(
::std::io::ErrorKind::Other,
format!(
"put({:?}) is not within subdimensions of buffer ({:?})",
pos, subdim
),
));
}
(pos.0 + subdim.0, pos.1 + subdim.1)
} else {
if pos.0 >= self.dimensions.0 || pos.1 >= self.dimensions.1 {
return Err(::std::io::Error::new(::std::io::ErrorKind::Other, format!("put({:?}) is not within dimensions of buffer ({:?})",
pos, self.dimensions
)));
return Err(::std::io::Error::new(
::std::io::ErrorKind::Other,
format!(
"put({:?}) is not within dimensions of buffer ({:?})",
pos, self.dimensions
),
));
}
pos
};
+4 -1
View File
@@ -230,7 +230,10 @@ impl ModuleImpl for Calendar {
self.offset += y;
self.dirty = true;
}
Input::Click { pos: (x, _), button: _ } => {
Input::Click {
pos: (x, _),
button: _,
} => {
if x < 448 {
self.offset -= 100.0;
} else if x >= 896 {
+1 -5
View File
@@ -166,11 +166,7 @@ pub fn draw_text_fixed_width(
Ok(())
}
pub fn draw_box(
buf: &mut Buffer,
c: &Color,
dim: (u32, u32),
) -> Result<(), ::std::io::Error> {
pub fn draw_box(buf: &mut Buffer, c: &Color, dim: (u32, u32)) -> Result<(), ::std::io::Error> {
let mut buf = buf.subdimensions((0, 0, dim.0, dim.1))?;
for x in 0..dim.0 {
+25 -25
View File
@@ -3,8 +3,8 @@ use crate::color::Color;
use crate::draw::{draw_text, draw_text_individual_colors, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl};
use std::io::Read;
use std::cmp::Ordering;
use std::io::Read;
use atty::Stream;
@@ -17,7 +17,7 @@ pub struct Launcher {
matches: Vec<String>,
cur: String,
offset: usize,
dirty: bool
dirty: bool,
}
impl Launcher {
@@ -25,7 +25,11 @@ impl Launcher {
if !atty::is(Stream::Stdin) {
let mut inbuf = String::new();
std::io::stdin().read_to_string(&mut inbuf).unwrap();
let options = inbuf.split("\n").into_iter().map(|s| s.to_string()).collect();
let options = inbuf
.split("\n")
.into_iter()
.map(|s| s.to_string())
.collect();
Ok(Launcher {
options: options,
@@ -35,7 +39,10 @@ impl Launcher {
dirty: true,
})
} else {
Err(::std::io::Error::new(::std::io::ErrorKind::Other, "input is a tty"))
Err(::std::io::Error::new(
::std::io::ErrorKind::Other,
"input is a tty",
))
}
}
}
@@ -53,16 +60,16 @@ impl ModuleImpl for Launcher {
ROBOTO_REGULAR,
&mut buf.subdimensions((0, 0, 128, 32))?,
bg,
&Color::new(0.75, 0.75, 0.75, 1.0),
&Color::new(0.75, 0.75, 0.75, 1.0),
32.0,
"Run: ",
)?;
let mut x_off: i32 = 0;
let mut width_remaining: i32 = 1280 - 64;
for (idx, m) in self.matches.iter().enumerate() {
let mut b = match buf.subdimensions((64 + x_off as u32, 0, width_remaining as u32, 32)) {
let mut b = match buf.subdimensions((64 + x_off as u32, 0, width_remaining as u32, 32))
{
Ok(b) => b,
Err(_) => break,
};
@@ -71,19 +78,13 @@ impl ModuleImpl for Launcher {
let off = m.to_lowercase().find(&self.cur.to_lowercase()).unwrap();
let mut colors = Vec::with_capacity(m.len());
for pos in 0..m.len() {
if pos >= off && pos < off + l {
if pos >= off && pos < off + l {
colors.push(Color::new(1.0, 1.0, 1.0, 1.0));
} else {
colors.push(Color::new(0.75, 0.75, 0.75, 1.0));
}
}
draw_text_individual_colors(
ROBOTO_REGULAR,
&mut b,
bg,
&colors,
32.0,
&m)?
draw_text_individual_colors(ROBOTO_REGULAR, &mut b, bg, &colors, 32.0, &m)?
} else {
draw_text(
ROBOTO_REGULAR,
@@ -93,7 +94,6 @@ impl ModuleImpl for Launcher {
32.0,
m,
)?
};
x_off += (size.0 + 8) as i32;
@@ -144,38 +144,38 @@ impl ModuleImpl for Launcher {
Input::Keypress { key, interpreted } => match key {
keysyms::XKB_KEY_BackSpace => {
if self.cur.len() > 0 {
self.cur = self.cur[..self.cur.len()-1].to_string();
self.cur = self.cur[..self.cur.len() - 1].to_string();
self.offset = 0;
self.dirty = true
}
},
}
keysyms::XKB_KEY_Return => {
if self.matches.len() > self.offset {
println!("{}", self.matches[self.offset]);
std::process::exit(0);
}
},
}
keysyms::XKB_KEY_Right => {
if self.matches.len() > 0 && self.offset < self.matches.len() - 1{
if self.matches.len() > 0 && self.offset < self.matches.len() - 1 {
self.offset += 1;
self.dirty = true;
}
},
}
keysyms::XKB_KEY_Left => {
if self.matches.len() > 0 && self.offset > 0 {
self.offset -= 1;
self.dirty = true;
}
},
}
_ => match interpreted {
Some(v) => {
self.cur += &v;
self.offset = 0;
self.dirty = true
},
}
None => {}
}
}
},
},
_ => {}
}
}
+19 -10
View File
@@ -1,17 +1,17 @@
use std::cmp::max;
use std::collections::VecDeque;
use std::io::{Read, Write};
use std::os::unix::io::AsRawFd;
use std::sync::mpsc::{channel, Sender};
use std::sync::{Arc, Mutex};
use std::cmp::max;
use nix::poll::{poll, PollFd, PollFlags};
use os_pipe::pipe;
use chrono::{Local};
use chrono::Local;
use smithay_client_toolkit::keyboard::{
map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatKind, KeyState, keysyms,
keysyms, map_keyboard_auto_with_repeat, Event as KbEvent, KeyRepeatKind, KeyState,
};
use smithay_client_toolkit::utils::DoubleMemPool;
@@ -22,25 +22,25 @@ use wayland_protocols::wlr::unstable::layer_shell::v1::client::{
};
mod backlight;
mod battery;
mod buffer;
mod calendar;
mod clock;
mod color;
mod draw;
mod launcher;
mod module;
mod sound;
mod battery;
mod launcher;
use crate::backlight::Backlight;
use crate::battery::UpowerBattery;
use crate::buffer::Buffer;
use crate::calendar::Calendar;
use crate::clock::Clock;
use crate::color::Color;
use crate::launcher::Launcher;
use crate::module::{Input, Module};
use crate::sound::PulseAudio;
use crate::battery::UpowerBattery;
use crate::launcher::Launcher;
enum Cmd {
Exit,
@@ -257,10 +257,20 @@ impl App {
&seat,
KeyRepeatKind::System,
move |event: KbEvent, _| match event {
KbEvent::Key { keysym, utf8, state, .. } => match state {
KbEvent::Key {
keysym,
utf8,
state,
..
} => match state {
KeyState::Pressed => match keysym {
keysyms::XKB_KEY_Escape => kbd_clone.lock().unwrap().push_back(Cmd::Exit),
v => kbd_clone.lock().unwrap().push_back(Cmd::KeyboardInput{input: Input::Keypress{ key: v, interpreted: utf8 }}),
v => kbd_clone.lock().unwrap().push_back(Cmd::KeyboardInput {
input: Input::Keypress {
key: v,
interpreted: utf8,
},
}),
},
_ => (),
},
@@ -425,7 +435,6 @@ impl App {
}
fn main() {
let (mut rx_pipe, mut tx_pipe) = pipe().unwrap();
let (tx_draw, rx_draw) = channel();
+17 -4
View File
@@ -7,9 +7,19 @@ use chrono::{DateTime, Local};
#[derive(Clone)]
pub enum Input {
Click { pos: (u32, u32), button: u32 },
Scroll { pos: (u32, u32), x: f64, y: f64 },
Keypress { key: u32, interpreted: Option<String> },
Click {
pos: (u32, u32),
button: u32,
},
Scroll {
pos: (u32, u32),
x: f64,
y: f64,
},
Keypress {
key: u32,
interpreted: Option<String>,
},
}
impl Input {
@@ -24,7 +34,10 @@ impl Input {
x: *x,
y: *y,
},
Input::Keypress { key, interpreted } => Input::Keypress { key: *key, interpreted: interpreted.clone() },
Input::Keypress { key, interpreted } => Input::Keypress {
key: *key,
interpreted: interpreted.clone(),
},
}
}
}
+23 -36
View File
@@ -1,6 +1,6 @@
use crate::buffer::Buffer;
use crate::color::Color;
use crate::draw::{draw_bar, draw_text, draw_box, ROBOTO_REGULAR};
use crate::draw::{draw_bar, draw_box, draw_text, ROBOTO_REGULAR};
use crate::module::{Input, ModuleImpl};
use std::cell::RefCell;
@@ -258,19 +258,17 @@ impl PulseAudioClient {
fn sink_info_callback(&mut self, result: ListResult<&SinkInfo>) {
match result {
ListResult::End | ListResult::Error => {}
ListResult::Item(sink_info) => {
match sink_info.name.clone() {
None => {}
Some(name) => {
let info = PulseAudioSinkInfo {
volume: sink_info.volume,
mute: sink_info.mute,
};
self.sinks.insert(name.into(), info);
self.listener.send(true).unwrap();
}
ListResult::Item(sink_info) => match sink_info.name.clone() {
None => {}
Some(name) => {
let info = PulseAudioSinkInfo {
volume: sink_info.volume,
mute: sink_info.mute,
};
self.sinks.insert(name.into(), info);
self.listener.send(true).unwrap();
}
}
},
}
}
@@ -414,7 +412,7 @@ impl PulseAudio {
dirty: true,
}));
let p = pa.clone();
std::thread::spawn(move|| loop {
std::thread::spawn(move || loop {
rx.recv().unwrap();
d.lock().unwrap().get_info().unwrap();
p.lock().unwrap().dirty = true;
@@ -448,31 +446,15 @@ impl ModuleImpl for Arc<Mutex<PulseAudio>> {
24.0,
"volume",
)?;
draw_bar(
&mut buf.subdimensions((128, 0, 432, 24))?,
&c,
432,
24,
vol,
)?;
draw_bar(&mut buf.subdimensions((128, 0, 432, 24))?, &c, 432, 24, vol)?;
let mut iter = 1.0;
while vol > 1.0 {
let c = &Color::new(0.75 / iter, 0.25 / iter, 0.25 / iter, 1.0);
vol -= 1.0;
iter += 1.0;
draw_bar(
&mut buf.subdimensions((128, 0, 432, 24))?,
&c,
432,
24,
vol,
)?;
draw_bar(&mut buf.subdimensions((128, 0, 432, 24))?, &c, 432, 24, vol)?;
}
draw_box(
&mut buf.subdimensions((128, 0, 432, 24))?,
&c,
(432, 24),
)?;
draw_box(&mut buf.subdimensions((128, 0, 432, 24))?, &c, (432, 24))?;
Ok(vec![buf.get_signed_bounds()])
}
@@ -493,8 +475,7 @@ impl ModuleImpl for Arc<Mutex<PulseAudio>> {
x: _x,
y,
} => {
self
.lock()
self.lock()
.unwrap()
.device
.lock()
@@ -504,7 +485,13 @@ impl ModuleImpl for Arc<Mutex<PulseAudio>> {
}
Input::Click { pos: _pos, button } => match button {
273 => {
self.lock().unwrap().device.lock().unwrap().toggle().unwrap();
self.lock()
.unwrap()
.device
.lock()
.unwrap()
.toggle()
.unwrap();
}
_ => {}
},