How to Write Panel Applets in Gnome

by Rajalaxmi Mishra & Samar Abbas, School of Math., Stats. and Computer Science, Utkal University, Bhubaneshwar-751005, Orissa, India.

Introduction

GNOME is one of the two major desktop environments in the Linux arena today. It is built upon the Gtk toolkit, in contrast to KDE, which is built upon the Qt toolkit. A very important part of the Gnome Desktop is the gnome panel, which is the usually horizontal bar found at the bottom of the desktop. It acts as a repository for menus, applets, drawers and various special objects. An applet is a Gnome application which resides in this panel. In this article, we learn how to program for this highly important part of the Gnome user interface. This article uses Red Hat Linux 7.2 and GTK+2.0. You must have the packages gtk+ and gtk+-devel installed.

Hello World

Let us start with the simple standard Hello World program. Either type the following text or cut and paste it:
#include <applet-widget.h>

int main(int argc, char **argv)
{
  GtkWidget *xapplet, *xbutton;

  applet_widget_init("PACKAGE", "VERSION", argc, argv, NULL, 0, NULL);
  xapplet = applet_widget_new("PACKAGE");

  xbutton = gtk_button_new_with_label("Hello World");
  gtk_widget_show(xbutton);

  applet_widget_add(APPLET_WIDGET(xapplet), xbutton);
  gtk_widget_show(xapplet);

  applet_widget_gtk_main();
  return EXIT_SUCCESS;
}
Then, compile it using the command,
$ gcc `gnome-config --cflags --libs applets` panel_hello.c

You may get some errors regarding CORBA, if that has not been configured properly on your machine. As of now, ignore these errors. The command gnome-config outputs a list of gnome libraries to be included in the gcc C oompiler. Thus, the --libs flag specifies that the `applets' library of GNOME is to be used. After compiling the applet, execute it using the command $./a.out. You should see the applet displaying "Hello World" in the panel. To stop the applet, hit ^-C (control-C).

Now, it is time to understand the code. The file to be included from the standard directory (ie. /usr/include is applet-widget.h , in contrast to gtk/gtk.h which must be included for non-panel applications. In case you get an error in compilation, check that the file /usr/include/applet-widget.h is present. The first function applet_widget_init() initializes the applet widget, taking the package name, version, and command-line arguments as inputs. Here, we just specify them as strings, but actual developers will want to specify some values for these variables. This is the counterpart of gtk_init() for non-panel applications.

Then, the applet_widget_new() function instantiates the applet. It is the counterpart of gtk_window_new() for non-panel applications. applet_widget_add() packs our applets into the applet container instead of the standard GTK container. We have to use type casting to cast our xapplet instance to the correct type. It is the counterpart of gtk_container_add() for non-panel applications. applet_widget_gtk_main() is the counterpart of gtk_main() for standard GTk applets.

Crude Digital Clock

After Hello World, it is time to move on to a crude digital clock applet. Here is the code:
#include <applet-widget.h>
#include <string.h>
#include <time.h>

time_t   xtime; 	

static void  myf (void)
{
	xtime = time (NULL);  
// time is the function defined in time.h, returns seconds since 1/1/1970
}				     	

static GtkWidget *xbutton;

static int xfunction(GtkWidget *button)
{
	char mytime[100];
	myf();   
        sprintf(mytime,"%d", xtime);
        gtk_label_set_text(GTK_LABEL(GTK_BIN(xbutton)->child),mytime);
       return 1;
}

int main(int argc, char **argv)
{
	  GtkWidget *xapplet;
	  //initialize the applet
	  applet_widget_init("PACKAGE", "VERSION", argc, argv, NULL, 0, NULL);
	  //Creates a button with label Time
	  xbutton = gtk_button_new_with_label("Time");
        	  gtk_widget_show(xbutton);
	  //Create a new applet widget
	  xapplet = applet_widget_new("PACKAGE");
	  // add the button to the widget
          applet_widget_add(APPLET_WIDGET(xapplet), xbutton);
	  gtk_timeout_add(1000, (GtkFunction)xfunction, xbutton);
	// after 1000 millisec xfunction will be attached to xbutton
	  gtk_widget_show(xapplet);	
	 applet_widget_gtk_main();
}


Compile using
$gcc `gnome-config --cflags --libs applets` panel_clock.c

The output should be a number of the order of one billion, displayed in the panel. Congratulations, your first clock is ready. To stop the application, use ^C in the active terminal.

The reason for this is because time() function returns the number of seconds elapsed since Jan.1, 1970, the birthday of Unix, and the output is stored in the xtime variable. Of course, displaying the number of seconds since 1/1/1970 is not very user-friendly, so we now move on to our next clock, which will show the time in a human-friendly manner.

Digital Clock:

After the crude digital clock, it is time to move on to a more advanced application: a digital clock. The following is the source code:
#include <applet-widget.h>
#include <string.h>
#include <time.h>

struct tm   *xstime; /* defined in time.h*/
time_t   xtime; 	/* defined in time.h */

static void  myf (void)
{
	xtime = time (NULL);  // seconds since 1/1/1970
    	xstime = localtime (&xtime);  /* converts seconds to h.m.s */
}				     	

static GtkWidget *xbutton;

static int xfunction(GtkWidget *button)
{
	int hr,mn,sc;
	char mytime[100];
	myf();   
	/*get hour, minute and second from xstime*/ 
	hr=xstime->tm_hour;
	mn= xstime->tm_min;
       	sc=xstime->tm_sec;
	/* time i.e hour, minute and second will be put in one variable mytime*/				
        sprintf(mytime,"%d:%d:%d", hr,mn,sc);
        gtk_label_set_text(GTK_LABEL(GTK_BIN(xbutton)->child),mytime);
	/* mytime will be displayed as a label on the applet*/
	  return 1;
}

int main(int argc, char **argv)
{
	  GtkWidget *xapplet;
	  //initialize the applet widget
	  applet_widget_init("PACKAGE", "VERSION", argc, argv, NULL, 0, NULL);
	  // a button called xbutton is created with label Time
	  xbutton = gtk_button_new_with_label("Time");
        	  gtk_widget_show(xbutton);
	  xapplet = applet_widget_new("PACKAGE");
	  // the button will be added to the applet widget
          applet_widget_add(APPLET_WIDGET(xapplet), xbutton);
	  gtk_timeout_add(1000, (GtkFunction)xfunction, xbutton);
	// afetr 1000 millisec xfunction is attached to xbutton
	  gtk_widget_show(xapplet);
	
	 applet_widget_gtk_main();
}

To compile, execute the following command:
$gcc `gnome-config --cflags --libs applets` -o panel_clock panel_clock.c

Now, this clock should display the hours, minutes and seconds time format.

Here, the function localtime is used to convert the time elapsed since 1/1/1970 into a more user-friendly format.