contents

Features & protocols#

What a client finds when it connects to carrot 0.1.0. Every interface here is hand-implemented rather than pulled in from a compositor library.

Wayland globals#

InterfaceVersionNotes
wl_compositor6
wl_subcompositor1
wl_shm2ARGB8888 and XRGB8888
zwp_linux_dmabuf_v14single-plane linear ARGB/XRGB advertised
wp_presentation2real DRM flip timestamps, see below
xdg_wm_base6toplevels, popups, positioners
zxdg_decoration_manager_v11server-side decorations
zwlr_layer_shell_v15panels, docks, wallpapers, lock UIs
zxdg_output_manager_v13
wl_seat9pointer + keyboard capabilities
wl_data_device_manager3clipboard and drag & drop
zwp_primary_selection_device_manager_v11middle-click paste
zwlr_data_control_manager_v12clipboard managers
zwp_relative_pointer_manager_v11game input
zwp_pointer_constraints_v11pointer lock and confine
wp_tearing_control_manager_v11consulted for the fullscreen surface
zwlr_screencopy_manager_v13shm buffers, full-frame damage
ext_image_copy_capture_manager_v11plus output and toplevel capture sources, shm
zwlr_foreign_toplevel_manager_v13taskbars; minimize/maximize are polite no-ops under tiling
ext_foreign_toplevel_list_v11
ext_idle_notifier_v11idle timers for lockers
zwp_idle_inhibit_manager_v11inhibitors hold only while their window is actually visible
ext_session_lock_manager_v11lock screens; survives a crashed locker
xdg_activation_v11single-use short-lived tokens; a valid activate focuses the window and follows it to its workspace
xwayland_shell_v11
wl_output4per connector; reports scale 1

Not there yet, and clients cope by falling back: wp_fractional_scale_v1 and wp_viewporter (the internal coordinate model is ready for them), wp_linux_drm_syncobj (carrot extracts implicit dmabuf fences into the renderer internally instead), wp_cursor_shape, and touch input.

Presentation timing#

wp_presentation feedback reports the kernel's actual page-flip completion: hardware clock, hardware vblank sequence, and the mode's refresh period (reported as 0 under VRR, where no fixed period exists). Timestamps are never backfilled from a clock read after the fact, and frames shipped by an async tearing flip drop the vsync flag, so a frame-timing overlay can tell a torn frame from a synced one.

Screen sharing#

carrot is its own xdg-desktop-portal ScreenCast backend (v4), with the video stream delivered over a pure-Rust PipeWire client. OBS, browsers, and anything else speaking the portal can cast outputs, individual windows, or whole workspaces; hidden or off-screen sources keep streaming instead of freezing.

Consent works three ways: a restore token from a previous session skips the dialog entirely; a configured picker command (the screencast { picker } config key) presents your own chooser; with no picker, the next pointer click selects the cast target. Restore tokens live in the portal's permission store, so an app you approved keeps working across restarts. Windows marked no-capture by a window rule leave every capture path as an opaque black box.

XWayland#

XWayland starts lazily on the first X11 client and respawns if it dies. carrot scans displays :100 through :199 and manages X windows with its own built-in window manager; the clipboard bridges both directions between X and Wayland. Not yet: streamed INCR clipboard transfers (very large pastes from X apps are dropped) and the X11 drag-and-drop bridge.

Output behavior#

  • VRR is per output: off, always, or on-demand, which engages while a fullscreen window is up. The display has to report vrr_capable.
  • Tearing means async page flips, and they happen only when the kernel supports them, allow-tearing is on for the output, and the fullscreen surface asked for tearing (or a window rule granted it allow-tearing).
  • Direct scanout: a lone, mode-sized, opaque fullscreen dmabuf rides the primary plane as its own framebuffer, no compositor render in the path, with presentation feedback flagging the frame ZERO_COPY.
  • The cursor rides a hardware plane, so pointer motion bypasses rendering entirely. carrot composites the cursor instead on pipe-joined ultra-high-refresh modes and when software-cursor is set.
  • Display and input device hotplug are live over raw netlink; outputs tile left to right, one workspace visible per output.
  • burrow dpms-off blanks every output, and any input wakes them.

Eye candy#

Two layouts ship, the dwindle tree and the scrolling strip, and a workspace switches between them live, windows animating into their new places. The animation system covers window open, close, move, and resize (a crossfade of old content into new), workspace switches, the strip's scroll, layer surfaces, and border color (blended in OkLab); every kind takes a spring or an easing, custom bezier curves included, and the clock samples the predicted moment each frame reaches glass. Full tour on Animations.

The decoration pass is a family of single-quad SDF effects: rounded corners clip the window's own sampling, borders follow the radius as rings, drop shadows fall off by distance with the window's body cut out, and dim-inactive shades unfocused windows with an animated fade. Kawase blur draws from a cached backdrop pyramid (the background and bottom layers), re-baked only when the backdrop changes, handed out per window and per layer surface by rules, and maskable by the surface's own alpha. Rounding and shadows ship on in the default config, dim and blur are opt-in, and whatever is off costs nothing; the knobs live in decoration config.

Input#

Keyboard and pointer today, with per-device configuration, adaptive or flat acceleration, real per-device DPI normalization, pointer constraints and relative motion for games, and key repeat delivered through the standard client-side repeat_info path. Every event timestamp rides the monotonic clock (set on the device at open and VT resume), one base shared by real devices, synthetic events, and presentation feedback. carrot also runs an EIS server (LIBEI_SOCKET) so launchers, XTEST via XWayland, and remote-desktop tools can inject input through the same code path as real devices.