当前位置: 首页>>技术教程>>正文


如何为Unity开发系统指标?

, , , , ,

问题描述

这不是How to create Unity indicators?的副本。我正在寻找系统指标而非应用指标。

Backgound:

从这两个问题:

我了解到有两种类型的指标:

  • 系统:声音,键盘,应用程序……(试试:ps ax | grep indicator)

  • 应用:nm-applet,sysmonitor,……以及什么应用指标可用?中列出的几乎所有产品

所有应用指标均由indicator-application(系统一)处理/显示。系统指示器由Unity面板直接显示。

这两个问题都与添加/删除登录和删除指标有关。锁屏。第一个是直接设置(处理系统指标时)。第二个是艰难的设置(当处理app指标时),需要修改锁定屏幕的面板服务(统一包)的来源以及用于登录屏幕的unity-greeter的来源。

作为sysmonitor的情况,对我来说是解决方法。最好的解决方案是实现系统指示器而不是应用程序指示器。

话题:

  • 系统指标是否有统一的API(最好是:Python然后是C /C++)?请参考官方文件。

  • 大多数系统指标都是使用Vala编程语言编写的。任何人都可以使用Python或C为系统指示器编写小型演示吗?

更新:

我找到了一些可能推动的链接:

  • Application Indicators项目页面中,他们列出了用于应用程序指标的AppIndicator-0.3 API(C& Python)的链接。他们还列出了Indicate-0.7 API(C& Python)。这是什么?好吧,它是桌面应用程序之间的DBus消息传递通道。

  • 另一方面,在System Indicators项目页面中,他们提到:

    使用libindicate的系统指示器API消息传递菜单。使用libunity的声音菜单。使用Evolution-Data-Server的日期/时间指示器

    他们似乎列出了数据API而非指标开发API,就像Evolution-Data-Server一样。但不确定libindicate& libunity。有没有人使用这两个库?

    尝试使用apt-cache rdepends libunity9 libindicator7 libindicator3-7查看哪个指标正在中继这些库。

Update2:这可以让感兴趣的用户保持更新。

从我收集到现在,这是可能的解决方案的顺序:

  1. libindicator3-7(高,许多指标依赖于它)我在源代码中发现了一些测试示例,我尝试过的一些虚拟指示器可以安装在/usr/lib/indicators3/7/中,它们是共享库.so。我可以将它们显示在Login&常规会话但不在锁定屏幕中。但是有一些测试指标服务,看起来像Unity系统服务。我还没有尝试过。

  2. libindicator7

    来自libdeicator3-7的相同来源,来自rdepends:

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

    它似乎被用来制作面板指示器的容器。

  3. libunity9(low)暂无研究

最佳解决办法

系统指标服务

嗯,这比我预想的要简单得多。它没有特定的API。因为它只是一个GSimpleActionGroup&通过DBus导出相应的GMenu,然后使用/usr/share/unity/indicators/中的相同名称的声明文件告知Unity它们的存在。不需要任何其他库。

这是一个非常小的C语言示例:

  1. libindicatorapt-get source libindicator
    cp libindicator-*/tests/indicator-test-service.c .
    cp libindicator-*/tests/com.canonical.indicator.test* .
    获取tests/indicator-test-service.c的副本

    • indicator-test-service.c没有变化

      #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修改为添加锁&迎宾模式

      [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从文件名中删除.in后缀并更改可执行文件路径

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

    gcc -o indicator-test-service indicator-test-service.c `pkg-config --cflags --libs gtk+-3.0`
    
  3. 手动安装

    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. Greeter的配置,覆盖默认指标列表

    • 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']
      
    • 安装

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

    sudo service lightdm restart
    

说明

  • 如果您希望用户能够随时关闭应用程序,那么DBus服务很麻烦。最好使用自动启动,就像默认指标一样。

  • 我在这里上传了就绪文件:https://github.com/sneetsher/mysystemindicator_minimum和修改后的副本:https://github.com/sneetsher/mysystemindicator我在不同的模式下尝试了不同的菜单。它可以快速安装和测试。

  • 这似乎太简单了,可以轻松移植到支持GIO Gnome lib(包括DBus)的任何其他语言。因为我正在寻找python,我可能会在以后添加它。

参考文献:


系统指标插件

这不是上面的完全独立指标,它只是一个共享lib插件,类似于libappmenu.so& libprintersmenu.so(应用程序菜单和打印机指示灯)。它只能在常规用户会话中显示。 greeter(不在锁定屏幕上)。

我无法在我当前的机器上工作,但我之前做过。这里的步骤,可能是我遗漏了一些东西。

  1. 使用libindicator test/libdummy-indicator-*.c上面的相同来源是示例(简单和可见的显示在面板上)

  2. ./autogen.sh
    make
    
  3. 安装

    sudo cp tests/.libs/libdummy-indicator-visible.so /usr/lib/indicators3/7/libdummy.so
    
  4. 配置为在欢迎屏幕中显示

    • 90_unity-greeter.gschema.override使用相同的名称,不带lib前缀和.so扩展名。

      [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']
      
    • 安装

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

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/1972.html,未经允许,请勿转载。