Add wlgrid: a window-thumbnail grid overlay for wlroots

A switcher to replace a wlthumbs + rofi pipeline, with the same look
(gruvbox, ceil(sqrt(n)) columns capped at 4, 16:9 tiles, a yellow
selection filling the element padding) but no thumbnails anywhere.

Each window is captured straight into a wl_shm buffer that is handed to
its own wl_subsurface, with wp_viewporter giving the compositor the
rectangle to scale it into. So there is no PNG encode, no scaler, no
full-resolution bitmap in this process, and the capture buffers are never
even mapped here — the compositor writes those pages and samples them
again for display. Opens in ~65ms for 8 windows (55ms of which is the
compositor reading pixels back out of the GPU) and holds ~9MB of RSS.

All capture sessions are opened before a single roundtrip and every frame
goes in flight together, the same batching wlthumbs uses, because the
readback is bandwidth-bound rather than latency-bound.

sway remains the source of truth: the window list, the con_ids and the
focusing all come from its IPC socket, joined to the Wayland side by
foreign_toplevel_identifier. Navigation reads raw evdev keycodes so it is
layout-independent, which does mean virtual-keyboard clients that invent
their own keymap can't drive it; that resolves when filtering brings xkb.

Labels, type-to-filter and live previews are next.
This commit is contained in:
Milad Alizadeh
2026-08-23 10:07:09 +01:00
commit dbfc06519a
8 changed files with 1662 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
[package]
name = "wlgrid"
version = "0.1.0"
edition = "2024"
description = "Live window switcher for wlroots compositors: a thumbnail grid with the look of a rofi theme"
license = "MIT"
[dependencies]
wayland-client = "0.31"
wayland-protocols = { version = "0.32", features = ["client", "staging"] }
wayland-protocols-wlr = { version = "0.3", features = ["client"] }
memmap2 = "0.9"
rustix = { version = "1", features = ["fs", "mm", "shm"] }
swayipc = "4"
[profile.release]
strip = true