An Introduction to the Message Indicator

Ken VanDine provides an introduction to the messaging indicator for developers, including code samples in C and Python.

Introduction

The messaging indicator, also known as the indicator-applet, is a central place to keep track of messages that you might need to be concerned about. The focus is on human-to-human messaging, such as instant messaging, e-mail, social networking, etc. By tracking these in a single applet, instead of displaying separate icons in the noticiation area or on the panel, we save a considerable amount of real estate and cut down on the clutter. We also get the benefit of a single place in the panel to find messages waiting review. For more information on the rationale, check out the specification.

Current applications that take advantage of the messaging indicator include:

  • Pidgin, with patches to pidgin-libnotify
  • Evolution, with evolution-indicator
  • Gajim, with patches already excepted upstream
  • Gwibber

To effectively use the messaging indicator with your application, you should keep two things in mind:

  1. Hide your applications icon from the notification area if it is using the indicator
  2. Rely on the indicator for raising/hiding your application as well as quick access to incoming messages

Examples

Lets walk through some examples. The library used to interact with the the messaging indicator is called libindicate, written in C. There are also python bindings to libindicate, which are called python-indicate. At this time the python-bindings only handle application side, not the listener.

Using it is actually pretty simple, you just need to have your application advertise it’s indicators using libindicate. The server object handles all of the DBus interactions so all you have to do is tell it about your indicators. The server registers itself with the indicator, which displays an item in the messaging menu for the application. When selecting the entry in the message menu, it calls the signal on the indicator. This is very useful for access to the application itself, like raising the buddy list in pidgin, etc. Examples included below in Python and you can find examples at the end of the article in C as well.

First we create the server object:

server = indicate.indicate_server_ref_default()

Set the message type and subtype, valid types include

  • “message”—a user level message. This includes e-mail, IM and SMS messages.
  • “system”—a software update or other notification about the system state.
  • “media”—a notification related media the user is listening to in the background

message.instant, message.micro, and message.im

server.set_type("message.im")

We can get some descriptive information to display in the messaging menu from a desktop file provided by the application:

server.set_desktop_file("/usr/share/applications/pidgin.desktop")

Now that all the setup work is done, we just need to connect it to the indicator. The second argument to this method call is the name of the method to call when selecting the entry in the messaging menu. The show method shows the indicator after connecting:

server.connect("server-display", server_display) server.show()

The client tells the server there is a message waiting, and when the message is selected in the the messaging menu it calls the display method for the client.

Setup the message object:

indicator = indicate.IndicatorMessage()

Then we need to set some properties for the message, available properties are: * “subject”—“message” (optional)—This is the subject line of an e-mail or message. * “sender”—“message” (required)—The person who sent the message * “body”—“message” (required)—The body of the message sent to the user
indicator.set_property("subtype", "instant") indicator.set_property("sender", "Test message") indicator.set_property("body", "Test message body") indicator.set_property_time("time", time())

The only things left to do is show the message and connect it to a method. The second argument in the connect method is the method to call when the message is selected:

indicator.show() indicator.connect("user-display", display)

Python Example

Here is a complete python example:

#!/usr/bin/env python

import indicate import gobject import gtk from time import time import os

curdir = os.getcwd() desktop_file = os.path.join(curdir, “example-indicator.desktop”)

def timeout_cb(indicator):

print "Modifying properties"
    indicator.set_property_time("time", time())
    return True

def display(indicator):

print "Ah, my indicator has been displayed"
    indicator.hide()

def server_display(server):

print "Ah, my server has been displayed"

if <i>name</i> == “<i>main</i>”:

    # Setup the server
    server = indicate.indicate_server_ref_default()
    server.set_type("message.im")
    server.set_desktop_file(desktop_file)
    server.connect("server-display", server_display)
    server.show()

    # Setup the message
    indicator = indicate.IndicatorMessage()
    indicator.set_property("subtype", "im")
    indicator.set_property("sender", "Test message")
    indicator.set_property("body", "Test message body")
    indicator.set_property_time("time", time())
    indicator.show()
    indicator.connect("user-display", display)

    # Loop
    gobject.timeout_add_seconds(5, timeout_cb, indicator)
    gtk.main()

C Example

C example:

#include <glib.h>

#include “libindicate/server.h”

#include “libindicate/indicator-message.h”

static gboolean timeout_cb (gpointer data) { g_debug(“Modifying properties”);

IndicateIndicator * indicator = INDICATE_INDICATOR(data);

GTimeVal time; g_get_current_time(&time); indicate_indicator_set_property_time(INDICATE_INDICATOR(indicator), “time”, &time);

return TRUE; }

static void display (IndicateIndicator * indicator, gpointer data) { g_debug(“Ah, my indicator has been displayed”); indicate_indicator_hide(indicator); }

static void server_display (IndicateServer * server, gpointer data) { g_debug(“Ah, my server has been displayed”); }

int main (int argc, char ** argv) { g_type_init();

IndicateServer * server = indicate_server_ref_default(); indicate_server_set_type(server, “message.im”); gchar * path = g_build_filename(g_get_current_dir(), “example-indicator.desktop”, NULL); indicate_server_set_desktop_file(server, path); g_free(path); g_signal_connect(G_OBJECT(server), INDICATE_SERVER_SIGNAL_SERVER_DISPLAY, G_CALLBACK(server_display), NULL);

IndicateIndicatorMessage * indicator;

indicator = indicate_indicator_message_new(); indicate_indicator_set_property(INDICATE_INDICATOR(indicator), “subtype”, “instant”); indicate_indicator_set_property(INDICATE_INDICATOR(indicator), “sender”, “IM Client Test”); GTimeVal time; g_get_current_time(&time); indicate_indicator_set_property_time(INDICATE_INDICATOR(indicator), “time”, &time); indicate_indicator_show(INDICATE_INDICATOR(indicator));

g_get_current_time(&time); indicate_indicator_set_property_time(INDICATE_INDICATOR(indicator), “time”, &time);

g_signal_connect(G_OBJECT(indicator), INDICATE_INDICATOR_SIGNAL_DISPLAY, G_CALLBACK(display), NULL);

g_timeout_add_seconds(5, timeout_cb, indicator);

g_main_loop_run(g_main_loop_new(NULL, FALSE));

return 0; }

.desktop Example

Example desktop file example-indicator.desktop:

[Desktop Entry]
Version=1.0
Name=Example Indicator
Type=Application

Conclusion

Lets clean up the notification area! To do this, we will need everyone’s help. If you maintain an application that could utilize the message indicator, please update it to support the indicator. If you aren’t a maintainer, but have an application you use regularly that could use the indicator and have the skills to create a patch, please do. Maintainers are usualy happy to receive patches, so patch something you care about and submit the patch. Let me also add, if you find bugs (or have suggestions for improvement) in the indicator APIs or the indicator itself, please file bugs in Launchpad.

About the Author

Ken VanDine is an Ubuntu Desktop Integration Engineer at Canonical. As a member of the GNOME Marketing team, Ken has written articles for the GNOME Journal (http://www.gnomejournal.org) and is now the maintainer of the GNOME LiveCD available at http://torrents.gnome.org and the GNOME Developer Kit available at http://live.gnome.org/GnomeDeveloperKit.

Discuss this story with other readers on the GNOME forums.

Advertisements

Posted on April 27, 2009, in April 2009. Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: