Skip to content

Releases

veiland 0.3.1

Choose a tag to compare

@sylflo sylflo released this 26 Sep 20:51

A packaging-only patch release for Nix users. Nothing in veiland itself
changed since v0.3.0 -- no core, protocol, SDK or plugin code was touched.

Fixed

  • NixOS: the Python plugins could not run. Every installed veiland-*
    Python widget died at startup with "cannot load libgbm". They now start
    normally. (8984950)

Full changelog: v0.3.0...v0.3.1

veiland 0.3.0

Choose a tag to compare

@sylflo sylflo released this 26 Aug 22:42

veiland 0.3.0

Veiland gains a GLSL shader tier: veiland-shader runs a
Shadertoy-convention fragment shader as a lock-screen layer. Seven
shaders ship in the binary, and a path to your own .frag runs that
instead, so a shader you like on Shadertoy usually drops in unchanged.

Upgrading from 0.2.0 is a straight upgrade: nothing was removed and no
configuration changed.

Added

The shader plugin

  • veiland-shader compiles a Shadertoy-convention mainImage shader
    and renders it into its region every frame. You write only that
    function; the version directive, precision qualifiers, uniform
    declarations, and the main() that calls it are prepended for you.
    fragCoord arrives with Shadertoy's bottom-left origin.
  • Seven embedded presets, needing nothing installed: nebula,
    deepfield, starfield, moon, meteor, warp, and plasma.
    Preset names are a stable interface, like a CLI flag.
  • path runs a .frag file of your own, and wins over preset when
    both are set.
  • The full single-pass Shadertoy uniform set is declared, so a shader
    mentioning one compiles even where the value is not meaningful here.
    iTime, iTimeDelta, iFrame, iFrameRate and iResolution are
    live; iChannel0 is a 256x256 tiling noise texture; iMouse is zero,
    since plugins receive no pointer events; iDate fills only its
    seconds-since-local-midnight component.
  • opacity below 1.0 switches the layer to premultiplied transparency,
    so a shader written with alpha in mind composites over what sits under
    it. At the default 1.0 the layer is opaque and the shader's alpha is
    ignored, which is the right default because Shadertoy shaders write
    undefined alpha.
  • render_scale and max_fps are the thermal knobs. max_fps defaults
    to 30 rather than the compositor rate, because a full-screen fragment
    shader runs your maths on every pixel of every frame.
  • loop_seconds wraps iTime at a period you choose, for shaders with
    a natural cycle or for very long locks, where a float iTime loses
    precision as it climbs.
  • veiland-shader --check [FILE] compiles a shader and prints the
    driver's own compile log, so a syntax error surfaces without locking
    the screen. It exits 0 when the shader compiles; with no argument it
    checks whatever your config selects.
  • A bad shader never costs you the scene. An unknown preset, an
    unreadable or oversized file, or a compile error logs the reason with
    the compiler's full output and draws a dark fill, with the plugin
    still running.

Scenes, widgets, and the SDK

  • A Deep Field astronomy example scene
    (docs/examples/deepfield-astronomy.toml): four shader layers, three
    of them transparent, under a markup clock and an ephemeris HUD.
    Entirely procedural, with no image asset.
  • The markup widget gained a {jd} substitution, the Julian Day
    Number that astronomers count in.
  • GbmEgl::new_es3 in veiland-plugin, for plugins whose shaders need
    a GLES 3 context to compile #version 300 es.

veiland 0.2.0

Choose a tag to compare

@sylflo sylflo released this 26 Aug 20:12

veiland 0.2.0

Veiland gains a Python plugin tier: a full SDK plus nine ready-made
widgets, so a scene can now show the weather, what's playing, or your
network state without writing Rust. Wallpapers can blur, plugins can be
anchored to a corner instead of pinned to pixel coordinates, and the
text tier moved to Pango markup.

Upgrading from 0.1.0: read Removed and Changed first. The
clock and label plugins are gone, and PAM no longer runs the account
phase.

Added

