Vaporwall is an engine for rendering web-based live wallpapers directly onto the Linux desktop background using gtk4-layer-shell and WebKit6.
Vaporwall standardizes the way wallpapers read user configuration and theme colors (like Pywal). By adhering to this standard, your HTML wallpapers can dynamically adjust their frame rate, resolution, speeds, and colors in real-time without requiring a reload.
To make a wallpaper compliant, you simply need to listen for the vaporwall:update event on the window object.
Whenever vaporwall loads your wallpaper or whenever the user changes their Pywal colors, vaporwall will dispatch this event with the latest configuration.
<script>
let isInitialized = false;
let vaporConfig = null;
let vaporColors = null;
window.addEventListener('vaporwall:update', (e) => {
// 1. Save the new settings
vaporConfig = e.detail.config;
vaporColors = e.detail.colors;
// 2. Either initialize the app, or update it
if (!isInitialized) {
initApp();
isInitialized = true;
} else {
updateDynamicSettings();
}
});
function initApp() {
// Initialize your canvas, THREE.js scene, etc.
// Use `vaporConfig` for performance settings
// Use `vaporColors` for initial theme colors
}
function updateDynamicSettings() {
// Apply new colors to your materials and HTML elements
// This is called automatically when Pywal generates a new palette!
}
</script>The e.detail object contains two properties: config and colors.
This matches the ~/.config/vaporwall/vapor.conf INI file. It contains:
performance.fps_limit: The target frame rate (e.g.,30or60).performance.resolution_scale: How much to scale the canvas (e.g.0.25for quarter-resolution).performance.enable_shadows: A boolean determining if shadows should be cast.performance.enable_antialiasing: A boolean determining if AA should be used.performance.detail_level: A multiplier (e.g.,0.5) to reduce particle counts or geometry detail.wall_specific.speed_multiplier: A multiplier to speed up or slow down animations.monitor_data: Data injected automatically by the engine to allow wallpapers to span across multiple monitors. Includesmode("duplicate" or "span"), and view offsets (total_width,total_height,view_x,view_y,view_width,view_height).
This contains the color palette generated by Pywal (or defaults). The colors are formatted as integer values (e.g., 0xff007c) making them easy to plug straight into WebGL or Three.js!
background: The terminal background color.color1throughcolor7: The 7 primary accent colors from the current palette.
If the user configures mode = span in their vapor.conf, the engine will render the wallpaper across multiple monitors by spawning separate WebKit views. You can seamlessly support this in Three.js by applying the injected offsets:
if (vaporConfig.monitor_data && vaporConfig.monitor_data.mode === 'span') {
const md = vaporConfig.monitor_data;
// Set aspect ratio of the combined global scene
camera.aspect = md.total_width / md.total_height;
// Offset the camera frustum so this monitor only draws its specific slice
camera.setViewOffset(
md.total_width, md.total_height,
md.view_x, md.view_y,
md.view_width, md.view_height
);
} else {
// Normal single-monitor setup
camera.aspect = window.innerWidth / window.innerHeight;
camera.clearViewOffset();
}
camera.updateProjectionMatrix();Because vaporwall relies on injecting this event, your wallpaper might not load if you just open it in a normal web browser. You can simulate the engine by dispatching the event yourself after a short delay:
setTimeout(() => {
if (!isInitialized) {
window.dispatchEvent(new CustomEvent('vaporwall:update', {
detail: {
config: {
performance: { fps_limit: 60, resolution_scale: 1.0, enable_shadows: true, enable_antialiasing: true, detail_level: 1.0 },
wall_specific: { speed_multiplier: 1.0 },
monitor_data: { mode: "span", total_width: 1920, total_height: 1080, view_x: 0, view_y: 0, view_width: 1920, view_height: 1080 }
},
colors: {
background: 0x1a0b2e, color1: 0xff007c, color2: 0x00f3ff, color3: 0x39ff14,
color4: 0xffffff, color5: 0x9400d3, color6: 0xfcee0a, color7: 0xff003c
}
}
}));
}
}, 500);Place your .html files inside ~/.config/vaporwall/walls/.
You can configure vaporwall globally by editing ~/.config/vaporwall/vapor.conf. The engine will auto-generate this file on first launch.