]>
1999-06-14 Érdi Gergő
cactus@cactus.rulez.org
1999 Gergő Érdi This document can be freely redistributed according to the terms of the GNU General Public License. Writing GNOME panel applets using the GTK+/GTK-- widget set panelapplet This document describes how to use the libpanel-applet library to write GNOME panel applets. It assumes the reader to have proficiency in the GTK+ or the GTK-- library. The SGML original can be found here.
Introduction If you've used GNOME before (or seen screenshots), you've undoubtly noticed the GNOME panel which dominates one or more edges of the screen. You can add application launchers, menus, and applets to it. A panel applet is a small program that uses some portion of the GNOME panel to display its user interface. There are some basic applets in the standard gnome-panel distribution, like the pager, or a sound mixer control. The library we'll use to create similar applets is called libpanel-applet. It allows seamless integration of GTK widgets into the panel. Of course you'll need both the runtime and the compile-time version (usually marked as -dev or -devel in distributions) Changes from an average GTK application Your average GTK application looks something like this: Non-panel application #include <gtk/gtk.h> int main(int argc, char **argv) { /* ... we build the user interface ... */ gtk_init(&argc, &argv); /* #1 */ GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* #2 */ gtk_window_set_title(GTK_WINDOW(window), PACKAGE); /* controls is the name of the container all our widgets are in */ gtk_container_add(GTK_CONTAINER(window), controls); /* #3 */ gtk_widget_show(window); /* Everything's ready to begin our main loop */ gtk_main(); /* #4 */ return 0; } All we need now is to change the numbered lines to their GNOME panel applet equivalents: Panel version #include <applet-widget.h> int main(int argc, char **argv) { applet_widget_init(PACKAGE, VERSION, argc, argv, NULL, 0, NULL); /* #1 */ GtkWidget* applet = applet_widget_new(PACKAGE); /* #2 */ applet_widget_add(APPLET_WIDGET(applet), controls); /* #3 */ gtk_widget_show(applet); applet_widget_gtk_main(); /* #4 */ return 0; } Line #2 and #3 are pretty self-explanatory: we use the applet container instead of a GTK window to pack our widgets into it. #1 needs the PACKAGE and VERSION information for registration purposes. argc and argv are parsed for command-line options used by the applet registration mechanism (see any_applet --help for a full list). The last three arguments (unused in our example) are described in the popt documentation. When using GTK--, since there's no wrapper for Applet_Widget yet, you'll have to use something like this: GTK-- modifications controls.show_all(); applet_widget_add(APPLET_WIDGET(window), GTK_WIDGET(controls.gtkobj())); /* #3 */ Customizing the menu If you click with button 3 on an existing applet, you'll notice that a stock menu pops up, with a "Remove" and a "Move" option. Some applets also have custom menu items like "About" or "Properties". These are the functions provided to manipulate the menu: void applet_widget_register_callback AppletWidget *applet char *name char *menutext AppletCallbackFunc func gpointer data void applet_widget_register_stock_callback AppletWidget *applet char *name char *stock_type char *menutext AppletCallbackFunc func gpointer data Inserts a menu item into the panel menu. name is used to identify the menu item. It is also the path of the menu item, this way you can specify which submenu the new item should go in. menutext is simply the label of the item. func is a pointer to a void function (it is called with two arguments: an AppletWidget* and a gpointer). The gpointer that is passed to *func is specified in data. applet_widget_register_stock_callback is the same as applet_widget_register_callback, the stock_type argument is used to specify a stock GNOME pixmap (see libgnomeui/gnome-stock.h for a list of definitions). void applet_widget_register_callback_dir AppletWidget *applet char *name char *menutext void applet_widget_register_stock_callback_dir AppletWidget *applet char *name char *stock_type char *menutext Creates a new sub-menu. You can later insert menu items to it by using applet_widget_register_callback, specifying name in the path. Again, applet_widget_register_stock_callback_dir also inserts a stock pixmap. void applet_widget_unregister_callback AppletWidget *applet char *name void applet_widget_unregister_callback_dir AppletWidget *applet char *name Removes the menu item or submenu specified by name. Examples Menu example applet_widget_register_stock_callback (APPLET_WIDGET(applet), "about", GNOME_STOCK_MENU_ABOUT, _("About"), &my_applet_cb_about, NULL); applet_widget_register_callback_dir (APPLET_WIDGET(applet), "submenu", _("Test submenu")); applet_widget_register_callback (APPLET_WIDGET(applet), "submenu/window", _("Open window"), &my_applet_cb_showwnd, NULL); The _("") functions are simply macros for GNU Gettext support, defined in one of the GNOME support headers. If you use GTK--, the data argument can be used to call an instance method, as seen in the following example: Using <parameter>data</parameter> for keeping the instance void my_applet_cb_foo(AppletWidget* caller, gpointer data) { ((My_Class*)data)->foo(); } void My_Class::foo() { /* For example, bar could be a member field */ bar = quux(); } void My_Class::My_Class() { /* ... */ applet_widget_register_callback (APPLET_WIDGET(applet), "foo", "Update foo", &my_applet_cb_foo, (gpointer)this); } If we passed &My_Class::foo as the callback function, there would be no way to get the object instance from the member function (this is, of course, not an issue with static members) When you pass this as a gpointer, be sure to cast it back exactly to the same type in the callback function, otherwise data corruption could occur (you can always use the various _cast<> functions for runtime pointer casting) Compiling the applet Compiling a GNOME panel applet requires some custom compiler flags. For your convenience, the gnome-config script can be used to automatically include the necessary flags. $ gcc `gnome-config --cflags applets` -o my_applet.o -c my_applet.c $ gcc `gnome-config --libs applets` -o my_applet my_applet.o $ ./my_applet If you get an error message, check that libpanel_applet is installed correctly Supplemental files In , you launched your applet manually from the command line. If you would like your applet to be available for other users on your system, accessible from the Add applet menu, you'll also have to provide two information files: /etc/CORBA/servers/my_applet.gnorba and /usr/share/applets/Category/my_applet.desktop. These are pretty straightforward, two examples will (hopefully) be sufficient. The .gnorba file [my_applet] type=exe repo_id=IDL:GNOME/Applet:1.0 description=Example panel applet location_info=my_applet The .desktop file [Desktop Entry] Name=My very own applet Name[hu]=Az én saját kisalkalmazásom Comment=An example applet Comment[hu]=Egy példa-kisalkalmazás Exec=my_applet --activate-goad-server=my_applet Icon=my_icon.xpm Terminal=0 Type=Application Be sure that the app_id passed to applet_widget_init is the same as the identifier used in the Exec line (see ) You can include a number of Name and Comment lines in the .desktop file, for different languages and locales. Links and helpful files Template .gnorba file Template .desktop file RadioActive, A simple GTK---based panel applet