LauncherAPI

Launcher API

We support adding quicklists, counters, and progress bars for apps in the Unity Launcher:

unityapi.png

quicklilst-static-entry.png

Using the Launcher API

The recommended and supported way to take control of your launcher icon is to use the API provided by libunity. This library wraps a low level DBus protocol which is documented below.

Each launcher icon can be controlled remotely by a discrete LauncherEntry object. New launcher entry object may be created by call unity_launcher_entry_get_for_desktop_id (char *id); where id is the name of the desktop file shipped by the application you wish to control. For example evolution ships "evolution.desktop" or empathy ships "empathy.desktop".

LauncherEntryes are able to control 4 major components of a Launcher Icon:

Count

The first aspect they can control is the count associated with the icon. The count may be set by calling

unity_launcher_entry_set_count (UnityLauncherEntry *self, gint64 count);

This will remotely prime the count, then calling

unity_launcher_entry_set_count_visible (UnityLauncherEntry *self, gboolean visible)

can toggle its visible status. Updates to the count and other properties are live, unsetting and resetting the visibility is not require nor is it encouraged.

Progress

progress can be set by

unity_launcher_entry_set_progress (UnityLauncherEntry *self, gdouble progress)

and made visible by calling

unity_launcher_entry_set_progress_visible (UnityLauncherEntry *self, gboolean visible);

The progress value should be between 0.0 and 1.0.

Urgency

You can set an urgency of your launcher icon by setting a boolean on the urgent property:

unity_launcher_entry_set_urgent (UnityLauncherEntry *self, gboolean urgent);

Quicklists

There are two kinds of Quicklists: the static ones which are always shown once on right-click from the launcher entry and dynamic ones which are only displayed once the application is started.

Static Quicklist entries

Adding a Static Quicklist entry is very easy, all you need is to add some support to the desktop file. This is based on the desktop file formats Action Groups.

Here is what needs to be added to gnome-screenshot to support Quicklist

 […]
 Actions=Screen;Window;

[Desktop Action Screen]
Name=Take a Screenshot of the Whole Screen
Exec=gnome-screenshot
OnlyShowIn=Unity;

[Desktop Action Window]
Name=Take a Screenshot of the Current Window
Exec=gnome-screenshot -w
OnlyShowIn=Unity;

Actions is referencing a Desktop Action. Each Desktop Action references an item entry in the Quicklist. Here, we have the "Screen" and "Window" entries, corresponding to :

[Desktop Action entry]

Then, each group have:

  • a Name=, which is the entry as it's displayed which should be in title case.

  • an Exec= referring a command line to execute once clicked. Details on additional syntax.

  • OnlyShowIn=Unity is recommended to tell "show that entry in the Unity Springboard Quicklist" so that the file can be given upstream without the possibility of showing up in other untested desktop environments. Please let upstream projects decide if they want to have this action shown more widely.

  • Optional Path= key can be used to define the working dir used to launch the exec.

In the desktop spec there is a full desktop file sample with actions. Here is an example of a patch for gnome-utils using the old X-Ayatana style, but shows how to format the patch, with links to ubuntu bug and forwarded upstream.

Dynamic Quicklist entries

Quicklists may also be created and appended to the launcher. To create a quicklist a root node must first be created as a container, and then child nodes are added to it. This final result may be packed into the launcher which is then shipped over the bus to Unity. Updates to the quicklist are also live. Rather than describe the entire API, an example of using quicklist (as well as progress and count) is provided below using the vala bindings.

It is important to note that the main loop must be invoked for the program to actual work. Libunity requires the usage of the main loop as work may be done async.

Quicklist elements

Quicklists can contain:

  • Textual links
  • Text with no associated action
  • Select options
  • Radio options
  • Horizontal dividers

See visual design to view examples of all these elements in context.

Filing Bugs

  • https://launchpad.net/libunity

  • If you're having a problem with the launcher not displaying or incrementing, then it's probably a libunity problem. If the rendering is wrong, it's probably a unity bug and not libunity.
  • Contact Us

Example Code

Vala Example

/* Compile with: valac --pkg unity launcherexample.vala */
namespace LauncherExample {

  public static void main ()
  {
    /* Pretend to be evolution for the sake of the example */
    var l = Unity.LauncherEntry.get_for_desktop_id ("evolution.desktop");

    /* Show a count of 124 on the icon */
    l.count = 124;
    l.count_visible = true;

    /* Set progress to 42% done */
    l.progress = 0.42;
    l.progress_visible = true;
    
    /* We also want a quicklist */
    var ql = new Dbusmenu.Menuitem ();
    var item1 = new Dbusmenu.Menuitem ();
    item1.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "Item 1");
    var item2 = new Dbusmenu.Menuitem ();
    item2.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "Item 2");
    ql.child_append (item1);
    ql.child_append (item2);
    l.quicklist = ql;

    new MainLoop().run();
  }
  
}

Python Example

from gi.repository import Unity, Gio, GObject, Dbusmenu

loop = GObject.MainLoop()

# Pretend to be evolution for the sake of the example 
launcher = Unity.LauncherEntry.get_for_desktop_id ("evolution.desktop")

# Show a count of 124 on the icon
launcher.set_property("count", 124)
launcher.set_property("count_visible", False)

# Set progress to 42% done 
launcher.set_property("progress", 0.42)
launcher.set_property("progress_visible", True)


# We also want a quicklist 
ql = Dbusmenu.Menuitem.new ()
item1 = Dbusmenu.Menuitem.new ()
item1.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "Item 1")
item1.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
item2 = Dbusmenu.Menuitem.new ()
item2.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "Item 2")
item2.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
ql.child_append (item1)
ql.child_append (item2)
launcher.set_property("quicklist", ql)

def update_urgency():
    if launcher.get_property("urgent"):
        print "Removing urgent flag"
        launcher.set_property("urgent", False)
    else:
        print "setting urgent flag"
        launcher.set_property("urgent", True)
    return True

GObject.timeout_add_seconds(5, update_urgency)

loop.run()

Low level DBus API: com.canonical.Unity.LauncherEntry

Info (!) While the libunity API is stable, the DBus protocol underneath is not. We strongly discourage anyone from relying on it

Application authors normally should not need to care about the raw DBus API. libunity implements all of this in a nice and convenient API.

This API is designed to minimize the number of DBus messages needed in order to set up the launcher icons, and generally cater for devices with less-than-desktop processing powers. Unity ships not only on netbooks but also on several 3rd party tablet setups. This demands special attention to CPU hungriness, power consumption, and IO.

  • signal com.canonical.Unity.LauncherEntry.Update (in s app_uri, in a{sv} properties)

This signal is emitted by an application whenever it wishes to change state of any of its launcher properties. It's important to emphasise that the signal only includes the properties that have changed. This ensures that the protocol is extensible without changing libunity.

Unity will pick up the Update signal by having a DBus match rule catching all signals from com.canonical.Unity.LauncherEntry disregarding its origin. It's the responsibility of the emitting party to Update with all know state when the name com.canonical.Unity becomes owned on the bus. Otherwise there may be synchronization issues on boot up or if the Unity shell is restarted for some reason.

  • app_uri : A URI on the form application://$desktop_file_id. The desktop file id of an application is defined to be the basename of the application's .desktop-file including the extension. So taking Firefox as an example it would be application://firefox.desktop

  • properties : A map of strings to variants with the properties to set on the launcher icon. Valid properties are:

    • "count" (type signature x): A number to display on the launcher icon. You must also set the "count-visible" property to true in order for this to show.

    • "progress" (type signature d) : A double precision floating point number between 0 and 1. This will be rendered as a progress bar or similar on the launcher icon. You must also set the "progress-visible" property to true in order for this to show.

    • "urgent" (type signature b) : Tells the launcher to get the users attention

    • "quicklist" (type signature s) : The object path to a DbusmenuServer instance on the emitting process. An empty string denotes that the quicklist has been unset. This also explains why we use signature s and not o. The empty string is not a valid object path.

    • count-visible (type signature b) : Determines whether the "count" is visible

    • progress-visible (type signature b) : Determines whether the "progress" is visible

Mainly for debugging purposes applications using the Update() signal must also expose a Query method on the same object path as they emitted the Update signal from:

  • method com.canonical.Unity.LauncherEntry.Query (out s app_uri, out a{sv} properties)

The return values match exactly the paramters described in the Update signal.

FAQ

  • Why not use the org.freedesktop.DBus.Properties interface instead?

  • Good question! The standard properties interface of DBus is designed in a polling fashion, and would require Unity to query a well known address for the properties, which in turn demands that we use some sort of registration mechanism. The beauty of the custom API is that it flips the roles, it's a pushing mechanism instead of a pulling mechanism. This makes the registration step implicit and book keeping easier. Not to mention requiring fewer DBus roundtrips.
  • Why not use the de-facto standard DockMangaer API instead?

  • Good question again! The introductory paragraph on the DBus API section gives the clue here. The DockManager API is great for a desktop dock. But if you analyze it you'll see that it requires a great many DBus messages exchanged when exercised fully. Thus not a great choice for devices with less-than-desktop powers.

  • The DockManager interface also doesn't interface with the Dbusmenu protocol which is more expressive than the DockManager counterpart. There are also both technical- and UI choices in the DockManager API that doesn't fit well with the vision for Unity.

  • Summing up; if we had gone with the DockManager interface it would have been an strict subset with a suite of custom non-compatible extensions. Some companies does not flinch from calling this behaviour "standard compliance", but let's be honest with our selves. It's no longer the DockManager interface we'd be supporting, but a custom one.

Unity/LauncherAPI (last edited 2013-08-09 12:17:35 by 3v1n0)