[RFC] Wrapper for launching user-preferred applications via alternatives sytem

Sergey "Shnatsel" Davidoff sergey at elementaryos.org
Mon Jan 28 11:51:35 UTC 2013


Hi,

You have probably noticed that Ubuntu has generic symlinks for
launching some types of applications, such as "x-www-browser",
"x-terminal-emulator", "gnome-text-editor", etc. However, the exact
application they launch is pretty much undefined from the user
perspecitve, e.g. "x-www-browser" will launch Chrome even Firefox is
set as preferred web browser.

The cause of it lies in Debian alternatives system (see
http://wiki.debian.org/DebianAlternatives) which controls the
symlinks; the priority for each candidate for the generic name is set
by package maintainer, thus alternatives system doesn't take user
preference into account. The symlinks can be controlled by the user
via "update-alternatives" command-line tool, but the preferences in
alternatives system are system-wide so if different users of an OS
instance prefer different web browsers, you can't satisfy both of
them. That aside, requiring the user to meddle with command line in
addition to flipping a switch in gnome-control-center just to change
the preferred app is not a great idea.

To solve this, I wrote a wrapper that registers itself in alternatives
system with a very high priority (500) and, when invoked via a symlink
controlled by alternatives system, it determines the symlink by which
it was invoked based on argv[0], then looks up the user preference for
this kind of app by its primary mimetype and launches it. If it fails
to do so, it falls back to the second-highest-priority item in
alternatives system, i.e. executes the behavior which would happen if
the wrapper wouldn't exist at all.

The wrapper is ~200 lines of Vala code; the runtime dependencies are
only Glib and Granite, but the latter is used for just one line -
initialization of its logger service - and may be trivially avoided.
The supported application types are hardcoded, because I don't think
using a plugin system like libpeas will be of any benefit while it
definitely will introduce much greater complexity. It currently
supports web browsers, text editors and terminal emulators. It should
be trivial to add support for other types of applications though.

When invoking an application, the wrapper passes all parameters it
receives to the target app as well as all open file descriptors, so
stdin input and stdout/stderr redirection work properly. The wrapper
is completely transparent, except one aspect: it launches applications
asynchronously and exits as soon as one is invoked, so it always
returns 0 if succeeds to launch the desired application and exits
before the desired application exits. However, it should not be a
problem since all the supported applications typically exhibit such
behavior themselves (e.g. Firefox, Gedit, gnome-terminal).

The wrapper doesn't support slave links, but they are rarely used for
GUI applications anyway, so I don't think it will be a problem. Also,
terminal emulators are kind of a special case because they don't have
an associated mimetype, so the wrapper currently checks
XDG_CURRENT_DESKTOP variable and if it's "unity", "gnome" or
"pantheon" it reads the relevant GSettings key. Otherwise it exhibits
the "I wasn't here" fallback behavior :)

The source code can be found at
https://code.launchpad.net/~elementary-os/elementaryos/user-specific-alternatives/
The branch includes Debian packaging as well; it's lintian-clean but
wasn't reviewed by a Debian maintainer or Ubunty MOTU.

The wrapper was originally written for use in elementary OS, but I
believe it will be of use to Ubuntu too. Any feedback is welcome, not
to mention instructions on proposing this for review and eventual
inclusion in Ubuntu :)

--
Sergey "Shnatsel" Davidoff




More information about the Ubuntu-devel-discuss mailing list