Browse Source

Merge branch 'dbusactivation-v1'

* dbusactivation-v1:
  Implement D-Bus Activation of desktop files manually
Marek Marczykowski-Górecki 5 years ago
parent
commit
feeb4b3816
1 changed files with 34 additions and 3 deletions
  1. 34 3
      qubesagent/xdg.py

+ 34 - 3
qubesagent/xdg.py

@@ -1,3 +1,5 @@
+import functools
+
 from gi.repository import Gio  # pylint: disable=import-error
 from gi.repository import GLib  # pylint: disable=import-error
 import sys
@@ -6,22 +8,51 @@ import os
 def pid_callback(launcher, pid, pid_list):
     pid_list.append(pid)
 
+def dbus_name_change(loop, name, old_owner, new_owner):
+    if not new_owner:
+        loop.quit()
+
 def launch(desktop, *files, **kwargs):
     wait = kwargs.pop('wait', True)
     launcher = Gio.DesktopAppInfo.new_from_filename(desktop)
     try:
         import dbus
+        from dbus.mainloop.glib import DBusGMainLoop
         if hasattr(launcher, 'get_boolean'):
             activatable = launcher.get_boolean('DBusActivatable')
             if activatable:
+                loop = GLib.MainLoop()
+                DBusGMainLoop(set_as_default=True)
                 bus = dbus.SessionBus()
                 service_id = launcher.get_id()
                 # cut the .desktop suffix
-                service_id = service_id[:-8]
+                service_id = service_id[:-len('.desktop')]
+                # see D-Bus Activation Desktop entry specification
+                object_path = '/' + service_id.replace('.', '/').\
+                    replace('-', '_')
                 try:
-                    bus.start_service_by_name(service_id)
-                except dbus.DBusException:
+                    proxy = bus.get_object(service_id, object_path)
+                    match = bus.add_signal_receiver(
+                        functools.partial(dbus_name_change, loop),
+                        'NameOwnerChanged',
+                        dbus.BUS_DAEMON_IFACE,
+                        dbus.BUS_DAEMON_NAME,
+                        dbus.BUS_DAEMON_PATH)
+                    if files:
+                        proxy.Open(files, {},
+                            dbus_interface='org.freedesktop.Application')
+                    else:
+                        proxy.Activate({},
+                            dbus_interface='org.freedesktop.Application')
+                except dbus.DBusException as e:
+                    print(e)
+                    # fallback to non-dbus version
                     pass
+                else:
+                    if wait:
+                        loop.run()
+                    match.remove()
+                    return
     except ImportError:
         pass
     if wait: