123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- use std::io::prelude::*;
- use std::io::BufReader;
- use std::process::{Command, Stdio};
- use std::sync::mpsc;
- use std::thread;
- use ui::widget;
- const MARGIN: u16 = 7;
- struct Desktop {
- name: String,
- selected: bool,
- urgent: bool
- }
- pub struct Bspwm {
- context: widget::DrawContext,
- tx: mpsc::Sender<widget::WidgetMessage>,
- desktops: Vec<Desktop>
- }
- impl Bspwm {
- pub fn new(tx: mpsc::Sender<widget::WidgetMessage>, context: widget::DrawContext) -> Bspwm {
- Bspwm {
- context: context,
- tx: tx,
- desktops: vec![]
- }
- }
- }
- impl widget::Widget for Bspwm {
- fn init(&mut self) {
- let tx = self.tx.clone();
- thread::spawn(move || monitor_thread(tx));
- }
- fn render(&mut self, x: u16) {
- let mut offset = x;
- for desktop in self.desktops.iter() {
- let text_width = self.context.measure_text(&desktop.name);
- if desktop.selected {
- self.context.set_bg_color(0x6666, 0xCCCC, 0x6666, 0xFFFF);
- }
- else if desktop.urgent {
- self.context.set_bg_color(0xCCCC, 0x0, 0x3333, 0xFFFF);
- }
- else {
- self.context.set_bg_color(0x0, 0x0, 0x0, 0xFFFF);
- }
- self.context.draw_bg(offset, text_width + MARGIN * 2);
- self.context.draw_text(&desktop.name, offset + MARGIN);
- offset += text_width + MARGIN * 2;
- }
- }
- fn width(&mut self) -> u16 {
- let mut sum = 0;
- for desktop in self.desktops.iter() {
- sum += self.context.measure_text(&desktop.name) + MARGIN * 2;
- }
- sum
- }
- fn handle_event(&mut self, event: &widget::WidgetMessage) -> bool {
- match event {
- &widget::WidgetMessage::BspwmEvent(ref line) => {
- self.desktops = parse_bspwm(line);
- self.tx.send(widget::WidgetMessage::Relayout).expect("Failed to send relayout");
- },
- _ => {}
- }
- false
- }
- }
- fn monitor_thread(tx: mpsc::Sender<widget::WidgetMessage>) {
- let bspc = Command::new("bspc")
- .arg("subscribe")
- .arg("report")
- .stdout(Stdio::piped())
- .spawn()
- .ok()
- .expect("Failed to start bspc subscribe");
- let stdout = bspc.stdout.unwrap();
- let mut reader = BufReader::new(stdout);
- let mut line = String::new();
- loop {
- line.clear();
- reader.read_line(&mut line).ok().expect("Failed to read line");
- let kind = line.remove(0);
- let line = line.trim();
- match kind {
- 'W' => {
- let event = widget::WidgetMessage::BspwmEvent(line.to_string());
- tx.send(event).expect("Failed to send bswpm event")
- },
- _ => {}
- }
- }
- }
- fn parse_bspwm(line: &str) -> Vec<Desktop> {
- let mut desktops = vec![];
- let elems = line.split(':');
- for elem in elems {
- let mut chars = elem.chars();
- let kind = chars.next().unwrap();
- let name = chars.collect::<String>();
- if kind == 'M' || kind == 'm' {}
- else if kind == 'L' {}
- else if kind == 'G' {}
- else if kind == 'T' {}
- else {
- let empty = kind == 'f';
- let urgent = kind == 'U' || kind == 'u';
- let selected = kind.is_uppercase();
- if !empty {
- desktops.push(Desktop {
- name: name,
- selected: selected,
- urgent: urgent
- })
- }
- }
- }
- desktops
- }
|