Порт панели Niti (Go/gotk4) на нативный Vala/GTK4 — без CGo/GC-прослойки
  • Vala 72.5%
  • Python 19.6%
  • SCSS 5%
  • Meson 2.1%
  • Shell 0.6%
  • Other 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
plafonlinux 23c55e1e40
All checks were successful
Vala pattern lint / lint (push) Successful in 20s
Sanitizers / memcheck (push) Successful in 4m59s
Sanitizers / asan-ubsan (push) Successful in 5m44s
Build check / Build and test NitiVala (push) Successful in 6m14s
RPM / rpm (push) Successful in 4m53s
Power: попап не уезжает за правый край экрана, быстрые переключатели LAVD/ananicy-cpp
Попап шире самой кнопки, а виджет сидит у правого края панели — без
явного halign=END GTK центрировал попап на кнопке и обрезал правый
верхний угол за пределами монитора. Добавлены переключатели LAVD и
ananicy-cpp прямо в попап (видны только если доступен sched_ext) —
те же юниты и то же полиси без пароля, что и в Tuner → Питание.
Массив юнитов для EnableUnitFiles/DisableUnitFiles собирается через
VariantBuilder, а не string[]-литералом в Variant(...) — последнее
валит процесс сегфолтом (тот же баг, что и в Tuner-плагине сегодня).
2026-10-10 20:04:35 +02:00
.forgejo/workflows Убрать type-launch из сборки Niti 2026-10-03 08:27:59 +02:00
api Добавить index.md с картой проекта, поправить тесты на устойчивые якоря 2026-10-09 16:58:50 +02:00
assets Диски: короткие имена папок на панели и в попапе, подробные подсказки 2026-10-10 07:29:29 +02:00
build-aux/altlinux Убрать type-launch из сборки Niti 2026-10-03 08:27:59 +02:00
core Добавить index.md с картой проекта, поправить тесты на устойчивые якоря 2026-10-09 16:58:50 +02:00
data Официальная иконка Niti (symbolic) в уведомлениях, hicolor и группе «Панель Niti»; Vitals: тип накопителя NVMe/SSD/HDD в свёрнутой строке, светлее фон подменю, читаемее подписи 2026-09-28 10:53:40 +02:00
docs Стресс-тест диагностики устанавливается в /usr/libexec/niti-stress-runner; тест 2026-09-27 09:52:28 +02:00
fuzz Добавить index.md с картой проекта, поправить тесты на устойчивые якоря 2026-10-09 16:58:50 +02:00
modules Убраны два use-after-free в Дисках и Power, найденные при разборе роста памяти панели 2026-10-10 08:52:52 +02:00
scripts Power: попап не уезжает за правый край экрана, быстрые переключатели LAVD/ananicy-cpp 2026-10-10 20:04:35 +02:00
services Добавить index.md с картой проекта, поправить тесты на устойчивые якоря 2026-10-09 16:58:50 +02:00
tests Не требовать GI-тайплибы в conftest при отсутствии собранных виджетов 2026-10-10 17:33:51 +02:00
widgets Power: попап не уезжает за правый край экрана, быстрые переключатели LAVD/ananicy-cpp 2026-10-10 20:04:35 +02:00
.gitignore Фикс миграции настроек Дисков, привязки действий Почты к аккаунту письма и пересверки профиля Power 2026-10-10 07:24:27 +02:00
build-native.sh Добавить index.md с картой проекта, поправить тесты на устойчивые якоря 2026-10-09 16:58:50 +02:00
build.sh Добавить index.md с картой проекта, поправить тесты на устойчивые якоря 2026-10-09 16:58:50 +02:00
CHANGELOG.md Агент секретов NetworkManager в панели: пароли Wi‑Fi/802.1X/VPN в связке ключей пользователя, русское окно запроса, тесты 2026-09-19 23:04:38 +02:00
Containerfile Плагины: подпись minisign проверяется внутри процесса (libsodium) по уже проверенному дескриптору; откат действительно возвращает рабочую версию; без записи за границу буфера; установка в отдельном потоке; libsodium в dev-контейнере, xorg-xvfb 2026-09-25 00:20:43 +02:00
CONTRIBUTING.md CI: статическая проверка шаблонов Vala (weak self, знаковый char, JSON-перезапись, FIFO/симлинки) 2026-09-29 15:52:25 +02:00
DANKMATERIALSHELL_PLAN.md core: мультимонитор — независимый бар на каждом подключённом экране 2026-09-08 18:41:42 +02:00
DESIGN.md Единая типографика попапов (vitals/disks/systeminfo) + гайдлайн DESIGN.md 2026-09-06 11:05:43 +02:00
dev-run.sh Добавить index.md с картой проекта, поправить тесты на устойчивые якоря 2026-10-09 16:58:50 +02:00
index.md Убраны два use-after-free в Дисках и Power, найденные при разборе роста памяти панели 2026-10-10 08:52:52 +02:00
pytest.ini test: add container audit gates and fix workspace crash 2026-09-13 17:01:25 +02:00
README.md Убрать type-launch из сборки Niti 2026-10-03 08:27:59 +02:00
SECURITY.md Стресс-тест диагностики устанавливается в /usr/libexec/niti-stress-runner; тест 2026-09-27 09:52:28 +02:00
Vala.md Vala.md: итог дня — реальная утечка найдена и локализована (toggle_fn cycle, подтверждено по generated C), материализация истории QC объяснена, частичный фикс плавности (async save), открытые вопросы на следующую сессию 2026-10-02 14:27:24 +02:00
Vala_Develop.md Vala_Develop: уточнить matugen warning() — диагностика, не расхождение с Go 2026-09-06 01:06:51 +02:00

NitiVala

Wayland-панель для тайлового скроллинг-композитора Niri. Написана на Vala (компилируется в нативный C/GObject-код) с использованием GTK4 и gtk4-layer-shell. Быстрая работа, мгновенный отклик и минимальное потребление ресурсов. Создана специально для ALT Atomic Niri и выступает там в качестве нативного псевдо-шелла по аналогии с gnome-shell.

NitiVala — официальное продолжение проекта Niti (Go-версия больше не разрабатывается). Полный переписанный с нуля порт на Vala с плагинной архитектурой, стандартизированной структурой виджетов и модульным ядром.

Quick Center — светлая тема Quick Center — тёмная тема

Что это

NitiVala — это панель плюс набор окон-компаньонов для Niri: лаунчер приложений, быстрое меню (Quick Center), уведомления, OSD-индикаторы, меню выключения, календарь, сетка приложений. Всё рисуется как нативные Wayland-слои (layer-shell) и управляется через IPC Niri. Сам композитор и сессию Niri не заменяет — работает рядом с ними.

Почему Vala

Переход с Go на Vala — не смена языка ради языка, а переход на технологию, для которой GObject/GTK — родная экосистема, а не набор биндингов поверх C API.

Преимущество Что это даёт
Нулевые накладные расходы биндингов Vala компилируется напрямую в тот же C/GObject код, который использует сам GTK — нет прослойки маршалинга типов, как в Go-биндингах (gotk4)
Плагинная архитектура (libpeas) каждый виджет — независимый .so-модуль, загружаемый динамически. Можно пересобрать и заменить один виджет, не трогая и не перезапуская остальную панель
Единый статический нативный бинарник ядра как и раньше — мгновенный запуск, минимальный RAM/CPU в простое
GObject Introspection из коробки у каждого сервиса есть .vapi/.gir/.typelib — сторонние плагины (в том числе не на Vala — Python, C, JS) видят типы друг друга автоматически, без ручного описания API
Нативный синтаксис для GObject-паттернов свойства и сигналы объявляются как public string foo { get; set; }, без генерируемого boilerplate
Кросс-языковая тестируемость чистая логика сервисов (парсеры, форматтеры, вычисления) покрыта pytest-тестами через ту же интроспекцию — тесты гоняют реальный скомпилированный код, не пересказ логики на другом языке

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

Плагинная система — свой виджет без правки ядра

Каждый виджет панели — самостоятельный плагин libpeas, реализующий один простой контракт:

namespace Niti {
    public abstract class Widget : Peas.ExtensionBase {
        public abstract Gtk.Widget get_root ();
    }
}

Панель ничего не знает о конкретных виджетах заранее — она сканирует каталог плагинов, инстанцирует всё, что реализует Niti.Widget, и расставляет по зонам (left/center/right) согласно config.json. Стандартная структура плагина-виджета:

widgets/<name>/
  meson.build
  data/
    <name>.plugin.in         — манифест libpeas (имя, модуль, описание)
    default_settings.json    — настройки виджета по умолчанию
    icons/                   — опционально: кастомные symbolic-иконки через GResource
  src/
    plugin.vala               — реализация Niti.Widget
    meson.build

Виджету доступны все системные сервисы через тот же механизм интроспекции (Niti.Upower.Service.get_default(), Niti.Network.Service.get_default() и т.д.) — не нужно ничего регистрировать в ядре вручную. Модули-оверлеи (Launcher, QuickCenter, Calendar...) устроены по тому же принципу — прозрачная граница между "ядром" и "обвесом" вокруг него.

Возможности

Панель (Bar)

Панель с виджетами в трёх зонах — левая, центр, правая. Состав по умолчанию:

Зона Виджеты
Левая Рабочие столы (workspaces), Таскбар (tasks)
Центр Часы (clock), Медиа (media)
Правая Горячие клавиши (hotkeys), Обновления (systeminfo), Диски (disks), Системный монитор (vitals, CPU/RAM/temp), Питание (power), Caffeine (caffeine), Раскладка клавиатуры (keyboard), Трей (tray), Быстрое меню (quickbutton)

Дополнительные виджеты, не включённые по умолчанию — подключаются добавлением в config.json: запись экрана (recording, PipeWire), заряд периферии (peripheria, клавиатура/мышь/геймпад), планировщик LAVD (lavd).

Состав зон, порядок и параметры каждого виджета — в ~/.config/niti-vala/config.json.

Профили потребления

В корне ~/.config/niti-vala/panel.json можно выбрать профиль:

{ "profile": "minimal" }

minimal оставляет часы, рабочие столы, таскбар и Launcher; balanced сохраняет обычный состав панели и оверлеев; full включает дополнительные виджеты, включая lavd и recording. Индивидуальная настройка модуля {"enabled": false} или {"enabled": true} имеет приоритет над профилем.

Окна и оверлеи

Модуль Что делает
Launcher запуск приложений (Mod+D): парсинг .desktop, поиск, закреплённые и недавние приложения
AppGrid сетка установленных приложений (Mod+G), кастомный порядок значков
QuickCenter быстрое меню: заряд периферии, ползунки громкости/яркости, WiFi/Bluetooth/DND/Ночной свет/Тёмный режим, медиаплеер, список уведомлений
OSD всплывающие индикаторы громкости и яркости
Notifications встроенный демон уведомлений (org.freedesktop.Notifications), поддержка DND
Calendar календарь-попап (клик по часам), интеграция с Evolution Data Server
Corners скруглённые углы экрана
Hotkeys оверлей со списком горячих клавиш из config.kdl Niri

Тема и внешний вид

Цветовая схема — Material You (Material 3), генерируется matugen из текущих обоев и переключается вместе с системным светлым/тёмным режимом (org.gnome.desktop.interface color-scheme) — панель, Quick Center и все всплывающие окна следуют за темой целиком, включая иконки. Автоматически синхронизируется акцентный цвет GTK-приложений (accent-color).

Стили написаны на SCSS и компилируются в рантайме, поэтому оформление можно менять «на лету» через ~/.config/niti-vala/styles/ и ~/.config/niti-vala/colors.scss, без пересборки панели.

Каноничность GTK4/GNOME

NitiVala старается не изобретать свои решения там, где платформа уже даёт правильный, ожидаемый способ — и следовать духу GNOME HIG даже в мелочах:

  • Кастомные иконки — только через GResource, никаких Gtk.Image.set_from_file() по абсолютному пути. SVG встраивается в бинарник плагина через gnome.compile_resources() и регистрируется в Gtk.IconTheme тем же способом, каким это делает любое нативное GNOME-приложение — icon-name, а не путь к файлу.
  • Symbolic-recoloring вместо хардкода цвета. Иконки поставляются как обычные -symbolic.svg с единственным заполняющим цветом — реальный цвет всегда берётся GTK4 из CSS color (текущего токена темы), поэтому светлая/тёмная схема подхватывается автоматически, без единой строчки «если тёмная тема — цвет такой-то».
  • UPower.Device.IconName, а не самодельные пороги. Индикатор заряда (ноутбук и периферия) использует готовое имя иконки по freedesktop icon naming spec (battery-level-N[-charging]-symbolic) прямо из системного сервиса, вместо таблицы захардкоженных Material-глифов на пороги процентов.
  • Gtk.Widget.overflow, а не самодельная обрезка. Скруглённые составные контейнеры (плитки Quick Center, попап уведомлений) клипают содержимое через нативное свойство виджета, а не вручную вычисленными масками поверх.
  • Слои Wayland по спецификации, не «лишь бы сверху». top для панели и большинства оверлеев — по протоколу wlr-layer-shell он корректно скрывается за полноэкранными окнами; overlay используется точечно и осознанно там, где окно обязано быть видно всегда (например, поверх видео/игр), а не как обходной путь для z-order.
  • Тема и акцент — через системные ключи GNOME, не свою настройку. org.gnome.desktop.interface (color-scheme, accent-color) — те же ключи, которыми пользуются Параметры GNOME и любое libadwaita-приложение; переключение темы в NitiVala остаётся синхронным с остальной системой, а не живёт своей отдельной жизнью.

Архитектура

core/                      — ядро: GTK Application, окно панели, менеджер плагинов, тема
api/                       — публичный API ядра для плагинов: Niti.Widget, Settings, Config, WindowRegistry
widgets/                   — виджеты панели, каждый — независимый libpeas-плагин (см. выше)
modules/                   — окна-оверлеи: launcher, appgrid (в составе launcher), quickcenter, calendar,
                              notifications, corners, hotkeys
services/                  — интеграции с системой, каждая — отдельная библиотека с .vapi/.gir
assets/                    — SCSS-стили, шрифты, шаблоны
tests/                     — pytest через GObject Introspection: чистая логика сервисов и виджетов

Сервисы — интеграции с системой

Каждый источник данных — отдельная библиотека (niti-<name>-1.0) с собственным .vapi/.gir, общающаяся через D-Bus или IPC:

niri (IPC Niri), audio (PipeWire), mpris (медиаплееры), network (NetworkManager), bluetooth (BlueZ), backlight (яркость), upower (питание/батарея, в т.ч. периферии), systemtray (SNI + DBusMenu), notifications (демон уведомлений), applications (парсинг .desktop), matugen (обои → цветовая схема), udisks (диски), pwrec (запись экрана), abooster (интеграция с Atomic Booster), eds (Evolution Data Server, календарь), layout (настраиваемые списки QC — плитки/слайдеры/шапка через JSON).

Системные интеграции: systemd и D-Bus

systemd

Панель работает как пользовательский сервис (niti-vala.service), сессия запускает её вместе с графическим окружением. Других сервисов панель при старте не поднимает; через systemctl выполняются только явные действия пользователя (меню выключения, управление планировщиком scx_lavd).

D-Bus

Шина Сервис Для чего
System org.freedesktop.NetworkManager Wi-Fi/сети
System org.bluez Bluetooth
System org.freedesktop.UPower питание/батарея, в т.ч. периферии
System org.freedesktop.UDisks2 диски
Session org.mpris.MediaPlayer2 медиаплееры (бар + Quick Center)
Session org.freedesktop.Notifications NitiVala регистрирует это имя — является демоном уведомлений
Session org.kde.StatusNotifierItem + com.canonical.dbusmenu системный трей (иконки + меню)
Session org.plafonlinux.AtomicBooster интеграция с Atomic Booster
Session org.gnome.evolution.dataserver.Calendar (через libecal) события календаря (EDS)

Прочие IPC

  • Niri — собственный IPC через unix-сокет: окна, воркспейсы, события, действия.
  • NitiVala ↔ NitiVala — единый unix-сокет для внешних команд (--open-window, --toggle-window, --set-text и т.д.) — так с панелью общаются биндинги Niri (Mod+D → Launcher и т.д.).

Сборка и разработка

Сборка происходит в контейнере (нужны valac/meson, которых нет на неизменяемом ALT Atomic хосте), а готовый бинарник устанавливается напрямую на хост и запускается нативно — версии libglib2/libgtk4/libpeas2 у контейнера сборки и хоста ALT Atomic совпадают, ABI-конфликтов нет.

git clone https://altlinux.space/plafonlinux/NitiVala.git
cd NitiVala
bash build-native.sh    # сборка в контейнере, установка в ~/.local
systemctl --user restart niti-vala.service

Зависимости для сборки (уже включены в образ сборки, см. Containerfile):

  • vala, meson, ninja-build, gcc, pkgconfig
  • libgtk4-devel, libgtk4-layer-shell-devel (+ -vala, -gir пакеты)
  • libpeas2-devel, gobject-introspection-devel
  • libjson-glib-devel
  • evolution-data-server-devel (+ -vala)
  • dart-sass (компиляция тем в рантайме)

Тесты

podman run --rm -v $PWD:/src:Z -w /src niti-vala-dev bash -c \
  "bash build.sh && python3 -m pytest tests/ -q"

Тесты гоняют реальную скомпилированную логику сервисов через GObject Introspection (Python ↔ Vala), не пересказ на другом языке.

Конфигурация

Файл Назначение
~/.config/niti-vala/config.json зоны панели, состав и включённость виджетов, режим/цвет/слой панели
~/.config/niti-vala/quickcenter-layout.json состав и порядок плиток/слайдеров/шапки Quick Center
~/.config/niti-vala/accent.json ручной оверрайд акцентного цвета и режима темы (авто/принудительно светлая/тёмная)
~/.config/niti-vala/appgrid.json сортировка и порядок иконок в сетке приложений
~/.config/niti-vala/colors.scss цветовая палитра (Material 3), генерируется matugen
~/.config/niti-vala/styles/ SCSS-стили, компилируются в рантайме

Подавляющее большинство параметров панели описано JSON-файлами — включение/выключение виджетов, их порядок, пороги, показывать ли периферию, режим слоя окна и т.д. Настройка не требует пересборки, только systemctl --user restart niti-vala.service (или живой hot-reload для стилей).

Агент секретов NetworkManager

Niti регистрирует org.altlinux.niti.SecretAgent на системной шине и org.altlinux.Niti.SecretAgent на сессионной. Пароли Wi-Fi, 802.1x и VPN сохраняются через libsecret в связке ключей пользователя; при необходимости панель показывает русское окно запроса пароля.

Санитайзеры и valgrind

В CI по dev и ежедневно выполняются сборка ASan/UBSan, тест API без дисплея и отдельный make memcheck. Локально используйте meson setup build --wipe -Db_sanitize=address,undefined, затем meson test -C build atomicbooster-api; подавления внешних библиотек находятся в tests/sanitizers/.