how-i-build

2026

LyricsLens

A synced lyrics overlay for Linux that stays on top of any window, reading what is playing from MPRIS.

LivePublicSole authorRustRust

Lyrics that follow the song, in a window that stays on top of whatever is on the screen — on a desktop where the window manager is the one that decides whether that is allowed.

Linux first, for a simple reason: here the hard part is the window, not the data. Finding out what is playing is just reading a property. Being able to stay on top of a fullscreen application is what really decides whether the idea works.

The protocol picks the toolkit

On Wayland, a client cannot simply choose where to put its window, or tell it to sit above another one. That is part of the protocol, and the compositor is the one making that call. So for an overlay that needs to stay visible over a fullscreen window, there is one specific path: wlr-layer-shell, a protocol that lets a surface be treated as a layer of the screen, instead of an ordinary window.

And then the toolkit choice gets a lot more specific: which toolkits can actually use this protocol from Rust today?

Two of them ended up out for reasons that were not a matter of preference. Slint is pure Rust and has a pleasant API, but it uses winit to draw, and winit does not implement layer-shell. There is a third-party solution, but the crate itself says it is not ready for production yet.

Qt with Kirigami did not fit either. There is no official Rust API for that path: the supported option uses cxx-qt together with CMake, while the interface is written in QML. That would put a second language and a second build system into the project.

Decision

gtk4-rs, with gtk4-layer-shell from the first commit, instead of leaving it as an option for later. That way the project stays in a single language, without node_modules, and with a binary that sits in the range of a few megabytes.

Trade-offs

  • Learning GTK4 is a real cost at the start, especially in the first few weeks.
  • The interface is built in Rust and Pango instead of CSS, so getting to a good visual finish takes longer.
  • Choosing wlr-layer-shell also limits the desktops. Mutter, used by GNOME, does not implement layer-shell and does not intend to. On GNOME, then, another path has to be worked out.
  • libadwaita would make the settings window a lot easier to build, but its background conflicts with the transparency the overlay needs. So it ends up making sense in one window, but not in the other.
  • The crates need to stay aligned on versions. When there is a mismatch, the error that shows up can be a fairly confusing type error, instead of simply saying the versions do not match.

References