Ubuntu: How to develop a System Indicator for Unity?



Question:

This is not a duplicate of How to create Unity indicators?. I'm looking for system indicator not application indicator.

Backgound:

From these two questions:

I learned that there are two types of indicators:

All application indicators are handled/showed by indicator-application (a system one). System indicators are showed directly by Unity panel.

Both questions are about adding/removing indicators from login & lock screen. The first was a straight forward setup (when dealing with system indicators). The second was a tough setup (when dealing with app indicators), which needs modifying the source of panel service (unity package) for lock screen and the source of unity-greeter for login screen.

As the case of sysmonitor, to me that was workaround. The best solution is to implement a system indicator instead of an application one.

Topic:

  • Is there a unified API for system indicators (Preferably: Python then C/C++)? Please, reference to the official documentations.

  • Most system indicators are written using Vala programming language. Could any one write small demo for a system indicator using Python or C?

Update:

I found few links that may give a push:

  • In Application Indicators project page, They listed links to AppIndicator-0.3 API (C & Python) used for application indicators.

    They listed also Indicate-0.7 API (C & Python). What is this? Well, it is a DBus messaging channel between Desktop Applications.

  • On other hand, in System Indicators project page, they mentioned:

    System Indicator APIs

    • Messaging Menu using libindicate.
    • Sound Menu using libunity.
    • Date/Time Indicator using Evolution-Data-Server

    They seem listing Data API not Indicator Development API like for Evolution-Data-Server. But not sure about libindicate & libunity. Did any one work with these two libraries?

    Try apt-cache rdepends libunity9 libindicator7 libindicator3-7 to see which indicator is relaying these libraries.

Update2: This to keep interested users updated.

From what I have collected till now, here is the order of possible solutions:

  1. libindicator3-7 (high, Many indicators depend on it)

    I found some test examples in the source, some dummy indicators that I have tried, could be installed in /usr/lib/indicators3/7/, they are shared lib .so. I could get them displayed in Login & Regular Session but Not in Lock Screen.

    However there are some test indicator services, which seems like Unity system ones. I haven't tried them yet.

  2. libindicator7

    From same source as libindicator3-7, from rdepends:

    mate-indicator-applet  lxpanel-indicator-applet-plugin  

    It seems to be used to make container for indicators in panels.

  3. libunity9 (low)

    No research yet


Solution:1

System Indicator Service

Well, it is really simpler then I expected. There is no specific API for it. Because it is just a GSimpleActionGroup & with corresponding GMenu's exported through DBus then Unity is told about their presence using declaration file with same name put in /usr/share/unity/indicators/. No need for any other library.

Here a very small C language example:

  1. Get a copy of tests/indicator-test-service.c from libindicator source

    apt-get source libindicator  cp libindicator-*/tests/indicator-test-service.c .  cp libindicator-*/tests/com.canonical.indicator.test* .  
    • indicator-test-service.c no changes

      #include <gio/gio.h>    typedef struct  {    GSimpleActionGroup *actions;    GMenu *menu;      guint actions_export_id;    guint menu_export_id;  } IndicatorTestService;    static void  bus_acquired (GDBusConnection *connection,                const gchar     *name,                gpointer         user_data)  {    IndicatorTestService *indicator = user_data;    GError *error = NULL;      indicator->actions_export_id = g_dbus_connection_export_action_group (connection,                                                                          "/com/canonical/indicator/test",                                                                          G_ACTION_GROUP (indicator->actions),                                                                          &error);    if (indicator->actions_export_id == 0)      {        g_warning ("cannot export action group: %s", error->message);        g_error_free (error);        return;      }      indicator->menu_export_id = g_dbus_connection_export_menu_model (connection,                                                                     "/com/canonical/indicator/test/desktop",                                                                     G_MENU_MODEL (indicator->menu),                                                                     &error);    if (indicator->menu_export_id == 0)      {        g_warning ("cannot export menu: %s", error->message);        g_error_free (error);        return;      }  }    static void  name_lost (GDBusConnection *connection,             const gchar     *name,             gpointer         user_data)  {    IndicatorTestService *indicator = user_data;      if (indicator->actions_export_id)      g_dbus_connection_unexport_action_group (connection, indicator->actions_export_id);      if (indicator->menu_export_id)      g_dbus_connection_unexport_menu_model (connection, indicator->menu_export_id);  }    static void  activate_show (GSimpleAction *action,                 GVariant      *parameter,                 gpointer       user_data)  {    g_message ("showing");  }    int  main (int argc, char **argv)  {    IndicatorTestService indicator = { 0 };    GMenuItem *item;    GMenu *submenu;    GActionEntry entries[] = {      { "_header", NULL, NULL, "{'label': <'Test'>,"                               " 'icon': <'indicator-test'>,"                               " 'accessible-desc': <'Test indicator'> }", NULL },      { "show", activate_show, NULL, NULL, NULL }    };    GMainLoop *loop;      indicator.actions = g_simple_action_group_new ();    g_simple_action_group_add_entries (indicator.actions, entries, G_N_ELEMENTS (entries), NULL);      submenu = g_menu_new ();    g_menu_append (submenu, "Show", "indicator.show");    item = g_menu_item_new (NULL, "indicator._header");    g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.root");    g_menu_item_set_submenu (item, G_MENU_MODEL (submenu));    indicator.menu = g_menu_new ();    g_menu_append_item (indicator.menu, item);      g_bus_own_name (G_BUS_TYPE_SESSION,                    "com.canonical.indicator.test",                    G_BUS_NAME_OWNER_FLAGS_NONE,                    bus_acquired,                    NULL,                    name_lost,                    &indicator,                    NULL);      loop = g_main_loop_new (NULL, FALSE);    g_main_loop_run (loop);      g_object_unref (submenu);    g_object_unref (item);    g_object_unref (indicator.actions);    g_object_unref (indicator.menu);    g_object_unref (loop);      return 0;  }  
    • com.canonical.indicator.test modified to add lock & greeter mode

      [Indicator Service]  Name=indicator-test  ObjectPath=/com/canonical/indicator/test    [desktop]  ObjectPath=/com/canonical/indicator/test/desktop    [desktop_greeter]  ObjectPath=/com/canonical/indicator/test/desktop    [desktop_lockscreen]  ObjectPath=/com/canonical/indicator/test/desktop  
    • com.canonical.indicator.test.service remove .in postfix from filename and change the executable path

      [D-BUS Service]  Name=com.canonical.indicator.test  Exec=/usr/lib/x86_64-linux-gnu/indicator-test/indicator-test-service  
  2. Compile it

    gcc -o indicator-test-service indicator-test-service.c `pkg-config --cflags --libs gtk+-3.0`  
  3. Manual Installation

    sudo su  mkdir /usr/lib/x86_64-linux-gnu/indicator-test/  cp indicator-test-service /usr/lib/x86_64-linux-gnu/indicator-test/  cp com.canonical.indicator.test /usr/share/unity/indicators/  cp com.canonical.indicator.test.service /usr/share/dbus-1/services/  
  4. Configuration for Greeter, override the default indicators list

    • 90_unity-greeter.gschema.override

      [com.canonical.unity-greeter]  indicators=['ug-accessibility', 'com.canonical.indicator.keyboard', 'com.canonical.indicator.session', 'com.canonical.indicator.datetime', 'com.canonical.indicator.power', 'com.canonical.indicator.sound', 'com.canonical.indicator.test', 'application']  
    • Install

      cp 90_unity-greeter.gschema.override /usr/share/glib-2.0/schemas/  glib-compile-schemas /usr/share/glib-2.0/schemas/  
  5. Test

    sudo service lightdm restart  

Notes

  • DBus service is troublesome, if you want user to be able to close application anytime. It is better to use autostart instead, like default indicators do.

  • I have uploaded ready files here:

    https://github.com/sneetsher/mysystemindicator_minimum

    and a modified copy here:

    https://github.com/sneetsher/mysystemindicator

    Where I have tried different menu for different mode. It could be installed and tested quickly.

  • This seems too simple and can be easily ported to any other language that have support for GIO Gnome lib (including DBus). As I'm looking for python, I may add it later.

References:


System Indicator Plugin

This is not full standalone indicator as the one above, it is just a share lib plugin, similar to libappmenu.so & libprintersmenu.so (application menu & printer indicator). It could be shown only in regular user session & greeter (Not on lock screen).

I couldn't make it work in my current machine, but I did before. Here the steps, may be I'm missing something.

  1. Using same source above of libindicator

    test/libdummy-indicator-*.c are examples (simple & visible the ones show up on the panel)

  2. Compile

    ./autogen.sh  make  
  3. Install

    sudo cp tests/.libs/libdummy-indicator-visible.so /usr/lib/indicators3/7/libdummy.so  
  4. Configure to show in greeter screen

    • 90_unity-greeter.gschema.override use same name without lib prefix and .so extension.

      [com.canonical.unity-greeter]  indicators=['ug-accessibility', 'com.canonical.indicator.keyboard', 'com.canonical.indicator.session', 'com.canonical.indicator.datetime', 'com.canonical.indicator.power', 'com.canonical.indicator.sound', 'application', 'dummy']  
    • Install

      cp 90_unity-greeter.gschema.override /usr/share/glib-2.0/schemas/  glib-compile-schemas /usr/share/glib-2.0/schemas/  


Solution:2

NOTE: Please check the bottom of this post for the final say on this answer.

I don't know if I am really of any assistance, but I hope that this idea may be useful.

From what I have searched, the difference in System and Application Indicators is distinct. With this in mind, I now introduce a questionable concept:

The use of Application Indicator API in a System Indicator (in opposed to creating a new, unified API for the same purpose)

The idea came to me while looking at the following posts:

https://askubuntu.com/a/234204/408654

https://askubuntu.com/a/42213/408654

The Unity API appears to be primarily built for use with Application Indicators, but both System and Application Indicators may use similar programming (C lang). However, you mentioned earlier that these two types of Indicators are handled by two different systems. As such, I then proceeded to read one of your sources:

How do I add or manipulate Application/System Indicators in the login screen?

The primary answer involved overriding an already-existing user to gain the access they required. It also provided a solution for adding and removing all existing Indicators. It's a unified management solution for Indicators. Would it be possible to override a default (pre-existing) user to run/introduce a System Indicator?

Can a System Indicator use Unity Application Indicator API (can the API be used and displayed properly by the Unity panel)? If the answers to these are yes, that would satiate the situation - if it doesn't cause other issues as a result. I know that this won't immediately seem like an answer, so I'll clarify what I've attempted - I am trying to break the task into smaller objectives. The main objective being, finding out whether the Application Indicator API can be used for coding System Indicators (as a pre-existing, unified API for System Indicators).

In response to this part of your query:

"Is there a unified API for system indicators "

Unfortunately, though, there is no way to use Application Indicator APIs for System Indicators. As such, my solution is void :(


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »