Setting up an application for D-Bus Launching

As of GLib 2.38, it is now possible to have applications launched using D-Bus activation.

You should already be using GtkApplication. See HowDoI/GtkApplication.

Mechanics

Instead of the typical UNIX-style fork()/exec() approach to process creation, launching an application is done by sending a D-Bus message to the well-known name of that application, causing a D-Bus activation. In the case that the application is already running, it can respond to the message by opening a new window or raising its existing window.

Why?

This question was asked on the xdg-list. Here's the reply: http://lists.freedesktop.org/archives/xdg/2013-June/012828.html

Starting processes with D-Bus activation ensures that each application gets started in its own pristine environment, as a direct descendent of the session -- not in the environment of whatever its parent happened to be. This is important for ensuring the app ends up in the correct cgroup, for example.

Another reason is that being D-Bus activatable is a prerequisite for using persistent notifications, see HowDoI/GNotification.

GApplication details

There are two approaches to handling D-Bus activation with GApplication. The first approach involved creating a dedicated service process with a separate commandline launcher (possibly written as a shellscript). This approach made debugging and running under jhbuild difficult and is no longer recommended.

The new approach, available since GLib 2.40, is very simple: any GApplication which uses the standard commandline parsing mechanisms (ie: does not override local_command_line()) now accepts a switch --gapplication-service. When started with this switch, the application will be in service mode, ready to receive the message that caused its activation.

All that is required for this to work is to ensure that your application is not handling commandline arguments using local_command_line() (which used to be the recommended way). See HowDoI/GtkApplication/CommandLine for the new recommended way.

Install a D-Bus service file

In order for D-Bus to know how to activate your service, you need to install a D-Bus service file.

The Name= line must be exactly equal to the application ID that you use with GApplication. The Exec= line must point to the spot where the application has been installed, and include the --gapplication-service switch.

This is best done with a Makefile fragment similar to the following:

dbusservicedir = $(datadir)/dbus-1/services
dbusservice_DATA = org.gnome.clocks.service

org.gnome.clocks.service: Makefile
        $(AM_V_GEN) (echo '[D-BUS Service]'; \
                     echo 'Name=org.gnome.clocks'; \
                     echo 'Exec=${bindir}/gnome-clocks --gapplication-service') > $@.tmp && \
                    mv $@.tmp $@

/!\ Be sure to convert the first 8 spaces at the start of lines to a hard tab character as is required by make.

Changes to the desktop file

So far, although your application supports being D-Bus activated, anyone running it will still be using fork()/exec() to spawn it. It is possible to advertise that your application supports D-Bus activation directly in its desktop file using the DBusActivatable key. If this key is found then the launching process will skip the Exec line and send the D-Bus message directly.

In order to use this feature, your desktop file must be named according to your GApplication application ID. If your application ID is "org.gnome.clocks" then your desktop file would have to have the name "org.gnome.clocks.desktop".

After that, the only change that is required is to add the following:

DBusActivatable=true

to the main group of the desktop file.

If DBusActivatable is true and the desktop file name looks like a valid application ID, then the Exec line will be ignored and your application will be started by way of D-Bus activation instead (using the name of the desktop file as the application ID).

Note that this also causes the Exec= line of additional desktop actions to be ignored. Instead, the application GAction with the name of the desktop action will be activated. For example, for a section named "[Desktop Action new-window]", the app.new-window action would be activated. Make sure your application has a GAction installed for each desktop action.

/!\ Make sure to update your POTFILES.in when renaming your desktop file!