summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock23
-rw-r--r--Cargo.toml3
-rw-r--r--src/main.rs96
-rw-r--r--src/status_cmd.rs15
4 files changed, 73 insertions, 64 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e559e77..78f6225 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -291,8 +291,9 @@ version = "0.1.3"
dependencies = [
"anyhow",
"clap",
+ "libc",
"memchr",
- "nix 0.26.2",
+ "nix",
"pangocairo",
"serde",
"serde_json",
@@ -357,18 +358,6 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nix"
-version = "0.26.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
-dependencies = [
- "bitflags 1.3.2",
- "cfg-if",
- "libc",
- "static_assertions",
-]
-
-[[package]]
-name = "nix"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
@@ -617,12 +606,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -741,7 +724,7 @@ version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4acba2f832601f9f57e1ff86347af792e6dcb19f5b6155328faec87257bfa76"
dependencies = [
- "nix 0.27.1",
+ "nix",
"thiserror",
"wayrs-scanner",
]
diff --git a/Cargo.toml b/Cargo.toml
index 16e335c..8fb6c03 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,7 @@ hyprland = []
[dependencies]
anyhow = "1"
memchr = "2"
-nix = { version = "0.26", default-features = false, features = ["fs", "poll"] }
+nix = { version = "0.27", default-features = false, features = ["fs"] }
pangocairo = "0.17"
serde_json = "1"
serde = { version = "1", features = ["derive"] }
@@ -24,6 +24,7 @@ wayrs-client = "0.12"
wayrs-protocols = { version = "0.12", features = ["wlr-layer-shell-unstable-v1", "viewporter", "fractional-scale-v1"] }
wayrs-utils = { version = "0.10", features = ["cursor", "shm_alloc", "seats"] }
clap = { version = "4.3.23", default-features = false, features = ["derive", "std", "help"] }
+libc = "0.2.147"
[profile.release]
lto = "fat"
diff --git a/src/main.rs b/src/main.rs
index d2f69d1..fc525ad 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -17,14 +17,12 @@ mod text;
mod utils;
mod wm_info_provider;
-use std::io::ErrorKind;
-use std::os::unix::io::AsRawFd;
+use std::io::{self, ErrorKind};
+use std::os::fd::{AsRawFd, RawFd};
use std::path::PathBuf;
use clap::Parser;
-use nix::errno::Errno;
use nix::fcntl::OFlag;
-use nix::poll::{poll, PollFd, PollFlags};
use signal_hook::consts::*;
use wayrs_client::{Connection, IoMode};
@@ -48,21 +46,10 @@ fn main() -> anyhow::Result<()> {
let mut state = State::new(&mut conn, &globals, args.config.as_deref());
conn.flush(IoMode::Blocking)?;
- let mut fds = Vec::with_capacity(3);
- fds.push(PollFd::new(conn.as_raw_fd(), PollFlags::POLLIN));
- fds.push(PollFd::new(sig_read, PollFlags::POLLIN));
- if let Some(cmd_fd) = state.status_cmd_fd() {
- fds.push(PollFd::new(cmd_fd, PollFlags::POLLIN));
- }
-
loop {
- match poll(&mut fds, -1) {
- Ok(_) => (),
- Err(Errno::EINTR) => continue,
- Err(e) => bail!(e),
- }
+ let poll = Poll::new(conn.as_raw_fd(), sig_read, state.status_cmd_fd())?;
- if fds[0].any().unwrap_or(false) {
+ if poll.wayland {
match conn.recv_events(IoMode::NonBlocking) {
Ok(()) => {
conn.dispatch_events(&mut state);
@@ -73,31 +60,68 @@ fn main() -> anyhow::Result<()> {
}
}
- if fds[1].any().unwrap_or(false) {
- nix::unistd::read(sig_read, &mut [0; 1])?;
+ if poll.signal {
+ nix::unistd::read(sig_read.as_raw_fd(), &mut [0; 1])?;
state.toggle_visibility(&mut conn);
conn.flush(IoMode::Blocking)?;
}
- if fds.len() > 2 && fds[2].any().unwrap_or(false) {
- match state
- .shared_state
- .status_cmd
- .as_mut()
- .unwrap()
- .receive_blocks()
- {
- Ok(None) => (),
- Ok(Some(blocks)) => {
- state.set_blocks(&mut conn, blocks);
- conn.flush(IoMode::Blocking)?;
+ 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)?;
+ }
}
- Err(e) => {
- let _ = state.shared_state.status_cmd.take().unwrap().child.kill();
- fds.pop().unwrap();
- state.set_error(&mut conn, e);
- conn.flush(IoMode::Blocking)?;
+ }
+ }
+ }
+}
+
+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,
+ });
}
}
}
diff --git a/src/status_cmd.rs b/src/status_cmd.rs
index 539ee3a..217ddab 100644
--- a/src/status_cmd.rs
+++ b/src/status_cmd.rs
@@ -1,12 +1,9 @@
-use std::io::{BufWriter, Write};
+use std::io::{self, BufWriter, ErrorKind, Write};
use std::os::unix::io::{AsRawFd, RawFd};
use std::process::{Child, ChildStdin, ChildStdout, Command, Stdio};
use anyhow::Result;
-use nix::errno::Errno;
-use nix::libc;
-
use crate::i3bar_protocol::{Block, Event, Protocol};
#[derive(Debug)]
@@ -44,7 +41,7 @@ impl StatusCmd {
match read_to_vec(self.output.as_raw_fd(), &mut self.buf) {
Ok(0) => bail!("status command exited"),
Ok(_n) => (),
- Err(Errno::EAGAIN) => return Ok(None),
+ Err(e) if e.kind() == ErrorKind::WouldBlock => return Ok(None),
Err(e) => bail!(e),
}
@@ -68,7 +65,7 @@ impl StatusCmd {
/// Read from a raw file descriptor to the vector.
///
/// Appends data at the end of the buffer. Resizes vector as needed.
-pub fn read_to_vec(fd: RawFd, buf: &mut Vec<u8>) -> nix::Result<usize> {
+pub fn read_to_vec(fd: RawFd, buf: &mut Vec<u8>) -> io::Result<usize> {
if buf.capacity() - buf.len() < 1024 {
buf.reserve(buf.capacity().max(1024));
}
@@ -81,7 +78,11 @@ pub fn read_to_vec(fd: RawFd, buf: &mut Vec<u8>) -> nix::Result<usize> {
)
};
- let read = Errno::result(res)? as usize;
+ if res == -1 {
+ return Err(io::Error::last_os_error());
+ }
+
+ let read = res as usize;
unsafe { buf.set_len(buf.len() + read) };
Ok(read)