Skip to content

[DOC] make systemd-run example more reliable#2048

Open
Atemu wants to merge 5 commits intodavatorium:nextfrom
Atemu:escape-systemd-run
Open

[DOC] make systemd-run example more reliable#2048
Atemu wants to merge 5 commits intodavatorium:nextfrom
Atemu:escape-systemd-run

Conversation

@Atemu
Copy link
Copy Markdown

@Atemu Atemu commented Nov 10, 2024

This is a follow-up to #1752

If the {cmd} had spaces in it, it would error out with something like

Failed to find executable gui-22345: No such file or directory

(In this case the command was
/nix/store/6jlqjighx0v0lqx9bahc7nl6npshim2r-lact-0.5.6/bin/lact gui)

This fixes that.

What this also fixes is that this would result in incredibly long names such as --unit=app-rofi--nix-store-6jlqjighx0v0lqx9bahc7nl6npshim2r\x2dlact\x2d0.5.6-bin-lact because the desktop entry contained the full path which can be quite long in Nix and is quite common in Nix packaging.

We only really care about the executable name here.

The current iteration still has command arguments in its name but getting rid of those would be quite bothersome in bash. IME apps also usually don't have command line args and if they do it's usually something short like in the example above. This could certainly be improved though.

cc @mweinelt

This is a follow-up to davatorium#1752

If the `{cmd}` had spaces in it, it would error out with something like

    Failed to find executable gui-22345: No such file or directory

(In this case the command was
`/nix/store/6jlqjighx0v0lqx9bahc7nl6npshim2r-lact-0.5.6/bin/lact gui`)

This fixes that.

What this also fixes is that this would result in incredibly long names such as
`--unit=app-rofi--nix-store-6jlqjighx0v0lqx9bahc7nl6npshim2r\x2dlact\x2d0.5.6-bin-lact`
because the desktop entry contained the full path which can be quite long in Nix
and is quite common in Nix packaging.

We only really care about the executable name here.

The current iteration still has command arguments in its name but getting rid of
those would be quite bothersome in bash. IME apps also usually don't have
command line args and if they do it's usually something short like in the
example above. This could certainly be improved though.
@Atemu
Copy link
Copy Markdown
Author

Atemu commented Nov 10, 2024

Aaaand I already found something that breaks this: The emacsclient desktop file does this:

Exec=sh -c "if [ -n \\"\\$*\\" ]; then exec /nix/store/fsglyaxfhlavaskr159b4yyjlajy4qq5-emacs-29.4/bin/emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" \\"\\$@\\"; else exec emacsclient --alternate-editor= --create-frame; fi" sh %F

Ugh.

What we really want here is the desktop file's name.

@DaveDavenport
Copy link
Copy Markdown
Collaborator

What we really want here is the desktop file's name.

We could pass the desktop file full path ? would that help?

@Atemu
Copy link
Copy Markdown
Author

Atemu commented Nov 10, 2024

That'd be immensely helpful indeed. We only need the basename but that's easy enough to extract as shown here. Although getting the name without the .desktop suffix would be rather annoying, hm.

@DaveDavenport
Copy link
Copy Markdown
Collaborator

A quick test, will this work?

diff --git a/include/helper.h b/include/helper.h
index ed161931..6e9a28f1 100644
--- a/include/helper.h
+++ b/include/helper.h
@@ -330,6 +330,23 @@ gboolean helper_execute_command(const char *wd, const char *cmd,
                                 gboolean run_in_term,
                                 RofiHelperExecuteContext *context);
 
+/**
+ * @param wd The work directory (optional)
+ * @param cmd The cmd to execute
+ * @param run_in_term Indicate if command should be run in a terminal
+ * @param context The startup notification context, if any
+ * @param ... tuples of extra parameters the string can search/replace
+ *
+ * Execute command.
+ * If needed members of context are NULL, they will be filled.
+ * Pass {cmd} into the va-arg list.
+ *
+ * @returns FALSE On failure, TRUE on success
+ */
+gboolean helper_execute_command_full(const char *wd, const char *cmd,
+                                     gboolean run_in_term,
+                                     RofiHelperExecuteContext *context, ...);
+
 /**
  * @param file The file path
  * @param height The wanted height
diff --git a/source/helper.c b/source/helper.c
index 53f366bf..0bf417c6 100644
--- a/source/helper.c
+++ b/source/helper.c
@@ -72,7 +72,8 @@ void cmd_set_arguments(int argc, char **argv) {
   stored_argv = argv;
 }
 
-int helper_parse_setup(char *string, char ***output, int *length, ...) {
+static int helper_parse_setup_v(char *string, char ***output, int *length,
+                                va_list ap) {
   GError *error = NULL;
   GHashTable *h;
   h = g_hash_table_new(g_str_hash, g_str_equal);
@@ -80,8 +81,6 @@ int helper_parse_setup(char *string, char ***output, int *length, ...) {
   g_hash_table_insert(h, "{terminal}", config.terminal_emulator);
   g_hash_table_insert(h, "{ssh-client}", config.ssh_client);
   // Add list from variable arguments.
-  va_list ap;
-  va_start(ap, length);
   while (1) {
     char *key = va_arg(ap, char *);
     if (key == (char *)0) {
@@ -93,7 +92,6 @@ int helper_parse_setup(char *string, char ***output, int *length, ...) {
     }
     g_hash_table_insert(h, key, value);
   }
-  va_end(ap);
 
   char *res = helper_string_replace_if_exists_v(string, h);
   // Destroy key-value storage.
@@ -115,6 +113,13 @@ int helper_parse_setup(char *string, char ***output, int *length, ...) {
   }
   return FALSE;
 }
+int helper_parse_setup(char *string, char ***output, int *length, ...) {
+  va_list ap;
+  va_start(ap, length);
+  int retv = helper_parse_setup_v(string, output, length, ap);
+  va_end(ap);
+  return retv;
+}
 
 void helper_tokenize_free(rofi_int_matcher **tokens) {
   for (size_t i = 0; tokens && tokens[i]; i++) {
@@ -1027,15 +1032,21 @@ gboolean helper_execute(const char *wd, char **args, const char *error_precmd,
 gboolean helper_execute_command(const char *wd, const char *cmd,
                                 gboolean run_in_term,
                                 RofiHelperExecuteContext *context) {
+  return helper_execute_command_full(wd, cmd, run_in_term, context, "{cmd}",
+                                     cmd, (char *)0);
+}
+
+static gboolean helper_execute_command_full_v(const char *wd, const char *cmd,
+                                              gboolean run_in_term,
+                                              RofiHelperExecuteContext *context,
+                                              va_list ap) {
   char **args = NULL;
   int argc = 0;
 
   if (run_in_term) {
-    helper_parse_setup(config.run_shell_command, &args, &argc, "{cmd}", cmd,
-                       (char *)0);
+    helper_parse_setup_v(config.run_shell_command, &args, &argc, ap);
   } else {
-    helper_parse_setup(config.run_command, &args, &argc, "{cmd}", cmd,
-                       (char *)0);
+    helper_parse_setup_v(config.run_command, &args, &argc, ap);
   }
 
   if (args == NULL) {
@@ -1063,10 +1074,19 @@ gboolean helper_execute_command(const char *wd, const char *cmd,
 
   return helper_execute(wd, args, "", cmd, context);
 }
+gboolean helper_execute_command_full(const char *wd, const char *cmd,
+                                     gboolean run_in_term,
+                                     RofiHelperExecuteContext *context, ...) {
+  va_list ap;
+  va_start(ap, context);
+  gboolean retv =
+      helper_execute_command_full_v(wd, cmd, run_in_term, context, ap);
+  va_end(ap);
+  return retv;
+}
 
 char *helper_get_theme_path(const char *file, const char **ext,
                             const char *parent_file) {
-
   char *filename = rofi_expand_path(file);
   g_debug("Opening theme, testing: %s\n", filename);
   if (g_path_is_absolute(filename)) {
diff --git a/source/modes/drun.c b/source/modes/drun.c
index c18d8f95..bdfebfb9 100644
--- a/source/modes/drun.c
+++ b/source/modes/drun.c
@@ -402,7 +402,10 @@ static void exec_cmd_entry(DRunModeEntry *e, const char *path) {
   // terminal.
   gboolean terminal =
       g_key_file_get_boolean(e->key_file, e->action, "Terminal", NULL);
-  if (helper_execute_command(exec_path, fp, terminal, sn ? &context : NULL)) {
+  if (helper_execute_command_full(exec_path, fp, terminal, sn ? &context : NULL,
+                                  "{cmd}", fp, "{desktop_file_path}", e->path,
+                                  "{app_id}", e->app_id, "{desktop_id}",
+                                  e->desktop_id, (char *)0)) {
     char *drun_cach_path = g_build_filename(cache_dir, DRUN_CACHE_FILE, NULL);
     // Store it based on the unique identifiers (desktop_id).
     history_set(drun_cach_path, e->desktop_id);

This adds:

Its completely untested.

@Atemu
Copy link
Copy Markdown
Author

Atemu commented Nov 11, 2024

It is no longer completely untested.

It works! Really well actually. Rofi is now able to launch all of my apps without issue using:

-run-command "bash -c 'systemd-run --user --unit=app-rofi-\"\$(systemd-escape \"{app_id}\")\"-\$RANDOM {cmd}'"

Thank you so much!

Tested-by: Atemu <git@atemu.net>

Though with the slight caveat that I'm using the wayland fork based on f2c0f75. It does not apply atop the Nixpkgs package of this repo (1.7.5 tag) but that's also quite old by now.

Should I add your patch as a commit to this branch or do you just want to do that yourself?

Atemu added a commit to Atemu/dotfiles that referenced this pull request Nov 11, 2024
@DaveDavenport
Copy link
Copy Markdown
Collaborator

Feel free to add the patch, can you update the documentation with the entries from this patch?

DaveDavenport and others added 2 commits November 12, 2024 03:12
This adds:
* `{desktop_file_path}`
* `{app_id}` // filename without .desktop
* `{desktop_id}`  // Path with all / replaced by -. -> https://specifications.freedesktop.org/desktop-entry-spec/latest/file-naming.html

These allow the user to use i.e. just the app name (based on its desktop file
name) for purposes such as running it as part of an ad-hoc systemd user service
via systemd-run.

Tested-by: Atemu <git@atemu.net>

(This was posted as a patch in
davatorium#2048 (comment).)
@Atemu Atemu force-pushed the escape-systemd-run branch from f2ffb5a to 0fecb6a Compare November 12, 2024 02:13
@Atemu
Copy link
Copy Markdown
Author

Atemu commented Nov 12, 2024

Hm, unfortunately I found something that breaks. scrcpy.desktop has this:

# For some users, the PATH or ADB environment variables are set from the shell
# startup file, like .bashrc or .zshrc… Run an interactive shell to get
# environment correctly initialized.
Exec=/bin/sh -c "\\$SHELL -i -c scrcpy"

That seems misguided but it should work.

However $SHELL appears to be escaped entirely in this context because it fails with this:

/bin/sh: line 1: $SHELL: command not found

It works in regular rofi execution. It also works using -run-command "bash -cx '{cmd}'" and only breaks once you add systemd-run: -run-command "bash -cx 'systemd-run --user {cmd}'".

I still haven't quite understood why this happens.

This PR's recommendation isn't a regression compared to status quo though as that also fails but with a different error:

Nov 12 08:55:02 HEPHAISTOS (sh)[257995]: app-rofi--25453.service: Invalid environment variable name evaluates to an empty string: SHELL -i -c scrcpy
Nov 12 08:55:02 HEPHAISTOS sh[257995]: /bin/sh: -c: option requires an argument

@Atemu Atemu changed the title [DOC] properly escape systemd-run example [DOC] make systemd-run example more reliable Nov 12, 2024
@Atemu
Copy link
Copy Markdown
Author

Atemu commented Nov 12, 2024

Another pitfall I just noticed is that this is not compatible with run of course as there's no desktop app_id it could provide.

I'll make the --unit flag optional for that case but ideally we'd have a way to fall back onto something else such as the binary name.

@DaveDavenport DaveDavenport added this to the 1.7.7 milestone Dec 26, 2024
@DaveDavenport DaveDavenport modified the milestones: 1.7.7, 1.7.8 Jan 3, 2025
@DaveDavenport DaveDavenport modified the milestones: 1.7.8, 1.7.9 Jan 19, 2025
@lbonn lbonn reopened this Jan 27, 2025
@DaveDavenport
Copy link
Copy Markdown
Collaborator

thanks,forgot to reopen yesterday.

Comment thread source/helper.c
Comment on lines -1034 to +1049
helper_parse_setup(config.run_shell_command, &args, &argc, "{cmd}", cmd,
(char *)0);
helper_parse_setup_v(config.run_shell_command, &args, &argc, ap);
} else {
helper_parse_setup(config.run_command, &args, &argc, "{cmd}", cmd,
(char *)0);
helper_parse_setup_v(config.run_command, &args, &argc, ap);
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed this: aren't these flipped now?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run_in terminal calls the 'run_shell_command'.. I think this is ok?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a clue how this code actually works, I only noticed that the _v-suffixed version is now called in the other conditional.

Comment thread doc/rofi.1.markdown

```bash
"bash -c 'systemd-run --user --unit=app-rofi-\$(systemd-escape {cmd})-\$RANDOM {cmd}'"
"bash -c 'systemd-run --user [--unit=app-rofi-\"\$(systemd-escape \"{app_id}\")\"-\$RANDOM] {cmd}'"
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it's nice to mark this as optional, that doesn't actually help anyone because you can only have one or the other but both drun and run could be used.

What we actually need is some sort of identifier that is unit-name-safe, represents what is being ran decently well and works with both drun and run.

For desktop applications, I see the desktop_id fulfilling that role. Though I'd prefer the .desktop suffix be stripped.

For commands, I see the (escaped) executable name as the best candidate. Of course it'd "break" (as in: not represent what is being ran) if you ran sh -c ... or something but at that point you're explicitly doing that.

Perhaps it'd be best to do that within rofi and provide an abstract execution_id or something that works like I described.

Perhaps it'd be even better if we had run-as-system service functionality built right into rofi?

Executing systemd-run like this in -run-command really isn't very robust as I've discovered with scrcpy, so perhaps "native" handling would be better.

I'm really not sure how to proceed with this.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know.. I never use systemd-run. What does 'run-as-system' service entail? do you have a link to some documentation?
(we did add the DBusActivatable to latest rofi).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It means that any app launched is started as an ad-hoc systemd unit. For example the firefox I'm typing this in runs as the app-rofi-firefox-24354.service user unit.

What this means in practice is that the initial process aswell as every process ever spawned it will be run in a cgroup that is separate from all other apps and you can apply any cgroup-based policy to it if you like.

This is most useful for stopping units (e.g. early OOM) but you could in theory do anything cgroups with this.

It also brings with it all of systemd's accounting and centralised log collection. See e.g. this example output:

$ systemctl --user status app-rofi-firefox-24354.service 
● app-rofi-firefox-24354.service - [systemd-run] /run/current-system/sw/bin/firefox --name firefox
     Loaded: loaded (/run/user/1000/systemd/transient/app-rofi-firefox-24354.service; transient)
  Transient: yes
     Active: active (running) since Wed 2025-01-29 14:04:39 CET; 1 day 8h ago
 Invocation: 06509bffe1dc46f79fafe6a952641d60
   Main PID: 437580 (.firefox-wrappe)
      Tasks: 594 (limit: 37644)
     Memory: 3.4G (peak: 3.8G, swap: 833M, swap peak: 1.8G, zswap: 231.6M)
        CPU: 1h 54min 32.764s
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/app-rofi-firefox-24354.service
             ├─437580 /nix/store/kbin6wx8bciz7c50i4y93n35wfqnrfzs-firefox-134.0.2/bin/.firefox-wrapped --name firefox
             ├─437678 /nix/store/kbin6wx8bciz7c50i4y93n35wfqnrfzs-firefox-134.0.2/lib/firefox/firefox -contentproc ...
...

Jan 30 19:56:22 THESEUS firefox[437699]: Failed to create /Users for shader cache (Permission denied)---disabling.
Jan 30 19:56:23 THESEUS firefox[437699]: Failed to create /Users for shader cache (Permission denied)---disabling.
...

I can see that the "firefox app" I launched currently uses 3.4GiB and has 833M in swap across all of its processes. I can also see all the processes Firefox has spawned. I can also see this app launch instance's logs in isolation.

Theoretically I could set e.g. memory or swap limits here though I'm not currently doing that.

Setting a memory limit without running firefox in its own cgroup would be very hard indeed and even finding out how much memory it's using usually isn't trivial with such multi-process applications. cgroups make everything simpler here.

AFAIK the big DEs' launchers also run every app launched within an ad hoc systemd unit but I don't use those, so I can't tell you how it works there.

There isn't really documentation on this other than standard systemd (user) service/unit docs and cgroup docs. There isn't really much to it other than simply using these systems.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know what it does, but not how to do this from the rofi? Is there a dbus API I can call to launch the service?

@Vladimir-csp
Copy link
Copy Markdown

Vladimir-csp commented Apr 4, 2025

app2unit might be of use here. It supports launching via desktop entry ID. If desktop entry path can be passed, it will be even faster.

@DaveDavenport DaveDavenport removed this from the 1.7.9 milestone May 18, 2025
@DaveDavenport
Copy link
Copy Markdown
Collaborator

@Tom94 that would break the run mode, so a special 'drun-command' option should be added :-/

I really would like to know if we can do this whole thing directly via dbus, instead of invoking an external tool.

@DaveDavenport
Copy link
Copy Markdown
Collaborator

@Vladimir-csp
Copy link
Copy Markdown

FYI, app2unit now supports DESKTOP_ENTRY_* entry metadata vars feature created in fuzzel. Would be cool if this feature spreads to other launchers.

@DaveDavenport
Copy link
Copy Markdown
Collaborator

@DaveDavenport
Copy link
Copy Markdown
Collaborator

diff --git a/source/modes/drun.c b/source/modes/drun.c
index 7c8f0f72..4e81833e 100644
--- a/source/modes/drun.c
+++ b/source/modes/drun.c
@@ -60,6 +60,8 @@
 
 #include "rofi-icon-fetcher.h"
 
+#include <gio-unix-2.0/gio/gdesktopappinfo.h>
+
 /** The filename of the history cache file. */
 #define DRUN_CACHE_FILE "rofi3.druncache"
 
