diff options
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 118 |
1 files changed, 45 insertions, 73 deletions
diff --git a/src/main.rs b/src/main.rs index fc525ad..54c1449 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ mod blocks_cache; mod button_manager; mod color; mod config; +mod event_loop; mod i3bar_protocol; mod output; mod pointer_btn; @@ -17,11 +18,12 @@ mod text; mod utils; mod wm_info_provider; -use std::io::{self, ErrorKind}; -use std::os::fd::{AsRawFd, RawFd}; +use std::io::ErrorKind; +use std::os::fd::AsRawFd; use std::path::PathBuf; use clap::Parser; +use event_loop::EventLoop; use nix::fcntl::OFlag; use signal_hook::consts::*; use wayrs_client::{Connection, IoMode}; @@ -43,86 +45,56 @@ fn main() -> anyhow::Result<()> { signal_hook::low_level::pipe::register(SIGUSR1, sig_write)?; let (mut conn, globals) = Connection::connect_and_collect_globals()?; - let mut state = State::new(&mut conn, &globals, args.config.as_deref()); + let state = State::new(&mut conn, &globals, args.config.as_deref()); conn.flush(IoMode::Blocking)?; - loop { - let poll = Poll::new(conn.as_raw_fd(), sig_read, state.status_cmd_fd())?; + let mut el = EventLoop::<(Connection<State>, State)>::new(); - if poll.wayland { - match conn.recv_events(IoMode::NonBlocking) { - Ok(()) => { - conn.dispatch_events(&mut state); - conn.flush(IoMode::Blocking)?; - } - Err(e) if e.kind() == ErrorKind::WouldBlock => (), - Err(e) => bail!(e), - } - } + el.register_with_fd(sig_read, move |(conn, state)| { + nix::unistd::read(sig_read, &mut [0; 1])?; + state.toggle_visibility(conn); + Ok(event_loop::Action::Keep) + }); - if poll.signal { - nix::unistd::read(sig_read.as_raw_fd(), &mut [0; 1])?; - state.toggle_visibility(&mut conn); - conn.flush(IoMode::Blocking)?; + el.register_with_fd(conn.as_raw_fd(), |(conn, state)| { + match conn.recv_events(IoMode::NonBlocking) { + Ok(()) => { + conn.dispatch_events(state); + conn.flush(IoMode::Blocking)?; + } + Err(e) if e.kind() == ErrorKind::WouldBlock => (), + Err(e) => bail!(e), } + Ok(event_loop::Action::Keep) + }); - if let Some(status_cmd) = &mut state.shared_state.status_cmd { - if poll.cmd { - match status_cmd.receive_blocks() { - Ok(None) => (), - Ok(Some(blocks)) => { - state.set_blocks(&mut conn, blocks); - conn.flush(IoMode::Blocking)?; - } - Err(e) => { - let _ = state.shared_state.status_cmd.take().unwrap().child.kill(); - state.set_error(&mut conn, e); - conn.flush(IoMode::Blocking)?; - } + if let Some(fd) = state.status_cmd_fd() { + el.register_with_fd(fd, |(conn, state)| { + match state + .shared_state + .status_cmd + .as_mut() + .unwrap() + .receive_blocks() + { + Ok(None) => Ok(event_loop::Action::Keep), + Ok(Some(blocks)) => { + state.set_blocks(conn, blocks); + conn.flush(IoMode::Blocking)?; + Ok(event_loop::Action::Keep) + } + Err(e) => { + let _ = state.shared_state.status_cmd.take().unwrap().child.kill(); + state.set_error(conn, e); + conn.flush(IoMode::Blocking)?; + Ok(event_loop::Action::Unregister) } } - } + }); } -} - -struct Poll { - wayland: bool, - signal: bool, - cmd: bool, -} - -impl Poll { - fn new(wayland: RawFd, signal: RawFd, cmd: Option<RawFd>) -> io::Result<Self> { - let mut fds = [libc::pollfd { - fd: 0, - events: libc::POLLIN, - revents: 0, - }; 3]; - - fds[0].fd = wayland.as_raw_fd(); - fds[1].fd = signal.as_raw_fd(); - fds[2].fd = cmd.map_or(0, |cmd| cmd.as_raw_fd()); - loop { - // nix' (0.27) poll() implementation is hard to work with because of the lifetimes. In - // particular, it makes reusing the same buffer across poll()s very hard. It is better - // to just call directly into the libc at this point, it's not that hard. At least it is - // safer that trying to trick nix by using `BorrowedFd::borrow_raw()`. - let result = - unsafe { libc::poll(fds.as_mut_ptr(), if cmd.is_some() { 3 } else { 2 }, -1) }; - - if result == -1 { - let err = io::Error::last_os_error(); - if err.kind() != ErrorKind::Interrupted { - return Err(io::Error::last_os_error()); - } - } else { - return Ok(Self { - wayland: fds[0].revents & libc::POLLIN != 0, - signal: fds[1].revents & libc::POLLIN != 0, - cmd: fds[2].revents & libc::POLLIN != 0, - }); - } - } + let mut el_state = (conn, state); + loop { + el.run(&mut el_state)?; } } |