Python plugin tier

  • veiland_plugin.py, a Python SDK mirroring the Rust one: wire codec,
    Connection, GBM buffer allocation, FramePacer, and BufferChain.
    Plugins are ordinary Python programs; the wire format was never tied
    to Rust, and this is the proof.
  • Four companions: veiland_text (Pango text), veiland_svg (SVG icon
    rendering), veiland_dbus (D-Bus, no async runtime), and
    veiland_layout (content anchoring and debug borders).
  • Nine widgets installed as veiland-* commands on every packaging
    target: markup, weather, now-playing, avatar, wifi,
    ethernet, bluetooth, battery, shape.
  • markup is the new text tier: one block of Pango markup with ten
    substitutions: {user}, {name}, {host}, {time}, {date},
    {uptime}, {loadavg}, {kernel}, {distro}, {distro_version}.
    {time} and {date} take a strftime format; a bad one shows the text
    you typed instead of crashing.
  • weather reads Open-Meteo by city name or latitude/longitude. No API
    key, and the fetch uses only the standard library, so it adds no
    dependency beyond the shared widget stack. Eleven CC0 icons included.
  • now-playing shows the current MPRIS track, read-only.
  • shape draws a rounded colored rectangle, a backdrop to group other
    widgets against.
  • Python tooling in CI: ruff, mypy --strict, and pytest.

Core

  • Anchored region placement: halign/valign with fraction-of-surface
    width, height, and margin (margin_x/margin_y per axis). A
    widget anchored to a corner lands in the same relative spot on 1080p
    and 4K, instead of at fixed pixel coordinates.
  • --help and --version. Version carries the git revision on builds
    off master, so a bug report says which build it came from.
  • VEILAND_GL_DEBUG=1 for GL diagnostics: the driver debug callback
    where available, with a glGetError fallback.

Plugins

  • wallpaper gained blur, darken, and blur_regions: blur the
    whole surface, then tint rounded regions on top as frosted cards.
  • particles gained an opt-in twinkle (with twinkle_speed and
    twinkle_depth) for a shimmering starfield.
  • Optional labels beside the glyph on wifi, bluetooth, and
    battery; avatar gained a rounded-square shape.

Scenes and docs

  • Four composed example scenes with screenshots: aurora-corners,
    aurora-card, aurora-dashboard, and deepfield.
  • A documentation website (Zola), with per-plugin reference pages
    generated from a single source and checked in CI.
  • docs/plugin-python.md, the Python SDK reference.
  • Manual VM packaging tests (scripts/vmtest/) that boot real Debian,
    Fedora, and Arch guests, install the built package, and verify the
    widget dependency closure resolves.

Changed

  • PAM now runs pam_authenticate only, not pam_acct_mgmt. A
    correct password was intermittently rejected right after a fast logout
    and login, because the account phase returned a transient error while
    logind tore down the previous session. A locker re-verifies an
    existing session; deciding whether an account may start one is a
    login manager's job, and applying it here could lock you out of your
    own live session with no way to change the password. Shipped PAM files
    drop the now-dead account line. Existing installs keep their current
    file, where the stale line is simply never evaluated. Trade-off: an
    account disabled while the screen is locked still unlocks with a
    correct password. The session is already open either way.
  • Configure now carries the plugin's region dimensions rather than the
    full surface size, so a plugin assigned a region renders at that
    region's size instead of drawing full-surface and being squashed into
    it.
  • Python widgets are referenced by bare veiland-* name in the example
    scenes, resolved on PATH like the Rust plugins.

Removed

  • The clock and label plugins. markup replaces both, with
    Pango markup, live substitutions, and font matching that follows the
    system's configuration. Scenes using them need
    binary = "veiland-markup" and a text key; see
    docs/examples/ for worked configurations.

Fixed

  • CPU-rendered plugins flickered because a single buffer was redrawn in
    place while the host was still sampling it. BufferChain double-buffers
    and fixes it.
  • Dmabufs that a driver only accepts as external textures rendered black
    (NVIDIA marks linear and CPU-written buffers this way, so every CPU
    plugin was affected). The core now samples them via
    GL_TEXTURE_EXTERNAL_OES, and falls back cleanly on stacks without the
    extension.
  • Glyphs bled into their neighbours in the text atlas; a 1px gutter fixes
    it.
  • A glyph the rasterizer can't render is now reported once instead of
    silently vanishing. Hairline font weights drop digits on some fonts,
    which previously looked like a bug in the clock.

veiland 0.1.0

Choose a tag to compare

@sylflo sylflo released this 14 Jul 12:37

First release. Veiland is a GPU lock screen for Wayland that you compose
from layers, each one a separate program.

Added

Core locker

  • ext-session-lock-v1 lock surface; works on any compositor implementing
    the protocol (tested on Hyprland and Sway). The compositor enforces the
    lock, so the session fails closed even if veiland crashes.
  • PAM authentication against the veiland service (auth + account
    phases), run on a worker thread so a wrong password never freezes the
    animation.
  • Configurable password indicator, always composited on top of all plugin
    output.
  • Multi-monitor support with per-plugin output targeting, and HiDPI-aware
    text rendering via veiland-text (cosmic-text backend).
  • Reliability across suspend/resume, DPMS off/on, and monitor
    unplug/replug — including unplugging every monitor at once and
    hot-plugging a display in while locked.
  • Password-buffer hygiene: mlock'd, zeroed after the PAM call, and the
    core sets prctl(PR_SET_DUMPABLE, 0) at startup to deny same-UID
    ptrace/proc-mem reads and core dumps (VEILAND_ALLOW_DUMP=1 opts out).

Plugin system and protocol

  • Process-isolated plugins: every layer is a separate program, spawned over
    a socketpair and speaking a versioned tagged-message protocol on an
    AF_UNIX SOCK_SEQPACKET socket. Plugins never receive keyboard input and
    have no unlock path — the API surface is absent by construction.
  • Zero-copy GPU rendering: plugins allocate buffers via GBM, render with
    their own EGL/OpenGL context, and pass DMA-BUF file descriptors to the
    core via SCM_RIGHTS; the core imports them as EGLImage textures. No
    pixel data crosses CPU memory.
  • Explicit sync: frames carry a sync-fence fd where the driver supports it,
    with a glFinish fallback negotiated automatically.
  • Scene composition: plugins layer by z_index, can target specific
    monitors, and are configured through [[plugin]] tables in
    ~/.config/veiland/config.toml.
  • A crashed or misbehaving plugin costs its own layer, never the locker:
    malformed messages close the plugin's socket and a fallback is drawn for
    its region.
  • veiland-plugin, the Rust plugin SDK: imperative primitives
    (Connection, FramePacer, DmaBuffer, GbmEgl) the plugin author
    drives from their own main(). The wire format is documented and not
    tied to Rust.
  • veiland-protocol, the wire-format implementation, with a cargo-fuzz
    harness for the codec.

Bundled plugins (14)

  • wallpaper — image wallpaper.
  • clock — time display.
  • label — static text.
  • vignette — darkened-edges overlay.
  • particles, sakura, snow, rain, embers, fireflies — the
    particle family: drifting particles, falling petals, dendritic ice
    crystals, slanted rain streaks, rising sparks, wandering glow.
  • gradient, parallax, blobs — ambient backgrounds: flowing color
    ramp, layered bokeh depth, lava-lamp metaballs.
  • raymarcher — raymarched gyroid tunnel drift.

Packaging

  • NixOS flake: package, dev shell, and checks, plus a NixOS module
    (services.veiland.enable = true) that installs the binary and reference
    plugins and registers the PAM service.
  • Arch Linux PKGBUILD (AUR).
  • Debian package for Debian testing (trixie), with the PAM service bundled.
  • RPM spec for Fedora/RHEL, with the PAM service bundled; .deb and .rpm
    artifacts are built by CI and attached to releases.
  • Reference PAM service files and an annotated example config under
    packaging/.

Documentation

  • docs/architecture.md — full write-up: trust boundaries, module map,
    security model.
  • docs/protocol.md — the wire-format specification (the spec is
    authoritative over the implementation).
  • docs/plugin-api.md — plugin SDK reference.
  • docs/plugin-authoring-claude.md — drop-in context file for writing
    plugins with an AI coding assistant.
  • docs/config.md — configuration reference.
  • Ready-made example scenes in docs/examples/, matching the README
    gallery (shinkai composes ten plugin instances across two monitors).
  • SECURITY.md and CONTRIBUTING.md.