wayland-cxx-scanner
A code-generation tool and companion C++23 framework for the
Wayland display protocol. Given a Wayland
XML protocol definition it produces type-safe, zero-overhead C++23 headers that
replace the hand-written C bindings normally provided by wayland-scanner.
Features
Type-safe protocol bindings — CRTP proxy and resource classes with compile-time event/request dispatch (no
void*casts in user code).Multiple output modes — client C++ header, server C++ header, and C-compatible header from a single XML source.
C++ standard selection — generate code targeting C++17, C++20, or C++23 (
--stdflag).Header-only framework — the
wayland-cxxlibrary installs to${includedir}/wl/and requires no link-time dependencies of its own.WTL-style message maps —
BEGIN_EVENT_MAP/EVENT_HANDLER/END_EVENT_MAPmacros for concise event wiring.RAII everywhere —
WlPtr<T>(owning proxy wrapper),FdHandle(file descriptor),FileHandle(C FILE*),ScopeExit(scope guard).Keyboard repeat —
KeyboardHandler<App>provides full xkbcommon keymap processing with POSIX-timer-based key repeat out of the box.Client-side decorations — pluggable CSD framework with Cairo and GTK back-ends.
Strict quality gates — CI enforces
-Werror, clang-tidy, clang-format, and CodeQL on every push.
Getting Started
Prerequisites
Tool / Library |
Minimum |
Notes |
|---|---|---|
1.1 |
Build system |
|
C++23 compiler |
GCC 13+ / Clang 17+ |
|
— |
Auto-fetched via Meson wrap if missing |
|
wayland-client / wayland-server |
— |
Optional; required for examples |
— |
Optional; required for some tests and examples |
|
— |
Optional; required for tests (auto-fetched) |
|
— |
Optional; required for keyboard examples/tests |
|
3.x |
Optional; required for |
Ubuntu / Debian:
sudo apt install meson ninja-build libpugixml-dev \
libwayland-dev wayland-protocols libxkbcommon-dev \
libgtest-dev
Fedora:
sudo dnf install meson ninja-build pugixml-devel \
wayland-devel wayland-protocols-devel libxkbcommon-devel \
gtest-devel
Building
# Clone the repository
git clone https://github.com/jwinarske/wayland-cxx-scanner.git
cd wayland-cxx-scanner
# Configure (scanner only)
meson setup build
# Build
ninja -C build
Building with examples
Most examples require wayland-client, wayland-protocols, and their
protocol-specific dependencies (see the Examples table below).
# Configure with examples enabled
meson setup build -Dexamples=true
# Build everything
ninja -C build
# Or build a single example
ninja -C build examples/presentation-shm/presentation_shm
ninja -C build examples/sdl3-presentation-shm/sdl3_presentation_shm
Building with tests
meson setup build -Dtests=true
ninja -C build
meson test -C build
Installation
meson setup build --prefix=/usr/local
ninja -C build install
This installs:
wayland-cxx-scanner— the code-generation tool.${includedir}/wl/*.hpp— the framework headers.wayland-cxx.pc— pkg-config file for downstream consumers.
Usage
wayland-cxx-scanner [--mode=<mode>] [--std=<std>] <protocol.xml> [<output.hpp>]
Flag |
Values |
Default |
Description |
|---|---|---|---|
|
|
|
Kind of header to generate |
|
|
|
Target C++ standard |
If <output.hpp> is omitted the generated code is written to stdout.
Example: generate a client header from the XDG shell protocol
wayland-cxx-scanner \
--mode=client-header \
/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml \
xdg_shell_client.hpp
Meson integration
The scanner integrates into Meson builds with custom_target or generator.
Every example under examples/ demonstrates this pattern — see
examples/minimal/meson.build for the simplest
case.
Architecture
See ARCHITECTURE.md for the full design document. A brief overview follows.
Pipeline
┌──────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ protocol.xml │─────▶│ XML Parser │─────▶│ Intermediate │
│ (Wayland) │ │ (xml_parser) │ │ Representation │
└──────────────┘ └──────────────────┘ │ (ir.hpp) │
└────────┬────────────┘
│
┌──────────────────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ codegen_client │ │ codegen_server │ │ codegen_c │
│ _cxx │ │ _cxx │ │ │
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
│ │ │
▼ ▼ ▼
client proxy .hpp server resource .hpp C-style .h
Repository layout
wayland-cxx-scanner/
├── include/wl/ Framework headers (installed as wayland-cxx)
├── src/ Scanner tool source code
├── protocols/ Bundled Wayland XML protocol definitions
├── tests/ Unit and integration tests (Google Test)
├── examples/ Example Wayland client/server applications
├── subprojects/ Meson wrap files (pugixml, gtest)
├── scripts/ Developer tooling (format.sh)
└── meta-wayland-cxx-scanner/ Yocto / OpenEmbedded recipe
Framework headers (include/wl/)
Header |
Purpose |
|---|---|
|
Non-owning |
|
CRTP |
|
Server-side |
|
|
|
Owning |
|
|
|
|
|
RAII file descriptor wrapper |
|
|
|
|
|
|
|
|
|
Pre-built wl_interface tables for XDG shell |
|
XDG decoration protocol support |
|
Linux DMA-BUF protocol support |
|
AGL (Automotive Grade Linux) shell protocol support |
|
Client-side decoration plugin interface |
|
Fallback CSD implementation |
|
Cairo-based CSD implementation |
|
GTK-based CSD implementation |
|
Umbrella include for common framework headers |
Examples
All examples live under examples/ and are built when -Dexamples=true is
passed to meson setup (requires wayland-client and wayland-server).
Example |
Description |
Extra dependencies |
|---|---|---|
Client ↔ server roundtrip with a custom protocol |
— |
|
Print compositor globals and capabilities |
wayland-protocols (optional) |
|
Keyboard input handling with xkbcommon |
xkbcommon |
|
Animated EGL/GLES triangle |
EGL, GLESv2 |
|
Subsurface protocol demonstration |
EGL, GLESv2 |
|
Frame-timing feedback via |
wayland-protocols |
|
SDL3 window with |
SDL3, wayland-protocols |
|
AGL compositor integration |
wayland-protocols |
|
IVI shell integration |
wayland-protocols |
|
Client-side decorations (Cairo / GTK back-ends) |
cairo or gtk+-3.0 |
|
Vulkan rendering with DMA-BUF export |
Vulkan |
Testing
The project uses Google Test with automatic download via Meson wraps when the system package is not found.
meson setup build -Dtests=true
meson test -C build
Test suite
Category |
Tests |
Timeout |
|---|---|---|
Unit — scanner |
ir, xml_parser, name_transform, codegen_c, codegen_client_cxx, codegen_server_cxx, cli |
15–30 s |
Unit — framework |
raii, event_map, proxy, proxy_impl, resource_impl, client_helpers, display |
15 s |
Unit — protocols |
agl_shell, xdg_shell (optional), seat/keyboard (optional) |
15 s |
Integration |
roundtrip (client + server in forked processes) |
60 s |
Build Options
Option |
Type |
Default |
Description |
|---|---|---|---|
|
boolean |
|
Build and run unit/integration tests |
|
boolean |
|
Build example applications |
|
boolean |
|
Generate Doxygen HTML documentation |
Code Quality
clang-format
All C++ sources follow the Chromium
formatting style enforced by clang-format-19. Run locally:
scripts/format.sh # reformat in-place
scripts/format.sh --check # dry-run (CI mode)
clang-tidy
A comprehensive .clang-tidy configuration enables checks from bugprone-*,
cert-*, cppcoreguidelines-*, modernize-*, performance-*,
readability-*, and clang-analyzer-security.*. All findings are treated as
errors (WarningsAsErrors: '*').
CodeQL
GitHub’s CodeQL analysis runs on every push and pull request, and weekly on a
schedule. The security-extended and security-and-quality query suites are
enabled.
CI Matrix
Platform |
Compilers |
Workflow |
|---|---|---|
Ubuntu 24.04 |
GCC, Clang 19 |
|
Fedora (latest) |
GCC, Clang |
|
Ubuntu 24.04 |
clang-format-19, clang-tidy-19 |
|
Ubuntu 24.04 |
CodeQL (C/C++) |
|
Yocto / OpenEmbedded
A BitBake recipe is provided in meta-wayland-cxx-scanner/ for integration
into Yocto-based embedded Linux builds.
Contributing
Fork the repository and create a feature branch.
Run
scripts/format.shbefore committing.Ensure
meson test -C buildpasses with-Dtests=true.Open a pull request — CI will verify formatting, clang-tidy, CodeQL, and the full test suite.
License
MIT — Copyright © 2026 Joel Winarske