Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] rofi does not spawn .desktop files with dbus activation #1924

Open
2 tasks done
russelltg opened this issue Nov 28, 2023 · 11 comments
Open
2 tasks done

[BUG] rofi does not spawn .desktop files with dbus activation #1924

russelltg opened this issue Nov 28, 2023 · 11 comments
Milestone

Comments

@russelltg
Copy link

russelltg commented Nov 28, 2023

It's possible this is a feature request and not bug (felt borderline), so feel free to update :)

Rofi version (rofi -v)

1.7.5

Configuration

https://gist.github.com/russelltg/302aa2af722d3c43192f53ee553da731

Theme

https://gist.github.com/russelltg/eb33d77bbb4645483bf2911fe2f507cb

Timing report

No response

Launch command

rofi -show drun

Step to reproduce

  1. Find a .desktop file with a different commandline for dbus activation and non-dbus activation. I use the easyeffects flatpak.
  2. Spawn it with rofi -show drun
  3. Check the commandline used. I use ps aux | grep easyeffects

Expected behavior

It uses d-bus activation. In the case of easyeffects, this means that the commndline is easyeffects --gapplication-service

Actual behavior

dbus activation is not use. In the case of easyeffects, the commandline is just easyeffects

Additional information

The author of easyeffects told me (wwmm/easyeffects#1215 (comment)) that rofi should use dbus activation. It seems gnome, kde, and gtk-launch all launch properly with dbus activation.

Using wayland display server protocol

  • No, I don't use the wayland display server protocol

I've checked if the issue exists in the latest stable release

  • Yes, I have checked the problem exists in the latest stable version
@russelltg russelltg added the bug label Nov 28, 2023
@russelltg russelltg changed the title [BUG] [BUG] rofi does not spawn .desktop files with dbus activation Nov 28, 2023
@DaveDavenport
Copy link
Collaborator

Can you attach easyeffects desktop file?

@russelltg
Copy link
Author

https://gist.github.com/russelltg/e432828354187ee7abc76620bff0b69e

g_app_info_launch seems to be the GIO call that gtk-launch uses

@DaveDavenport
Copy link
Collaborator

A quick fix would be to change the Exec line to
Exec=gapplication launch appidforeasyeffects

I see this is how most applications setup their .desktop file.

@russelltg
Copy link
Author

russelltg commented Nov 28, 2023

Could you send me the examples so I can pass them along to easyeffects folks? (or is it more of a hack and I just should do it locally)

@DaveDavenport
Copy link
Collaborator

diff --git a/source/modes/drun.c b/source/modes/drun.c
index b05ce48e..ea28807b 100644
--- a/source/modes/drun.c
+++ b/source/modes/drun.c
@@ -44,6 +44,9 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+
 #include "helper.h"
 #include "history.h"
 #include "mode-private.h"
@@ -321,6 +324,7 @@ static void launch_link_entry(DRunModeEntry *e) {
   g_snprintf(command, command_len, "%s %s", config.drun_url_launcher, url);
   g_free(url);
 
+
   g_debug("Link launch command: |%s|", command);
   if (helper_execute_command(NULL, command, FALSE, NULL)) {
     char *path = g_build_filename(cache_dir, DRUN_CACHE_FILE, NULL);
@@ -398,15 +402,28 @@ static void exec_cmd_entry(DRunModeEntry *e, const char *path) {
         g_key_file_get_string(e->key_file, e->action, "StartupWMClass", NULL);
   }
 
-  // Returns false if not found, if key not found, we don't want run in
-  // 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)) {
-    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);
-    g_free(drun_cach_path);
+  if ( g_key_file_get_boolean ( e->key_file, e->action, "DBusActivatable", NULL) ) {
+         GAppInfo *info = G_APP_INFO(g_desktop_app_info_new_from_keyfile(e->key_file));
+         printf("Desktop dbus launch\r\n");
+         if ( g_app_info_launch(info, NULL, NULL, NULL ) ) {
+                 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);
+                 g_free(drun_cach_path);
+         }
+         g_object_unref(info);
+  } else {
+
+         // Returns false if not found, if key not found, we don't want run in
+         // 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)) {
+                 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);
+                 g_free(drun_cach_path);
+         }
   }
   g_free(wmclass);
   g_free(exec_path);

For me it does not launch it with --gapplication-service, maybe I need the right GAppLaunchContext.

@russelltg
Copy link
Author

@DaveDavenport

This comment was marked as duplicate.

1 similar comment
@DaveDavenport
Copy link
Collaborator

