Как разработать системный индикатор для Unity?

38

Это не дубликат Как создать индикаторы Unity? , Я ищу индикатор системы, а не индикатор приложения.

Backgound:

Из этих двух вопросов:

Я узнал, что есть два типа индикаторов:

Все индикаторы приложения обрабатываются / показываются индикатором-приложением (системным). Системные индикаторы отображаются непосредственно на панели Unity.

Оба вопроса касаются добавления / удаления индикаторов с экрана входа и блокировки. Первая была простой настройкой (при работе с системными индикаторами). Второй - жесткая настройка (при работе с индикаторами приложения), которая требует изменения источника службы панели (пакет Unity) для экрана блокировки и источника сообщения Unity-Greeter для экрана входа в систему.

Как в случае sysmonitor, для меня это был обходной путь. Лучшее решение - внедрить системный индикатор вместо прикладного.

Тема:

  • Существует ли унифицированный API для системных индикаторов (предпочтительно: Python, а затем C / C ++)? Пожалуйста, ознакомьтесь с официальной документацией.

  • Большинство системных индикаторов написаны на языке программирования Vala. Может ли кто-нибудь написать небольшую демонстрацию системного индикатора с использованием Python или C?

Обновить:

Я нашел несколько ссылок, которые могут дать толчок:

  • На странице проекта « Индикаторы приложений » были перечислены ссылки на API-интерфейс AppIndicator-0.3 ( C & Python ), используемый для индикаторов приложений.

    Они перечислили также API-интерфейс Indicate-0.7 ( C & Python ). Что это? Ну, это канал обмена сообщениями DBus между настольными приложениями.

  • С другой стороны, на странице проекта « Системные индикаторы » они упоминали:

    API системного индикатора

    • Меню сообщений с использованием libindicate.
    • Звуковое меню с использованием 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/, они являются общими lib .so. Я мог бы отобразить их в разделе «Вход в систему и обычный сеанс», но не на экране блокировки.

    Однако есть некоторые сервисы тестовых индикаторов, которые похожи на системы Unity. Я еще не пробовал их.

  2. libindicator7

    Из того же источника, что и libindicator3-7, из rdepends:

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

    Кажется, он используется для создания контейнера для индикаторов на панелях.

  3. libunity9 (низкий)

    Пока нет исследований

user.dz
источник

Ответы:

12

Служба системного индикатора

Ну, это действительно проще, чем я ожидал. Для этого нет конкретного API. Поскольку это просто GSimpleActionGroup и с соответствующими GMenu , экспортируемыми через DBus, Unity сообщается об их присутствии, используя файл декларации с тем же именем /usr/share/unity/indicators/. Нет необходимости в какой-либо другой библиотеке.

Вот очень маленький пример языка Си :

  1. Получить копию tests/indicator-test-service.cиз libindicatorисточника

    apt-get source libindicator
    cp libindicator-*/tests/indicator-test-service.c .
    cp libindicator-*/tests/com.canonical.indicator.test* .
    
    • индикатор-тест-сервис.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, я могу добавить его позже.

Ссылки:


Плагин системного индикатора

Это не полностью автономный индикатор, как показано выше, это просто плагин share lib, похожий на libappmenu.so& libprintersmenu.so(меню приложения и индикатор принтера). Это может быть показано только в обычном сеансе пользователя и приветствии (не на экране блокировки).

Я не мог заставить это работать в моей текущей машине, но я сделал прежде. Здесь шаги, может быть, я что-то упустил.

  1. Используя тот же источник выше libindicator

    test/libdummy-indicator-*.c примеры (простые и видимые те, что отображаются на панели)

  2. Compile

    ./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/
      
user.dz
источник
2
Интересно, можно ли это сделать в Python ... C выглядит немного страшно.
Сет
@ Я верю, что да, это можно сделать на Python. Как я только что проверил, все необходимые функции ( export_action_group, export_menu_model) и объекты ( SimpleActionGroup, Menu) находятся в gi.repository.Gio. Я постараюсь написать один в ближайшие несколько дней.
user.dz
0

ПРИМЕЧАНИЕ. Пожалуйста, проверьте нижнюю часть этого поста, чтобы узнать окончательное мнение об этом ответе.

Я не знаю, действительно ли я помогаю, но я надеюсь, что эта идея может быть полезной.

Из того, что я искал, разница в показателях системы и приложения отличается. Имея это в виду, я сейчас представлю сомнительную концепцию:

Использование API индикатора приложения в системном индикаторе (в отличие от создания нового унифицированного API для той же цели)

Идея пришла ко мне при просмотре следующих постов:

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

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

Unity API, по-видимому, в первую очередь создан для использования с индикаторами приложений, но как системные индикаторы, так и индикаторы приложений могут использовать аналогичное программирование (язык). Однако вы упомянули ранее, что эти два типа индикаторов обрабатываются двумя разными системами. Поэтому я приступил к прочтению одного из ваших источников:

Как добавить или изменить индикаторы приложения / системы на экране входа в систему?

Основной ответ заключался в переопределении уже существующего пользователя, чтобы получить доступ, который ему необходим. Он также предоставил решение для добавления и удаления всех существующих индикаторов. Это единое решение для управления индикаторами. Можно ли переопределить пользователя по умолчанию (существовавшего ранее) для запуска / введения системного индикатора?

Может ли системный индикатор использовать API индикатора приложений Unity (можно ли использовать и правильно отображать этот интерфейс на панели Unity)? Если ответы на эти вопросы положительные, это могло бы насытить ситуацию, если в результате не возникнут другие проблемы. Я знаю, что это не сразу покажется ответом, поэтому я поясню, что я пытался - я пытаюсь разбить задачу на более мелкие цели. Основная цель заключается в том, чтобы выяснить, можно ли использовать API индикаторов приложений для кодирования системных индикаторов (как существовавший ранее унифицированный API для системных индикаторов).

В ответ на эту часть вашего запроса:

«Есть ли единый API для системных индикаторов»

К сожалению, однако, нет никакого способа использовать API индикатора приложения для системных индикаторов. Таким образом, мое решение недействительно :(

TopHatProductions115
источник
К сожалению, нет, API индикатора приложения не может быть использован для создания индикатора системы. это будет тот же случай, что и для индикатора-системного монитора , он нуждается в модифицированных сборках единства и единства-приветствующего.
user.dz
В этом случае это выглядит так, как будто необходим новый API - только для индикатора системы. В его нынешнем виде системный индикатор имеет несколько отдельных API от Ubuntu. Я думаю, что у нас есть возможность использовать сторонние библиотеки, как указано в конце поста «Вопрос».
TopHatProductions115