Sunday, 28 June 2009

Migrating applets to Awn 0.4

Since we're trying really hard to get Awn 0.4 into a usable state with all the glory and most of the applets we had in the previous releases, I'll try to describe the important changes that happened in the API, so it's easier to convert existing applets to work in 0.4. Please note that if you were using onox's awnlib, the conversion should be painless, because it wraps libawn API and therefore applets did not need to be modified (but I might be wrong, onox will know better).

If you're interested in an article about how to write an actual applet from the beggining, I do plan to write that too, so check back later.
I also plan to write an article about the completely new functions/methods/classes, so you'll have to wait for that a bit as well.

Note that for the sake of simplicity I'll be using pythonish syntax, even though I mostly write C code, so here and there the class names etc. might more resemble C.

So here is a quick list of the most important changes:
  1. AwnApplet was completely revamped - now its base class is GtkPlug (as opposed to GtkEventBox) and it handles connecting to main Awn process, sending signals to whoever is interested, etc.
  2. therefore AwnPlug died.
  3. many (if not all) of AwnAppletSimple's methods were renamed.
  4. AwnAppletDialog is now AwnDialog.
  5. AwnTitle got also renamed to AwnTooltip.
  6. the job of AwnIcons now handles AwnThemedIcon (which is part of AppletSimple).
And now to show you some actual code, I'll help myself by looking at the modifications that were needed to get media-control applet to work in 0.4 (thank you `bzr diff` for making this easy):

I'll start with the AwnApplet(Simple) constructor. In 0.2 (note that I use 0.2 for Awn versions 0.2.x and 0.3.x, since the API was pretty much the same) you'd have:
class MyApplet(awn.AppletSimple):
def __init__(self, uid, orient, height):
awn.AppletSimple.__init__(self, uid, orient, height)
# do stuff

# creating an instance looked like this
if __name__ == '__main__':
awn.init (sys.argv[1:])
applet = MyApplet(awn.uid, awn.orient, awn.height)
# ...
This will now be:
class MyApplet(awn.AppletSimple):
def __init__(self, uid, panel_id):
# of course you can pass also the "applet-name", that's up to you
awn.AppletSimple(self, "applet-name", uid, panel_id)
# do stuff
# to get the former "height" ie. size of the applet, you can now do:
size = self.get_size()

# creating an instance is now:
if __name__ == '__main__':
awn.init (sys.argv[1:])
applet = MyApplet(awn.uid, awn.panel_id)
# ...
Now let's talk about the methods of AppletSimple, these methods no longer exist:
# imagine we have "self" an instance of awn.AppletSimple
self.set_awn_icon(applet_name, icon_name)

# and now the commonly used methods of AwnIcons:
self.get_awn_icons().get_icon_simple() # returned icon with size equal to 48
But you can use these instead:
# if you want to show tooltip on mouse-over and hide it on mouse-out you DON'T
# need to call these, there are properties of AwnTooltip which handle it.
# this means you probably no longer need to connect to enter/leave-notify-events
# and show/hide the tooltip manually
# (for more info see "smart-behavior" property on libawn API pages)
self.get_tooltip().show() or self.get_tooltip().hide()
self.set_icon_name(icon_name) # applet_name is taken from what you passed to the constructor
self.get_icon() # returns awn.ThemedIcon

# you can get former AwnIcons functionality with:

As for "awn.AppletDialog", the only thing you need to do is to substitute it for "awn.Dialog".

And that's it, these are all the changes that had to be done for media-control applet and it should hopefully help you convert your applet.

Our API is still not officially "frozen", so there could be some more changes, but we will try to minimize them, for me the only unknown is malept's config client (awn.Config) which probably will need to be renamed, since it will be now part of libdesktop-agnostic, but other than that its API should be more or less compatible.

Also current version of libawn API can be currently found at

Edit: There was one more change to the AwnApplet constructor, now you need to pass canonical-name for the applet as first parameter. The code above was updated to reflect this change.


  1. I read elsewhere that the plugins api was going to be rewritten before the rewrite was merged with trunk, but from the commits on launchpad, it doesn't look like anyone has started working on a rewrite of plugins. Does this mean that the idea has been dropped, or just that the merge is farther off than we were lead to believe?

  2. @Forest:
    As for the DBus plugin API, we are rewriting it, but we will still support also the old API (not completely, but the methods that were used by most plugins will still be there).

    This means that the taskmanager applet will be accessible by both the old API ( and the new one (probably org.awnproject.Applet.Taskmanager).