diff options
| author | Max Verevkin <maxxverrr@gmail.com> | 2022-04-06 18:47:13 +0300 |
|---|---|---|
| committer | Max Verevkin <maxxverrr@gmail.com> | 2022-04-06 18:49:52 +0300 |
| commit | 9009579fd9328c4beaea7daa47533aa6dc4df11b (patch) | |
| tree | 2e47121f887efc39ae968cdcd0e66b58a7a0f655 /src/status_cmd.rs | |
| parent | b759c7ec2ac5411f7dd254bb19a20c27a166e7e2 (diff) | |
| download | i3bar-mango-9009579fd9328c4beaea7daa47533aa6dc4df11b.tar.gz | |
heavy refacotring, improve error handling, make `command` optional
Diffstat (limited to 'src/status_cmd.rs')
| -rw-r--r-- | src/status_cmd.rs | 119 |
1 files changed, 50 insertions, 69 deletions
diff --git a/src/status_cmd.rs b/src/status_cmd.rs index e77e4b2..9824be4 100644 --- a/src/status_cmd.rs +++ b/src/status_cmd.rs @@ -1,97 +1,78 @@ -use crate::Surface; use std::cell::RefCell; -use std::io::Result; -use std::io::{BufRead, BufReader, Write}; -use std::os::unix::prelude::{AsRawFd, RawFd}; -use std::process::{ChildStdin, ChildStdout, Command, Stdio}; +use std::io::{BufRead, BufReader, Result, Write}; +use std::os::unix::prelude::AsRawFd; +use std::process::{Child, ChildStdin, ChildStdout, Command, Stdio}; use std::rc::Rc; +use smithay_client_toolkit::reexports::calloop::{self, LoopHandle}; + use crate::i3bar_protocol::{Block, Event, Protocol}; -use crate::pointer_btn::PointerBtn; +use crate::BarState; -#[derive(Clone)] pub struct StatusCmd { - inner: Rc<RefCell<Inner>>, -} - -struct Inner { + child: Child, output: BufReader<ChildStdout>, input: ChildStdin, protocol: Protocol, - blocks: Rc<RefCell<Vec<Block>>>, - surfaces: Rc<RefCell<Vec<Surface>>>, -} - -impl AsRawFd for StatusCmd { - fn as_raw_fd(&self) -> RawFd { - self.inner.borrow().output.get_ref().as_raw_fd() - } -} - -impl Inner { - pub fn notify_available(&mut self) -> Result<()> { - let buf = self.output.fill_buf()?; - self.protocol.process_new_bytes(buf)?; - let consumed = buf.len(); - self.output.consume(consumed); - if let Some(new_blocks) = self.protocol.get_blocks() { - *self.blocks.borrow_mut() = new_blocks; - for s in &mut *self.surfaces.borrow_mut() { - s.blocks_need_update = true; - } - } - Ok(()) - } } impl StatusCmd { - pub fn new( - cmd: &str, - blocks: Rc<RefCell<Vec<Block>>>, - surfaces: Rc<RefCell<Vec<Surface>>>, - ) -> Result<Self> { + pub fn new(cmd: &str) -> Result<Self> { let mut child = Command::new("sh") .args(["-c", &format!("exec {cmd}")]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn()?; - let output = BufReader::new(child.stdout.take().unwrap()); + let output = child.stdout.take().unwrap(); let input = child.stdin.take().unwrap(); Ok(Self { - inner: Rc::new(RefCell::new(Inner { - output, - input, - protocol: Protocol::Unknown, - blocks, - surfaces, - })), + child, + output: BufReader::new(output), + input, + protocol: Protocol::Unknown, }) } - pub fn notify_available(&mut self) -> Result<()> { - self.inner.borrow_mut().notify_available() + pub fn notify_available(&mut self) -> Result<Option<Vec<Block>>> { + let buf = self.output.fill_buf()?; + self.protocol.process_new_bytes(buf)?; + let consumed = buf.len(); + self.output.consume(consumed); + Ok(self.protocol.get_blocks()) } - pub fn send_click_event( - &mut self, - button: PointerBtn, - name: Option<&str>, - instance: Option<&str>, - ) -> Result<()> { - let mut inner = self.inner.borrow_mut(); - if inner.protocol.supports_clicks() { - writeln!( - inner.input, - "{}", - serde_json::to_string(&Event { - name, - instance, - button, - ..Default::default() - }) - .unwrap() - )?; + pub fn send_click_event(&mut self, event: &Event) -> Result<()> { + if self.protocol.supports_clicks() { + writeln!(self.input, "{}", serde_json::to_string(event).unwrap(),)?; } Ok(()) } + + pub fn quick_insert(&self, handle: LoopHandle<()>, bar_state: Rc<RefCell<BarState>>) { + handle + .insert_source( + calloop::generic::Generic::new( + self.output.get_ref().as_raw_fd(), + calloop::Interest { + readable: true, + writable: false, + }, + calloop::Mode::Level, + ), + move |ready, _, _| { + if ready.readable { + bar_state.borrow_mut().notify_available()?; + Ok(calloop::PostAction::Continue) + } else { + let mut bar_state = bar_state.borrow_mut(); + bar_state.set_error("error reading from status command"); + if let Some(mut child) = bar_state.status_cmd.take() { + let _ = child.child.kill(); + } + Ok(calloop::PostAction::Remove) + } + }, + ) + .expect("failed to inser calloop source"); + } } |
