В этом уроке, мы рассмотрим процесс создания простого аплета, для изучения Applet API. Здесь мы создадим Force Quit applet.
Для тех, кто не знаком с Force Quit: когда окно перестает отвечать и не хочет закрываться, самый эффективный способ его закрыть - убить его процесс. Вы можете использовать команду
ps
, чтобы найти ID процесса и убить его командой kill
. Или же вы можете выполнить команду xkill
и просто нажать на окно, которое вы хотите убить. И это именно то, что делает Force Quit applet. После того, как вы кликните на него, курсор мыши превращается в убийцу окна, которым вы выберете окно которое необходимо закрыть.Создание базовой структуры аплета.
Аплет - это в основном каталог, имя которого будет uuid, содержащий два файла:
metadata.json
- файл, который содержит информацию о приложении, такую как его название, описание и т.д..В файле
applet.js
содержится код аплета.Перейдём в
~/.local/share/cinnamon/applets
(или в /usr/share/cinnamon/applets
, если вы хотите, чтобы аплет был доступен для всех пользоватей) и создадим файлы и папки, необходимые для аплета.Код: Выделить всё
cd
mkdir -p .local/share/cinnamon/applets/force-quit@cinnamon.org
cd .local/share/cinnamon/applets/force-quit@cinnamon.org
touch metadata.json
touch applet.js
Определение метаданных аплета.
Давайте откроем metadata.json и опишем наш аплет. Этот файл определяет идентификатор UUID, название, описание, значок аплета и используется Cinnamon для отображения его пользователям в настройках.
Код: Выделить всё
{
"uuid": "force-quit@cinnamon.org",
"name": "Force Quit",
"description": "Click on the applet to launch xkill and force any window to quit immediately",
"icon": "force-exit"
}
По умолчанию только один экземпляр каждого аплета может быть размещен на панели пользователя. Но если у пользователя несколько панелей, он не может иметь аплет force-quit на каждой панели, что очень плохо. Следовательно, мы должны также добавить max-instance экземпляра. Мы можем задать любое число (например, 3), или сделать его неограниченным, сделав его -1. В этом случае, наш новый metadata.json будет:
Код: Выделить всё
{
"uuid": "force-quit@cinnamon.org",
"name": "Force Quit",
"description": "Click on the applet to launch xkill and force any window to quit immediately",
"icon": "force-exit",
"max-instances": "-1"
}
Пишем аплет
Это код нашего аплета
Код: Выделить всё
const Applet = imports.ui.applet;
const Util = imports.misc.util;
function MyApplet(orientation, panel_height, instance_id) {
this._init(orientation, panel_height, instance_id);
}
MyApplet.prototype = {
__proto__: Applet.IconApplet.prototype,
_init: function(orientation, panel_height, instance_id) {
Applet.IconApplet.prototype._init.call(this, orientation, panel_height, instance_id);
this.set_applet_icon_name("force-exit");
this.set_applet_tooltip(_("Click here to kill a window"));
},
on_applet_clicked: function() {
Util.spawn('xkill');
}
};
function main(metadata, orientation, panel_height, instance_id) {
return new MyApplet(orientation, panel_height, instance_id);
}
Код: Выделить всё
function main(metadata, orientation, panel_height, instance_id) {
return new MyApplet(orientation, panel_height, instance_id);
}
main - единственная функция которую понимает Cinnamon. Чтобы загрузить аплет, Cinnamon вызывает функцию main в код аплета, и ожидает получения объекта аплета, который будет добавлен на панель. Поэтому здесь мы создаем объект MyApplet (чьи данные указаны выше), и возвращаем его.
Вы заметите, что есть много параметров, плавающие вокруг metadata содержат, в основном, информацию в metadata.json плюс еще немного. От этого мало пользы в целом, но иногда может предоставить некоторую нужную информацию.
orientation - где находится панель, в верхней или нижней части. Аплет может вести себя по-разному в зависимости от его позиции, например. чтобы сделать всплывающее меню появляещееся на правой стороне.
panel_height сообщает высоту панели. Таким образом, мы можем масштабировать иконки вверх и вниз в зависимости от того, насколько большая группа.
instance_id говорит, какой это экземпляр аплета, так как там может быть несколько экземпляров аплета. Пока это просто номер, присвоенный аплету и не имеет особого смысла.
Здесь мы передаем информацию в конструктор, и конструктор будет позже передать его в API аплета.
Так что же происходит, когда мы создаем аплет? Сначала посмотрим на первые две строки:
Код: Выделить всё
const Applet = imports.ui.applet;
const Util = imports.misc.util;
/usr/share/cinnamon/js/ui/applet.js
. Аналогично, imports.misc.util доступна в /usr/share/cinnamon/js/misc/util.js
. Затем мы называем эти вещи Applet и Util соответственно, чтобы не набирать кучу кода.Ничего интересного. Далее!
Код: Выделить всё
function MyApplet(orientation, panel_height, instance_id) {
this._init(orientation, panel_height, instance_id);
}
Это стандартная конструкция объекта JavaScript. Когда кто-то делает этот вызов, он вызывает функцию _init объекта. Обратите внимание, что здесь мы назвали наш аплет MyApplet. Вы вольны называть его как угодно (и измененить функцию main соответственно).
Также отметим, что мы передаем все orientation по цепочке, пока она в конечном счете достигнет API для аплетов.
Теперь мы переходим к телу кода:
Код: Выделить всё
MyApplet.prototype = {
__proto__: Applet.IconApplet.prototype,
_init: function(orientation, panel_height, instance_id) {
Applet.IconApplet.prototype._init.call(this, orientation, panel_height, instance_id);
this.set_applet_icon_name("force-exit");
this.set_applet_tooltip(_("Click here to kill a window"));
},
on_applet_clicked: function() {
Util.spawn('xkill');
}
};
Здесь мы видим то, что я называют "API-интерфейс аплета" все время. Несколько основных объектов определяются в applet.js и мы наследуем один из них. Здесь мы объявляем наследование Applet.IconApplet, который отображает значок.
Наследование в JavaScript немного странные. Сначала мы копируем Applet.IconApplet с помощью:
Код: Выделить всё
__proto__: Applet.IconApplet.prototype,
Далее, в нашей функции _init, мы вызываем _init функцию Applet.IconApplet. Здесь мы передаем всю информацию об ориентации и т.д. для функции _init, и эта функция необходима для отображения аплета правильно.
Однако, вопреки распространенному мнению, API аплета не является экстрасенсом. Он понятия не имеет, что ваш аплет хочет делать (помимо отображения иконки). Вы должны сначала сказать ему, что значок, должен быть в строке
Код: Выделить всё
this.set_applet_icon_name("force-exit");
/usr/share/icons/
).Следующая строка:
Код: Выделить всё
this.set_applet_tooltip(_("Click here to kill a window"));
Это весь код нашей функции _init. Теперь мы будем ждать когда пользователь кликнет на аплет. API-интерфейс аплета автоматически слушает эти события, и когда пользователь нажимает на аплет, то API будет вызывать on_applet_clicked вашего аплета. Здесь мы имеем:
Код: Выделить всё
on_applet_clicked: function() {
Util.spawn('xkill');
}
Перевод статьи с Mint Developer Center