Tiling & windows#
carrot ships two layouts: the dwindle tree, which is the default, and the scrolling strip. mode in the layout config sets what new workspaces start with, and the set-layout action flips the focused workspace live between "dwindle", "scrolling", or "toggle"; the windows re-tile with move animations carrying them to their new places. Each workspace keeps its own mode.
The dwindle tree#
Dwindle tiles with a binary split tree. Each new window splits the focused leaf in two, and the split direction is not stored anywhere: it is derived from the shape of the box being split, every time layout runs. A wide box splits side by side, a tall box splits top over bottom. Resize an output or close a neighbor and the tree re-derives, so layouts stay sensible instead of preserving stale directions.
gaps-in spaces windows from each other, gaps-out from the screen edge, and the border block draws the frames. All in layout.
Split ratios#
Every split holds a ratio. adjust-split-ratio "+0.1" (bind or IPC) walks up from the focused window to the nearest ancestor split along the matching axis and nudges it. Dragging a tiled window's edge with the mouse does the same thing: the drag is translated into a ratio change on exactly the right ancestor, so tiles resize the way free windows do.
Moving focus and windows#
focus-left/right/up/downpicks the candidate across the facing edge with the greatest perpendicular overlap, so diagonal neighbors resolve the way your eyes expect.swap-left/right/up/downtrades places: the two windows exchange leaves while the split geometry stays put, so nothing else in the layout jumps.focus-next/focus-prevcycle through the workspace in order.
Focus carries the pointer with it: it warps to the same relative spot in the new window when it was inside the old one, and to the center when it was somewhere else, so the mouse never gets orphaned on the wrong window. The warp fully no-ops while a game holds a pointer lock, so the drawn cursor never leaves the frozen one.
The scrolling strip#
mode "scrolling" swaps the tree for an endless sideways strip of columns. Every new window opens as its own column, just right of the focused one, at the configured default-width; nothing behind you gets squeezed, the strip just grows longer. Inside a column, windows stack vertically.
The directional actions turn column-aware: focus-left/right walk across columns while focus-up/down move within one. swap-left/right trade the focused window with the neighbor column's active window (the slots keep their widths and weights; only the windows cross), swap-up/down reorder within the column, and move-column-left/right leapfrog the whole column along the strip, stackmates and all. Closing a window you only just opened returns focus and view to where you were before it appeared.
Columns#
consume-or-expel-left/-right: a window alone in its column merges into the neighbor column on that side; a window sharing a column pops out into a fresh column on that side.cycle-column-widthandcycle-column-width-backstep the column through yourpreset-widthsladder (a third, a half, and two thirds by default).adjust-split-rationudges the column width freely, and dragging a side edge with the mouse pins an exact pixel width.toggle-full-widthflips the column to the whole screen and back to what it was.
The view#
The strip scrolls only as far as needed to keep the focused column on screen, and the scroll itself is animated: the strip slides under the windows (view-movement). center-focus "always" in the scrolling config centers the focused column on every move, "on-overflow" centers only when the previous and the current column cannot share the screen, and the center-column action centers on demand. A column wider than the screen aligns to its left edge.
One side effect reaches everywhere: while any workspace is scrolling, workspace switches slide vertically, because the strip owns the horizontal axis. All-dwindle sessions pick their own direction with workspace-axis. Details on Workspaces & monitors.
Animations#
Opens pop in, closes pop out (outliving the window: its last frame is captured and animated), moves are target-chasing motion, and the border color blends between focus states in OkLab. Every kind takes its own spring or easing, with custom bezier curves and styles; the full reference is the Animations page.
Floating#
toggle-floating is the only way a window floats; there are no auto-float heuristics. A newly floated window gets half the output, centered. Toggling back returns it to the layout: into the tree at the cursor position on a dwindle workspace, or as a new column beside the focused one on a scrolling workspace. Floats keep their own z-order (last raised on top), above tiled windows and below fullscreen, unless float-above-fullscreen flips that.
Window rules can start a window floating with a default-size and open-centered, or force tiling; see Window rules.
Interactive move & resize#
Every drag runs through one grab machine, whether it starts from a window's own decorations (the standard xdg_toplevel move and resize requests) or from the pointer-move and pointer-resize actions. Bound to a mouse chord (Mod+MouseLeft { pointer-move; }), the grab lives while the button is held; bound to a key, it lives while the key is held and ends on release. pointer-resize picks its edges from the quadrant the pointer starts in.
- Floating windows move freely and resize from any edge or corner, down to 50 px.
- Tiled windows edge-resize: on a dwindle workspace the drag becomes a split-ratio change on exactly the right ancestor, and on a scrolling workspace a side edge pins the column to a fixed pixel width while a top or bottom edge shifts height between the stacked windows.
- Dragging a tiled window swaps slots live: carry it over another tile and the two trade places on the spot, keep moving and it trades again. On dwindle this works across outputs, so a drag can carry a window to another monitor's workspace.
While a grab is held, the window tracks the pointer 1:1; move animations stay out of the way and take over again when the drag ends.
Fullscreen#
toggle-fullscreen puts the focused window fullscreen on its workspace, covering the whole output with no borders or gaps. A fullscreen window occludes the workspace, which also releases idle inhibitors of hidden windows, and it skips move and close animations, so nothing tweens over it. It owns the focus verbs too: directional and cycle focus stay put instead of wandering the buried pile beneath it.
Fullscreen is also where tearing, automatic VRR, and direct scanout engage.