Writing Hildon Desktop Plug-ins for Maemo

This document has been reviewed for maemo 4.0.

Introduction

desktop-architecture-picture

This tutorial shows how to write Status Bar, Task Navigator, Control Panel and Home Area plug-ins for Hildon Desktop.

Hildon Desktop consists of several subcomponents: Task Navigator, Home Area and Status Bar. They support additional plug-ins that are displayed on each these components, extending the functionality of the host application. This tutorial will explain how to write plug-ins for the desktop components using the new GTypeModule -based API. The tutorial also explains the API for writing applets for Control Panel.

Task Navigator Plug-ins

The Task Navigator implements a modular plug-in architecture allowing binary plug-ins to be loaded. This extends the functionality of the Task Navigator, and is achieved with task buttons. The license for the Task Navigator plug-in can be open source or closed source; in this way, the Task Navigator is versatile and ideal for use in many kinds of devices and applications.

Task Navigator Plug-in API

Task Navigator plug-ins can have any widget as their representation on the Task Navigator plug-in area. The plug-in representation, statically visible in the task navigator, can be e.g. GtkButton. Task navigator loads the library and displays the main widget of the plug-in in the plug-in area of the Task Navigator.

The plug-ins are responsible for their own signals, e.g. clicked, toggle and related events, and implementing the callback functions for them. Task navigator only provides a container for the plug-ins; the plug-ins themselves are responsible for implementing their own UI.

Desktop File Location

Task Navigator plug-ins must provide a desktop file. It is placed in the directory given by:

 pkg-config osso-af-settings  --variable=tasknavigatordesktopentrydir
and is by default: /usr/share/applications/hildon-navigator/

Desktop File Contents

The following describes the required contents of the .desktop file.

The Task Navigator Configuration Control Panel applet is the only one involved with the contents of these .desktop files. Thus, the Task Navigator itself does not read them, and the absence of the file does not prevent the plug-in from working.

The following is an example .desktop file for the Task Navigator applet:

[Desktop Entry]
Name=Hello World
Type=default
X-Path=/usr/lib/hildon-navigator/libhelloworld-tn.so
  • Name of the plugin in Control Panel.
  • Type is always default.
  • X-Path tells where to find the plugin.

Public interface

Should look like an usual GObject-based class/object declation. The following is an example implementation:

#ifndef HELLO_NAVIGATOR_PLUGIN_H
#define HELLO_NAVIGATOR_PLUGIN_H

#include 

/* For Task Navigator plugins */
#include 

G_BEGIN_DECLS

/* Common struct types declarations */
typedef struct _HelloNavigatorPlugin HelloNavigatorPlugin;
typedef struct _HelloNavigatorPluginClass HelloNavigatorPluginClass;
typedef struct _HelloNavigatorPluginPrivate HelloNavigatorPluginPrivate;

/* Common macros */
#define HELLO_TYPE_NAVIGATOR_PLUGIN            (hello_navigator_plugin_get_type ())
#define HELLO_NAVIGATOR_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), HELLO_TYPE_NAVIGATOR_PLUGIN, HelloNavigatorPlugin))
#define HELLO_NAVIGATOR_PLUGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  HELLO_TYPE_NAVIGATOR_PLUGIN, HelloNavigatorPluginClass))
#define HELLO_IS_NAVIGATOR_PLUGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HELLO_TYPE_NAVIGATOR_PLUGIN))
#define HELLO_IS_NAVIGATOR_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  HELLO_TYPE_NAVIGATOR_PLUGIN))
#define HELLO_NAVIGATOR_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  HELLO_TYPE_NAVIGATOR_PLUGIN, HelloNavigatorPluginClass))

/* Instance struct */
struct _HelloNavigatorPlugin
{
    TaskNavigatorItem tnitem;

    HelloNavigatorPluginPrivate *priv;
    GtkWidget              *button;
    GtkWidget              *menu;
};

/* Class struct */
struct _HelloNavigatorPluginClass
{
    TaskNavigatorItemClass parent_class;
};

GType  hello_navigator_plugin_get_type  (void);
GtkWidget *hello_world_button_new (int padding);


G_END_DECLS

#endif /* HELLO_NAVIGATOR_PLUGIN_H */

hello_navigator_plugin_init

The function is called upon initialization. It is declared with HD_DEFINE_PLUGIN. It creates the widget that is displayed on the Task Navigator. As mentioned earlier, this is typically a GtkButton. The Task Navigator automatically sizes the button correctly. It also initializes the popup menu.

If the button needs to have proper skin, its name should be set as "hildon-navigator-button-one" with gtk_widget_set_name function.

The following is an example implementation:

HD_DEFINE_PLUGIN (HelloNavigatorPlugin, hello_navigator_plugin, TASKNAVIGATOR_TYPE_ITEM);

static void
hello_navigator_plugin_init (HelloNavigatorPlugin *navigator_plugin)
{
  GtkWidget *button;

//  button = gtk_button_new_with_label ("HW");
  button = hello_world_button_new (10);
  navigator_plugin->button=button;
  navigator_plugin->menu=create_menu();
  //gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_stock (GTK_STOCK_CONVERT, GTK_ICON_SIZE_LARGE_TOOLBAR));

  g_signal_connect (G_OBJECT (button), "clicked",
                      G_CALLBACK (popup_menu), navigator_plugin);

  gtk_widget_set_size_request (button, 80, 80);
  gtk_widget_set_name (button, "hildon-navigator-button-one");

  gtk_widget_show_all (button);

  gtk_container_add (GTK_CONTAINER (navigator_plugin), button);
  gtk_widget_show_all (navigator_plugin);
}

static void
hello_navigator_plugin_class_init (HelloNavigatorPluginClass *class)
{
}

It is advisable to set a pointer to the button in the data that is returned, since it is used later on (navigator_plugin->button).

Initializing menu

The menu is created, proper popup, position and action (show_dialog) functions are defined.

The following is an example implementation:

static void
show_dialog (GtkWidget *item, HelloNavigatorPlugin *thw)
{
    GtkWidget *dialog;
    dialog = gtk_message_dialog_new (NULL,
                                     GTK_DIALOG_MODAL |
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                                     GTK_MESSAGE_INFO,
                                     GTK_BUTTONS_CLOSE,
                                     "Hello world!");

    gtk_window_set_title (GTK_WINDOW(dialog), "TN Plugin Example");
    gtk_dialog_run (GTK_DIALOG (dialog));
    gtk_widget_destroy (dialog);
}

static void
menu_position (GtkMenu *menu,
               gint *x,
               gint *y,
               gboolean *push_in,
               HelloNavigatorPlugin *thw)
{
    g_return_if_fail (thw->button);
    *push_in = TRUE;

    *x = thw->button->allocation.x + thw->button->allocation.width;
    *y = thw->button->allocation.y;
}

static void
popup_menu (GtkWidget *button, HelloNavigatorPlugin *plugin)
{
    if (!plugin->menu)
        return;

    gtk_menu_popup (GTK_MENU (plugin->menu),
                    NULL,
                    NULL,
                    (GtkMenuPositionFunc)menu_position,
                    plugin,
                    0,
                    gtk_get_current_event_time());
}

static GtkWidget*
create_menu (void)
{
    GtkWidget  *menu;
    GtkWidget  *menu_item;

    menu = gtk_menu_new ();

    menu_item = gtk_menu_item_new_with_label ("Hello World!");
    g_signal_connect (G_OBJECT (menu_item), "activate",
                      G_CALLBACK (show_dialog), NULL);

    gtk_menu_append (menu, menu_item);

    /* Name the menu to get the appropriate theming */
    gtk_widget_set_name (menu, "menu_from_navigator");

    gtk_widget_show_all (menu);

    return menu;
}

Installing plugin

The plugin install path can be received using command:

pkg-config osso-af-settings --variable=hildondesktoplibdir

Home Plug-ins

Home plug-ins are located in the Home Area of the desktop. They can be resized if the resizability flag X-home-applet-resizable is mentioned in the .desktop file of the plug-in.

Desktop file location

Each home applet needs to provide a .desktop file. The .desktop file location is determined with:

 pkg-config osso-af-settings --variable=homedesktopentrydir 
and it defaults to: /usr/share/applications/hildon-home

Desktop file contents

The following is an example hello-world-applet.desktop:

[Desktop Entry]
Name=Hello, World!
Comment=Example Home plugin
Type=default
X-Path=libhelloworld-home.so

The mandatory fields are the same as for Task Navigator plugins.

Home plug-in implementation

Home plugins should inherit from libhildondesktop's HildonDesktopHomeItem. Here's an example header file:

#ifndef HELLO_HOME_PLUGIN_H
#define HELLO_HOME_PLUGIN_H

#include <glib-object.h>

#include <libhildondesktop/hildon-desktop-home-item.h>

G_BEGIN_DECLS

/* Common struct types declarations */
typedef struct _HelloHomePlugin HelloHomePlugin;
typedef struct _HelloHomePluginClass HelloHomePluginClass;
typedef struct _HelloHomePluginPrivate HelloHomePluginPrivate;

/* Common macros */
#define HELLO_TYPE_HOME_PLUGIN            (hello_statusbar_plugin_get_type ())
#define HELLO_HOME_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), HELLO_TYPE_HOME_PLUGIN, HelloHomePlugin))
#define HELLO_HOME_PLUGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  HELLO_TYPE_HOME_PLUGIN, HelloHomePluginClass))
#define HELLO_IS_HOME_PLUGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HELLO_TYPE_HOME_PLUGIN))
#define HELLO_IS_HOME_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  HELLO_TYPE_HOME_PLUGIN))
#define HELLO_HOME_PLUGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  HELLO_TYPE_HOME_PLUGIN, HelloHomePluginClass))

/* Instance struct */
struct _HelloHomePlugin
{
     HildonDesktopHomeItem hitem;

     HelloHomePluginPrivate *priv;
};

/* Class struct */
struct _HelloHomePluginClass
{
     HildonDesktopHomeItemClass parent_class;
};

GType  hello_home_plugin_get_type  (void);

G_END_DECLS

#endif

The main functionality consists of required headers, HD_DEFINE_PLUGIN and init functions. The following example creates a button which is defined in the libhelloworld.h header (see example files) and assigns a dialog showing function to it. Instead of a button, any other suitable GTK+ widget may be used. The widget will be shown in the Home view.

#include <glib.h>
#include <gtk/gtk.hh>

#include <libhildondesktop/libhildondesktop.hh>

#include "hello-world-home.h"
#include "libhelloworld.h"


HD_DEFINE_PLUGIN (HelloHomePlugin, hello_home_plugin, HILDON_DESKTOP_TYPE_HOME_ITEM);

static void
hello_home_plugin_init (HelloHomePlugin *home_plugin)
{
  GtkWidget *button;

  button = hello_world_button_new (10);
  g_signal_connect (button, "clicked",
                    G_CALLBACK (hello_world_dialog_show),
                    NULL);

  gtk_widget_show_all (button);

  /* Set the resizing behavior */
  hildon_desktop_home_item_set_resize_type (HILDON_DESKTOP_HOME_ITEM (home_plugin),
                                            HILDON_DESKTOP_HOME_ITEM_RESIZE_BOTH);

  gtk_container_add (GTK_CONTAINER (home_plugin), button);
}

static void
hello_home_plugin_class_init (HelloHomePluginClass *class)
{
}

Installing plugin

The plugin install path can be received using command:

pkg-config osso-af-settings --variable=hildondesktoplibdir

Status Bar Plug-ins

The Status Bar contains status-bar plugins. Order of plug-ins and other properties can be set with the Task Navigator and Status Bar configuration applet found on the Control Panel ("Navigation applet").

Status Bar plug-ins are divided into three categories, namely: permanent, conditional and temporal. Permanent plug-ins are shown all the time. Conditional and temporal plug-ins are shown only when the condition is fulfilled.

Desktop file location

The .desktop file shall be placed in the directory given by:

pkg-config osso-af-settings --variable=statusbardesktopentrydir
which defaults to: /usr/share/applications/hildon-status-bar/.

Desktop file contents

Each plug-in has to offer a .desktop file:

  [Desktop Entry]
  Name=<logical name identifier>
  Icon=<logical icon identifier>
  Category=<permanent/conditional/temporal>, 
            the default value is permanent if the key value read fails.
  X-Path=lib<plugin name>.so
  Type=default
  Mandatory=<true/false>,
            if not set, the default value is false

Here is an example:
[Desktop Entry]
Name=Hello world
Icon=hello-world
Category=temporal
Type=default
X-Path=libhelloworld_sb.so

Header file

Example header file:

#ifndef _HILDON_STATUS_BAR_HELLOWORLD_H_
#define _HILDON_STATUS_BAR_HELLOWORLD_H_

/* StatusbarItem */
#include <libhildondesktop/statusbar-item.h>

/* osso_context_t */
#include <libosso.h>

/* gboolean, gint, G_BEGIN_DECLS/G_END_DECLS */
#include <glib.h>

/* GtkWidget */
#include <gtk/gtk.h>

G_BEGIN_DECLS

/* Every plugin has a constant priority */
#define HILDON_STATUS_BAR_HELLOWORLD_PRIORITY   1

#define HILDON_STATUS_BAR_HELLOWORLD_ICON_SIZE  40

typedef struct _HildonStatusBarHelloWorld HildonStatusBarHelloWorld;
typedef struct _HildonStatusBarHelloWorldClass HildonStatusBarHelloWorldClass;

#define HILDON_TYPE_STATUS_BAR_HELLOWORLD            (hildon_status_bar_helloworld_get_type ())
#define HILDON_STATUS_BAR_HELLOWORLD(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_TYPE_STATUS_BAR_HELLOWORLD, HildonStatusBarHelloWorld))
#define HILDON_STATUS_BAR_HELLOWORLD_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  DUMMY_TYPE_STATUS_BAR_HELLOWORLD, HildonStatusBarHelloWorldClass))
#define HILDON_IS_STATUS_BAR_HELLOWORLD(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DUMMY_TYPE_STATUS_BAR_HELLOWORLD))
#define HILDON_IS_STATUS_BAR_HELLOWORLD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  DUMMY_TYPE_STATUS_BAR_HELLOWORLD))
#define HILDON_STATUS_BAR_HELLOWORLD_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  DUMMY_TYPE_STATUS_BAR_HELLOWORLD, HildonStatusBarHelloWorldClass))

struct _HildonStatusBarHelloWorld
{
    StatusbarItem parent;
};

struct _HildonStatusBarHelloWorldClass
{
    StatusbarItemClass parent_class;
};

GType hildon_status_bar_helloworld_get_type(void);

typedef struct
{
    osso_context_t       *osso;         /* osso */
    GtkWidget            *icon;         /* icon in button */
    GtkWidget            *button;       /* button in StatusBar */
} HildonStatusBarHelloWorldPrivate;

G_END_DECLS

#endif

Status Bar Functions

The most important function is the init function, which is called when the library is opened. If any g_timeouts or such are used, the IDs of these must be stored for removal. The following example illustrates the init function:

static void hildon_status_bar_helloworld_init(HildonStatusBarHelloWorld *helloworld)
{
    HildonStatusBarHelloWorldPrivate *info = 
        HILDON_STATUS_BAR_HELLOWORLD_GET_PRIVATE(helloworld);

    ULOG_OPEN("hildon-sb-helloworld");

    g_return_if_fail(info);

    info->icon = gtk_image_new_from_pixbuf(NULL);
    info->button = gtk_toggle_button_new();

    set_helloworld_icon("hello-world", info);

    gtk_container_add(GTK_CONTAINER(info->button),
                      GTK_WIDGET(info->icon));

    gtk_container_add(GTK_CONTAINER(helloworld), info->button);

    /* Signal for icon (button) */
    g_signal_connect(G_OBJECT(info->button), "button-press-event",
                     G_CALLBACK(hello_world_dialog_show), NULL);

    /* Initialize osso */
    info->osso = osso_initialize("hildon_sb_helloworld", "1.0", FALSE, NULL);
    if (!info->osso)
        ULOG_WARN("%s: error while initializing osso\n", __FUNCTION__);

    gtk_widget_show_all(GTK_WIDGET(helloworld));
}

Destroying Plug-in

When the item is destroyed, the finalize function is called. The function is defined in class initialization. It should free all the memory and release all the notifications that can lead to the plug-in code. The following example illustrates the finalize function:

static void hildon_status_bar_helloworld_class_init(
		HildonStatusBarHelloWorldClass *klass)
{
    GObjectClass *object_class = G_OBJECT_CLASS(klass);
    object_class->finalize = hildon_status_bar_helloworld_finalize;
    g_type_class_add_private(klass, sizeof(HildonStatusBarHelloWorldPrivate));
}

...

static void hildon_status_bar_helloworld_finalize(GObject *object)
{
    HildonStatusBarHelloWorldPrivate *info = HILDON_STATUS_BAR_HELLOWORLD_GET_PRIVATE(object);

    osso_deinitialize(info->osso);

    LOG_CLOSE();

    G_OBJECT_CLASS(g_type_class_peek_parent(G_OBJECT_GET_CLASS(object)))->finalize(object);
}

There is the possibility of avoiding reloading of plug-ins by setting the plug-in as mandatory in the .desktop file, so that it is never unloaded under any circumstances. If so, the plug-in cannot be deselected in control panel navigator applet.

Building Shared Object

The shared object can be built like any normal binary, by only giving the "-shared" flag to gcc:

        
[sbox-CHINOOK_X86: ~] > gcc -shared `pkg-config gtk+-2.0 libosso hildon-1 libhildondesktop --libs --cflags` hello-world-statusbar.c -o libhelloworld_sb.so

The binary produced by gcc must be installed to the path specified in the "osso-af-settings pkg-config" entry. This path can be obtained with

pkg-config osso-af-settings --variable=hildondesktoplibdir
By default, it is /usr/share/applications/hildon-status-bar.

Hildon Control Panel Plug-ins

Hildon Control Panel follows the same approach with its plug-ins as the other components in the Hildon Desktop environment. Control panel is a standardized place for putting settings, changeable by the end-users, for applications, servers etc. in the system.

The Control Panel is divided into four categories: General, Connectivity, Personalization and Extras.

Desktop file contents

Each Control Panel applet has to provide a .desktop file in the following format:

  [Desktop Entry]
  Name=<logical applet name identifier>
  Comment=Task Navigator Control Panel Applet
  Type=default
  Icon=<logical icon name identifier>
  Categories=<general/connectivity/personalisation/extras>, from which 
              the extras is the default value, in case the key value 
              read fails. 
  X-Path=lib<applet name>.so

Init function

Hildon Control Panel calls the init function as defined by the HD_DEFINE_PLUGIN macro when the plugin is launched.

Creating Makefiles and Package for Applet

Following the instructions in this document, simple Home applets can be made. The applet basically just contains an eventbox whose state can be saved. The building of applets makes use of autotools: autogen.sh, configure.ac and Makefile.am, which are created in addition to the actual applet source code.

The directory structure of the package is:

/hello_world_applet
/hello_world_applet/debian
/hello_world_applet/data
/hello_world_applet/src

First, the autogen.sh script (this script does not contain any applet-specific details):

#!/bin/sh
set -x
libtoolize --automake
aclocal-1.7 || aclocal
autoconf
autoheader
automake-1.7 --add-missing --foreign || automake --add-missing --foreign

The configure.ac file is as follows:

AC_PREREQ(2.59)
AC_INIT(maemo-hello-world-applet, 0.1, xxxx@maemo.org)

AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h)

dnl ##################
dnl This script generates host names
dnl ##################
AC_CANONICAL_HOST

dnl ##################
dnl Check for installed programs that is needed
dnl ##################
AC_PROG_CC
AM_PROG_CC_STDC
AC_PROG_INSTALL
AC_PROG_RANLIB
AC_PROG_INTLTOOL([0.21])
AC_PROG_LIBTOOL

AM_PATH_GLIB_2_0

AC_CHECK_PROG(HAVE_PKG_CONFIG, pkg-config, yes, no)
if test "x$HAVE_PKG_CONFIG" = "xno"; then
AC_MSG_ERROR([You need to install pkg-config tool])
fi

dnl ##################
dnl Compiler flags, note that the -ansi flag is not used because
dnl in that case the rint function is not available in math.h
dnl ##################

CFLAGS="$CFLAGS -g -Wall -Werror -ansi -Wmissing-prototypes -Wmissing-declarations"

dnl ##################
dnl Check needed headers, like C standard headers, GLib, GStreamer etc.
dnl ##################
AC_HEADER_STDC

GLIB_REQUIRED=2.6.0
GTK_REQUIRED=2.4.0
LIBOSSO_REQUIRED=0.8.3

PKG_CHECK_MODULES(HELLO, [
glib-2.0 >= $GLIB_REQUIRED,
gtk+-2.0 >= $GTK_REQUIRED,
libhildondesktop,
])

AC_SUBST(HELLO_LIBS)
AC_SUBST(HELLO_CFLAGS)

dnl ##################
dnl directories
dnl ##################

localedir=`pkg-config osso-af-settings --variable=localedir`
AC_SUBST(localedir)

pluginlibdir=`pkg-config osso-af-settings --variable=hildondesktoplibdir`
AC_SUBST(pluginlibdir)

AC_CONFIG_FILES([Makefile
src/Makefile
data/Makefile
])

AC_OUTPUT

The package config file is used to provide information about the installation directory of the compiled plug-in by querying the value of pluginlibdir variable. All version numbers for various components above should be interpreted as illustrative only.

The master Makefile.am is:

SUBDIRS = src data

EXTRA_DIST= \
autogen.sh \
intltool-extract.in \
intltool-merge.in \
intltool-update.in \
debian/rules \
debian/control \
debian/copyright \
debian/changelog \
debian/maemo-hello-world-applet.install 

deb_dir = $(top_builddir)/debian-build

INCLUDES = $(DEPS_CFLAGS)

deb:    dist
-mkdir $(deb_dir)
cd $(deb_dir)    &&   tar xzf ../$(top_builddir)/$(PACKAGE)-$(VERSION).tar.gz
cd $(deb_dir)/$(PACKAGE)-$(VERSION)   &&   dpkg-buildpackage -rfakeroot
-rm -rf $(deb_dir)/$(PACKAGE)-$(VERSION)

Makefile.am of the src subdirectory:

pluginlib_LTLIBRARIES = libhello_applet.la

common_CFLAGS = \
$(HELLO_CFLAGS) \
-DPREFIX=\"$(prefix)\" \
-DLOCALEDIR=\"$(localedir)\"

common_LDADD = \
$(HELLO_LIBS) 

libhello_applet_la_LDFLAGS= -module -avoid-version

libhello_applet_la_CFLAGS = $(common_CFLAGS)

libhello_applet_la_LIBADD = $(common_LDADD)

libhello_applet_la_SOURCES = \
hello-world-home.h \
hello-world-home.c \
libhelloworld.h \
libhelloworld.c

Makefile.am of data directory:

homeapplet_desktopdir=`pkg-config osso-af-settings --variable=homedesktopentrydir`
homeapplet_desktop_DATA=hello-world-applet.desktop

EXTRA_DIST=$(homeapplet_desktop_DATA)

The debian/control is as follows:

Source: maemo-hello-world-applet
Section: misc
Priority: optional
Maintainer: Mr Maemo <xxxx@maemo.org>
Build-Depends: libgtk2.0-dev (>=2.4.0-1), pkg-config, libhildondesktop-dev
Standards-Version: 3.6.1

Package: maemo-hello-world-applet
Section: user/internet
Architecture: any
Depends: ${shlibs:Depends},${launcher:Depends}
Description: Maemo Hello World home panel applet 
Home panel applet for showing Hello World.   

The debian/changelog is:

maemo-hello-world-applet (0.1) experimental; urgency=low

* Created package

-- Mr Maemo <xxxx@maemo.org>  Tue, 30 May 2006 10:04:45 +0200

The debian/rules are:

#!/usr/bin/make -f

# export DH_VERBOSE=1

# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)

CFLAGS = -Wall -g
PACKAGENAME = maemo-hello-world-applet

ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
else
CFLAGS += -O2
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif

config.status: 
dh_testdir
# Add here commands to configure the package.
CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info

build: build-stamp

build-stamp: config.status
dh_testdir

# Add here commands to compile the package.
$(MAKE)

touch build-stamp

clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp

# Add here commands to clean up after the build process.
-$(MAKE) clean

dh_clean 

install: build
dh_testdir
dh_testroot
dh_clean -k 
dh_installdirs

# Add here commands to install the package
$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp

# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.

# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
#   dh_installchangelogs 
dh_installdocs
#   dh_installexamples
dh_install -v --sourcedir=debian/build
#   dh_installmenu
#   dh_installdebconf   
#   dh_installlogrotate
#   dh_installemacsen
#   dh_installpam
#   dh_installmime
#   dh_installinit
#   dh_installcron
#   dh_installinfo
#   dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
#   dh_perl
#   dh_python
dh_makeshlibs
dh_installdeb
dh_shlibdeps -V
dh_gencontrol
dh_md5sums
dh_builddeb

binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

The debian/maemo-hello-world-applet.install is:

usr/lib/hildon-desktop/*.so
usr/share/applications/hildon-home/hello-word-applet.desktop

The data/hello-word-applet.desktop is:

[Desktop Entry]
Name=Hello, world
Comment=Example hello
Type=default
X-Path=libhello_applet.so

Code examples

The example source package contains C source code examples demonstrating the use of the Hildon Desktop plug-ins.



Improve this page