diff --git a/qubesagent/xdg.py b/qubesagent/xdg.py index 8b57411..3b9f08d 100755 --- a/qubesagent/xdg.py +++ b/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: