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#
| Interface | Version | Notes |
|---|---|---|
wl_compositor | 6 | |
wl_subcompositor | 1 | |
wl_shm | 2 | ARGB8888 and XRGB8888 |
zwp_linux_dmabuf_v1 | 4 | single-plane linear ARGB/XRGB advertised |
wp_presentation | 2 | real DRM flip timestamps, see below |
xdg_wm_base | 6 | toplevels, popups, positioners |
zxdg_decoration_manager_v1 | 1 | server-side decorations |
zwlr_layer_shell_v1 | 5 | panels, docks, wallpapers, lock UIs |
zxdg_output_manager_v1 | 3 | |
wl_seat | 9 | pointer + keyboard capabilities |
wl_data_device_manager | 3 | clipboard and drag & drop |
zwp_primary_selection_device_manager_v1 | 1 | middle-click paste |
zwlr_data_control_manager_v1 | 2 | clipboard managers |
zwp_relative_pointer_manager_v1 | 1 | game input |
zwp_pointer_constraints_v1 | 1 | pointer lock and confine |
wp_tearing_control_manager_v1 | 1 | consulted for the fullscreen surface |
zwlr_screencopy_manager_v1 | 3 | shm buffers, full-frame damage |
ext_image_copy_capture_manager_v1 | 1 | plus output and toplevel capture sources, shm |
zwlr_foreign_toplevel_manager_v1 | 3 | taskbars; minimize/maximize are polite no-ops under tiling |
ext_foreign_toplevel_list_v1 | 1 | |
ext_idle_notifier_v1 | 1 | idle timers for lockers |
zwp_idle_inhibit_manager_v1 | 1 | inhibitors hold only while their window is actually visible |
ext_session_lock_manager_v1 | 1 | lock screens; survives a crashed locker |
xdg_activation_v1 | 1 | single-use short-lived tokens; a valid activate focuses the window and follows it to its workspace |
xwayland_shell_v1 | 1 | |
wl_output | 4 | per 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-tearingis on for the output, and the fullscreen surface asked for tearing (or a window rule granted itallow-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-cursoris set. - Display and input device hotplug are live over raw netlink; outputs tile left to right, one workspace visible per output.
burrow dpms-offblanks 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.