Ir para o conteúdo

Beta · 1.0.0-beta.1

veil: Um daemon de papel de parede para compositores Wayland.

O veil mostra uma imagem ou um vídeo em loop em cada monitor, pode dar a cada monitor um papel de parede próprio, pausa um vídeo que ninguém consegue ver e restaura o que cada monitor exibia depois de uma reinicialização.

É escrito em Rust, reproduz vídeos com GStreamer e é controlado pela linha de comando, por um arquivo de configuração ou por um socket que scripts e barras de status podem usar.

Versão
1.0.0-beta.1
Licença
PolyForm Strict
Escrito em
Rust
Requer
wlr-layer-shell
veil · início rápido
# draws on every monitor (black until a wallpaper is set)
veil daemon &

# a video or a picture; saved, and shown again after a restart
veil set --input ~/Videos/waves.mp4

# what each monitor shows
veil status

Depois de instalar o veil, na sua sessão Wayland. Para iniciá-lo junto com a sessão, use a unidade de usuário do systemd no lugar de veil daemon &.

Imagens e vídeo, em todos os monitores.

Suportado significa implementado, coberto por testes automatizados e verificado em um compositor. Experimental significa que funciona, com uma limitação que convém conhecer.

  • Imagens

    Suportado

    PNG, JPEG, WebP, BMP, TIFF, GIF e os demais formatos do crate image. Uma imagem é desenhada na resolução física do monitor, e a cópia decodificada é liberada em seguida.

  • Vídeo em loop

    Suportado

    Sem áudio, em qualquer formato que os plugins GStreamer instalados reproduzam. Verificados: H.264, HEVC, VP8, VP9 e AV1, e dez contêineres.

  • Cada monitor com o seu

    Suportado

    Todos os monitores, ou os que forem indicados, cada um com um papel de parede próprio, e monitores conectados depois. Um monitor mantém o papel de parede pelo nome.

    com vídeo, uma mudança de monitor é experimental

  • Pausa o que ninguém vê

    Suportado

    Atrás de uma janela em tela cheia, um vídeo mantém o quadro na tela e não decodifica nada. Uma tela bloqueada ou um monitor desligado o interrompe após dois segundos.

    sway · experimental no Hyprland

  • Lembra

    Suportado

    O papel de parede de cada monitor é salvo e exibido de novo após uma reinicialização. veil set --no-persist evita isso.

  • Nunca uma tela em branco no meio

    Suportado

    Um novo papel de parede só substitui o anterior quando está pronto. Um vídeo assume quando o primeiro quadro está na tela; um arquivo que não pode ser exibido deixa o papel de parede anterior como está.

  • HiDPI e escala fracionária

    Suportado

    As imagens são desenhadas na resolução física do monitor. Verificado pixel a pixel nas escalas 1; 1,25; 1,5 e 2.

  • Controlado de qualquer lugar

    Suportado

    set, clear, pause, resume, toggle, status, outputs, quit e ping, com códigos de saída estáveis, além de um socket de controle para scripts e barras de status.

Cinco maneiras de ajustar uma imagem a um monitor.

--mode define como um papel de parede é ajustado ao seu monitor, para imagens e vídeos. O --mode e o --bg-color do daemon também são os padrões de veil set.

  • --mode fill

    Cobre o monitor inteiro, mantendo a proporção. O excesso é cortado por igual dos dois lados. O padrão.

  • --mode fit

    A imagem inteira fica visível, mantendo a proporção. Barras de --bg-color preenchem o resto.

  • --mode stretch

    Ajustada exatamente ao tamanho do monitor; a proporção não é mantida.

  • --mode center

    Tamanho nativo, um pixel por pixel do dispositivo, centralizada. Cortada se for maior que o monitor, cercada por --bg-color se for menor.

  • --mode tile

    Tamanho nativo, repetida a partir do canto superior esquerdo. Vídeos voltam para center.

Um comando para todos os monitores, ou para um só.

Execute os comandos em dois monitores de exemplo. O que os monitores mostram e o que veil status imprime são uma ilustração, no formato que o veil usa.

Exemplos: ~/Pictures/sunset.jpg, ~/Pictures/dawn.jpg e o vídeo ~/Videos/sunrise.mp4.

DP-3
DP-3 · 1920x1080 at scale 1
HDMI-A-1
HDMI-A-1 · 2048x1152 at scale 1.25
veil status
veil 1.0.0-beta.1 (pid 4218), running for 7s; videos pause on: fullscreen
default: ~/Pictures/sunset.jpg (fill, #000000)
DP-3: playing ~/Videos/sunrise.mp4 (fill, #000000); 1920x1080 at scale 1; video 1920x1080, 25 fps
HDMI-A-1: showing ~/Pictures/sunset.jpg (fill, #000000); 2048x1152 at scale 1.25

Um vídeo que ninguém vê custa quase nada.

No Hyprland e no sway, o veil acompanha o IPC do compositor e pausa um vídeo que ninguém consegue ver. Em qualquer compositor, um vídeo cujos quadros o compositor não aceita é interrompido e seu pipeline é liberado.

DP-3
O que está na frente do vídeo
CPU do daemon
19,5 %
veil status diz
playing

O vídeo é reproduzido e decodifica todos os quadros.

CPU do daemon
≈ 0 %
veil status diz
paused (hidden by a window)

Oculto por um segundo, o vídeo mantém o quadro na tela e não decodifica nada. Continua do mesmo quadro quando volta a ser visível.

CPU do daemon
≈ 0 %
veil status diz
stopped while the compositor does not show it

O compositor não aceita quadros por 2 segundos, então o veil solta o vídeo. Ele recomeça do início.

CPU é a parcela do daemon em um núcleo, para um vídeo H.264 de 1080p a 30 fps decodificado em uma placa NVIDIA. Atrás de uma janela em tela cheia, mediu no máximo um tick de tempo de CPU em 5 segundos.

O que um papel de parede custa.

Medido na compilação de 2026-10-19 em um sway headless, uma saída de 1920x1080 em fill, 60 segundos após 5 segundos de aquecimento, em um Intel Core i5-11400F com uma NVIDIA GeForce RTX 3060 Ti. Ainda não se mediu nada em uma sessão real.

CPU, quadros exibidos, memória e threads do daemon por tipo de papel de parede. A linha tracejada nas barras é um núcleo inteiro.
Papel de paredeCPU, parcela de um núcleoQuadros exibidos por segundoMemória (RSS)Threads
Um PNG de 1920x1080sem decodificador
0,02 %
—20 MiB1
H.264, 1080p, 30 fpsnvh264dec (GPU)
19,5 %
30,0 de 30203 MiB15
H.264, 1080p, 60 fpsnvh264dec (GPU)
39,7 %
59,8 de 60203 MiB15
VP9, 1080p, 60 fpsnvvp9dec (GPU)
37,9 %
59,9 de 60251 MiB15
H.264, 2160p, 60 fpsnvh264dec (GPU)
136 %
60,2 de 60297 MiB15
H.264, 1080p, 30 fpsavdec_h264 (software)
24,5 %
30,0 de 30161 MiB22
H.264, 2160p, 60 fpsavdec_h264 (software)
174 %
60,1 de 60458 MiB22
  • Uma imagem estática custa quase nada depois de desenhada: uma thread e um tick de tempo de CPU em um minuto.
  • Um vídeo custa CPU em proporção aos seus pixels por segundo, seja qual for o codec. Na NVIDIA, o decodificador na GPU custa cerca de 1 %; o resto é converter cada quadro de NV12 para RGB na CPU.
  • A meta de projeto do veil, menos de 1 % para um vídeo, não é atingida neste hardware. Em Intel e AMD, o VA-API poderia evitar essa conversão; isso não foi medido.
  • Memória, threads e descritores de arquivo permanecem estáveis ao longo de dez minutos de loop e 500 trocas de papel de parede, com uma única arena do alocador (MALLOC_ARENA_MAX=1, definido pelo pacote Nix e pela unidade systemd).

A linha de comando, um arquivo ou um socket.

Todo comando do veil é um cliente do socket do daemon, e qualquer outra coisa também pode ser: uma barra de status, um atalho de teclado, um script em qualquer linguagem.

Linha de comando

Todo comando aceita --help e tem uma página de manual. veil set retorna quando o papel de parede está na tela e termina com código de saída 1, mantendo o anterior, se o arquivo não puder ser exibido.

terminal
# every monitor
veil set --input ~/Videos/waves.mp4

# one monitor; the others keep theirs
veil set --input ~/Pictures/photo.jpg --output DP-3

# pause videos until `veil resume`
veil pause

# what each monitor shows, as JSON for scripts
veil status --json
Uso

Arquivo de configuração

~/.config/veil/config.toml guarda as opções do daemon e o papel de parede de cada monitor. veil config check o lê como o daemon leria e informa uma chave incorreta com a linha e a coluna.

config.toml
[defaults]
mode = "fill"           # --mode
bg_color = "#000000"    # --bg-color
pause_on = "covered"    # --pause-on

[output."DP-3"]
input = "~/Videos/waves.mp4"
mode = "fit"

[output."*"]            # every monitor without a section of its own
input = "~/Pictures/wallpaper.png"
Configuração

Socket de controle

Uma requisição JSON e uma resposta JSON por conexão, apenas para processos do mesmo usuário. Campos, comandos e códigos de erro só são acrescentados, nunca renomeados nem removidos.

socket
sock="$XDG_RUNTIME_DIR/veil-${WAYLAND_DISPLAY##*/}.sock"
echo '{"cmd":"ping"}' | socat - UNIX-CONNECT:"$sock"
# {"version":1,"status":"ok"}
echo '{"cmd":"toggle"}' | socat - UNIX-CONNECT:"$sock"
# {"version":1,"status":"ok","result":{"paused":true}}
Socket de controle

O que foi executado, e por quem.

Da matriz de suporte do próprio veil. Não testado significa que ninguém tentou ainda, não que se saiba que falha.

Compositores

  • sway 1.12 (headless)

    Todas as verificações dos testes headless e das medições, 2026-10-19.

    Verificado
  • Hyprland 0.56.2

    Imagens, vídeo H.264 em dois monitores e a pausa automática, 2026-10-20. Fluidez, bloqueio, DPMS, logout e recuperação de falhas não foram testados.

    Funcionamento relatado
  • river, niri, Wayfire, labwc e outros compositores com wlr-layer-shell

    Deve funcionar. Sem pausa automática: todo vídeo conta como visível.

    Não testado
  • KDE Plasma (KWin)

    Tem wlr-layer-shell; ninguém testou.

    Não testado
  • GNOME (Mutter)

    Sem wlr-layer-shell.

    Sem suporte

Gráficos

  • NVIDIA (NVDEC)

    RTX 3060 Ti, driver 595.91.07, sway e Hyprland. Todo quadro de vídeo é convertido na CPU.

    Funcionamento relatado
  • Intel e AMD (VA-API)

    O caminho de cópia zero não foi verificado em nenhum hardware.

    Não testado
  • Decodificação por software

    Nos testes, e removendo os decodificadores de hardware.

    Funcionamento relatado

Arquiteturas

  • x86_64

    O tarball em um contêiner de seis distribuições, 2026-10-19.

    Funcionamento relatado
  • aarch64

    O workflow de lançamento o compila e executa os testes nele; nunca foi executado com um compositor.

    Não testado

Distribuições

  • Debian 12 e 13, Ubuntu 22.04 e 24.04, Fedora 44, Arch Linux

    O tarball pré-compilado em um sway headless, 2026-10-19. GIFs animados exigem GStreamer 1.26 ou mais recente.

    Funcionamento relatado
  • NixOS (o flake)

    nix run e nix profile, com sway e Hyprland. 2026-10-20 e 2026-11-04.

    Verificado

As arestas, declaradas de antemão.

O veil é um beta. Isto é o que se sabe estar errado hoje; os detalhes, as medições e as opções consideradas estão nos problemas conhecidos.

  • Uma mudança de monitor durante a reprodução de um vídeo derruba o daemon

    O defeito está no waylandsink do GStreamer: ele sofre um segfault quando o compositor informa uma mudança em qualquer monitor. As imagens não são afetadas. Execute o veil pela sua unidade systemd: ele volta com os papéis de parede em cerca de três segundos.

    Problema conhecido 1

  • Um vídeo consome CPU na NVIDIA

    Cerca de 20 % de um núcleo para 1080p a 30 fps, porque cada quadro é convertido para RGB na CPU.

    Problema conhecido 7

  • A memória cresce com as trocas de vídeo sem uma única arena do alocador

    O pacote Nix e a unidade systemd definem MALLOC_ARENA_MAX=1; defina-o ao iniciar à mão um binário compilado a partir do código-fonte.

    Problema conhecido 3

Binários pré-compilados, Nix ou código-fonte.

O veil precisa de um compositor Wayland com wlr-layer-shell e do GStreamer 1.x, com os conjuntos de plugins base, good, bad e libav, em tempo de execução. XDG_RUNTIME_DIR deve estar definido, como em qualquer sessão de desktop.

Pré-compilado

Cada lançamento tem um tarball para Linux x86_64 e outro para aarch64: o binário, a unidade de usuário do systemd, as páginas de manual, o autocompletar do shell e um script de instalação. Os binários pré-compilados ainda são experimentais.

pré-compilado
version=1.0.0-beta.1
tarball=veil-$version-$(uname -m)-unknown-linux-gnu.tar.gz
curl -LO https://github.com/ordreth/veil/releases/download/v$version/$tarball
curl -LO https://github.com/ordreth/veil/releases/download/v$version/SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMS
tar -xzf "$tarball" && cd "${tarball%.tar.gz}"
./install.sh --prefix ~/.local

Cada tarball tem uma atestação de proveniência de compilação: gh attestation verify "$tarball" --repo ordreth/veil.

Nix

O pacote do flake vem empacotado com seus próprios plugins do GStreamer e um registro do GStreamer próprio, e inclui a unidade de usuário do systemd, o autocompletar e as páginas de manual.

nix
nix run github:ordreth/veil -- daemon     # try it without installing
nix profile add github:ordreth/veil       # install it

Por causa da licença, o nixpkgs considera o veil unfree. Os pacotes do próprio flake já a permitem; com o overlay, permita-a na configuração.

Do código-fonte

São necessários Rust 1.89 ou mais recente, um compilador C e o pkg-config, e os arquivos de desenvolvimento do Wayland, do libxkbcommon e do GStreamer. O guia de instalação lista os pacotes para Arch, Debian, Ubuntu e Fedora.

terminal
git clone https://github.com/ordreth/veil && cd veil
cargo build --release --locked
install -Dm755 target/release/veil ~/.local/bin/veil

Ao iniciar à mão um binário compilado por você, use MALLOC_ARENA_MAX=1, como em MALLOC_ARENA_MAX=1 veil daemon.

Uso gratuito, código-fonte disponível, não é código aberto.

O veil é licenciado sob a PolyForm Strict License 1.0.0, com permissões adicionais. É permitido ler o código e usar o veil para qualquer fim não comercial.

Permitido

  • Usar o veil para qualquer fim não comercial.
  • Compilar o veil a partir do código-fonte para uso próprio.
  • Redistribuir os tarballs de lançamento, sem alterações, byte a byte.
  • Citar até 50 linhas do código-fonte, com atribuição.
  • Usar o nome e o ícone para se referir ao veil.

Não permitido

  • Distribuir o código-fonte ou uma compilação própria.
  • Alterá-lo ou criar novas obras a partir dele.
  • Usá-lo comercialmente.
  • Usar o nome ou o ícone para outro produto ou para uma versão modificada.

O veil não aceita pull requests, patches nem issues. Relatos de como ele funciona na sua máquina são bem-vindos no GitHub Discussions, e problemas de segurança, em particular, como diz o SECURITY.md.

Os documentos do próprio veil.

Estas páginas são cópias dos documentos do repositório do veil, e por isso são lidas do mesmo jeito aqui e lá.

O ícone do veil: uma janela para um entardecer

Beta · 1.0.0-beta.1

Uso gratuito, código-fonte disponível e inacabado. O que se sabe estar errado está nesta página; o que você encontrar na sua máquina é bem-vindo nas discussões.