Skip to content

1ay1/neowall

Repository files navigation

NeoWall

Run GLSL shaders as your Linux wallpaper.

Build License Release

neowall_demo.mp4
neowall_mouse.mp4


Paste a Shadertoy shader into a file, point neowall at it, get an animated desktop. Wayland + X11, multi-monitor, single static binary, no daemon-in-Python anywhere.

neowall

It pauses itself the moment a window covers the wallpaper, so it isn't burning your battery while you actually use the computer.

Install

# Arch (AUR)
yay -S neowall-git

# Prebuilt binary
# https://github.com/1ay1/neowall/releases/latest
tar -xzf neowall-linux-x86_64-*.tar.gz
sudo install -m755 neowall /usr/local/bin/

# From source
git clone https://github.com/1ay1/neowall && cd neowall
meson setup build && ninja -C build
sudo ninja -C build install
Build dependencies
# Debian/Ubuntu
sudo apt install build-essential meson ninja-build libwayland-dev \
    libgles2-mesa-dev libpng-dev libjpeg-dev wayland-protocols \
    libx11-dev libxrandr-dev

# Arch
sudo pacman -S base-devel meson ninja wayland mesa libpng libjpeg-turbo \
    wayland-protocols libx11 libxrandr

# Fedora
sudo dnf install gcc meson ninja-build wayland-devel mesa-libGLES-devel \
    libpng-devel libjpeg-turbo-devel wayland-protocols-devel \
    libX11-devel libXrandr-devel

Config

~/.config/neowall/config.vibe

default {
  shader retro_wave.glsl
  shader_speed 0.8
}

Image slideshow:

default {
  path ~/Pictures/Wallpapers/
  duration 300
  transition glitch
}

Per-output:

output {
  DP-1     { shader matrix_rain.glsl }
  HDMI-A-1 { path ~/Pictures/ duration 600 }
}

Full reference: config/docs/CONFIG.md.

Commands

neowall          # start
neowall kill     # stop
neowall reload   # reload config
neowall next     # next wallpaper / shader
neowall pause    # pause cycling
neowall resume
neowall pause-shader   # freeze the shader animation in place
neowall resume-shader  # resume a frozen shader animation
neowall list     # show queue
neowall set 3    # jump to index
neowall current  # print what's playing

Shaders

30+ in the box. Bring your own — neowall accepts unmodified Shadertoy GLSL: drop a .glsl file into ~/.config/neowall/shaders/ and reference it from your config.

Vibe A few
Synthwave retro_wave · synthwave · neonwave_sunrise
Nature ocean_waves · aurora · sunrise
Cyber matrix_rain · matrix_real · glowing_triangles
Abstract fractal_land · plasma · mandelbrot
Space star_next · starship_reentry

Pair it with GLEditor for a live-preview shader workflow that one-clicks into neowall.

Reactive shaders — a living desktop

neowall is a superset of Shadertoy: on top of full compatibility it feeds shaders live data from your machine and ships a GLSL std-lib (noise, SDFs, palettes, tonemap) injected automatically — no #include. Shaders can react to system audio (FFT), CPU/RAM/network load, battery, the real time of day, and your mouse/keyboard. See docs/REACTIVE_SHADERS.md.

Shader Reacts to
audio_pulse · audio_bars system audio — spectrum, bass, beats
mouse_ripples water ripples from your cursor (click = splash)
plasma_touch plasma you push around with the mouse
fireflies a swarm that gathers at your pointer, flares on beat
starfield_warp warp speed scales with mouse motion + audio
system_monitor CPU heat, RAM tide, network pulses, battery
system_deck a command-deck HUD: CPU/RAM gauges, scrolling history graph, per-core meters, net traces, battery, clock
rain_window rain on glass — heavier with network, lightning on beat
circadian_sky a sky synced to your real clock: dawn → noon → dusk → stars

Drop a .neowall sidecar next to any shader for explicit channel bindings and custom reactive uniforms (e.g. uniform uGlow audio_bass). Audio capture uses parec (PipeWire/PulseAudio) and degrades to silence if it's not installed.

Changing what feeds iChannel0..3 (audio, noise, self-feedback, another buffer, a texture): a bare .glsl guesses via a heuristic; a .neowall sidecar lets you bind each channel explicitly — channel0 audio, channel1 self, etc. See docs/REACTIVE_SHADERS.md.

How it works

Single C binary. The event loop is built on timerfd + signalfd — there is no polling thread anywhere. Rendering goes through EGL → OpenGL 3.3 (desktop) with a GLES 2.0 fallback for older GPUs.

config.vibe → event loop ─┬─→ EGL / OpenGL 3.3
                          ├─→ Wayland (layer-shell)
                          └─→ X11 (root window + EWMH)

Smart pause is the main thing that separates neowall from the obvious one-evening hack:

  • Wayland: wl_surface.frame watchdog + wlr-foreign-toplevel state bits, plus a Hyprland-specific IPC path that handles the awkward "tiled mosaic of small windows covers the wallpaper" case
  • X11: EWMH _NET_WM_STATE_FULLSCREEN on every output

Result: while a fullscreen game, a maximized browser, or a wall of tiled terminals is covering the screen, neowall draws zero frames. The moment you switch workspaces, it picks back up.

Compared to

neowall swww mpvpaper hyprpaper
Animated GLSL shaders
Drop-in Shadertoy support
Image slideshow
Video gifs only
Wayland
X11
Pauses when occluded

If you want video wallpapers, use mpvpaper — neowall is deliberately not that.

Caveats, honestly

  • KDE Plasma: native desktop icons may hide while neowall owns the background layer. Use a dock or plasma-desktop's widgets.
  • GNOME: works through the fallback path; Mutter doesn't expose layer-shell, so z-order behavior is less guaranteed than on wlroots compositors.
  • No video: by design.

Hacking

meson setup build --buildtype=debug
ninja -C build
./build/neowall -f -v

Architecture, threading model, and contribution conventions are documented in docs/ARCHITECTURE.md. Run the test suite (headless, no display server needed) with meson test -C build; for the memory-safety and concurrency gates use a sanitized build:

meson setup build-asan -Db_sanitize=address,undefined && meson test -C build-asan
meson setup build-tsan -Db_sanitize=thread && meson test -C build-tsan output_refcount

Shaders, bug reports, and compositor coverage PRs are all welcome. Issue tracker is the place.

License

MIT.


Issues · Discussions · ★ if it's your thing