UnityLauncherIntegration

Supercharging Your Apps with Unity Launcher Integration - Instructors: DBO

Hi everyone, my name is Jason Smith, I am a developer from the Canonical Desktop Experience team (DX for short) 
I'll be giving a talk on supercharging applications with unity launcher integration for the next hour or so 
anyone reading along should feel free to ask questions as they pop into their heads 
First I want to start off by making sure everyone is familiar with the general terminology I am going to be using through this talk 
Unity is (of course) the new shell being developed on top of GNOME for Ubuntu 11.04 and newer 
the Launcher refers to the bar full of icons on the left side of the screen during usage of Unity 
what we have found over the course of the last year is that application developers have desired a better way to display tiny pieces of information to users without doing rather drastic things like popping up alert boxes 
many application authors have resorted to doing things like changing the title of their application to indicate new messages, urgency, or task progress 
so we decided to make those three things in particular an explicit and consistent API for usage with the Unity Launcher 
this API has been included in a library called libunity, and is available in the Ubuntu main repositories, you can also find its source code here: https://launchpad.net/libunity 
Libunity will allow application developers to convey tiny bits of information about their application (or actually any application) they wish with very little work 
we'll look at this piece by piece 
I'll be using Vala as code snippets, but python and C bindings are also available (or anything else that supports GIR) 
The first thing we do with libunity is get a LauncherEntry object 
LauncherEntry objects serve as a control center for a single item on the launcher. They are asyncronous and currently one way (can be used to push information but not to inspect remote state) 
LauncherEntry objects are keyed on the desktop file, so to create an entry for banshee, we would do: 
var launcher_entry = Unity.LauncherEntry.get_for_desktop_file ("banshee.desktop"); 
the resulting launcher_entry will be remotely watched and tracked by the Unity Launcher as soon as it is created 
(there is a caveat here that you must have a running main loop for any communication to work, otherwise it will queue until you run your main loop) 
you may create as many launcher entry objects as you like, for as many different applications as you like in a single program. This is useful for creating applications to bridge public API's between two different programs (say skype where we dont have source code access) 
now that we have a LauncherEntry, we can do 4 different, useful things with it 
1) Mark or unmark the application as urgent 
2) Set a count on the object (useful for unread messages) 
3) Set a progress on the object 
4) Add quicklist menu items to the object 
Each of these is very simple, so we will just go through them in order, at the end I will post the entire source code for the example program 
Setting our launcher_entry as urgent is as easy as "launcher_entry.urgent = true" 
this state will be immediately communicated over dbus to unity where it will be reflected on the launcher 
setting this back to false will reset the state 
mhr3 asked: aren't there other methods to mark app urgent? shouldn't those be used instead? 
Yes, there are other methods for marking an application as urgent 
these methods are based on window hints applied to the xproperties of a related window 
while these methods are quite useful, and should be preferred when the make sense 
there are some cases where they dont, such as when an application that has no mapped windows still wishes to be marked urgent 
Ubuntu One is an example of such an application 
it will mark itself urgent when the user runs out of space, even though it has no mapped windows 
kermit66676 asked: so there has to exist an <app_name>.desktop file somewhere? That file has to be included in a deb package by convention? 
In short yes, there must be a desktop file somewhere. This is what the unity launcher considers an "application" 
However, that file does not have to be added by a deb package 
there was a bug last cycle where the daemon responsible for matching wouldn't seen manually added desktop files 
but that has been fixed now 
Libunity also allows users to set a count and a progress very simply, the api is almost identical for this so we'll just do them together 
launcher_entry.count = 1; 
launcher_entry.count_visible = true; 
these two lines of code set the count to 1, then instruct the launcher to actually display the count. The count and its display are decoupled so it can be turned on and off as needed 
similarly, progress can be done as: 
launcher_entry.progress = 0.0; 
launcher_entry.progress_visible = true; 
again, the progress is set to 0, and then made visible 
Trevinho asked: is actually impossible to check if a launcher entry is actually shown in the unity bar and maybe notified when it is there... Is this something planned (or that I can do :) )? 
Currently there is no method for checking the contents of the launcher, this is a planned feature we feel desperately needs fixing :) 
and yes Trevinho, this is certainly something you could do :) 
ask me in #ayatana later and I will help you with the dbus work if needed 
The last major item libunity allows developers to modify the launcher with is the addition of new quicklist items 
is now known as Guest738 
these are done using the dbusmenu library, which has been covered in previous sessions and is fairly well documented, so I will only deal with the basic coupling code required for libunity 
first we need to create a quicklist 
some example code looks a bit like: 
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); 
this will create a quicklist, called ql, containing two label items 
those items have signals on them you can subscribe to in order to get information about when they are clicked :) 
adding them to the launcher is then as easy as: 
launcher_entry.quicklist = ql; 
This concludes the basic usage of libunity 
unfortunately there are some limitations currently 
and they mostly deal with applications wishing to use concurrent libunity connections 
First, an application wishing to show a state on the launcher MUST remain active. The launcher watches the application on the session bus, and when it dies it reverts any changes it has made to the launcher icons state 
so progress, count, urgent, and menu items all go away if you application dies 
Second, state is currently last write overwrites previous data for multiple connections 
this is very limiting and needs to be fixed, but people should be aware of it in the mean time :) 
mhr3 asked: what is undone when the process which changed something on the launcher disappears? 
The changes go away :) I think I was slow to answer this but if I wasn't clear, yeah, the changes just get reverted :) 
mhr3 asked: any plans with the DockManager spec? :) 
DockManager is a beautiful specification, and I really deeply regret we dont support it 
its very comprehensive and covers a lot of corner cases pretty well 
the one major advantage I think the libunity implementation covers better is it allows multiple consumers AND multiple subscribers 
so you could, in theory, have many docks all listening to the same signals from applications 
this was a shortcoming of dock manager (if I recall correctly) 
kermit66676 asked: how come the Dbusmenu code is not masked using something more intuitive, such as ql = new Unity.Quicklist()? That would make it independent of the underlying technology (even though it might never change to something else). 
I think the thought process is that dbusmenu is used in more places that just libunity (in the indicators for example), so making it a consistent API across the entire ecosystem was important 
oh I forgot to pastebin the program :) 
here we are: http://paste2.org/p/1636674 
As libunity grows, I hope we can see it used more consistently across the ubuntu desktop. Items in the desktop switcher, nautilus, and maybe the dash will see increased usage of these signals and display the same hints 
anyhow, unless there are more questions, that is about all I got 
rsajdok asked: Why did you choose value instead python? 
Vala is just the language I used in the example 
its all gobject introspection 
so you can use python too 
I picked vala here just because thats what my test program is written in and I didn't feel like re-writing it :) 

MeetingLogs/appdevweek1109/UnityLauncherIntegration (last edited 2011-09-08 09:15:59 by dpm)