39

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

2 Answers 2

13

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/
      
7
  • 2
    I wonder if this could be done in Python.. the C looks a little scary.
    – Seth
    May 24, 2016 at 3:58
  • @Seth I believe yes it can be made in Python. As I have just checked all needed functions (export_action_group,export_menu_model) and objects (SimpleActionGroup, Menu) are in gi.repository.Gio. I will try writing one in the coming few days.
    – user.dz
    May 25, 2016 at 5:32
  • 1
    I've just uploaded a raw "working" Python example ported from the @user.dz C example: github.com/sneetsher/mysystemindicator I will update it as I go along but any contribution is welcome. Thanks for the useful information!
    – Marto
    Nov 5, 2020 at 23:15
  • Welcome to Ask Ubuntu. Thank you Marto. I was looking for Python system indicator for long, may be still some users uses Unity. This question is about C. When you get a working copy let me know if you could comment under the question. I will reopen the other Python question here askubuntu.com/q/786831/26246 . If you could link repo I will be happy to test it.
    – user.dz
    Nov 5, 2020 at 23:28
  • @Marto I have tested it, It does show, great well, thank you. I asked to reopen my other python question. So you could submit you answer there.
    – user.dz
    Nov 10, 2020 at 15:10
0

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 :(

2
  • Unfortunately no, the application indicator API could not be used to create system indicator. it will be same case as for indicator-sysmonitor, It needs modified builds of unity & unity-greeter.
    – user.dz
    Mar 26, 2016 at 20:23
  • In that case, it looks as though a new API is needed - one that's just for the System Indicator. As it stands, the System Indicator has multiple, separate APIs from Ubuntu. I think we're left with the option of using third-party libraries, as stated at the end of the Question post.
    – user408654
    Mar 26, 2016 at 21:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .