Перейти к содержимому

Прозрачность и блюр: терминал как у craftzdog

Ты видел это на скриншотах: терминал, сквозь который просвечивает обой, причём не резкий, а мягко размытый — будто за стеклом. У craftzdog, у половины r/unixporn, и — после этой главы — у тебя. Эффект выглядит как «одна строчка в конфиге», но на деле это трёхслойный бутерброд: композитор размывает, терминал пропускает, редактор не заливает. Пока не поймёшь все три слоя, будешь получать либо непрозрачный прямоугольник, либо мыльное месиво, в котором нечитаем текст.

В прошлых главах раздела мы собрали рабочее место: Omarchy как систему, Neovim как редактор, tmux как мультиплексор. Всё работает — но выглядит стоково. Эта глава — финальный штрих, и она не только про красоту. Прозрачность — лучший учебный пример для понимания, как вообще устроен рендеринг в Wayland-стеке: кто в каком порядке смешивает цвета и почему одна и та же настройка «не работает» в трёх разных местах по трём разным причинам.

Настраивать будем на реальном стеке Omarchy: терминал foot, редактор — Neovim с штатным механизмом прозрачности Omarchy, композитор — Hyprland, у которого блюр по умолчанию выключен. Все конфиги из главы — живые, проверенные на боевой системе; команды проверки прилагаются. Поехали снизу вверх: сначала композитор, потом терминал, потом редактор.

Запомни картинку раз и навсегда — большинство «не работает» в этой теме происходит из путаницы между слоями:

┌─────────────────────────────────────────────┐
│ Слой 1. Hyprland (композитор) │
│ смешивает пиксели окон и обоев, │
│ размывает то, что просвечивает │
│ ┌─────────────────────────────────────────┐ │
│ │ Слой 2. foot (терминал) │ │
│ │ рисует свой фон с alpha=0.92 — │ │
│ │ почти непрозрачный, но пропускает │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ Слой 3. Neovim │ │ │
│ │ │ заливает окно СВОИМ фоном темы — │ │ │
│ │ │ и если его не убрать, слои 1-2 │ │ │
│ │ │ вообще не видны │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘

Ключевой вывод из схемы: прозрачный терминал сам по себе недостаточен. Neovim — это приложение внутри терминала, и оно честно красит каждую ячейку символа в цвет фона из своей темы (например, тёмно-синий Tokyo Night). Для терминала это «непрозрачный пиксель, обычный цвет» — и он рисует его поверх всего. Ты можешь поставить alpha=0.5 в foot и не увидеть никакой разницы, потому что всё пространство окна залито Neovim. Поэтому правило номер один: прозрачность делается одновременно на всех трёх слоях, и начинать удобнее снизу — с композитора.

В Omarchy блюр по умолчанию выключен — дефолтный decoration в конфиге Hyprland его не включает. Включаем в своём слое, ~/.config/hypr/looknfeel.lua (помнишь главу про Omarchy: /usr/share/omarchy не трогаем, правим только ~/.config):

-- ~/.config/hypr/looknfeel.lua — включение блюра прозрачных областей
hl.config({
decoration = {
blur = {
enabled = true,
size = 6, -- радиус размытия: больше — «матовее» и дороже
passes = 2, -- проходы блюра: 2 — баланс качества и цены
new_optimizations = true, -- оптимизированный путь рендера, всегда включаем
popups = true, -- блюрить и всплывающие окна тоже
},
},
})

Применение и проверка — тремя командами:

Окно терминала
hyprctl reload # перечитать конфиги
hyprctl configerrors # должно быть пусто
hyprctl getoption decoration:blur:enabled # ожидаем: 1 (true)

Важно: отдельный window-rule не нужен. Hyprland блюрит то, что просвечивает сквозь прозрачные области окон, автоматически — это свойство блюра как такового, а не пер-оконная настройка. Если после включения блюра ничего не изменилось, проблема не в «забытом правиле», а в том, что у окна просто нет прозрачных пикселей — слои 2 и 3 ещё не настроены.

foot — лёгкий Wayland-терминал, который Omarchy ставит альтернативой Alacritty. Его конфиг ~/.config/foot/foot.ini начинается с подключения текущей темы Omarchy:

[main]
# Тема Omarchy (генерируется при omarchy theme set) — подключаем первой
include=~/.local/state/omarchy/current/theme/foot.ini
term=xterm-256color
font=JetBrainsMono Nerd Font:size=9
[colors-dark]
# Полупрозрачный фон терминала (сквозь него виден блюр Hyprland)
alpha=0.92

Здесь две тонкости, обе — потенциальные грабли. Первая: порядок. Строка alpha стоит после include’а темы. foot читает ini последовательно, и более позднее значение побеждает: тема приносит своё alpha=1.0 (непрозрачный), а наша строка ниже переопределяет его на 0.92. Поставишь alpha выше include — тема молча перезапишет её обратно в единицу, и ты будешь полчаса искать, «почему не работает».

Вторая: секция. Значение alpha живёт в секции цветов — [colors-dark] (у Omarchy темы бывают светлые и тёмные; правь ту, которой пользуешься, или обе). Засунуть alpha в [main] — типичная ошибка: foot либо проигнорирует неизвестный ключ, либо поведёт себя не так, как ты ожидал. Проверка простая: перезапустил foot, открыл окно поверх обоев — фон должен едва просвечивать. 0.92 — хорошая стартовая точка: текст остаётся читаемым, а эффект заметен. Ниже 0.85 код начинает сливаться с фоном — держи в голове, что терминал в первую очередь рабочий инструмент.

Остался редактор — самый коварный слой. Как мы выяснили, Neovim заливает фон цветом темы. Чтобы он «пропускал» прозрачность терминала, фоновые цвета highlight-групп нужно снять — в терминах Vim это guibg=NONE. Вручную перебирать группы муторно, поэтому Omarchy несёт штатный механизм — ~/.config/nvim/plugin/after/transparency.lua:

-- Снимаем фон с highlight-групп, сохраняя остальные атрибуты
local function make_transparent(name)
local ok, hl = pcall(vim.api.nvim_get_hl, 0, { name = name, link = false })
if ok then
hl.bg = nil
vim.api.nvim_set_hl(0, name, hl)
end
end
local groups = {
"Normal", "NormalFloat", "FloatBorder", "Pmenu", "Terminal",
"EndOfBuffer", "SignColumn", "LineNr", "NormalNC",
-- snacks picker (LazyVim)
"SnacksPicker", "SnacksPickerBorder", "SnacksPickerInput", "SnacksPickerList",
-- neotree
"NeoTreeNormal", "NeoTreeNormalNC", "NeoTreeWinSeparator",
-- notify, telescope, which-key… — всего ~50 групп
}
for _, name in ipairs(groups) do
make_transparent(name)
end

Разберём, что здесь происходит. Подсветка в Neovim — это набор highlight-групп: Normal — обычный текст, Pmenu — попап автодополнения, SignColumn — колонка с git-знаками, NeoTreeNormal — файловое дерево, и так далее. У каждой группы есть атрибуты: цвет текста, цвет фона, начертание. make_transparent берёт группу, читает её текущее определение (nvim_get_hl с link = false — важно: разворачивает ссылки, чтобы не сломать группу-источник), обнуляет только bg и записывает обратно. Остальные атрибуты — цвет текста, жирность — остаются от темы.

Список покрывает около пятидесяти групп: основной текст, плавающие окна, пикер snacks, neo-tree, nvim-tree, уведомления. Именно полнота списка отличает «прозрачность, которая работает» от «прозрачности, у которой половина интерфейса на непрозрачных заплатках»: забыл Pmenu — автодополнение висит непрозрачным прямоугольником; забыл SnacksPicker* — непрозрачный fuzzy-поиск.

Под капотом: как композитор считает блендинг и почему блюр — это цена

Заголовок раздела «Под капотом: как композитор считает блендинг и почему блюр — это цена»

Теперь физика процесса — то, ради чего глава полезна даже тем, кто не фанат прозрачности.

Альфа-блендинг. Когда Hyprland собирает кадр, он идёт по окнам снизу вверх (от обоев к верхнему окну) и смешивает пиксели по формуле C = C_src * α + C_dst * (1 - α). Непрозрачное окно (α=1) — просто перезапись. Окно с α=0.92 — смесь: 92% цвета терминала плюс 8% того, что под ним. Это дёшево: одна multiply-add операция на пиксель, GPU делает миллиарды таких в секунду, и на практике прозрачность «бесплатна» на любом железе последних пятнадцати лет.

Блюр. Размытие — другое дело. Чтобы получить размытый фон за прозрачной областью, композитору нужно: отрендерить то, что под окном, в отдельную текстуру, прогнать её через фильтр размытия (гауссово: каждый выходной пиксель — взвешенная сумма соседних в радиусе size), и уже результат подставить в формулу блендинга. Параметры из нашего конфига — это ручки ровно этой математики: size — радиус ядра (больше — больше соседних пикселей на один выходной), passes — сколько раз прогнать фильтр (два прохода дают более гладкий результат при меньшем радиусе — классическая оптимизация, аппроксимация гаусса). new_optimizations включает более дешёвый путь рендера, где блюр считается не на полный экран, а только под прозрачными областями.

Цена вопроса: на современном дискретном или приличном встроенном GPU блюр с size=6, passes=2 — единицы процентов GPU-времени, незаметно. На слабом встроенном видео (старые Intel iGPU) или в виртуальной машине без GPU-ускорения (llvmpipe, программный рендер) тот же блюр превращается в заметную нагрузку: прокрутка в прозрачном терминале начинает проседать по FPS, а батарея ноутбука — разряжаться быстрее. Практический вывод: на слабом железе режь passes до 1 и size до 3-4, либо отключай блюр и оставляй только alpha — прозрачность без размытия почти бесплатна, а выглядит всё равно прилично. И обрати внимание: в VM от Omarchy эффект может вообще не проявиться — не потому что конфиг неверен, а потому что композитор работает на программном рендере.

  • Правка дефолтов в /usr/share/omarchy. Классика всего раздела: поправил blur или конфиг foot в системном слое — omarchy refresh снёс правки. Только ~/.config/hypr/looknfeel.lua и ~/.config/foot/foot.ini.
  • Попытка включить блюр window-rule’ом. У omarchy-хелпера o.window нет поля blur — правило либо не применится, либо упадёт с ошибкой в hyprctl configerrors. И главное: оно не нужно — прозрачные области блюрятся автоматически глобальным decoration { blur }.
  • alpha до include или не в той секции. Выше include’а темы — тема перезапишет в 1.0; в секции [main] — foot проигнорирует. Место одно: [colors-dark] (и/или [colors-light]) после всех include.
  • Прозрачный терминал без make_transparent в nvim. Редактор заливает фон темой — прозрачность терминала физически не видна. Симптом: «поставил alpha, ничего не поменялось». Лечение: третий слой, hl-группы.
  • Непрозрачные заплатки: забыл группы. Убрал фон у Normal, но забыл Pmenu, SignColumn, пикер, дерево файлов — интерфейс в непрозрачных лоскутах выглядит хуже, чем без прозрачности вообще. Держи список групп полным (~50) и дополняй, когда ставишь новый плагин с собственным UI.
  • Двойная заливка статусных строк. lualine и bufferline рисуют собственный фон своих сегментов: снял фон с Normal — а статусная строка всё равно непрозрачная. Их темы нужно либо тоже пропустить через make_transparent (группы lualine_*/StatusLine), либо осознанно оставить непрозрачными — иногда это выглядит лучше, но решение должно быть сознательным, а не «забыл».
  • Гонка colorscheme и transparency. Если прозрачность применяется до загрузки темы — тема перезапишет группы своими фонами. Порядок важен: сначала colorscheme, потом снятие фонов (директория plugin/after в Omarchy как раз про это).
  1. Почему прозрачный терминал не показывает прозрачность, когда внутри открыт vim? Потому что прозрачность терминала относится к пикселям, которые терминал рисует как «фон», а vim красит каждую ячейку в свой цвет фона — для терминала это непрозрачные пиксели. Нужно снять фон у highlight-групп редактора (guibg=NONE).
  2. Как устроен альфа-блендинг в Wayland-композиторе? Композитор собирает кадр снизу вверх, смешивая пиксели по C = C_src·α + C_dst·(1−α). Окна — текстуры, приложения отдают композитору буферы, окончательное смешивание — на GPU при композиции.
  3. Почему блюр дороже прозрачности? Прозрачность — одна операция на пиксель. Блюр требует отрендерить содержимое под окном в отдельную текстуру и прогнать фильтр размытия: каждый выходной пиксель — сумма десятков соседних, умноженная на число проходов. На слабом GPU и программном рендере это заметно по FPS и батарее.
  4. Что означают size и passes в настройках блюра Hyprland? size — радиус ядра размытия (сколько соседних пикселей учитывается), passes — число прогонов фильтра. Несколько проходов с меньшим радиусом — стандартная аппроксимация гауссова размытия, дешевле одного прохода с большим радиусом при сопоставимом качестве.
  5. Что делает guibg=NONE (или hl.bg = nil)? Убирает фоновый цвет highlight-группы: ячейки этой группы не заливаются, и терминал показывает сквозь них свой фон — который, в свою очередь, может быть полупрозрачным.
  6. Как проверить, что настройка Hyprland реально применилась? hyprctl reload, затем hyprctl configerrors (пусто — конфиг валиден) и hyprctl getoption <путь:опции> — фактическое значение в работающем композиторе, а не то, что написано в файле.
  7. Почему в ini-конфиге foot порядок строк имеет значение? Парсер применяет значения последовательно, позднее побеждает. Include темы приносит alpha=1.0; переопределение должно стоять ниже include’а и в правильной секции ([colors-dark]).
  1. Включи блюр в ~/.config/hypr/looknfeel.lua по конфигу из главы. Критерий: hyprctl configerrors пуст, hyprctl getoption decoration:blur:enabled возвращает 1.
  2. Настрой alpha в foot ([colors-dark], alpha=0.92, после include темы). Критерий: пустой терминал поверх обоев заметно просвечивает, а foot не ругается на конфиг при запуске.
  3. Проверь слой редактора. Открой в nvim файл, пикер (Space Space), дерево (Space e) и попап автодополнения: все должны быть прозрачными. Непрозрачный элемент — найди его highlight-группу (:Inspect под курсором) и добавь в список transparency.lua.
  4. Продиагностируй сломанный сценарий. Временно закомментируй make_transparent для Pmenu, перезапусти nvim, наблюдай непрозрачный автодополнение. Верни обратно. Цель — на живом примере увидеть границу слоёв 2 и 3.
  5. Замерь цену блюра (если есть слабое железо или VM): passes=1 против passes=3 на прокрутке длинного файла. Сформулируй, где для твоей машины баланс качества и плавности.
  6. Смени тему через omarchy theme set и убедись, что прозрачность и блюр пережили смену: hot-reload пересчитал группы, alpha в foot не слетел (include темы теперь другой — а твоя строка alpha всё ещё ниже него).
  • Hyprland Wiki: Decoration — все параметры blur с описанием: size, passes, оптимизации.
  • foot.ini(5) — man-страница — секции конфига foot, включая [colors-dark] и семантику alpha.
  • Neovim: :h highlight-guibg — что значит NONE для фона и как устроены highlight-группы.
  • Omarchy Manual — как Omarchy линкует темы в приложения, включая механику прозрачности Neovim.
  • Wayland Book: Surfaces — как приложения отдают буферы композитору и где в этом конвейере живёт блендинг.