Working with the Ubuntu Messaging Menu

Today I had a frustrating time working with the Ubuntu Messaging Menu, so here are some notes for the next time I hit this problem. Thanks awfully to Ken Vandine for clearing up my confusion!

There is little to no documentation (at the moment) about how to properly integrate with the Messaging Menu from a program. The specification has an API section, which is not programming documentation, and it’s confusing. It says, in part:

While running, a registered application can also provide either a single count of new messages, or a set of separate message sources (for example, mail folders or syndicated feeds) with their own counts or times. For example, a Laconica client may provide only the single count, because it presents its updates in a single list and not as separately navigable items. A Usenet newsreader, on the other hand, may provide an item for each newsgroup that has new messages.

This suggests that an item in the Messaging Menu, for a specific program, should be able to provide a count of messages, or have a number of “sub-items” (message sources) which each have their own count. The mockup image on that wiki page also suggests that this is the case: see “GMail Notify” in the mockup:

mockup

As far as I can tell, this isn’t possible. First, a little terminology.

menu

A program in the messaging menu can have three types of menu entry. The main entry for a program I’ve called the server, because that’s how it’s referred to in code. If a program is registered with the messaging menu, the server item will appear in the MM even if the program isn’t running. A program can also, if registered, add extra shortcuts to the menu to do specific things. Finally, while the program is running, it may add one or more message sources to the menu which show a count or time for the messages that have arrived for that source; the mail application would have one source for each mail account you have, for example.

So, according to the mockup and the spec, and using our new terminology, it should be possible to set a message count on a server. It is not.

count on server

Instead, you have to create both a server and at least one source.

Here I’m only going to talk about adding MM items while your program is running. If you want the server item to appear in the MM even when your program is not running (that is, make it so people can start your program from the MM) then read up on registration in the spec.

To create the server item:

# get the indicate module, which does all the work
import indicate
# Create a server item
mm = indicate.indicate_server_ref_default()
# If someone clicks your server item in the MM, fire the server-display signal
mm.connect("server-display", show_window_function)
# Set the type of messages that your item uses. It's not at all clear which types
# you're allowed to use, here.
mm.set_type("message.im")
# You must specify a .desktop file: this is where the MM gets the name of your
# app from.
mm.set_desktop_file("/usr/share/applications/myapp.desktop")
# Show the item in the MM.
mm.show()

Ideally, as mentioned, you’d now be able to set a count on that server item, but you can’t. So we need to create a source as well. (Some people call this an “indicator” for this server; the spec calls it a “message source”.)

# Create a source item
mm_source = indicate.Indicator()
# Again, it's not clear which subtypes you are allowed to use here.
mm_source.set_property("subtype", "im")
# "Sender" is the text that appears in the source item in the MM
mm_source.set_property("sender", "Unread")
# If someone clicks this source item in the MM, fire the user-display signal
mm_source.connect("user-display", show_window_function)
# Light up the messaging menu so that people know something has changed
mm_source.set_property("draw-attention", "true")
# Set the count of messages in this source.
mm_source.set_property("count", "15")
# If you prefer, you can set the time of the last message from this source,
# rather than the count. (You can't set both.) This means that instead of a
# message count, the MM will show "2m" or similar for the time since this
# message arrived.
# mm_source.set_property_time("time", time.time())
mm_source.show()

Hope this helps someone confused by it; at the least it’ll help me next time I’m confused by this!