Saw that, but I do not really want to pull in Gdk as an dependency.

@DaveDavenport
Copy link
Collaborator

Maybe the easiest is to just call gtk-launch with the path to the desktop file and action/arguments.

@DaveDavenport
Copy link
Collaborator

Might have a solution by going to low-level dbus.. Will post a patch later.

@DaveDavenport
Copy link
Collaborator

Not something usable yet, but good to do some tests..

diff --git a/source/modes/drun.c b/source/modes/drun.c
index b05ce48e..57936556 100644
--- a/source/modes/drun.c
+++ b/source/modes/drun.c
@@ -44,6 +44,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <gio/gio.h>
+
 #include "helper.h"
 #include "history.h"
 #include "mode-private.h"
@@ -329,6 +331,37 @@ static void launch_link_entry(DRunModeEntry *e) {
     g_free(path);
   }
 }
+static gchar *app_path_for_id(const gchar *app_id) {
+  gchar *path;
+  gint i;
+
+  path = g_strconcat("/", app_id, NULL);
+  for (i = 0; path[i]; i++) {
+    if (path[i] == '.')
+      path[i] = '/';
+    if (path[i] == '-')
+      path[i] = '_';
+  }
+
+  return path;
+}
+static GVariant *app_get_platform_data(void) {
+  GVariantBuilder builder;
+  const gchar *startup_id;
+
+  g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
+
+  if ((startup_id = g_getenv("DESKTOP_STARTUP_ID")))
+    g_variant_builder_add(&builder, "{sv}", "desktop-startup-id",
+                          g_variant_new_string(startup_id));
+
+  if ((startup_id = g_getenv("XDG_ACTIVATION_TOKEN")))
+    g_variant_builder_add(&builder, "{sv}", "activation-token",
+                          g_variant_new_string(startup_id));
+
+  return g_variant_builder_end(&builder);
+}
+
 static void exec_cmd_entry(DRunModeEntry *e, const char *path) {
   GError *error = NULL;
   GRegex *reg = g_regex_new("%[a-zA-Z%]", 0, 0, &error);
@@ -398,15 +431,66 @@ static void exec_cmd_entry(DRunModeEntry *e, const char *path) {
         g_key_file_get_string(e->key_file, e->action, "StartupWMClass", NULL);
   }
 
-  // Returns false if not found, if key not found, we don't want run in
-  // 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)) {
-    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);
-    g_free(drun_cach_path);
+  if (g_key_file_get_boolean(e->key_file, e->action, "DBusActivatable", NULL)) {
+    printf("Try dbus launch %s\r\n", e->app_id);
+    GDBusConnection *session;
+    GError *error = NULL;
+    gchar *object_path;
+    GVariant *result;
+
+    session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
+    if (!session) {
+      fprintf(stderr, ("unable to connect to D-Bus: %s\n"), error->message);
+      g_error_free(error);
+      return;
+    }
+
+    object_path = app_path_for_id(e->app_id);
+
+    GVariantBuilder files;
+
+    g_variant_builder_init(&files, G_VARIANT_TYPE_STRING_ARRAY);
+
+    GVariant *params = NULL;
+    const char *method = "Activate";
+    if (path != NULL) {
+      method = "Open";
+      params = g_variant_new("(as@a{sv})", &files, app_get_platform_data());
+    } else {
+      params = g_variant_new("(@a{sv})", app_get_platform_data());
+    }
+    if (path) {
+      GFile *file = g_file_new_for_commandline_arg(path);
+      g_variant_builder_add_value(
+          &files, g_variant_new_take_string(g_file_get_uri(file)));
+      g_object_unref(file);
+    }
+    result = g_dbus_connection_call_sync(
+        session, e->app_id, object_path, "org.freedesktop.Application", method,
+        params, G_VARIANT_TYPE_UNIT, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+
+    g_free(object_path);
+
+    if (result) {
+      g_variant_unref(result);
+    } else {
+      fprintf(stderr, ("error sending %s message to application: %s\n"), "Open",
+              error->message);
+      g_error_free(error);
+    }
+    g_object_unref(session);
+  } else {
+
+    // Returns false if not found, if key not found, we don't want run in
+    // 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)) {
+      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);
+      g_free(drun_cach_path);
+    }
   }
   g_free(wmclass);
   g_free(exec_path);

Does not support actions yet and does not fall back to classic style when failed.

@DaveDavenport DaveDavenport added this to the 1.7.6 milestone Apr 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants