An 100kb native Wallpaper Engine translation layer for GNU/Linux based compositors, without re-inventing the wheel. Proton does most of the heavy lifting, while wallpiper re-implements/patches niche portions of the PE/COFF Windows API Wallpaper Engine needs.
Wallpiper then metaphorically "pipes" your wallpaper (using zero-copy dma-buf) from an internal frame buffer to a desktop portal. No overhead.
If you find this utility/tool useful, please consider giving it a star ⭐
It's simple. Wallpiper is a translation layer, not a re-implementation. It doesn't depend on Wallpaper Engine, or any program it could theoretically run. Think of it more like Proton itself. Other projects, such as linux-wallpaperengine, are re-implementations. This means Wallpaper Engine's private spec/codebase is being cloned/mirrorred (largely by AI). By design, its far more unstable, and not actually Wallpaper Engine.
NOTE: wallpiper is early in development. Although backed by proper design, you may face breaking issues.
When built from source, wallpiper is NOT installed to
PATHautomatically. All binaries live at./target/releaserelative to the repository root.
# check config
$ wallpiperctl check-config
# run wallpiperd (manages proton and wallpaper engine. YOU DO NOTHING)
$ WALLPIPER_PORTAL=portal WALLPIPER_*... wallpiperd- wallpaper-engine
- proton (>= v11.0 was tested working)
- fontconfig (optional: for local-font overrides)
- vulkan-headers
- vulkan-icd-loader
- make
- dbus
- c99 compiler
On Arch Linux:
$ pacman -S base-devel dbus vulkan-headers vulkan-icd-loader fontconfigGet it from the AUR, or compile manually below.
Important
It is highly recommended that you have a clean, never before ran installation of Wallpaper Engine before continuing. Running it through Steam, Proton, Wine, or other compatability tools may silently break your install before you even start.
If you face any issues during install, this should be your first hunch.
Start by building the core of wallpiper
$ make build-core
# optionally install wallpiper to `%HOME/.local/lib/wallpiper/`
$ make install-wallpiperdWallpiper supports the following DE/WM(s) through the following portals. Jump to whatever section is relevant to you.
- wallpiper-portal-gnome
- wallpiper-portal-kde
- wallpiper-portal-hyprland
- wallpiper-portal-sway
- wallpiper-portal-cosmic
- wallpiper-portal-i3
Pull requests are welcome for additional portals. You can also submit an issue report to suggest other portals.
Implemented as an in-process GObject-Introspection library driven by a GNOME Shell extension.
- mutter
- gobject-introspection
- mesa
- libdrm
- libxrandr
- libx11
On Arch Linux:
$ pacman -S mutter gobject-introspection mesa libdrm libxrandr libx11$ make build-gnome
$ make install-gnomeLog out and back in, then ensure the extension is enabled.
Implemented as a Qt Quick/QML plugin, installed as a Plasma 6 Wallpaper KPackage.
- cmake
- extra-cmake-modules
- qt6-base
- qt6-declarative
- mesa (for EGL)
- libx11
On Arch Linux:
$ pacman -S cmake extra-cmake-modules qt6-base qt6-declarative mesa libx11$ make build-kde
$ make install-kde- Open System Settings -> Wallpaper
- Open the Wallpaper type dropdown at the top of the panel
- Select Wallpiper
Uses wlr-layer-shell. No shell extension, and no install step.
- wayland
- wayland-protocols
On Arch Linux:
$ pacman -S wayland wayland-protocols$ make build-hyprlandWarning
Sway's IPC has no query for the compositor's global cursor position, so this portal can't support cursor-reactive wallpapers.
I agree with the sway maintainer. Unfortunately, an after-thought-patch like this is not a proper solution and should not be merged.
Solutions like https://github.com/cjacker/wl-find-cursor/ exist, however this is a single event library, not meant to be constantly
driving mouse events. Mounting to OVERLAY instead of the BACKGROUND surface to actually intercept the mouse is not a proper solution.
OVERLAY can't watch the cursor without also being the sole consumer. Sway would be unusable.
Uses wlr-layer-shell. No shell extension, and no install step.
- wayland
- wayland-protocols
On Arch Linux:
$ pacman -S wayland wayland-protocols$ make build-swayWarning
COSMIC's IPC has no query for the compositor's global cursor position, so this portal can't support cursor-reactive wallpapers.
Uses wlr-layer-shell. No shell extension, and no install step.
- wayland
- wayland-protocols
On Arch Linux:
$ pacman -S wayland wayland-protocols$ make build-cosmicInterfaces with X11 directly. No shell extension, and no install step.
- libxcb (including its
xcb-dri3andxcb-shmextensions)
On Arch Linux:
$ pacman -S libxcb$ make build-i3wallpiperd has no persistent configuration, all variability is mutable through environment variables.
Which portal to use: hyprland, sway, cosmic, i3, gnome, kde
Default: auto-detected (~/.local/share/Steam, ~/.steam/steam, ~/.steam/root, or the Flatpak path)
Your Steam library root
Default: auto-detected under compatibilitytools.d/*/proton or steamapps/common/Proton */proton
Path to the proton binary to run Wallpaper Engine with
Default: $STEAM_ROOT/steamapps/common/wallpaper_engine/wallpaper64.exe
Path to Wallpaper Engine's executable
Default: /tmp/wallpiper
Directory used for ephemeral, session-scoped files (control sockets, the Vulkan capture layer's search path, tracked renderer PIDs)
Default: $XDG_STATE_HOME/wallpiper, or ~/.local/state/wallpiper
Directory used for state that should persist across reboots (e.g. the applied-DPI marker)
Default: unset (no scaling override)
Forces N scale factor on Wallpaper Engines properties-panel process. Not auto-detected.
Default: native
Controls how the Wallpaper Engine tray icon is translated: native, notray, passthrough
nativeoverorg.kde.StatusNotifierItem/dbusmenu(supports all portals)notrayno tray rendered at all.passthroughpushes a raw legacy XEmbed tray icon, which only appears if your desktop runs a legacy tray host.
wallpiperctl is a control process for the wallpiperd daemon, and wallpaper-engine.
usage: wallpiperctl <command>
daemon commands (require a running wallpiperd):
debug-on | debug-off
wallpaper engine commands:
pause | play | stop
next | prev | reset
mute | unmute | volume <0-100>
set <path|workshop-id> [monitor; int; 0-indexed]
prop <path|workshop-id> <name> <value> [monitor; int; 0-indexed]
list
standalone commands:
check-config
Likely an issue with your underling translation layer. Only GE-Proton-11 and Valve-Proton-11 have been tested working.
All users experiencing this issue fixed it upgrading to a later version of Proton.
Issues and pull requests are welcome. See CONTRIBUTING.md. If wallpiper is useful to you, a star helps others find it!
MIT see LICENSE.