xwayland: Make abstract socket optional and Linux-only

Hopefully fixes build on FreeBSD.
This commit is contained in:
Ivan Molodetskikh
2025-07-31 14:34:21 +03:00
parent 365274e5e2
commit 4ac4cb4a44
2 changed files with 58 additions and 36 deletions
+14 -5
View File
@@ -1,5 +1,4 @@
use std::os::fd::OwnedFd;
use std::os::linux::net::SocketAddrExt;
use std::os::unix::net::{SocketAddr, UnixListener};
use anyhow::{anyhow, ensure, Context as _};
@@ -17,7 +16,8 @@ const X11_TMP_UNIX_DIR: &str = "/tmp/.X11-unix";
struct X11Connection {
display_name: String,
abstract_fd: OwnedFd,
// Optional because there are no abstract sockets on FreeBSD.
abstract_fd: Option<OwnedFd>,
unix_fd: OwnedFd,
_unix_guard: Unlink,
_lock_guard: Unlink,
@@ -82,7 +82,10 @@ fn bind_to_socket(addr: &SocketAddr) -> anyhow::Result<UnixListener> {
Ok(listener)
}
#[cfg(target_os = "linux")]
fn bind_to_abstract_socket(display: u32) -> anyhow::Result<UnixListener> {
use std::os::linux::net::SocketAddrExt;
let name = format!("/tmp/.X11-unix/X{display}");
let addr = SocketAddr::from_abstract_name(name).unwrap();
bind_to_socket(&addr)
@@ -97,8 +100,14 @@ fn bind_to_unix_socket(display: u32) -> anyhow::Result<(UnixListener, Unlink)> {
bind_to_socket(&addr).map(|listener| (listener, guard))
}
fn open_display_sockets(display: u32) -> anyhow::Result<(UnixListener, UnixListener, Unlink)> {
let a = bind_to_abstract_socket(display).context("error binding to abstract socket")?;
fn open_display_sockets(
display: u32,
) -> anyhow::Result<(Option<UnixListener>, UnixListener, Unlink)> {
#[cfg(target_os = "linux")]
let a = Some(bind_to_abstract_socket(display).context("error binding to abstract socket")?);
#[cfg(not(target_os = "linux"))]
let a = None;
let (u, g) = bind_to_unix_socket(display).context("error binding to unix socket")?;
Ok((a, u, g))
}
@@ -138,7 +147,7 @@ fn setup_connection() -> anyhow::Result<X11Connection> {
};
let display_name = format!(":{display}");
let abstract_fd = OwnedFd::from(a);
let abstract_fd = a.map(OwnedFd::from);
let unix_fd = OwnedFd::from(u);
Ok(X11Connection {
+44 -31
View File
@@ -163,27 +163,29 @@ fn setup_watch(state: &mut State) {
event_loop.remove(token);
}
let fd = satellite.x11.abstract_fd.try_clone().unwrap();
let fd = clear_out_pending_connections(fd);
let source = Generic::new(fd, Interest::READ, Mode::Level);
let token = event_loop
.insert_source(source, move |_, _, state| {
if let Some(satellite) = &mut state.niri.satellite {
// Remove the other source.
if let Some(token) = satellite.unix_token.take() {
state.niri.event_loop.remove(token);
}
// Clear this source.
satellite.abstract_token = None;
if let Some(fd) = &satellite.x11.abstract_fd {
let fd = fd.try_clone().unwrap();
let fd = clear_out_pending_connections(fd);
let source = Generic::new(fd, Interest::READ, Mode::Level);
let token = event_loop
.insert_source(source, move |_, _, state| {
if let Some(satellite) = &mut state.niri.satellite {
// Remove the other source.
if let Some(token) = satellite.unix_token.take() {
state.niri.event_loop.remove(token);
}
// Clear this source.
satellite.abstract_token = None;
debug!("connection to X11 abstract socket; spawning xwayland-satellite");
let path = state.niri.config.borrow().xwayland_satellite.path.clone();
spawn(path, satellite);
}
Ok(PostAction::Remove)
})
.unwrap();
satellite.abstract_token = Some(token);
debug!("connection to X11 abstract socket; spawning xwayland-satellite");
let path = state.niri.config.borrow().xwayland_satellite.path.clone();
spawn(path, satellite);
}
Ok(PostAction::Remove)
})
.unwrap();
satellite.abstract_token = Some(token);
}
let fd = satellite.x11.unix_fd.try_clone().unwrap();
let fd = clear_out_pending_connections(fd);
@@ -211,7 +213,11 @@ fn setup_watch(state: &mut State) {
fn spawn(path: String, xwl: &Satellite) {
let _span = tracy_client::span!("satellite::spawn");
let abstract_fd = xwl.x11.abstract_fd.try_clone().unwrap();
let abstract_fd = xwl
.x11
.abstract_fd
.as_ref()
.map(|fd| fd.try_clone().unwrap());
let unix_fd = xwl.x11.unix_fd.try_clone().unwrap();
let to_main = xwl.to_main.clone();
@@ -257,15 +263,20 @@ fn spawn(path: String, xwl: &Satellite) {
}
}
fn spawn_and_wait(path: &Path, mut process: Command, abstract_fd: OwnedFd, unix_fd: OwnedFd) {
let abstract_raw = abstract_fd.as_raw_fd();
fn spawn_and_wait(
path: &Path,
mut process: Command,
abstract_fd: Option<OwnedFd>,
unix_fd: OwnedFd,
) {
let abstract_raw = abstract_fd.as_ref().map(|fd| fd.as_raw_fd());
let unix_raw = unix_fd.as_raw_fd();
process
.arg("-listenfd")
.arg(abstract_raw.to_string())
.arg("-listenfd")
.arg(unix_raw.to_string());
process.arg("-listenfd").arg(unix_raw.to_string());
if let Some(abstract_raw) = abstract_raw {
process.arg("-listenfd").arg(abstract_raw.to_string());
}
unsafe {
process.pre_exec(move || {
@@ -273,12 +284,14 @@ fn spawn_and_wait(path: &Path, mut process: Command, abstract_fd: OwnedFd, unix_
// that we want to pass it.
// We're not dropping these until after spawn().
let abstract_fd = BorrowedFd::borrow_raw(abstract_raw);
let unix_fd = BorrowedFd::borrow_raw(unix_raw);
fcntl_setfd(abstract_fd, FdFlags::empty())?;
fcntl_setfd(unix_fd, FdFlags::empty())?;
if let Some(abstract_raw) = abstract_raw {
let abstract_fd = BorrowedFd::borrow_raw(abstract_raw);
fcntl_setfd(abstract_fd, FdFlags::empty())?;
}
Ok(())
})
};