From e44410c5a173f92fac521b5ec82cc4d1c79824b7 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Fri, 26 Jun 2026 18:17:23 +0200 Subject: [PATCH 1/2] Support nameless ListenSocketSources Only sockets created inside XDG_RUNTIME_DIR have names. This is necessary as a step towards support for creating the Wayland socket at a specific absolute path. Since the "socket" value was mostly used previously as the value of WAYLAND_DISPLAY for clients, I've renamed it to wayland_display, to make it clear that its value can be any value suitable for WAYLAND_DISPLAY: either a relative path in XDG_RUNTIME_DIR, or an absolute path. Only in one place (kms/socket.rs) do we care which it is, so there we just check whether the path is absolute to know which ListeningSocketSource constructor to call. --- Cargo.lock | 32 +++++++++++--------------------- Cargo.toml | 12 +++++++++++- src/backend/kms/socket.rs | 33 +++++++++++++++++---------------- src/dbus/mod.rs | 2 +- src/input/actions.rs | 2 +- src/lib.rs | 18 +++++++++--------- src/session.rs | 3 ++- src/state.rs | 8 ++++---- src/systemd.rs | 2 +- 9 files changed, 57 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1bc58958..5173e7b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4797,7 +4797,7 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smithay" version = "0.7.0" -source = "git+https://github.com/smithay/smithay.git?rev=8eb4076#8eb4076cad8705c56f5e3bac8577b83576b6ce76" +source = "git+https://github.com/alyssais/smithay.git?tag=v0.7.0-cosmic-comp-1.2.0-spectrum-0#b05863561c466fd8f3fd51afe59dc7c0a18a1d95" dependencies = [ "aliasable", "appendlist", @@ -5811,8 +5811,7 @@ dependencies = [ [[package]] name = "wayland-backend" version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "cc", "downcast-rs", @@ -5825,8 +5824,7 @@ dependencies = [ [[package]] name = "wayland-client" version = "0.31.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "bitflags 2.11.0", "rustix 1.1.4", @@ -5848,8 +5846,7 @@ dependencies = [ [[package]] name = "wayland-cursor" version = "0.31.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "rustix 1.1.4", "wayland-client", @@ -5859,8 +5856,7 @@ dependencies = [ [[package]] name = "wayland-egl" version = "0.32.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b97bdb7c49e5bd9b7562f38ff84f0dad47079fdc9e926f691a787f6dbc05451" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "wayland-backend", "wayland-sys", @@ -5869,8 +5865,7 @@ dependencies = [ [[package]] name = "wayland-protocols" version = "0.32.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -5895,8 +5890,7 @@ dependencies = [ [[package]] name = "wayland-protocols-misc" version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -5922,8 +5916,7 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -5936,8 +5929,7 @@ dependencies = [ [[package]] name = "wayland-scanner" version = "0.31.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "proc-macro2", "quick-xml", @@ -5947,8 +5939,7 @@ dependencies = [ [[package]] name = "wayland-server" version = "0.31.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1846eb04c49182e04f4a099e2a830a2b745610bbc1d61246e206f29c7000a0" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "bitflags 2.11.0", "downcast-rs", @@ -5960,8 +5951,7 @@ dependencies = [ [[package]] name = "wayland-sys" version = "0.31.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +source = "git+https://github.com/alyssais/wayland-rs?tag=release-2026-03-30-spectrum-0#643927b7a936dcd474b5c073aa6a8d9b185cd6eb" dependencies = [ "dlib", "log", diff --git a/Cargo.toml b/Cargo.toml index f1a04f02..6f6774d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -143,4 +143,14 @@ cosmic-protocols = { git = "https://github.com/pop-os//cosmic-protocols", branch cosmic-client-toolkit = { git = "https://github.com/pop-os//cosmic-protocols", branch = "main" } [patch.crates-io] -smithay = { git = "https://github.com/smithay/smithay.git", rev = "8eb4076" } +smithay = { git = "https://github.com/alyssais/smithay.git", tag = "v0.7.0-cosmic-comp-1.2.0-spectrum-0" } +wayland-backend = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } +wayland-client = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } +wayland-cursor = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } +wayland-egl = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } +wayland-protocols = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } +wayland-protocols-misc = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } +wayland-protocols-wlr = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } +wayland-scanner = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } +wayland-server = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } +wayland-sys = { git = "https://github.com/alyssais/wayland-rs", tag = "release-2026-03-30-spectrum-0" } diff --git a/src/backend/kms/socket.rs b/src/backend/kms/socket.rs index 3babd35a..c56a49cd 100644 --- a/src/backend/kms/socket.rs +++ b/src/backend/kms/socket.rs @@ -15,7 +15,7 @@ use smithay::{ socket::ListeningSocketSource, }, }; -use std::sync::Arc; +use std::{path::Path, sync::Arc}; use tracing::{info, warn}; use crate::state::{ClientState, Common, State, advertised_node_for_client}; @@ -34,16 +34,13 @@ impl Common { render_node: DrmNode, formats: FormatSet, ) -> Result { - let socket_name = format!( - "{}-{}", - &self.socket.to_string_lossy(), - render_node - .dev_path() - .unwrap() - .file_name() - .unwrap() - .to_string_lossy() - ); + let dev_path = render_node.dev_path().unwrap(); + let render_node_name = dev_path.file_name().unwrap(); + + let mut wayland_display = self.wayland_display.clone().into_os_string(); + wayland_display.push("-"); + wayland_display.push(render_node_name); + let wayland_display = wayland_display.to_string_lossy().into_owned(); // initialize globals let filter = move |client: &Client| advertised_node_for_client(client) == Some(render_node); @@ -71,9 +68,13 @@ impl Common { ); // add a special socket for the gpu - let listener = ListeningSocketSource::with_name(&socket_name) - .with_context(|| format!("Failed to bind socket to {}", socket_name))?; - let socket_name_clone = socket_name.clone(); + let listener = if Path::new(&wayland_display).is_absolute() { + ListeningSocketSource::with_path(wayland_display.clone().into()) + } else { + ListeningSocketSource::with_name(&wayland_display) + } + .with_context(|| format!("Failed to bind socket to {}", wayland_display))?; + let wayland_display_clone = wayland_display.clone(); let token = self .event_loop_handle .insert_source(listener, move |client_stream, _, state: &mut State| { @@ -85,7 +86,7 @@ impl Common { }), ) { warn!( - socket_name = socket_name_clone, + display = wayland_display_clone, ?err, "Error adding wayland client." ); @@ -93,7 +94,7 @@ impl Common { }) .context("Failed to add gpu-wayland socket to the event loop")?; - info!(socket_name, ?render_node, "Added gpu-specific socket."); + info!(wayland_display, ?render_node, "Added gpu-specific socket."); Ok(Socket { token, diff --git a/src/dbus/mod.rs b/src/dbus/mod.rs index 5b9754c3..beddd52c 100644 --- a/src/dbus/mod.rs +++ b/src/dbus/mod.rs @@ -154,7 +154,7 @@ pub fn ready(common: &Common) -> Result<()> { let dbus = zbus::fdo::DBusProxy::new(conn).await?; dbus.update_activation_environment(HashMap::from([ - ("WAYLAND_DISPLAY", common.socket.to_str().unwrap()), + ("WAYLAND_DISPLAY", common.wayland_display.to_str().unwrap()), ( "DISPLAY", &common diff --git a/src/input/actions.rs b/src/input/actions.rs index 3d017697..dccb81cf 100644 --- a/src/input/actions.rs +++ b/src/input/actions.rs @@ -1054,7 +1054,7 @@ impl State { data.user_data .insert_if_missing(move || ActivationContext::Workspace(handle)); - let wayland_display = self.common.socket.clone(); + let wayland_display = self.common.wayland_display.clone(); let display = self .common .xwayland_state diff --git a/src/lib.rs b/src/lib.rs index 09d1b961..c76877f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,8 +19,8 @@ use anyhow::{Context, Result}; use state::{LastRefresh, State}; use std::{ env, - ffi::OsString, os::unix::process::CommandExt, + path::PathBuf, process, sync::Arc, time::{Duration, Instant}, @@ -161,17 +161,17 @@ pub fn run(hooks: crate::hooks::Hooks) -> Result<(), Box> { // init event loop let mut event_loop = EventLoop::try_new().with_context(|| "Failed to initialize event loop")?; // init wayland - let (display, socket) = init_wayland_display(&mut event_loop)?; + let (display_handle, wayland_display) = init_wayland_display(&mut event_loop)?; // init state let mut state = state::State::new( - &display, - socket, + &display_handle, + wayland_display, event_loop.handle(), event_loop.get_signal(), with_xwayland, ); // init backend - backend::init_backend_auto(&display, &mut event_loop, &mut state)?; + backend::init_backend_auto(&display_handle, &mut event_loop, &mut state)?; if let Err(err) = theme::watch_theme(event_loop.handle()) { warn!(?err, "Failed to watch theme"); @@ -264,13 +264,13 @@ Options: fn init_wayland_display( event_loop: &mut EventLoop, -) -> Result<(DisplayHandle, OsString)> { +) -> Result<(DisplayHandle, PathBuf)> { let display = Display::new().unwrap(); let handle = display.handle(); let source = ListeningSocketSource::new_auto().unwrap(); - let socket_name = source.socket_name().to_os_string(); - info!("Listening on {:?}", socket_name); + let socket_path = source.socket_path().to_path_buf(); + info!("Listening on {:?}", socket_path); event_loop .handle() @@ -303,7 +303,7 @@ fn init_wayland_display( ) .with_context(|| "Failed to init the wayland event source.")?; - Ok((handle, socket_name)) + Ok((handle, socket_path)) } fn refresh(state: &mut State) { diff --git a/src/session.rs b/src/session.rs index 0b4025a6..b9f40eb3 100644 --- a/src/session.rs +++ b/src/session.rs @@ -61,8 +61,9 @@ pub fn get_env(common: &Common) -> Result> { env.insert( String::from("WAYLAND_DISPLAY"), common - .socket + .wayland_display .clone() + .into_os_string() .into_string() .map_err(|_| anyhow!("wayland socket is no valid utf-8 string?"))?, ); diff --git a/src/state.rs b/src/state.rs index 18de36ba..9af9c20b 100644 --- a/src/state.rs +++ b/src/state.rs @@ -124,7 +124,7 @@ use std::{ cell::RefCell, cmp::min, collections::HashSet, - ffi::OsString, + path::PathBuf, process::Child, sync::{Arc, LazyLock, Once, atomic::AtomicBool}, time::{Duration, Instant}, @@ -230,7 +230,7 @@ smithay::delegate_dispatch2!(State); pub struct Common { pub config: Config, - pub socket: OsString, + pub wayland_display: PathBuf, pub display_handle: DisplayHandle, pub event_loop_handle: LoopHandle<'static, State>, pub event_loop_signal: LoopSignal, @@ -625,7 +625,7 @@ fn client_not_sandboxed(client: &Client) -> bool { impl State { pub fn new( dh: &DisplayHandle, - socket: OsString, + wayland_display: PathBuf, handle: LoopHandle<'static, State>, signal: LoopSignal, with_xwayland: bool, @@ -734,7 +734,7 @@ impl State { State { common: Common { config, - socket, + wayland_display, display_handle: dh.clone(), event_loop_handle: handle, event_loop_signal: signal, diff --git a/src/systemd.rs b/src/systemd.rs index 422d91c9..3848e215 100644 --- a/src/systemd.rs +++ b/src/systemd.rs @@ -9,7 +9,7 @@ pub fn ready(common: &Common) { if booted() { match Command::new("systemctl") .args(["--user", "import-environment", "WAYLAND_DISPLAY", "DISPLAY"]) - .env("WAYLAND_DISPLAY", &common.socket) + .env("WAYLAND_DISPLAY", &common.wayland_display) .env( "DISPLAY", common -- 2.54.0 From f3f5d571ff68a72b608368b049c39b2f40986154 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Fri, 26 Jun 2026 18:26:36 +0200 Subject: [PATCH 2/2] Add --socket-path argument This allows specifying an absolute path where cosmic-comp will put its Wayland socket. This is useful for integrated systems that know they'll have a single seat, and benefit from the predictability of a known path for it. It also makes it easier to implement strong privilege separation on such systems, by enabling running clients as different users than the compositor (with different XDG_RUNTIME_DIRs). --- src/lib.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c76877f3..652b079d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -115,6 +115,7 @@ pub fn run(hooks: crate::hooks::Hooks) -> Result<(), Box> { let mut cursor = raw_args.cursor(); let git_hash = option_env!("GIT_HASH").unwrap_or("unknown"); + let mut socket_path = None; let mut with_xwayland = true; // Parse the arguments while let Some(arg) = raw_args.next_os(&mut cursor) { @@ -127,6 +128,10 @@ pub fn run(hooks: crate::hooks::Hooks) -> Result<(), Box> { tracing::info!("Running without Xwayland"); with_xwayland = false; } + Some("--socket-path") => { + let path = raw_args.next_os(&mut cursor).expect("no socket name given"); + socket_path = Some(path.into()); + } Some("--version") | Some("-V") => { println!( "cosmic-comp {} (git commit {})", @@ -161,7 +166,7 @@ pub fn run(hooks: crate::hooks::Hooks) -> Result<(), Box> { // init event loop let mut event_loop = EventLoop::try_new().with_context(|| "Failed to initialize event loop")?; // init wayland - let (display_handle, wayland_display) = init_wayland_display(&mut event_loop)?; + let (display_handle, wayland_display) = init_wayland_display(socket_path, &mut event_loop)?; // init state let mut state = state::State::new( &display_handle, @@ -263,12 +268,18 @@ Options: } fn init_wayland_display( + socket_path: Option, event_loop: &mut EventLoop, ) -> Result<(DisplayHandle, PathBuf)> { let display = Display::new().unwrap(); let handle = display.handle(); - let source = ListeningSocketSource::new_auto().unwrap(); + let source = if let Some(socket_path) = socket_path { + ListeningSocketSource::with_path(socket_path).unwrap() + } else { + ListeningSocketSource::new_auto().unwrap() + }; + let socket_path = source.socket_path().to_path_buf(); info!("Listening on {:?}", socket_path); -- 2.54.0