@@ -505,7 +507,31 @@ static void exec_cmd_entry(DRunModePrivateData *pd, DRunModeEntry *e,
    * If its required to launch via dbus, do that.
    */
   gboolean launched = FALSE;
-  if (!(pd->disable_dbusactivate)) {
+
+  GDesktopAppInfo *gdai = g_desktop_app_info_new_from_keyfile(e->key_file);
+
+  if (gdai != NULL) {
+    GError *ai_error = NULL;
+    GList *files = NULL;
+    if (path) {
+      GFile *file = g_file_new_for_path(path);
+      files = g_list_append(files, (void *)file);
+    }
+    launched = g_app_info_launch(G_APP_INFO(gdai), files, NULL, &ai_error);
+    if (ai_error) {
+      g_warning("Failed to launch application using GAppInfo::Launch: %s",
+                ai_error->message);
+      g_error_free(ai_error);
+    }
+    g_object_unref(gdai);
+    if (files != NULL) {
+      g_list_free_full(files, g_object_unref);
+    }
+  } else {
+    g_warning("Failed to create GDesktopAppInfo for: %s", e->path);
+  }
+
+  if (launched == FALSE && !(pd->disable_dbusactivate)) {
     if (g_key_file_get_boolean(e->key_file, e->action, "DBusActivatable",
                                NULL)) {
       printf("DBus launch\n");

This feels like a workable solution.

@DaveDavenport
Copy link
Copy Markdown
Collaborator

I think the above patch fixes Tom's issue, but not the 'original' issue.

@Tom94
Copy link
Copy Markdown

Tom94 commented Mar 16, 2026

Wow, thanks a lot for figuring this out so quickly and even going as far as providing a patch.

I’m on KDE, though, and at least based on a quick web search, gio doesn’t seem to offer full DE integration over there if it works at all. 😅 Though I’m really nowhere near deep enough in the weeds to properly grok whether a unified dbus implementation is possible across different DEs or not… or whether I interpreted my web search results might be completely off and gio works well on non-gnome environments after all

@DaveDavenport
Copy link
Copy Markdown
Collaborator

DaveDavenport commented Mar 16, 2026

you can test it by doing a gio launch {path to a desktop file} in kde and see if that works correctly?

(it works for me under i3)

@Tom94
Copy link
Copy Markdown

Tom94 commented Mar 16, 2026

It works in the sense of launching the app, but it doesn't seem to integrate with KDE / systemd. I tried a bunch of other launch mechanisms like dex or xdg-open, but it seems that only kioclient exec <file.desktop> ends up as its own systemd unit and triggers other DE integrations like cursor busy animations and so on.

@DaveDavenport
Copy link
Copy Markdown
Collaborator

does the above linked app2unit work?

@Tom94
Copy link
Copy Markdown

Tom94 commented Mar 16, 2026

app2unit would need the {app_id} feature from this PR, no? If that's at all in the cards, I'd much prefer using {desktop_file_path} and sticking with the launch mechanism that's bundled with my environment. 😅

@DaveDavenport
Copy link
Copy Markdown
Collaborator

I was more wondering if you tries to launch something using app2unit it would integrate as expected.. you can test this easily without needing the patch?

@Vladimir-csp
Copy link
Copy Markdown

app2unit can handle both {app_id} and {desktop_file_path}, the latter is preferable because it is faster.

It just starts apps as units (with proper dependencies/ordering to graphical-session.target), it does not belong to any DE and does not try do hook into any DE-specific mechanisms.

@Tom94
Copy link
Copy Markdown

Tom94 commented Mar 16, 2026

Sure, app2unit seems to start the app fine, similar to gio, but neither seems to integrate, nor show up in user services on my KDE system (despite -t service). I use systemctl --user list-units --type=service to check.

app2unit does spawn a systemd service, but doesn't integrate with the DE beyond that.

@Vladimir-csp
Copy link
Copy Markdown

I use systemctl --user list-units --type=service to check.

This is strange. Which unit(s) do actual processes of launched apps belong to then?

@Tom94
Copy link
Copy Markdown

Tom94 commented Mar 16, 2026

I use systemctl --user list-units --type=service to check.

This is strange. Which unit(s) do actual processes of launched apps belong to then?

My mistake. I had used app2unit systemsettings.desktop -t service instead of app2unit -t service systemsettings.desktop and it became a scope instead of a service. The latter command works as expected on the systemd front, at least. Still doesn't integrate with other KDE app management features as expected.

DaveDavenport added a commit that referenced this pull request Mar 16, 2026
To work with app2unit and some other launcher helpers.

Issue: #2048
@DaveDavenport
Copy link
Copy Markdown
Collaborator

made a branch mr2048, there you can try:

rofi -show drun -run-command 'bash -c "kioclient exec $DESKTOP_ENTRY_PATH"'  -drun-gio-launch false

@DaveDavenport
Copy link
Copy Markdown
Collaborator

I mixed up DESKTOP_FILE in commit message on that branch 👎 but it is DESKTOP_ENTRY_{PATH,ID,NAME}.

@Tom94
Copy link
Copy Markdown

Tom94 commented Mar 16, 2026

Thank you! I'll have to go AFK for a bit but will be able to test in 1-2 hours.

@Vladimir-csp
Copy link
Copy Markdown

Still doesn't integrate with other KDE app management features as expected.

I do not know how KDE tracks its units, but suspect that there are some custom unit properties involved. Check systemctl --user show ${some-kde-unit}.service for any KDE-related keys/values. You can try adding similar properties via -p option in app2unit.

@Tom94
Copy link
Copy Markdown

Tom94 commented Mar 16, 2026

made a branch mr2048, there you can try:

rofi -show drun -run-command 'bash -c "kioclient exec $DESKTOP_ENTRY_PATH"'  -drun-gio-launch false

Works like a charm, thank you.

@Vladimir-csp
Copy link
Copy Markdown

With DESKTOP_ENTRY_{PATH,ID,NAME} set this will work transparently: rofi -show drun -run-command "app2unit -- {cmd}" -drun-gio-launch false. Although having DESKTOP_ENTRY_{NAME,GENERICNAME}_L would result in even nicer unit descriptions.

@Vladimir-csp
Copy link
Copy Markdown

...also wouldn't it be logical to automatically disable gio launch if -run-command is used?

@DaveDavenport
Copy link
Copy Markdown
Collaborator

DaveDavenport commented Mar 16, 2026

...also wouldn't it be logical to automatically disable gio launch if -run-command is used?

Not really, -run-command is not only used by the drun mode, but also run, etc.

@DaveDavenport
Copy link
Copy Markdown
Collaborator

Made a MR for this. #2275

@Tom94
Copy link
Copy Markdown

Tom94 commented Mar 16, 2026

Once again thank you so much. Would have never expected that quick of a response and for the feature (plus the whole extra gio one) to be implemented within hours. You rock!

By the way, is there a place I can set up recurring donations? I'm a long-time rofi user and I usually try to at least give back a little to the software I use so much.

@DaveDavenport
Copy link
Copy Markdown
Collaborator

I don't have a donation option.

DaveDavenport added a commit that referenced this pull request Mar 20, 2026
* [DRUN] Replace DBusActivation to launch, to use gio-unix to launch desktop files

Offload all complexity to a known good implementation.

* [DRUN] If gio-launch false, set DESKTOP_FILE_{ID,PATH,NAME}

To work with app2unit and some other launcher helpers.

Issue: #2048

* [DRUN] app_id should be including .desktop.

* [DRUN] Add {GENERICNAME|NAME}_L env variables
Atemu added a commit to Atemu/dotfiles that referenced this pull request Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants