Приветствую всех!
Уже достаточно давно появилась разработка небезызвестной компании 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
//Подключаем заголовок dbusmenu. Нужно для создания своего меню.
#include
//Если не нужно GTK+, то можно использовать простой glib
//#include
//Подключаем GTK+
#include
//Наша иконка
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
(
&
amp
;
argc
,
&
amp
;
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.