vwWayland × Vulkan

libvw · Wayland × Vulkan

Your desktop, drawn on the GPU.

vw builds bars, docks, notification centres, launchers, lock screens and ordinary windows. Describe a surface in C++ or Lua every frame; vw keeps state, animates it, and renders it with Vulkan compute.

One function per surface

No widget tree to keep in sync. The build function runs again after input, events and on its refresh interval; anything that must survive — scroll offsets, text fields, tweens — is keyed by id.

#include <vw/vw.hpp>

int main() {
  vw::App app([](vw::Ui& ui) {
    const bool playing = vw::mpris::available();
    ui.rectangle({.width = 220, .height = 56, .radius = 28,
                  .color = vw::rgb(0x263b4d)});
    ui.text({.text = playing ? "Now playing" : "Quiet",
             .font = "Roboto Flex", .size = 17,
             .color = vw::rgb(0xd2e5ff),
             .place = {.x = 24, .y = 17}});
    ui.surface({.anchor = vw::anchor::top, .margin = {12, 0, 0, 0}});
  });
  app.on_event(vw::mpris::event_fd(), vw::mpris::drain_events);
  return app.run();
}
Draws
Now playing

A layer surface anchored to the top edge, rebuilt whenever a media player changes.

How a frame happens

  1. 1Build

    Your function describes the whole surface through a Ui, from scratch.

  2. 2Scene

    Rectangles, shaped text, images and input regions, compared to the last one.

  3. 3Compute

    Vulkan compute shaders rasterise it, rounded corners and all, in scene order.

  4. 4Present

    A linear dma-buf goes to the compositor as a layer surface, window or lock.

What's in the box

Widgets, layout and motion, plus the services a shell needs — each one an event source the loop can wait on.

01InstallNix dev shell, CMake, clang.02Build a shellLayer surfaces, exclusive zones, click-through.03Script it in LuaHot-reloading configs, same widgets.