Как написать Applet для панели

Блог Всячепуза
 
http://kde-apps.org/content/show.php?content=18046
https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationIndicators
http://wandathefish.com/blog
https://wiki.ubuntu.com/CustomStatusMenuDesignGuidelines

Статья-туториал:
2004, https://projects.gnome.org/ORBit2/appletstutorial.html
Используется другой макрос, и это позволяет работать с DBus вместо Bonobo, вот дока по этому поводу:
2012-12-01, http://wiki.mate-desktop.org/matecorba_to_dbus
In addition to the mate-panel-applet file we use a D-Bus service file so that applets can be started by the session bus.
It's a normal D-Bus file org.mate.panel.applet.MateWnckletFactory.service.in
[D-BUS Service]
Name=org.mate.panel.applet.MateWnckletFactory
Exec=@LOCATION@

Демо-исходники, использующие новый макрос:
2013-03-13, https://github.com/mate-desktop/mate-university
В этом примере инклюдятся заголовочные файлы:
#include <mate-panel-applet.h>
#include <mate-panel-applet-gsettings.h>
И через макрос вызывается функция
static gboolean university_factory (MatePanelApplet* applet, const char* iid, gpointer data)
Надо расковырять, как работает макрос MATE_PANEL_APPLET_OUT_PROCESS_FACTORY.
Он реализовывает main, принимает параметры командной строки, которые передаёт в gtk,
и заворачивает из в Gtk-объекты.
внутри вызывается функция mate_panel_applet_factory_main
оттуда
mate_panel_applet_factory_new и mate_panel_applet_factory_register_service
создаётся объект-структура MatePanelAppletFactory

struct _MatePanelAppletFactory {
	GObject    base;

	gchar     *factory_id;
	guint      n_applets;
	GType      applet_type;
	GClosure  *closure;
};
указатель на функцию, обрабатывающую вызов, передаётся внутри closure (вместе с указателем на данные для функции)
кладётся в локальный-на-стеке указатель factory
этот указатель на объект регистрируется в dbus при помощи функции g_bus_own_name
Ещё раз, что происходит:
1) апплет запускается как процесс (потому что это описано в метафайле для панели)
2) апплет создаёт сервис для dbus и регистрирует этот сервис
3) панель вызывает сервис через dbus, передавая ему параметры
Что тут неясно?
Как формируется параметр applet (при вызыве через dbus), то есть как описать его (независимо от C-кода, например на другом языке)?
Where "MatePanelApplet* applet" parameter of DBus call is described? I want to implement DBus service on language which is not related to C, so I wish to see the description of DBus interface for applets.
Зачем нужно отдельное описание сервиса для dbus, если аплет регистрирует сервис при запуске?
Why one need to register his custom mate-panel-applet service in dbus with configuration file, if applet's code registers the service at startup?


В чём проблема с пониманием? в исходном туториале отсутствуют ссылки на всё. Что такое Bonobo, как обычно пишут Gtk+ приложения и т.д.,

System Tray Protocol Specification

http://standards.freedesktop.org/systemtray-spec/latest/
Чем mate-panel-applet-ы лучше чем иконки в системном трее?
Почему вообще существует два механизма?
System trays are not specific to Gnome.
As a general rule, applications provide an icon by following the .
с какой версии mate переходит на DBus ?
All mate-panel applets need to be ported to libmatepanelapplet-4.0 and gsettings.

mate-applets

Gnome Panel

Technically, applets are Bonobo controls embedded in the Gnome panel.
each applet requires a .server file, which contains a description of the Bonobo capabilities.

<oaf_info>
<oaf_server iid="OAFIID:ExampleApplet_Factory" type="exe"
            location="/usr/lib/gnome-panel/myexample">

        <oaf_attribute name="repo_ids" type="stringv">
                <item value="IDL:Bonobo/GenericFactory:1.0"/>
                <item value="IDL:Bonobo/Unknown:1.0"/>
        </oaf_attribute>
        <oaf_attribute name="name" type="string" value="Example Applet Factory"/> <!-- название аплета -->
        <oaf_attribute name="description" type="string" value="Factory to create the example applet"/> <!-- описание аплета -->
</oaf_server>

<oaf_server iid="OAFIID:ExampleApplet" type="factory"
            location="OAFIID:ExampleApplet_Factory">

        <oaf_attribute name="repo_ids" type="stringv">
                <item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/>
                <item value="IDL:Bonobo/Control:1.0"/>
                <item value="IDL:Bonobo/Unknown:1.0"/>
        </oaf_attribute>
        <oaf_attribute name="name" type="string" value="Example Applet"/>
        <oaf_attribute name="description" type="string" value="An example applet"/>
        <oaf_attribute name="panel:category" type="string" value="Amusements"/>
        <oaf_attribute name="panel:icon" type="string" value="myicon.png"/>
</oaf_server>
</oaf_info>
Bonobo
/usr/lib/gnome-panel/myexample - путь до выполняемого файла
Example Applet Factory.server file, and is usually placed in /usr/lib/bonobo/servers/
# ls -1 /usr/lib/bonobo/servers/
Bonobo_CosNaming_NamingContext.server
Bonobo_Moniker_std.server
GNOME_Moniker_std.server

How does Gnome find the link between our C code and the .server file?
а разве не наоборот - только что же искали бинарник по пути, записанному в .server-file
зачем потребовалось искать .server-файл по бинарнику?

(они наверное хотят сказать, что адрес функции myexample_applet_fill запихивается в этот макрос)

That's resolved by the call to PANEL_APPLET_BONOBO_FACTORY.


#include <string.h>

#include <panel-applet.h>
#include <gtk/gtklabel.h>

static gboolean
myexample_applet_fill (PanelApplet *applet,
   const gchar *iid,
   gpointer data)
{
	GtkWidget *label;

	if (strcmp (iid, "OAFIID:ExampleApplet") != 0)
		return FALSE;

	label = gtk_label_new ("Hello World");
	gtk_container_add (GTK_CONTAINER (applet), label);

	gtk_widget_show_all (GTK_WIDGET (applet));

	return TRUE;
}

PANEL_APPLET_BONOBO_FACTORY ("OAFIID:ExampleApplet_Factory",
                             PANEL_TYPE_APPLET,
                             "The Hello World Applet",
                             "0",
                             myexample_applet_fill,
                             NULL);

Icon

Our applet will be represented by the icon myicon.png, which needs to be placed in /usr/share/pixmaps/

libpanel-applet library

PKG_CONFIG_PATH environment variable must contain the path to libpanelapplet-2.0.pc

bash$ PKG_CONFIG_PATH=/usr/lib/pkgconfig
bash$ export $PKG_CONFIG_PATH
bash$ gcc $(pkg-config --cflags --libs libpanelapplet-2.0) -o my_applet my_applet.c
possible error:
Package libpanelapplet-2.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `libpanelapplet-2.0.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libpanelapplet-2.0' found