Skip to content

Commit

Permalink
feat: add desktop entry actions
Browse files Browse the repository at this point in the history
  • Loading branch information
oknozor committed Jun 6, 2022
1 parent eaa21ff commit fd6e2f9
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 19 deletions.
26 changes: 21 additions & 5 deletions src/exec/dbus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ trait Application {
}

impl DesktopEntry<'_> {
pub(crate) fn dbus_launch(&self, conn: &Connection, uris: &[&str]) -> Result<(), ExecError> {
pub(crate) fn dbus_launch(
&self,
conn: &Connection,
uris: &[&str],
action: Option<String>,
) -> Result<(), ExecError> {
let dbus_path = self.appid.replace('.', "/");
let dbus_path = format!("/{dbus_path}");
let app_proxy = ApplicationProxyBlocking::builder(conn)
Expand All @@ -41,10 +46,21 @@ impl DesktopEntry<'_> {
}
}

if !uris.is_empty() {
app_proxy.open(uris, platform_data)?;
} else {
app_proxy.activate(platform_data)?;
match action {
None => {
if !uris.is_empty() {
app_proxy.open(uris, platform_data)?;
} else {
app_proxy.activate(platform_data)?;
}
}
Some(action) => {
let parameters: Vec<OwnedValue> = uris
.iter()
.map(|uri| OwnedValue::from(Str::from(*uri)))
.collect();
app_proxy.activate_action(&action, parameters.as_slice(), platform_data)?
}
}

Ok(())
Expand Down
12 changes: 12 additions & 0 deletions src/exec/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ pub enum ExecError<'a> {
#[error("Exec key not found in desktop entry '{0:?}'")]
MissingExecKey(&'a Path),

#[error("Action '{action}' not found for desktop entry '{desktop_entry:?}'")]
ActionNotFound {
action: String,
desktop_entry: &'a Path,
},

#[error("Exec key not found for action :'{action}' in desktop entry '{desktop_entry:?}'")]
ActionExecKeyNotFound {
action: String,
desktop_entry: &'a Path,
},

#[error("Failed to launch aplication via dbus: {0}")]
DBusError(#[from] zbus::Error),
}
83 changes: 73 additions & 10 deletions src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,69 @@ pub mod error;
mod graphics;

impl DesktopEntry<'_> {
/// Launch the given desktop entry action either via dbus or via its `Exec` key with the default gpu or
/// the alternative one if available.
pub fn launch_action(&self, action: &str, uris: &[&str]) -> Result<(), ExecError> {
let has_action = self
.actions()
.map(|actions| actions.split(';').any(|act| act == action))
.unwrap_or(false);

if !has_action {
return Err(ExecError::ActionNotFound {
action: action.to_string(),
desktop_entry: self.path,
});
}

match Connection::session() {
Ok(conn) => {
if self.is_bus_actionable(&conn) {
self.dbus_launch(&conn, uris, Some(action.to_string()))
} else {
self.shell_launch(uris, Some(action.to_string()))
}
}
Err(_) => self.shell_launch(uris, Some(action.to_string())),
}
}

/// Launch the given desktop entry either via dbus or via its `Exec` key with the default gpu or
/// the alternative one if available.
pub fn launch(&self, uris: &[&str]) -> Result<(), ExecError> {
match Connection::session() {
Ok(conn) => {
if self.is_bus_actionable(&conn) {
self.dbus_launch(&conn, uris)
self.dbus_launch(&conn, uris, None)
} else {
self.shell_launch(uris)
self.shell_launch(uris, None)
}
}
Err(_) => self.shell_launch(uris),
Err(_) => self.shell_launch(uris, None),
}
}

fn shell_launch(&self, uris: &[&str]) -> Result<(), ExecError> {
let exec = self.exec();
if exec.is_none() {
return Err(ExecError::MissingExecKey(self.path));
}
fn shell_launch(&self, uris: &[&str], action: Option<String>) -> Result<(), ExecError> {
let exec = match action {
None => {
let exec = self.exec();
if exec.is_none() {
return Err(ExecError::MissingExecKey(self.path));
}
exec.unwrap()
}
Some(action) => {
let exec = self.action_exec(&action);
if exec.is_none() {
return Err(ExecError::ActionExecKeyNotFound {
action,
desktop_entry: self.path,
});
}

let exec = exec.unwrap();
exec.unwrap()
}
};

let mut exec_args = vec![];

Expand Down Expand Up @@ -281,12 +322,34 @@ mod test {
let de = DesktopEntry::decode(path.as_path(), &input).unwrap();
let path = std::env::current_dir().unwrap();
let path = path.to_string_lossy();
let path = format!("file:///{path}");
let path = format!("file://{path}");
let result = de.launch(&[path.as_str()]);

assert_that!(result).is_ok();
}

#[test]
#[ignore = "Needs a desktop environment with alacritty installed, run locally only"]
fn should_launch_action() {
let path = PathBuf::from("/usr/share/applications/Alacritty.desktop");
let input = fs::read_to_string(&path).unwrap();
let de = DesktopEntry::decode(path.as_path(), &input).unwrap();
let result = de.launch_action("New", &[]);

assert_that!(result).is_ok();
}

#[test]
#[ignore = "Needs a desktop environment with Nautilus installed, run locally only"]
fn should_launch_action_via_dbus() {
let path = PathBuf::from("/usr/share/applications/org.gnome.Nautilus.desktop");
let input = fs::read_to_string(&path).unwrap();
let de = DesktopEntry::decode(path.as_path(), &input).unwrap();
let result = de.launch_action("new-window", &[]);

assert_that!(result).is_ok();
}

#[test]
fn should_build_command_with_gpu() {
let cmd = with_non_default_gpu(Command::new("glxgears"));
Expand Down
2 changes: 1 addition & 1 deletion tests/entries/empty-exec.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Exec=
Terminal=false
Type=Application
Name=Alacritty
Name=NoExecKey
2 changes: 1 addition & 1 deletion tests/entries/non-terminal-cmd.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Exec=alacritty -e glxgears -info
Terminal=false
Type=Application
Name=Alacritty
Name=GlxGearNoTerminal
2 changes: 1 addition & 1 deletion tests/entries/terminal-cmd.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Exec=glxgears -info
Terminal=true
Type=Application
Name=Alacritty
Name=GlxGearTerminal
2 changes: 1 addition & 1 deletion tests/entries/unmatched-quotes.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Exec="alacritty -e
Terminal=false
Type=Application
Name=Alacritty
Name=InvalidCommand

0 comments on commit fd6e2f9

Please sign in to comment.