fix: pass systemd user env vars to cosmic-session
Read the env vars of the systemd user manager before cosmic-comp starts and pass them to it. fixes #171
This commit is contained in:
parent
ad097e98ec
commit
a692a3006a
3 changed files with 54 additions and 54 deletions
|
|
@ -99,6 +99,7 @@ pub fn run_compositor(
|
||||||
process_manager: &ProcessManager,
|
process_manager: &ProcessManager,
|
||||||
exec: String,
|
exec: String,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
|
env: Vec<(String, String)>,
|
||||||
_token: CancellationToken,
|
_token: CancellationToken,
|
||||||
env_tx: oneshot::Sender<HashMap<String, String>>,
|
env_tx: oneshot::Sender<HashMap<String, String>>,
|
||||||
session_dbus_tx: mpsc::Sender<SessionRequest>,
|
session_dbus_tx: mpsc::Sender<SessionRequest>,
|
||||||
|
|
@ -119,6 +120,7 @@ pub fn run_compositor(
|
||||||
OwnedFd::from(std_stream)
|
OwnedFd::from(std_stream)
|
||||||
};
|
};
|
||||||
mark_as_not_cloexec(&comp).expect("Failed to mark fd as not cloexec");
|
mark_as_not_cloexec(&comp).expect("Failed to mark fd as not cloexec");
|
||||||
|
|
||||||
Ok(tokio::spawn(async move {
|
Ok(tokio::spawn(async move {
|
||||||
// Create a new process handler for cosmic-comp, with our compositor socket's
|
// Create a new process handler for cosmic-comp, with our compositor socket's
|
||||||
// file descriptor as the `COSMIC_SESSION_SOCK` environment variable.
|
// file descriptor as the `COSMIC_SESSION_SOCK` environment variable.
|
||||||
|
|
@ -127,7 +129,10 @@ pub fn run_compositor(
|
||||||
Process::new()
|
Process::new()
|
||||||
.with_executable(exec)
|
.with_executable(exec)
|
||||||
.with_args(args)
|
.with_args(args)
|
||||||
.with_env([("COSMIC_SESSION_SOCK", comp.as_raw_fd().to_string())])
|
.with_env(env.into_iter().chain([(
|
||||||
|
"COSMIC_SESSION_SOCK".to_string(),
|
||||||
|
comp.as_raw_fd().to_string(),
|
||||||
|
)]))
|
||||||
.with_on_exit(move |pman, _, err_code, _will_restart| {
|
.with_on_exit(move |pman, _, err_code, _will_restart| {
|
||||||
let session_dbus_tx = session_dbus_tx.clone();
|
let session_dbus_tx = session_dbus_tx.clone();
|
||||||
async move {
|
async move {
|
||||||
|
|
|
||||||
40
src/main.rs
40
src/main.rs
|
|
@ -24,9 +24,9 @@ use std::path::PathBuf;
|
||||||
#[cfg(feature = "autostart")]
|
#[cfg(feature = "autostart")]
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use systemd::is_systemd_used;
|
|
||||||
#[cfg(feature = "systemd")]
|
#[cfg(feature = "systemd")]
|
||||||
use systemd::{get_systemd_env, spawn_scope};
|
use systemd::spawn_scope;
|
||||||
|
use systemd::{get_systemd_env, is_systemd_used};
|
||||||
use tokio::signal::unix::{SignalKind, signal};
|
use tokio::signal::unix::{SignalKind, signal};
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
use tokio::sync::mpsc::{Receiver, Sender};
|
||||||
use tokio::sync::{Mutex, oneshot};
|
use tokio::sync::{Mutex, oneshot};
|
||||||
|
|
@ -143,10 +143,12 @@ async fn start(
|
||||||
.await;
|
.await;
|
||||||
let token = CancellationToken::new();
|
let token = CancellationToken::new();
|
||||||
let (env_tx, env_rx) = oneshot::channel();
|
let (env_tx, env_rx) = oneshot::channel();
|
||||||
|
let systemd_env = get_systemd_env().await;
|
||||||
let compositor_handle = comp::run_compositor(
|
let compositor_handle = comp::run_compositor(
|
||||||
&process_manager,
|
&process_manager,
|
||||||
executable.clone(),
|
executable.clone(),
|
||||||
args,
|
args,
|
||||||
|
systemd_env.clone(),
|
||||||
token.child_token(),
|
token.child_token(),
|
||||||
env_tx,
|
env_tx,
|
||||||
session_tx,
|
session_tx,
|
||||||
|
|
@ -163,8 +165,12 @@ async fn start(
|
||||||
env_vars
|
env_vars
|
||||||
);
|
);
|
||||||
|
|
||||||
// now that cosmic-comp is ready, set XDG_SESSION_TYPE=wayland for new processes
|
// now that cosmic-comp is ready, extend the env vars with the systemd_env and set XDG_SESSION_TYPE=wayland for new processes
|
||||||
env_vars.push(("XDG_SESSION_TYPE".to_string(), "wayland".to_string()));
|
env_vars.extend(
|
||||||
|
systemd_env
|
||||||
|
.into_iter()
|
||||||
|
.chain([("XDG_SESSION_TYPE".to_string(), "wayland".to_string())]),
|
||||||
|
);
|
||||||
systemd::set_systemd_environment("XDG_SESSION_TYPE", "wayland").await;
|
systemd::set_systemd_environment("XDG_SESSION_TYPE", "wayland").await;
|
||||||
|
|
||||||
// expose the session version
|
// expose the session version
|
||||||
|
|
@ -176,32 +182,6 @@ async fn start(
|
||||||
|
|
||||||
#[cfg(feature = "systemd")]
|
#[cfg(feature = "systemd")]
|
||||||
let _inhibit_fd = if *is_systemd_used() {
|
let _inhibit_fd = if *is_systemd_used() {
|
||||||
match get_systemd_env().await {
|
|
||||||
Ok(env) => {
|
|
||||||
for systemd_env in env {
|
|
||||||
// Only update the envvar if unset
|
|
||||||
if std::env::var_os(&systemd_env.key).is_none() {
|
|
||||||
// Blacklist of envvars that we shouldn't touch (taken from KDE)
|
|
||||||
if (!systemd_env.key.starts_with("XDG_")
|
|
||||||
|| systemd_env.key == "XDG_DATA_DIRS"
|
|
||||||
|| systemd_env.key == "XDG_CONFIG_DIRS")
|
|
||||||
&& systemd_env.key != "DISPLAY"
|
|
||||||
&& systemd_env.key != "XAUTHORITY"
|
|
||||||
&& systemd_env.key != "WAYLAND_DISPLAY"
|
|
||||||
&& systemd_env.key != "WAYLAND_SOCKET"
|
|
||||||
&& systemd_env.key != "_"
|
|
||||||
&& systemd_env.key != "SHELL"
|
|
||||||
&& systemd_env.key != "SHLVL"
|
|
||||||
{
|
|
||||||
env_vars.push((systemd_env.key, systemd_env.value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
warn!("Failed to sync systemd environment {}.", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#[cfg(feature = "logind")]
|
#[cfg(feature = "logind")]
|
||||||
match zbus::Connection::system().await {
|
match zbus::Connection::system().await {
|
||||||
Ok(connection) => match logind_zbus::manager::ManagerProxy::new(&connection).await {
|
Ok(connection) => match logind_zbus::manager::ManagerProxy::new(&connection).await {
|
||||||
|
|
|
||||||
|
|
@ -4,24 +4,10 @@ use std::path::Path;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
#[cfg(feature = "systemd")]
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
use zbus::zvariant::{Array, OwnedValue};
|
use zbus::zvariant::{Array, OwnedValue};
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct EnvVar {
|
|
||||||
pub key: String,
|
|
||||||
pub value: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(&str, &str)> for EnvVar {
|
|
||||||
fn from(val: (&str, &str)) -> Self {
|
|
||||||
EnvVar {
|
|
||||||
key: val.0.to_owned(),
|
|
||||||
value: val.1.to_owned(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "systemd")]
|
#[cfg(feature = "systemd")]
|
||||||
use zbus_systemd::systemd1::ManagerProxy as SystemdManagerProxy;
|
use zbus_systemd::systemd1::ManagerProxy as SystemdManagerProxy;
|
||||||
|
|
||||||
|
|
@ -54,18 +40,47 @@ pub fn is_systemd_used() -> &'static bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "systemd")]
|
#[cfg(feature = "systemd")]
|
||||||
pub async fn get_systemd_env() -> Result<Vec<EnvVar>, zbus::Error> {
|
async fn load_systemd_env() -> zbus::Result<Vec<String>> {
|
||||||
let connection = Connection::session().await?;
|
let connection = Connection::session().await?;
|
||||||
let systemd_manager = SystemdManagerProxy::new(&connection).await?;
|
let systemd_manager = SystemdManagerProxy::new(&connection).await?;
|
||||||
let systemd_env = systemd_manager.environment().await?;
|
systemd_manager.environment().await
|
||||||
|
}
|
||||||
|
|
||||||
let mut out: Vec<EnvVar> = Vec::new();
|
/// Get the systemd user manager environment variables.
|
||||||
for i in systemd_env {
|
/// Is Empty if systemd isn't used.
|
||||||
if let Some(b) = i.split_once("=") {
|
pub async fn get_systemd_env() -> Vec<(String, String)> {
|
||||||
out.push(b.into());
|
#[cfg(feature = "systemd")]
|
||||||
}
|
if *is_systemd_used() {
|
||||||
|
return match load_systemd_env().await {
|
||||||
|
Ok(env) => {
|
||||||
|
env.iter()
|
||||||
|
// split into key value pairs
|
||||||
|
.filter_map(|var| var.split_once("="))
|
||||||
|
.filter(|&(key, _value)| {
|
||||||
|
// Only update the envvar if unset
|
||||||
|
std::env::var_os(key).is_none()
|
||||||
|
// Blocklist of envvars that we shouldn't touch (taken from KDE)
|
||||||
|
&& (!key.starts_with("XDG_")
|
||||||
|
|| key == "XDG_DATA_DIRS"
|
||||||
|
|| key == "XDG_CONFIG_DIRS")
|
||||||
|
&& key != "DISPLAY"
|
||||||
|
&& key != "XAUTHORITY"
|
||||||
|
&& key != "WAYLAND_DISPLAY"
|
||||||
|
&& key != "WAYLAND_SOCKET"
|
||||||
|
&& key != "_"
|
||||||
|
&& key != "SHELL"
|
||||||
|
&& key != "SHLVL"
|
||||||
|
})
|
||||||
|
.map(|(key, value)| (key.to_owned(), value.to_owned()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("Failed to sync systemd environment {}.", err);
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Ok(out)
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "systemd")]
|
#[cfg(feature = "systemd")]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue