lark/docs/BUILD.md
Niko Marmeladkov 725ca2ba37 Интерфейс Material 3 и сборка в Docker на удалённой машине
Сборка:
- Dockerfile (builder/runtime/headless/binary) и .dockerignore
- scripts/build-remote.sh: сборка на другой машине, возврат бинарника
  и проверка без дисплея (--check)
- в требования добавлен libseat-dev; dev-run.sh принимает LARK_BIN

Интерфейс:
- свой программный холст (src/canvas.rs): скругления, градиенты, тени,
  значки; слои кэшируются по отпечатку состояния, поэтому неизменный
  слой не перерисовывается
- панель задач в раскладке Windows 10: «Пуск», строка поиска, рабочие
  области, кнопки окон с подписями и индикатором, трей, часы и полоска
  «показать рабочий стол»
- меню «Пуск» «1 в 1»: полоса со списком, настройками и питанием,
  поиск, список по алфавиту с группами, плитки, прокрутка
- настройки в стиле Windows 11: разделы и карточки, обои, анимации,
  раскладки, ввод, окна, сброс общий и у каждой настройки
- рабочий стол: шесть вариантов обоев, значки приложений и ~/Desktop
- значки вместо прямоугольников: свой набор фигур, включая кнопки
  заголовков окон
- растровщик текста: целые кегли и базовая линия, кривая контраста
  вместо «загустения», кэш ширин для измерений

Ввод и состояние:
- список приложений читается из .desktop-файлов, ярлыки ~/Desktop тоже
- индикаторы трея читают батарею, Wi-Fi, звук и Bluetooth
- переключение раскладок (Super+Space) и настраиваемый их список
- поиск в интернете через uv + ddgs из меню «Пуск»
- анимации появления меню и настроек (отключаются в настройках)
- исправлено: обои перекрывали окна, клик оболочки уходил приложению,
  значки рабочего стола отбирали указатель, тень вылезала из-за
  скруглений прямоугольником, ярлыки не сдвигались при панели сверху

Документация: раздел про удалённую сборку, описание интерфейса и
настроек, холст и слои в архитектуре, обновлённая дорожная карта.
2026-10-18 14:46:30 +03:00

27 KiB
Raw Permalink Blame History

Сборка и запуск Lark DE

Требования

Системные зависимости

# Debian/Ubuntu
sudo apt install \
    libwayland-dev \
    libxkbcommon-dev \
    libdrm-dev \
    libgbm-dev \
    libpipewire-0.3-dev \
    libseat-dev \
    libdbus-1-dev \
    libudev-dev \
    libinput-dev

# Fedora
sudo dnf install \
    wayland-devel \
    libxkbcommon-devel \
    libdrm-devel \
    mesa-libgbm-devel \
    pipewire-devel \
    libseat-devel \
    dbus-devel \
    libudev-devel \
    libinput-devel

Rust

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Сборка

cargo build --release

Сборка на удалённой машине в Docker

Слабому устройству не обязательно собирать проект самому: это можно сделать на другой машине, а готовый бинарник вернуть.

На удалённой машине нужны ssh, rsync и Docker. Скрипт копирует исходники, собирает образ по Dockerfile и забирает бинарник:

./scripts/build-remote.sh niko@n1ko.dev 2241        # target/release/lark
./scripts/build-remote.sh niko@n1ko.dev 2241 --check   # ещё и проверка без дисплея
Переменная Назначение
LARK_REMOTE_DIR каталог сборки на удалённой машине (/tmp/lark-build)
LARK_LOCAL_BIN куда положить бинарник (target/release/lark)
LARK_CHECK непустое значение равносильно --check

Этапы Dockerfile:

Этап Что внутри
builder Rust и библиотеки разработки, cargo build --release
runtime библиотеки времени выполнения и сам композитор
headless плюс Xvfb, imagemagick, weston-terminal и xdotool
binary только исполняемый файл: docker build --target binary -o dist .

Реестр Cargo, git-зависимости и target подключены кэшем BuildKit: повторная сборка после правки кода занимает секунды, зависимости не пересобираются.

docker build -t lark .                              # образ для запуска
docker build --target binary -o dist .              # только бинарник: dist/lark
docker build --target headless -t lark:headless .   # образ для проверки
docker run --rm lark:headless                       # снимок экрана и журнал

Проверка --check поднимает Xvfb в контейнере, запускает композитор с weston-terminal, снимает экран и складывает снимок и журнал в target/lark-headless/. Образ headless содержит xdotool: им можно «нажать» кнопку «Пуск» перед снимком, чтобы проверить меню.

Запуск

Композитор открывает окно через winit, поэтому запускается внутри существующей X11/Wayland-сессии — вложенно, что удобно для разработки. Поверх DRM/KMS он пока не запускается: бэкенд не реализован (дорожная карта), поэтому из TTY (без графической сессии) запуск невозможен — композитор скажет об этом и подскажет, что делать.

Требуется переменная XDG_RUNTIME_DIR: сокет Wayland создаётся в ней.

# Вложенный запуск в текущей сессии
./target/release/lark

Композитор сам занимает свободный сокет wayland-N и сообщает его при старте. Дочерние процессы (меню «Пуск», терминал) наследуют WAYLAND_DISPLAY, поэтому запускать их нужно после инициализации композитора.

Завершение: Ctrl+Esc в окне композитора либо SIGINT/SIGTERM.

Журнал

По умолчанию показываются сообщения Lark и предупреждения библиотек: фильтр lark=info,warn. Без него smithay печатает на несколько экранов список расширений OpenGL и параметры инициализации — это вытесняет всё, что действительно нужно читать.

RUST_LOG=debug ./target/release/lark    # подробно, включая smithay
RUST_LOG=lark=trace ./target/release/lark   # только свой код, максимум

Вывод запущенных приложений в консоль композитора не попадает: иначе приложение вместе со своей шиной D-Bus и запущенными ею службами засыпал бы терминал сообщениями об ошибках, которые к Lark отношения не имеют.

Горячие клавиши

Сочетание Действие
Ctrl+Esc Выход из сессии
Super Свернуть активное окно
Super+Shift Развернуть окно / вернуть к прежнему размеру
Super+Delete Закрыть активное окно
Super+1 … Super+4 Перейти на рабочую область
Super+Shift+1 … Super+Shift+4 Перенести активное окно на область
Ctrl+Super+← / Ctrl+Super+→ Шаг по рабочим областям по кругу
Alt+Tab Переключение окон (список, пока Alt удержан)
Alt+Shift+Tab Переключение окон в обратную сторону
Super+Space Следующая раскладка клавиатуры
Super+Shift+Space Предыдущая раскладка клавиатуры
Escape Закрыть меню «Пуск», настройки или отменить переключение

Клик по кнопке окна на панели задач переводит на него фокус, повторный клик по активному окну сворачивает его, клик по свёрнутому — возвращает. Ни то, ни другое не двигает окно по экрану.

Переключение окон

Alt+Tab показывает список открытых окон текущей рабочей области. Tab перебирает их по кругу, Alt+Shift+Tab — в обратную сторону. Фокус переводится только при отпускании Alt: иначе быстрый пролёт по списку переключал бы окна на каждом шаге и приложения мигали бы. Escape отменяет переключение, клик по пункту списка выбирает его сразу.

Список строится по z-порядку сверху вниз, поэтому первым идёт текущее окно, а следующее за ним — то, на которое переключится первое нажатие Tab.

Окна

Заголовок рисует композитор ([decoration] server_side = true). В нём показывается название окна, а справа — кнопки «свернуть», «развернуть» и «закрыть» со значками. Верхние углы заголовка скруглены, кнопка под указателем подсвечивается, а кнопка закрытия — красным.

Окно нельзя утащить за пределы рабочей области, поэтому заголовок всегда остаётся на экране. Развёрнутое окно показывает в кнопке значок возврата.

Окно меняет размер мышью за край рамки и за углы. Верх заголовка тянет размер по вертикали, середина — перетаскивает окно.

Панель задач

Раскладка повторяет Windows 10, оформление — Material 3 Expressive.

Слева идут:

  • «Пуск» — плитка с логотипом; открывает меню «Пуск»
  • Поиск — строка с лупой; клик открывает меню, запрос набирается сразу
  • Рабочие области — четыре скруглённые кнопки; текущая залита акцентом
  • Окна — значок приложения и подпись, у активного окна акцентная полоска снизу, у свёрнутого — приглушённые значок и подпись

Справа идут индикаторы состояния, раскладка клавиатуры, часы (время над датой) и полоска «показать рабочий стол» у самого края.

Индикаторы показывают настоящее состояние системы, а не заглушки: заряд и статус батареи читаются из /sys/class/power_supply, уровень сигнала Wi-Fi — из /proc/net/wireless, наличие адаптера Bluetooth — из /sys/class/bluetooth, громкость — через wpctl (PipeWire) или pactl. Значок батареи меняется по заряду (разряжена, половина, заряжена, идёт зарядка), звук перечёркивается при выключенном, у Wi-Fi без соединения появляется перечёркнутый значок. Индикатор, о котором нет данных (например, батарея на стационарной машине), не показывается вовсе: пустой значок был бы выдумкой. Опрос идёт раз в две секунды.

Кнопки окон подстраиваются под длину названия. Если подписи перестают помещаться, они отбрасываются и остаются значки; если не помещаются сами кнопки, лишние окна сворачиваются в счётчик +N. Место под счётчик резервируется заранее, поэтому он не наезжает на часы.

Панель задач показывает только окна текущей рабочей области.

Меню «Пуск»

Раскладка — «1 в 1» из Windows 10, оформление — Material 3 Expressive. Открывается кликом по «Пуску» или по строке поиска, закрывается по Esc или клику мимо меню.

Слева — полоса: кнопка «Все приложения» (раскрывает список на всю ширину), учётная запись, настройки и завершение работы. Правее — строка поиска, список приложений по алфавиту с заголовками букв и колонка закреплённых плиток.

Действие Результат
Ввод символов поиск по названию, без учёта регистра
Backspace удалить символ; на пустой строке уходит в окно
↑ / ↓ перемещение выделения
Enter запустить выделенное приложение
Esc закрыть меню
Прокрутка листает список
Клик по плитке запустить приложение
Клик по шестерне открыть настройки
Клик по питанию завершить сессию

Список приложений читается из системы: просматриваются каталоги .desktop-файлов (/usr/share/applications, /usr/local/share/applications, ~/.local/share/applications) и берутся записи Type=Application без NoDisplay и Hidden. Локализованное имя (Name[ru]) важнее английского, команда разбирается с учётом кавычек и кодов полей, а значок подбирается по категории: терминал получает терминал, файловый менеджер — папку. Приложения с Terminal=true запускаются внутри первого найденного терминала.

Кроме установленных программ в меню есть встроенные пункты:

Пункт Что запускается
Файлы nautilus, thunar, pcmanfm, dolphin — первый найденный; иначе xdg-open ~/
Терминал foot, alacritty, kitty, gnome-terminal, konsole, xfce4-terminal, xterm — первый найденный
Настройки встроенное окно настроек
Завершение сессии завершает Lark

Поиск в интернете

Когда в строке меню набран запрос, под списком приложений появляется строка поиска в интернете. Поиск выполняет пакет ddgs (DuckDuckGo), запускаемый через uv run --with ddgs; если uv в системе нет, берётся системный python3 с уже установленным пакетом. Результаты показываются строками меню — клик открывает страницу браузером по умолчанию.

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

Пункт, у которого нет ни одной программы в системе, не запускается: перебор кандидатов идёт до первого найденного.

Рабочий стол

Обои рисуются градиентом с двумя мягкими пятнами. Варианты — по акценту темы («По акценту»), синие, фиолетовые, зелёные, графит и однотонные по цвету [desktop] background; выбор — в настройках, там же есть анимации интерфейса.

Значки собраны в столбец у левого края: встроенные приложения и, если включено [desktop] show_home, содержимое каталога ~/Desktop. Ярлыки .desktop на рабочем столе читаются как программы, каталоги и файлы открываются через xdg-open. Одиночный клик выделяет значок, двойной — запускает приложение или открывает файл; клик по пустому месту снимает выделение.

При панели задач сверху значки начинаются под ней, а не под краем экрана.

Настройки

Встроенное окно в стиле Windows 11: полоса разделов слева, карточки параметров справа. Открывается из меню «Пуск» (шестерня или пункт «Настройки»), закрывается по Esc, кнопке закрытия или клику мимо окна.

Раздел Что настраивается
Оформление тёмная или светлая тема, акцентный цвет из восьми, варианты обоев, анимации интерфейса
Панель задач положение (внизу или сверху), высота, центрирование значков, прозрачность
Рабочий стол число рабочих областей, значки из ~/Desktop
Клавиатура список раскладок (переключаются Super+Space), вариант, чем переключать (Alt+Shift, Super+Space, Caps Lock), задержка и частота автоповтора
Ввод тачпад, скорость прокрутки
Окна заголовки рисует композитор, высота заголовка, ширина кнопок
О системе версия, шрифт, разрешение, файл настроек, сброс настроек

У каждой настройки есть кнопка сброса: она возвращает только эту настройку к значению по умолчанию, не трогая остальные. Значения по умолчанию берутся из Config::default(), поэтому они не могут разойтись с файлом конфигурации.

Изменения применяются сразу и сохраняются в ~/.config/lark/config.toml. Панель, рабочие области, декорации, раскладка клавиатуры и скорость прокрутки принадлежат композитору: после изменения настроек он заново читает конфигурацию, поэтому сброс настроек не оставляет после себя старых значений. Развёрнутые окна раскладываются заново, если панель изменила размер или положение.

Почему приложения запускаются через dbus-run-session

Lark часто запускают вложенно — внутри другой сессии (niri, GNOME). Окружение композитора наследуется правильно, но этого мало: однопользовательские программы (thunar, gedo, файловые менеджеры) через GApplication ищут уже запущенный экземпляр и передают ему свои аргументы. Найденный экземпляр принадлежит внешней сессии, и окно открывается не в Lark, а в ней.

Поэтому каждое приложение запускается в отдельной сессии D-Bus:

dbus-run-session -- thunar

Собственная шина отрезает приложение от внешней: запущенного там экземпляра оно не находит и поднимает своё — уже в Lark. Если dbus-run-session в системе нет, приложение запускается напрямую (тогда возможен возврат к поведению выше).

Рабочие области

Количество задаётся [desktop] workspaces (по умолчанию 4) и меняется в настройках. Окно открывается в текущей области; перенесённое окно остаётся открытым, но не показывается на панели и не попадает на экран до возврата на его область. Если число областей уменьшают, окна исчезнувших областей переезжают в последнюю.

Текст и шрифты

Подписи рисует собственный растровщик на fontdb + fontdue. Шрифт выбирается автоматически: перебираются системные гарнитуры и выбирается первая, умеющая нарисовать кириллицу — иначе русский интерфейс превратился бы в пустые прямоугольники. Моноширинные и знаковые шрифты пропускаются.

Кегль округляется до целых пикселей, а базовая линия — до целого пикселя строки: дробный размер размывает сразу все штрихи, и текст выглядит «потекшим». Дополнительно покрытие глифа проходит через кривую контраста: она отодвигает полутона от середины, поэтому штрих собирается в один плотный столбик вместо двух бледных. Концы шкалы кривая не трогает — мягкие края остаются мягкими.

Ширины строк кэшируются отдельно от растров: раскладка меряет текст каждый кадр, и полная растеризация на каждое измерение была бы напрасной работой.

Поддерживаемые протоколы

Помимо wl_compositor, wl_subcompositor, wl_shm, xdg_wm_base, wl_seat, wl_output и xdg-output, регистрируются:

  • wp_viewporter — рисование в поверхности меньше окна
  • wp_presentation — обратная связь о времени показа кадра
  • xdg-decoration — согласование декораций с клиентом

Не реализовано: XWayland и DRM/KMS, см. docs/ROADMAP.md.

Проверка без дисплея

Скрипт поднимает Xvfb, запускает композитор с тестовым клиентом и делает снимок экрана:

sudo apt install xvfb x11-apps imagemagick mesa-utils   # eglgears_wayland
./scripts/dev-run.sh

Снимок сохраняется в /tmp/lark-shot.png. Скрипт сообщает, работает ли клиент: если клиент завершился (например, не смог инициализировать графику), окна на снимке не будет, и это не ошибка композитора.

Полезные переменные окружения:

Переменная Назначение
LARK_BIN собранный композитор (по умолчанию target/debug/lark)
LARK_TEST_DISPLAY дисплей Xvfb (по умолчанию :78)
LARK_TEST_CLIENT тестовый клиент (по умолчанию eglgears_wayland)
LARK_TEST_WAIT секунд до снимка (по умолчанию 6)
LARK_TEST_SHOT путь к снимку
RUST_LOG уровень журналирования

При проверке ввода с клавиатуры под Xvfb окно нужно сфокусировать: без оконного менеджера фокус не ставится автоматически.

DISPLAY=:78 xdotool search --name "" | while read w; do xdotool windowfocus $w; done

На реальном железе

Пока только вложенно — из графической сессии:

./target/release/lark

Запуск поверх DRM/KMS (из TTY, без графической сессии) появится вместе с бэкендом DRM/KMS: см. дорожную карту.

Тесты

cargo test

Тесты покрывают обработку ввода и трейты KeyboardKeyEvent, PointerButtonEvent, распознавание сочетаний клавиш, геометрию декораций и зон изменения размера, раскладку панели задач и меню «Пуск», переключатель рабочих областей, растровщик текста и раскладку клавиатуры.

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

Файл конфигурации: ~/.config/lark/config.toml. Создаётся автоматически при первом запуске с значениями по умолчанию.

[compositor]
backend = "auto"      # auto, vulkan, gl, cpu
socket = "wayland-1"  # запасное имя сокета, если auto не подошёл
animations = true     # анимации появления меню и настроек

[desktop]
workspaces = 4        # число рабочих областей
background = "#0F0F17" # цвет однотонных обоев
wallpaper = "auto"    # auto, blue, violet, green, graphite, solid
show_home = true      # значки из ~/Desktop на рабочем столе

[panel]
position = "bottom"   # bottom, top
centered = false      # false — значки от левого края, как в Windows 10
height = 48
transparent = true

[theme]
name = "dark"         # light, dark
accent = "#0078D4"

[decoration]
server_side = true    # заголовок рисует композитор
titlebar_height = 32
button_width = 46

[language]
code = "ru-RU"        # ru-RU, en-US

[keyboard]
xkb_layout = "us"     # запасная раскладка, если список пуст
layouts = ["us", "ru"] # раскладки по порядку переключения (Super+Space)
xkb_variant = ""
xkb_model = "pc105"
xkb_rules = "evdev"
xkb_options = ""      # например "grp:alt_shift_toggle"
repeat_delay = 25     # мс до автоповтора
repeat_rate = 600     # символов в секунду

[input]
touchpad = true
scroll_speed = 1.0

[seat]
name = "seat0"