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
622aebe1c9
commit
a2c9a4ede2
2 changed files with 59 additions and 5 deletions
|
|
@ -33,7 +33,9 @@ desktop = [
|
||||||
"dep:freedesktop-desktop-entry",
|
"dep:freedesktop-desktop-entry",
|
||||||
"dep:mime",
|
"dep:mime",
|
||||||
"dep:shlex",
|
"dep:shlex",
|
||||||
|
"dep:tokio",
|
||||||
"dep:textdistance",
|
"dep:textdistance",
|
||||||
|
"dep:zbus",
|
||||||
]
|
]
|
||||||
# Enables keycode serialization
|
# Enables keycode serialization
|
||||||
serde-keycode = ["iced_core/serde"]
|
serde-keycode = ["iced_core/serde"]
|
||||||
|
|
@ -96,7 +98,7 @@ tokio = { version = "1.24.2", optional = true }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
unicode-segmentation = "1.6"
|
unicode-segmentation = "1.6"
|
||||||
url = "2.4.0"
|
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]
|
[target.'cfg(unix)'.dependencies]
|
||||||
freedesktop-icons = "0.2.5"
|
freedesktop-icons = "0.2.5"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use std::{
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
use zbus::zvariant;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum IconSource {
|
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
|
where
|
||||||
S: AsRef<str>,
|
S: AsRef<str>,
|
||||||
I: IntoIterator<Item = (K, V)>,
|
I: IntoIterator<Item = (K, V)>,
|
||||||
|
|
@ -314,11 +315,14 @@ where
|
||||||
V: AsRef<OsStr>,
|
V: AsRef<OsStr>,
|
||||||
{
|
{
|
||||||
let mut exec = shlex::Shlex::new(exec.as_ref());
|
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,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut cmd = std::process::Command::new(&executable);
|
||||||
|
|
||||||
for arg in exec {
|
for arg in exec {
|
||||||
// TODO handle "%" args here if necessary?
|
// TODO handle "%" args here if necessary?
|
||||||
if !arg.starts_with('%') {
|
if !arg.starts_with('%') {
|
||||||
|
|
@ -328,5 +332,53 @@ where
|
||||||
|
|
||||||
cmd.envs(env_vars);
|
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