Wayland Protocol Surface — margo vs niri vs Hyprland vs mango#
Last refreshed: 2026-05-21 Sources walked (all at that day's
HEAD): - margo — this repo (smithaydelegate_*!macros + hand-rolledGlobalDispatch). - niri26.4.0(4294948) — same smithay method. - Hyprland0.55.0(v0.55.0-55-g95d9ae2) —src/protocols/*.cpp+src/protocols/core/. - mango0.13.1(0.13.1-19-gda1e1ca) — wlrootswlr_*_create()call sites +protocols/*.xml.
This document is the source-of-truth audit of which Wayland protocols
each daily-driver compositor advertises. mango — the C/wlroots
(dwl-derived) compositor that margo is the Rust rewrite of — is
included so the comparison shows what margo gained, kept, and dropped
relative to its own origin. Maintained alongside road_map.md
§15.10; this file is the read-side reference for "what does each
compositor actually advertise."
Legend#
| Mark | Meaning |
|---|---|
| ✅ | shipped / advertised |
| ⚠️ | partial (e.g. read-only, no write-side; or reached via a different mechanism) |
| ❌ | not advertised |
Headline score#
Counted with each project's native method (delegate macros / protocol
files / wlr_*_create globals), core protocols included so the
numbers are comparable.
| Compositor | Protocols (approx.) | Stack | Note |
|---|---|---|---|
Hyprland 0.55.0 |
~67 | C++ (hand-rolled) | Widest surface — 61 protocol modules + 6 core, plus Hyprland-only extensions |
| margo | ~57 | Rust / smithay | Modern surface; passed niri and mango; pursuing Hyprland |
mango 0.13.1 |
~53 | C / wlroots | Broad-but-legacy: wlroots hands it everything for free |
niri 26.4.0 |
~41 | Rust / smithay | Tightest surface; deliberately minimal |
The headline story shifted this refresh: margo (~57) has overtaken its
own C ancestor mango (~53) after hand-rolling three protocols mango got
from wlroots — zwlr_foreign_toplevel_manager_v1 (write-side, P2),
ext_workspace_v1 (P5) and zwlr_virtual_pointer_manager_v1 (P7). margo
already led on the modern surface (HDR colour-management, content-type,
fifo/commit-timing, security-context, pointer-warp, xdg-dialog,
system-bell, toplevel-icon, toplevel-tag, xwayland-keyboard-grab) that
mango's wlroots base doesn't expose; closing the workspace / toplevel /
virtual-pointer gap puts it ahead outright. The three protocols still
unadvertised (output_power, tearing_control, drm_lease) are
blocked, not just deferred — see "remaining three gaps" below.
Core baseline — present in all four#
All four advertise these. No comparison table — assume ✅ everywhere.
wl_compositor/wl_subcompositor/wl_shm/wl_seat/wl_outputwp_viewporter,wp_presentation_time,wp_cursor_shape_v1,wp_fractional_scale_v1zwlr_layer_shell_v1xdg_shell,xdg_activation_v1,xdg_decoration_unstable_v1,xdg_foreign_v2linux_dmabuf_v1ext_session_lock_v1,ext_idle_notifier_v1,zwp_idle_inhibit_manager_v1wl_data_device,zwlr_data_control_manager_v1,ext_data_control_manager_v1,zwp_primary_selection_device_manager_v1zwp_pointer_constraints_v1,zwp_relative_pointer_manager_v1,zwp_pointer_gestures_v1zwp_text_input_manager_v3,zwp_input_method_manager_v2,zwp_virtual_keyboard_manager_v1zwp_tablet_manager_v2zwlr_gamma_control_manager_v1,zwlr_screencopy_manager_v1org_kde_kwin_server_decoration,wp_single_pixel_buffer_v1zwp_keyboard_shortcuts_inhibit_v1zwlr_output_manager_v1(output-management — read topology + apply scale/transform/position; all four ship it, was previously missing from this audit)
Modern protocol surface — where margo leads the pack#
These are the protocols that separate a current compositor from a legacy wlroots one. margo and Hyprland carry almost the full set; niri and mango each miss large chunks.
| Protocol | margo | niri | Hyprland | mango | Use case |
|---|---|---|---|---|---|
wp_color_management_v1 (HDR) |
✅ | ❌ | ✅ | ❌ | HDR / wide-gamut output |
linux_drm_syncobj_v1 (explicit sync) |
✅ | ❌ | ✅ | ✅ | Tear-free GPU sync, NVIDIA |
ext_image_copy_capture_v1 + capture-source |
✅ | ❌ | ✅ | ✅ | Modern screencast (replaces screencopy) |
xwayland_shell_v1 |
✅ | ⚠️ diff path | ✅ | ❌ | HiDPI XWayland scaling |
wp_content_type_v1 |
✅ | ❌ | ✅ | ❌ | Game / video / photo hint |
wp_fifo_v1 |
✅ | ❌ | ✅ | ❌ | FIFO commit ordering |
wp_commit_timing_v1 |
✅ | ❌ | ✅ | ❌ | Explicit commit-time targets |
wp_alpha_modifier_v1 |
✅ | ❌ | ✅ | ✅ | Per-surface alpha hint |
xdg_wm_dialog_v1 |
✅ | ❌ | ✅ | ❌ | Modal dialog hint |
xdg_system_bell_v1 |
✅ | ❌ | ✅ | ❌ | System bell |
wp_pointer_warp_v1 |
✅ | ❌ | ✅ | ❌ | Programmatic cursor warp |
wp_security_context_v1 |
✅ | ✅ | ✅ | ❌ | Flatpak / sandboxed clients |
margo's unique / near-unique protocols#
| Protocol | margo | niri | Hyprland | mango | Note |
|---|---|---|---|---|---|
zwp_xwayland_keyboard_grab_v1 |
✅ | ❌ | ❌ | ❌ | margo unique — X11-side kb grab for VNC/VM/remote |
xdg_toplevel_icon_v1 |
✅ | ❌ | ❌ | ❌ | margo unique — inline app icons on toplevels |
xdg_toplevel_tag_v1 |
✅ | ❌ | ✅ | ❌ | Semantic toplevel tags (Hyprland ships XDGTag too) |
Correction this refresh:
xdg_toplevel_tag_v1is no longer margo-unique — Hyprland 0.55 ships it asXDGTag.cpp. The previous "margo unique vs both niri and Hyprland" claim was stale. Onlyxwayland_keyboard_grabandxdg_toplevel_iconremain unique to margo across all four.
Recently shipped — the wlroots-freebie catch-up (P2 / P5 / P7)#
Three protocols mango/Hyprland get for free from wlroots, hand-rolled in margo (ported from niri) so it no longer trails on them:
| Protocol | margo | niri | Hyprland | mango | What it unlocks |
|---|---|---|---|---|---|
zwlr_foreign_toplevel_manager_v1 (write-side) |
✅ | ✅ | ✅ | ✅ | Taskbar click-to-activate / close / (un)fullscreen (mshell active-window pill) |
ext_workspace_v1 |
✅ | ✅ | ✅ | ✅ | Workspace state for shells that don't speak dwl-ipc (sfwbar, ironbar) |
zwlr_virtual_pointer_manager_v1 |
✅ | ✅ | ✅ | ✅ | Synthetic pointer — wtype --click, remote desktop, accessibility |
margo's foreign-toplevel write-side runs alongside the existing
smithay ext-foreign-toplevel-list-v1 (read side stays untouched).
ext_workspace_v1 maps each output to a workspace group with 9 fixed
tag-workspaces (active = bitmask membership); dwl-ipc still runs in
parallel. virtual_pointer feeds margo's normal input path.
The remaining three gaps — blocked, not just deferred#
These three are not a matter of effort — each hits a concrete upstream or architectural wall (confirmed by source audit 2026-05-21):
| Protocol | margo | niri | Hyprland | mango | Why margo can't ship it cleanly today |
|---|---|---|---|---|---|
zwlr_output_power_management_v1 |
❌ | ❌ | ✅ | ✅ | Doable via margo's deferred-queue pattern, but DPMS off/on is an untested DRM-path change with a black-screen failure mode — needs on-hardware iteration |
wp_tearing_control_v1 |
❌ | ❌ | ✅ | ✅ | Upstream-blocked: smithay's DrmCompositor exposes no tearing / async page-flip (FrameFlags has no tearing variant) and the wp_tearing_control bindings aren't in the pinned wayland-protocols. Advertising it would be a no-op lie to clients |
wp_drm_lease_device_v1 |
❌ | ✅ | ✅ | ✅ | Architecture-blocked: lease_request must synchronously build a DrmLeaseBuilder from the live DrmDevice, which lives in the udev BackendData that MargoState deliberately cannot reach (the deferred-queue pattern can't help — the return is synchronous) |
Both niri and margo lack output_power + tearing; only drm_lease
is something niri has that margo doesn't. None blocks daily-driver use.
Compositor-specific protocols (informational, not gaps)#
Tied to each project's own ecosystem; not counted as margo gaps.
| Protocol | Who | What it does |
|---|---|---|
focus_grab |
Hyprland | Internal grab semantics |
global_shortcuts |
Hyprland | xdg-desktop-portal global-shortcuts helper |
toplevel_export / toplevel_mapping |
Hyprland | Hyprland-flavored toplevel export |
hyprland_surface |
Hyprland | Rounding / opacity surface hints |
CTM_control |
Hyprland | Color-transform-matrix (pre-wp_color_management) |
mesa_drm |
Hyprland | Compat shim for older mesa |
background_effect |
niri and Hyprland | Surface blur / effect extension |
mutter_x11_interop |
niri | XWayland tweak inherited from mutter |
xdg_output_v1 (legacy) |
Hyprland and mango | Pre-wl_output v4 HiDPI workaround |
zwlr_export_dmabuf_manager_v1 |
mango only | Legacy wlroots screencast (superseded by image-copy-capture) |
Unblocking the remaining three#
Each needs a prerequisite, not just a coding session:
zwlr_output_power_management_v1— implementable now via margo's deferred-queue pattern (pending_output_mode_changesis the model), but the DPMS apply needs on-hardware iteration before it's safe to ship — a wrong re-enable path black-screens the output.wp_tearing_control_v1— wait for smithay'sDrmCompositorto expose tearing / async page-flip (FrameFlags variant). Until then any advertisement is a no-op. Track upstream smithay.wp_drm_lease_device_v1— needsMargoStateto reach the udevDrmDevicesynchronously (a small backend-access change to the deliberate State/BackendData split). Lowest value (VR / leased connectors), so lowest priority.
See road_map.md §15.10 for the full work log and blocker analysis.