
Приветствую всех!
Уже достаточно давно появилась разработка небезызвестной компании Canonical — Unity. Вызвала она крайне неоднозначные эмоции у всех пользователей. Но разработчики ПО нашли ее интересной и стараются интегрировать свои приложения в Unity, а Unity в свои приложения. Не будем же отставать и мы.
Я хотел бы поговорить с вами об одной из интереснейших возможностей Unity — Unity Launcher. Эта панель, которую мы можем наблюдать в левой части экрана. Но панель это не простая, мы можем интегрировать в нее приложения, а именно можем выводить следующую информацию: шкалу, отображающую какой-либо процесс, количество чего-либо и можем привлекать внимание пользователей.
Я постараюсь подробно описать API и показать примеры на C/C++ и Python.
Приступим к делу.
Для начала создаем нашу экспериментальную площадку. Для этого сначала создаем файл UnityTest.cpp, в котором будет наш исходный код.
Теперь установим необходимый пакет — libunity-dev (sudo apt-get install libunity-dev).
Можно приступать к разработке.
За иконку в Unity Launcher отвечает тип данных UnityLauncherEntry. Увы, насколько мне известно, нету метода, с помощь которого можно было бы получить текущую иконку в Launcher. Иконка получается по названию файла запуска. Для меня это показалось несколько необычным, непривычным, но позже я понял, что ничего сверхъестественного в этом нет. Основной метод для получения иконки:
1 |
UnityLauncherEntry* unity_launcher_entry_get_for_desktop_id (const gchar* desktop_id) |
Где desktop_id — название файла запуска.
Примечание:
Опытным путем было установлено, что если иконки текущего приложения нету, не существует, то при запуске приложения она будет временно создана с именем: «Имя_приложения.desktop» (если ошибаюсь, то прошу поправить). Я советую самому создавать данную кнопку запуска, причем давать имя файлу по правилу, описанному ранее («Имя_приложения.desktop»).
Следующие методы нужны для работы с шкалой, которая будет отображена поверх иконки в Launcher:
1 2 3 4 |
void unity_launcher_entry_set_progress (UnityLauncherEntry* self, gdouble value) void unity_launcher_entry_set_progress_visible (UnityLauncherEntry* self, gboolean value) gdouble unity_launcher_entry_get_progress (UnityLauncherEntry* self) gboolean unity_launcher_entry_get_progress_visible (UnityLauncherEntry* self) |
Где self — ранее полученная иконка.
В первом методе value может принимать значение от 0 до 1, которое показывает количество процентов на шкале.
Во втором методе value может принимать значения true и false, которые показывают, отображена ли сейчас шкала.
Третий и четвертый методы действуют обратно первому и второму, то есть получают значения.
Следующие методы нужны для работы с количеством чего-либо на нашей иконке:
1 2 3 4 |
void unity_launcher_entry_set_count (UnityLauncherEntry* self, gint64 value); gint64 unity_launcher_entry_get_count (UnityLauncherEntry* self); gboolean unity_launcher_entry_get_count_visible (UnityLauncherEntry* self); void unity_launcher_entry_set_count_visible (UnityLauncherEntry* self, gboolean value); |
Где self — ранее полученная иконка.
В первом методе value может принимать любое численное значение, которое будет отображено поверх иконки.
Второй метод действует обратно первому.
Третий и четвертый методы работают сходно аналогичным методам для работы со шкалой.
Следующие два метода служат для привлечения внимания пользователя:
1 2 |
void unity_launcher_entry_set_urgent (UnityLauncherEntry* self, gboolean value); gboolean unity_launcher_entry_get_urgent (UnityLauncherEntry* self); |
Где self — ранее полученная иконка.
value — статус приложения. True — активный режим для назойливого привлечения внимания пользователя, False — обычный режим.
Два последних метода служат для подключения своего меню к иконке:
1 2 |
void unity_launcher_entry_set_quicklist (UnityLauncherEntry* self, DbusmenuMenuitem* value) DbusmenuMenuitem* unity_launcher_entry_get_quicklist (UnityLauncherEntry* self) |
А теперь пример с подробными комментариями, который нужно скопировать в файл UnityTest.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
//Подключаем заголовок unity #include <unity.h> //Подключаем заголовок dbusmenu. Нужно для создания своего меню. #include <libdbusmenu-glib/dbusmenu-glib.h> //Если не нужно GTK+, то можно использовать простой glib //#include <glib.h> //Подключаем GTK+ #include <gtk/gtk.h> //Наша иконка UnityLauncherEntry* launcher; //Данный метод будет вызываться при клике на одну единственную кнопку в нашем окне int onclick(GtkWidget* widget, gpointer data) { //Меняем статус приложения на противоположный unity_launcher_entry_set_urgent(launcher, !unity_launcher_entry_get_urgent(launcher)); //unity_launcher_entry_set_urgent(UNITY_LAUNCHER_ENTRY(data), !unity_launcher_entry_get_urgent(UNITY_LAUNCHER_ENTRY(data))); } //Данный метод будет вызываться при фокусе окна int onfocus(GtkWidget* widget, gpointer data) { //При фокусе окна делаем статус приложения обычным unity_launcher_entry_set_urgent(launcher, false); //unity_launcher_entry_set_urgent(UNITY_LAUNCHER_ENTRY(data), false); } int main(int argc, char *argv[]) { //Инициализируем GTK+ gtk_init(&argc, &argv); //g_type_init(); //Создаем наше окно GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //Ставим заголовок gtk_window_set_title(GTK_WINDOW(window), "Unity Test"); //Колбек на завершение приложения g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); //Ищем нашу иконку launcher = unity_launcher_entry_get_for_desktop_id("UnityTest.desktop"); //Рисуем шкалу в 50 процентов unity_launcher_entry_set_progress_visible(launcher, true); unity_launcher_entry_set_progress(launcher, 0.5); //Ставим количество чего-нибудь в 50 unity_launcher_entry_set_count_visible(launcher, true); unity_launcher_entry_set_count(launcher, 50); //Создаем главное меню. Оно не будет отображено, нужно лишь как связывающее звено между другими пунктами меню DbusmenuMenuitem* menu = dbusmenu_menuitem_new(); //Данные пункты будут отображены в меню DbusmenuMenuitem* menu1 = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(menu1, "label", "test1"); DbusmenuMenuitem* menu2 = dbusmenu_menuitem_new(); dbusmenu_menuitem_property_set(menu2, "label", "test2"); //Подключаем их к главному меню dbusmenu_menuitem_child_append(menu, menu1); dbusmenu_menuitem_child_append(menu, menu2); //При клике на пункты меню мы будем менять статус приложения g_signal_connect(menu1, "item_activated", G_CALLBACK(onclick), launcher); g_signal_connect(menu2, "item_activated", G_CALLBACK(onclick), launcher); //Приклеиваем наше меню к меню иконки unity_launcher_entry_set_quicklist(launcher, menu); //Создать кнопку, при нажатии на которую будем менять статус нашего приложения GtkWidget* button = gtk_button_new_with_label("Привлечь внимание!"); gtk_container_add(GTK_CONTAINER(window), button); g_signal_connect(button, "clicked", G_CALLBACK(onclick), launcher); //Ставим колбек на фокус окна g_signal_connect(window, "focus-in-event", G_CALLBACK(onfocus), NULL); //Показываем наше окно gtk_widget_show_all(window); //Запускаем главный цикл gtk_main(); /*GMainLoop* loop = g_main_loop_new(NULL, false); g_main_loop_run(loop);*/ } |
Собрать можно следующей командой:
g++ pkg-config unity gtk+-2.0 dbusmenu-glib-0.4 --cflags --libs
UnityTest.cpp -o UnityTest
Также имеется возможность использовать интеграцию с Unity Launcher в Python-приложениях. Вот небольшой пример, который добавляет несколько пунктов меню в иконку Chromium:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from gi.repository import Unity, GObject, Dbusmenu launcher = Unity.LauncherEntry.get_for_desktop_id("chromium-browser.desktop") launcher.set_property("count_visible", True) launcher.set_property("count", 50) launcher.set_property("progress_visible", True) launcher.set_property("progress", 0.5) menu = Dbusmenu.Menuitem.new() menu1 = Dbusmenu.Menuitem.new() menu1.property_set("label", "Test1") menu2 = Dbusmenu.Menuitem.new() menu2.property_set("label", "Test2") menu.child_append(menu1) menu.child_append(menu2) launcher.set_property("quicklist", menu) GObject.MainLoop().run() |
Пробуем, адаптируем, развиваем!
Источник: habrahabr.ru.