Call systemd StartTransientUnit what starting app
This is needed for things like `xdg-desktop-portal` to get the app ID from a pid, in unsandboxed apps. https://systemd.io/DESKTOP_ENVIRONMENTS documents this, and this sets things similarly to how Gnome does. Which should be good for now. Making `spawn_desktop_exec` an `async` function is reasonable given it is called in `async` functions in `cosmic-app-list`/`cosmic-launcher`/`cosmic-applibrary`.
This commit is contained in:
parent
fe035e37b0
commit
621de17cad
2 changed files with 59 additions and 5 deletions
|
|
@ -33,7 +33,9 @@ desktop = [
|
|||
"dep:freedesktop-desktop-entry",
|
||||
"dep:mime",
|
||||
"dep:shlex",
|
||||
"dep:tokio",
|
||||
"dep:textdistance",
|
||||
"dep:zbus",
|
||||
]
|
||||
# Enables keycode serialization
|
||||
serde-keycode = ["iced_core/serde"]
|
||||
|
|
@ -96,7 +98,7 @@ tokio = { version = "1.24.2", optional = true }
|
|||
tracing = "0.1"
|
||||
unicode-segmentation = "1.6"
|
||||
url = "2.4.0"
|
||||
zbus = { version = "4.2.1", default-features = false, optional = true }
|
||||
zbus = { version = "4.2.1", default-features = false, features = ["tokio"], optional = true }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
freedesktop-icons = "0.2.5"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use std::{
|
|||
ffi::OsStr,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use zbus::zvariant;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum IconSource {
|
||||
|
|
@ -306,7 +307,7 @@ impl DesktopEntryData {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn spawn_desktop_exec<S, I, K, V>(exec: S, env_vars: I)
|
||||
pub async fn spawn_desktop_exec<S, I, K, V>(exec: S, env_vars: I, app_id: Option<&str>)
|
||||
where
|
||||
S: AsRef<str>,
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
|
|
@ -314,11 +315,14 @@ where
|
|||
V: AsRef<OsStr>,
|
||||
{
|
||||
let mut exec = shlex::Shlex::new(exec.as_ref());
|
||||
let mut cmd = match exec.next() {
|
||||
Some(cmd) if !cmd.contains('=') => std::process::Command::new(cmd),
|
||||
|
||||
let executable = match exec.next() {
|
||||
Some(executable) if !executable.contains('=') => executable,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let mut cmd = std::process::Command::new(&executable);
|
||||
|
||||
for arg in exec {
|
||||
// TODO handle "%" args here if necessary?
|
||||
if !arg.starts_with('%') {
|
||||
|
|
@ -328,5 +332,53 @@ where
|
|||
|
||||
cmd.envs(env_vars);
|
||||
|
||||
crate::process::spawn(cmd);
|
||||
// https://systemd.io/DESKTOP_ENVIRONMENTS
|
||||
//
|
||||
// Similar to what Gnome sets, for now.
|
||||
if let Ok(Some(pid)) = tokio::task::spawn_blocking(|| crate::process::spawn(cmd)).await {
|
||||
if let Ok(session) = zbus::Connection::session().await {
|
||||
if let Ok(systemd_manager) = SystemdMangerProxy::new(&session).await {
|
||||
let _ = systemd_manager
|
||||
.start_transient_unit(
|
||||
&format!("app-cosmic-{}-{}.scope", app_id.unwrap_or(&executable), pid),
|
||||
"fail",
|
||||
&[
|
||||
(
|
||||
"Description".to_string(),
|
||||
zvariant::Value::from("Application launched by COSMIC")
|
||||
.try_to_owned()
|
||||
.unwrap(),
|
||||
),
|
||||
(
|
||||
"PIDs".to_string(),
|
||||
zvariant::Value::from(vec![pid]).try_to_owned().unwrap(),
|
||||
),
|
||||
(
|
||||
"CollectMode".to_string(),
|
||||
zvariant::Value::from("inactive-or-failed")
|
||||
.try_to_owned()
|
||||
.unwrap(),
|
||||
),
|
||||
],
|
||||
&[],
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[zbus::proxy(
|
||||
interface = "org.freedesktop.systemd1.Manager",
|
||||
default_service = "org.freedesktop.systemd1",
|
||||
default_path = "/org/freedesktop/systemd1"
|
||||
)]
|
||||
trait SystemdManger {
|
||||
async fn start_transient_unit(
|
||||
&self,
|
||||
name: &str,
|
||||
mode: &str,
|
||||
properties: &[(String, zvariant::OwnedValue)],
|
||||
aux: &[(String, Vec<(String, zvariant::OwnedValue)>)],
|
||||
) -> zbus::Result<zvariant::OwnedObjectPath>;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue