The KDE panel (below referred to as "kicker") has been rewritten from scratch for KDE 2.0 and one of the main goals of the rewrite was to increase extensibility. For this reason with KDE 2.0 an API for panel applets has been introduced followed by an API for panel extension introduced with the KDE 2.1 release. Panel applets and extensions are simply referred to as "plugins" in the following paragraphs.
Panel applets are small applications living inside the panel. Available applets range from desktop pagers and task bars to little games or other toys. In contrast to applets the panel extension API is an interface for extensions living outside of the panel, in the window manager dock area (as defined in the freedesktop.org window manager specifications and are managed by the panel. Examples for panel extensions are the external task bar and the dock application bar which adds support for Window Maker applets and other applications using the standard X11 docking mechanism to kicker.
Starting with a short technology overview this tutorial discusses the implementation of a simple panel applet. Both the applet and extension APIs are simple. This qualifies writing a panel applet as a suitable task for an introduction to KDE programming. This tutorial presumes that the reader has some basic C++ and Qt knowledge. You can find a basic Qt tutorial at: http://doc.trolltech.com/tutorial.html
Panel plugins are implemented as DSO s (Dynamic Shared Objects). The panel locates available applets by searching for applet description files in (ALL_KDEDIRS)/share/apps/kicker/applets Every plugin must install a description file to be recognized by the panel. Available panel extensions are located by searching (A_KDEDIR)/share/apps/kicker/extensions for similar description files.
Implementing a panel applet is as easy as inheriting from the base class KPanelApplet (declared in kdelibs/kdeui/kpanelapplet.h), providing a factory function and installing the description file mentioned above. For extensions the respective base class is KPanelExtension , declared in kdelibs/kdeui/kpanelextension.h.
While plugins are implemented as shared libraries and thus loaded into the panel's address space, for security and stability reasons kicker also implements loading of plugins via external proxy processes called appletproxy and extensionproxy. The loading behavior is user configurable via kcontrol, with the obvious benefit that users may configure their panel to load untrusted third party plugins via the proxies to avoid buggy plugins taking the whole panel down with them.
While as an plugin author you don't have to be concerned about these implementation details it is good to know what happens behind the scenes. Therefore I might mention here that the panel communicates with the proxies via the DCOP protocol (see kdelibs/dcop) and makes use of QXEmbed (see kdelibs/kdeui/qxembed.h) to embed external (loaded via one of the two proxies) plugins into the panel.
A hello world panel applet
We start with a hello world panel applet that can be implemented in only a few lines of code and is a good base upon which to build a more complex applet. As already mentioned in the overview section all that needs to be done is inheriting from KPanelApplet , providing a factory function and a .desktop description file.
Our little project consists of four files: helloworldapplet.h containing the class declaration, helloworldapplet.cpp containing the class implementation and the factory function, helloworldapplet.desktop the description file and Makefile.am as input for the automake/autoconf KDE build system.
HelloWorldApplet class declaration
class HelloWorldApplet : public KPanelApplet
HelloWorldApplet( const QString& configFile, Type t = Stretch, int actions = 0, QWidget *parent = 0, const char *name = 0 );
int widthForHeight( int height ) const;
int heightForWidth( int width ) const;