← Otto Developer GuideWayland protocols

Otto follows Smithay’s “one big compositor state” architecture: nearly all protocol state and every handler hangs off a single struct, Otto<BackendData>. Learning where that struct is built, and how Smithay routes requests into it, makes the rest of the codebase navigable.

The big state: Otto<BackendData>

Otto<BackendData> lives in src/state/mod.rs and holds:

So self.xdg_shell_state or self.shm_state is one of those Smithay objects stored directly inside Otto. There is no separate protocol layer to look for.

Where it is initialized

Most globals are created in Otto::init(...) in src/state/mod.rs:

Backends create their own globals in their entrypoints — most notably zwp_linux_dmabuf_v1, which is per backend.

How delegation works

Smithay protocols are wired with delegate_* macros. The pattern is always the same three pieces:

  1. Otto stores the protocol state object (xdg_shell_state: XdgShellState).
  2. Otto implements the matching handler trait (impl XdgShellHandler for Otto<BackendData>).
  3. A delegate_* macro is invoked for Otto<BackendData>.

The macro generates the dispatch glue, so requests arriving for that global end up in your handler impl.

Finding a protocol

When you need to know where protocol X is implemented:

  1. Grep for the delegate macrodelegate_xdg_shell!, delegate_layer_shell!, delegate_presentation!, …
  2. Find the handler implimpl<BackendData: Backend> XdgShellHandler for Otto<BackendData>
  3. Find where the state is constructed — usually Otto::init(...) in src/state/mod.rs; backend-specific globals (dmabuf) live in src/udev/, src/winit.rs, src/x11.rs.

Handlers are split roughly like this:

Common entrypoints

ProtocolHandlerState + delegation
wl_compositor / commitsCompositorHandler in src/shell/mod.rssrc/state/mod.rs
xdg_wm_baseXdgShellHandler in src/shell/xdg.rssrc/state/mod.rs
zwlr_layer_shell_v1WlrLayerShellHandler in src/shell/mod.rssrc/state/mod.rs
wl_seatsrc/state/seat_handler.rsseat wiring in Otto::init
wl_data_device_managersrc/state/data_device_handler.rs
primary selection, data controlsrc/state/selection_handler.rs
wp_presentationfeedback emitted in post_repaint / take_presentation_feedbacksrc/state/mod.rs
zwp_linux_dmabuf_v1impl DmabufHandler per backendsrc/udev/, src/winit.rs, src/x11.rs
ext_session_lock_v1src/state/session_lock_handler.rs, src/lock.rs
zwlr_screencopy_manager_v1src/state/screencopy.rs
foreign toplevel (both protocols)src/state/foreign_toplevel_list_handler.rs, src/state/wlr_foreign_toplevel.rssee foreign-toplevel.md
ext_background_effect_manager_v1src/background_effect.rsStandard blur-behind; maps onto the same BackgroundBlur layer path as otto-surface-style. See specs/background-effect.md

Otto’s own protocols

Three protocols are Otto-specific. Their XML lives in protocols/:

ProtocolImplementationWhat it does
otto-surface-style-unstable-v1src/surface_style/Lets a client style and animate its own surface through the compositor’s scene graph — corner radius, shadow, opacity, transforms, batched in transactions. See sc-layer-protocol-design.md for the design history.
otto-dock-v1src/otto_dock/Lets a client contribute items to the compositor-drawn dock
wlr-gamma-control-unstable-v1src/state/gamma_control.rsGamma ramps, used for night shift

protocols/sc-layer-v1.xml is the ancestor of otto-surface-style and is no longer implemented; only stale comments still say sc_layer.