Writing Hildon Desktop Plug-ins for Maemo
This document has been reviewed for maemo 4.0.
Introduction
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=tasknavigatordesktopentrydirand 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=homedesktopentrydirand 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=statusbardesktopentrydirwhich 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 falseHere 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=hildondesktoplibdirBy 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