| subprojects | ||
| wlr-protocols | ||
| .gitignore | ||
| meson.build | ||
| README.md | ||
| tabbed-wlroots.c | ||
| xdg-decoration-client.h | ||
| xdg-decoration-protocol.c | ||
| xdg-shell-client.h | ||
| xdg-shell-protocol.c | ||
| xdg-shell-server.h | ||
tabbed-wlroots
A nested Wayland compositor (built on wlroots) that presents several client apps as tabs in a single window on the host Wayland compositor. Each command-line argument launches one tab.
Building
The project builds with Meson + Ninja. On most
distributions the non-wlroots dependencies are available in the standard
repositories; wlroots is used from the system where one is installed, and
otherwise is fetched and built automatically from a pinned source tarball
(subprojects/wlroots.wrap).
meson setup build
meson compile -C build
The resulting binary is build/tabbed-wlroots.
Debian / Ubuntu
sudo apt install build-essential meson ninja-build pkg-config \
libwayland-dev libwayland-bin wayland-protocols \
libwlroots-dev libxkbcommon-dev \
libegl1-mesa-dev libgles2-mesa-dev \
libpixman-1-dev libdisplay-info-dev libliftoff-dev libseat-dev
libwlroots-dev already satisfies the wlroots dependency on this platform.
Arch
sudo pacman -S base-devel meson ninja pkgconf wayland wayland-protocols \
wlroots xkbcommon mesa pixman
Fedora
sudo dnf install gcc meson ninja-build pkgconf-pkg-config \
wayland-devel wayland-protocols-devel wlroots-devel \
libxkbcommon-devel mesa-libEGL-devel mesa-libGLES-devel pixman-devel
When the system wlroots dep is missing / the fallback can't find one
The Meson setup searches for wlroots-0.19 then wlroots; if neither is
installed it builds the pinned 0.19.1 from subprojects/wlroots.wrap, which
only needs the wayland, wayland-protocols, xkbcommon and EGL/GLES2 dev
packages listed above. Optional wlroots features (Vulkan, X11, libinput,
etc.) are auto-detected and skipped when their build deps aren't present, so
a minimal install works too.
Usage
tabbed-wlroots <prog> [prog...]
Each <prog> is one shell command; quote it when it takes arguments, e.g.
tabbed-wlroots "foot -e htop" "firefox -no-remote".
Every argument starts a new tab. There is no tab-count limit. Client apps run
as children of tabbed-wlroots and connect to its private Wayland socket, so
DISPLAY is unset for them and their WAYLAND_DISPLAY points at the tabbed
compositor (clients are launched with the GDK and Qt Wayland backends forced).
Notes:
- An argument written bare (starting with
-) is taken as a tab launcher too (unless quoted); a warning is printed when it looks like a stray option. - Without any arguments a usage message is printed and the program exits.
- The client applications run inside the session, so closing their windows only closes their tab; closing the host tabbed-wlroots window, or sending SIGINT/SIGTERM, shuts the whole session down and kills all client children.
Key bindings
| Key | Action |
|---|---|
Ctrl+PageUp |
Previous tab (hold to keep cycling) |
Ctrl+PageDown |
Next tab (hold to keep cycling) |
F11 |
Toggle the host window fullscreen |
F9 |
Dump composed scene buffer to /tmp/scene_N.ppm |
F10 |
Dump host back buffer to /tmp/host_N.ppm |
The tab-cycling hotkey only emits a physical press for the first tab switch;
repeats are synthesized, so holding Ctrl+PageUp/PageDown keeps stepping
through tabs while any other key stops it.
Logging (TABBED_LOG)
Quiet by default: a plain launch prints nothing to the launching terminal
except fatal errors. Set TABBED_LOG before starting:
| Value | Meaning |
|---|---|
unset/0 |
Quiet. Only fatal errors are shown. |
1 |
Info. Status lines, dump summaries, host notes (e.g. socket). |
2 |
Debug. Adds a per-frame [diag] trace and EGL/render/import messages, and client stdout/stderr flows through. |
At debug level (2) client programs also inherit the launching terminal's
stdout/stderr instead of being silenced, which makes client errors visible.
Frame dumps (F9 / F10 / SIGUSR1 / TABBED_AUTODUMP)
The frame-dump keys, SIGUSR1, and TABBED_AUTODUMP all write raw P6
portable-pixmap files to /tmp regardless of the log level:
F9orSIGUSR1writes/tmp/scene_N.ppm— the composed scene (whatever tabbed-wlroots rendered for the host).F10orSIGUSR1writes/tmp/host_N.ppm— the host compositor's back buffer, so you can see what the host actually displayed.Nis an incrementing per-run counter; a singleSIGUSR1produces a matching scene/host pair.- With
TABBED_AUTODUMP(any value, e.g.TABBED_AUTODUMP=1), a scene and host dump are taken automatically once the first frame in which a client committed a CPU-readable (shared-memory) buffer — handy for capturing exactly what a newly launched client drew. - At
TABBED_LOG=2the diagnostic that detects the client's own shm buffer additionally writes that buffer to/tmp/client_N.ppm.