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,
|
||||
exec: String,
|
||||
args: Vec<String>,
|
||||
env: Vec<(String, String)>,
|
||||
_token: CancellationToken,
|
||||
env_tx: oneshot::Sender<HashMap<String, String>>,
|
||||
session_dbus_tx: mpsc::Sender<SessionRequest>,
|
||||
|
|
@ -119,6 +120,7 @@ pub fn run_compositor(
|
|||
OwnedFd::from(std_stream)
|
||||
};
|
||||
mark_as_not_cloexec(&comp).expect("Failed to mark fd as not cloexec");
|
||||
|
||||
Ok(tokio::spawn(async move {
|
||||
// Create a new process handler for cosmic-comp, with our compositor socket's
|
||||
// file descriptor as the `COSMIC_SESSION_SOCK` environment variable.
|
||||
|
|
@ -127,7 +129,10 @@ pub fn run_compositor(
|
|||
Process::new()
|
||||
.with_executable(exec)
|
||||
.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| {
|
||||
let session_dbus_tx = session_dbus_tx.clone();
|
||||
async move {
|
||||
|
|
|
|||
40
src/main.rs
40
src/main.rs
|
|
@ -24,9 +24,9 @@ use std::path::PathBuf;
|
|||
#[cfg(feature = "autostart")]
|
||||
use std::process::{Command, Stdio};
|
||||
use std::sync::Arc;
|
||||
use systemd::is_systemd_used;
|
||||
#[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::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::{Mutex, oneshot};
|
||||
|
|
@ -143,10 +143,12 @@ async fn start(
|
|||
.await;
|
||||
let token = CancellationToken::new();
|
||||
let (env_tx, env_rx) = oneshot::channel();
|
||||
let systemd_env = get_systemd_env().await;
|
||||
let compositor_handle = comp::run_compositor(
|
||||
&process_manager,
|
||||
executable.clone(),
|
||||
args,
|
||||
systemd_env.clone(),
|
||||
token.child_token(),
|
||||
env_tx,
|
||||
session_tx,
|
||||
|
|
@ -163,8 +165,12 @@ async fn start(
|
|||
env_vars
|
||||
);
|
||||
|
||||
// now that cosmic-comp is ready, set XDG_SESSION_TYPE=wayland for new processes
|
||||
env_vars.push(("XDG_SESSION_TYPE".to_string(), "wayland".to_string()));
|
||||
// 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.extend(
|
||||
systemd_env
|
||||
.into_iter()
|
||||
.chain([("XDG_SESSION_TYPE".to_string(), "wayland".to_string())]),
|
||||
);
|
||||
systemd::set_systemd_environment("XDG_SESSION_TYPE", "wayland").await;
|
||||
|
||||
// expose the session version
|
||||
|
|
@ -176,32 +182,6 @@ async fn start(
|
|||
|
||||
#[cfg(feature = "systemd")]
|
||||
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")]
|
||||
match zbus::Connection::system().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::sync::OnceLock;
|
||||
|
||||
#[cfg(feature = "systemd")]
|
||||
use zbus::Connection;
|
||||
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")]
|
||||
use zbus_systemd::systemd1::ManagerProxy as SystemdManagerProxy;
|
||||
|
||||
|
|
@ -54,18 +40,47 @@ pub fn is_systemd_used() -> &'static bool {
|
|||
}
|
||||
|
||||
#[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 systemd_manager = SystemdManagerProxy::new(&connection).await?;
|
||||
let systemd_env = systemd_manager.environment().await?;
|
||||
systemd_manager.environment().await
|
||||
}
|
||||
|
||||
let mut out: Vec<EnvVar> = Vec::new();
|
||||
for i in systemd_env {
|
||||
if let Some(b) = i.split_once("=") {
|
||||
out.push(b.into());
|
||||
}
|
||||
/// Get the systemd user manager environment variables.
|
||||
/// Is Empty if systemd isn't used.
|
||||
pub async fn get_systemd_env() -> Vec<(String, String)> {
|
||||
#[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")]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue