Implement D-Bus Activation of desktop files manually
This part of GIO library isn't suitable for short-lived processes (the call is done asynchronously and may not reach the application before qubes-desktop-run process is terminated). To fix this, implement dbus activation manually, synchronously. While at it, implement waiting for application to terminate (useful in DispVM), by waiting for its dbus name to disappear. dbus-python API isn't particularly nice, but don't switch to completely different library as a stable update. Fixes QubesOS/qubes-issues#2449
This commit is contained in:
parent
3d65517886
commit
75e54cd5ef
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user