Saturday, May 26, 2018

python - How to develop a System Indicator for Unity?



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







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 


      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:











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/



No comments:

Post a Comment

11.10 - Can&#39;t boot from USB after installing Ubuntu

I bought a Samsung series 5 notebook and a very strange thing happened: I installed Ubuntu 11.10 from a usb pen drive but when I restarted (...