Layout
Tiling layout, special workspace, gaps, and window borders.
These blocks shape how tiled windows are arranged and drawn: the master/stack split, special workspace overlay, spacing between windows, and borders around them.
sweets.layout{ ... }
Controls tiling behavior and the layout new workspaces start in.
sweets.layout {
master = 50,
new_window = "master",
reorder_ratio = 0.1,
default = "tile",
master_position = "left",
cycle = { "tile", "monocle", "dwindle" },
}| Key | Type | Default | Description |
|---|---|---|---|
master | int | 50 | Master size, 1–99 percent (starting value; adjustable at runtime) |
new_window | string | master | Placement of a newly opened window: master or stack |
reorder_ratio | number | 0.1 | Drag-to-reorder threshold, 0.1–0.9 |
default | string | tile | Layout new workspaces start in: tile, monocle, dwindle, centered, grid, columns, deck, or tabbed |
master_position | string | left | Side the master area sits on: left, right, top, or bottom |
cycle | array | all layouts | Ordered set of layout names the cycle_layout action steps through |
Layouts
Each workspace has its own layout, so different workspaces (and the special
workspace) can use different arrangements at the same time. New workspaces start
in default; change a workspace's layout at runtime with the layout and
cycle_layout actions (see Key bindings).
tile— master/stack: one master area beside the stack. This is the layout themaster,new_window,reorder_ratio,master_position, drag-reorder, and keyboard-resize controls below apply to.monocle— every window fills the whole usable area and only the focused one is shown, like a stack of full-screen cards. Switching focus (focus_next/focus_prev) brings the next window to the front. The master/stack split and resize controls do nothing in monocle; gaps and borders still apply.dwindle— fibonacci split: each new window halves the remaining space, alternating between a vertical and a horizontal cut, so windows spiral inward. The first window takes the left column, the next the top of what's left, and so on. Every window stays visible. The first split honors themasterpercentage, so the horizontal resize controls (resize_grow/resize_shrink) widen and narrow the master column just like intile. The vertical resize controls resize the divider the focused window borders, at any depth — horizontal actions (resize_grow/resize_shrink) move the vertical divider beside it, vertical actions (resize_grow_vertical/resize_shrink_vertical) the horizontal one. Resizing a deep window adjusts its own split, not the master. The pointer (MOD+right-drag) works the same way and additionally lets a corner drag move both dividers at once. Each split remembers its own ratio. Gaps and borders apply throughout.centered— centered master: the master window sits in a centered column taking themasterpercentage of the width, with stack windows split into a left and a right column on either side. New stack windows alternate right, left, right, left… so the side columns stay balanced. Within each column windows stack top to bottom, evenly by default. With one window the master fills the area; with two it degrades to a plain two-column split (master beside a single stack). Best on wide and 4K displays. Every window stays visible. The horizontal resize controls (resize_grow/resize_shrink) widen and narrow the master column like intile, and aMOD+right-drag on the edge a window shares with the master resizes it with the pointer (the dragged edge tracks the cursor as the master grows symmetrically). The vertical resize controls (resize_grow_vertical/resize_shrink_vertical) and aMOD+right-drag on the top or bottom edge of a side-column window resize it against its neighbor in that column, so each column's heights are adjustable independently.master_positionis ignored (always horizontal-centered). Gaps and borders apply throughout.grid— even grid: windows fill a grid of roughlyceil(sqrt(n))columns, row by row, every window the same size. When the last row is short its windows stretch to fill the full width, so the grid always reaches every edge with no leftover gap. Best when you have several equally important windows. AMOD+right-drag resizes cells against their neighbors: a left or right edge moves the column divider between the window and its row neighbor, a top or bottom edge moves the shared divider between that row and the adjacent one, and a corner drag moves both. The keyboard resize actions work too:resize_grow/resize_shrinkmove the focused cell's column divider (its right neighbor, or its left when it is last in the row) andresize_grow_vertical/resize_shrink_verticalmove the divider between its row and the one below (or above, for the bottom row), always enlarging or shrinking the focused cell. Thegrid_balanceaction resets every row and column back to even, undoing all resizing in one keystroke. There is no master, so the master/stack controls do nothing andmaster_positionis ignored; gaps and borders apply throughout.columns— equal-width columns: every window becomes a full-height column side by side, left to right in open order, each the same width by default (the last column takes any rounding remainder so the columns always reach both edges). Unlikegridit never wraps and unliketilethere is no master, so it stays a single band however many windows you open. Best on wide and 4K displays for a few side-by-side windows. Every window stays visible.master_positionreorients the band:left(default) andrightgive vertical columns side by side,topandbottomgive full-width rows stacked instead, and therightandbottomvariants reverse the open order so the first window sits at the far edge. Because columns only have two orientations,cycle_master_positiontoggles straight between columns and rows (one press per flip); use an explicitmaster_position "right"or"bottom"bind if you want the reversed order. Bands are resizable against their neighbor along the run axis: the resize controls (resize_grow/resize_shrinkfor columns,resize_grow_vertical/resize_shrink_verticalfor rows) grow and shrink the focused band against the next one (or the previous one when it is last), and aMOD+right-drag on the leading or trailing edge does the same with the pointer. Resizing across the other axis does nothing. There is no master, so the master/stack controls do nothing; gaps and borders apply throughout.deck— master plus a tabbed stack: the master takes its slot exactly liketile, but the whole stack shares one slot and only the focused stack window is shown, like a deck of cards behind the master. Opening more windows never shrinks the stack, so it stays readable however many you pile up. Switching focus (focus_next/focus_prev, or focusing a stack window directly) brings that window to the front of the stack; the master stays put. Themasterpercentage andmaster_positionplace the split just liketile, and the split resizes the same way: the resize controls (resize_grow/resize_shrinkalong the split axis) widen and narrow the master, and aMOD+right-drag on the master/stack divider does the same with the pointer. Because the stack is a single slot there is nothing to resize within it, so the cross-axis controls do nothing. Gaps and borders apply throughout.tabbed— sway/i3-style tabs: every window fills one slot below a tab strip along the top, and only the focused window is shown, likemonoclewith a title bar. The strip draws one tab per window with its title, the focused tab highlighted, so you can see everything open at a glance. Switching focus (focus_next/focus_prev, which walk the tabs in open order) brings the next window to the front and moves the highlight. You can also drive the strip with the pointer: left-click a tab to focus its window, middle-click a tab to close it, or scroll the wheel over the strip to cycle tabs (scroll down for the next tab).move_left/move_rightreorder the focused window within the strip. A tab whose window asks for attention is drawn in the urgent color until you focus it. Opening more windows never shrinks the visible window; tabs just get narrower. There is no master, so the master/stack and resize controls do nothing andmaster_positionis ignored. Style the strip withsweets.tabbar{ ... }below; gaps and borders apply throughout.
These actions are not bound by default. Bind them yourself, for example:
sweets.bind("MOD+e", "cycle_layout")
sweets.bind("MOD+t", "layout", "tile")
sweets.bind("MOD+w", "layout", "monocle")
sweets.bind("MOD+d", "layout", "dwindle")
sweets.bind("MOD+c", "layout", "centered")
sweets.bind("MOD+g", "layout", "grid")
sweets.bind("MOD+n", "layout", "columns")
sweets.bind("MOD+k", "layout", "deck")
sweets.bind("MOD+b", "layout", "tabbed")Cycling layouts
cycle_layout advances the active workspace to the next layout. By default it
walks every layout in the order listed above (tile → monocle → dwindle → …
→ tabbed → back to tile). Set cycle in sweets.layout{ ... } to restrict
and reorder that walk to just the layouts you use:
sweets.layout {
cycle = { "tile", "dwindle", "monocle" },
}Only the listed layouts take part, and the array order is the cycle order — so
this example steps tile → dwindle → monocle → back to tile. The list must
name at least one valid layout with no duplicates, or it is a config error that
keeps the last valid config active. The default layout and the explicit
layout action are independent of cycle; if the current workspace is on a
layout that is not in the list, cycling jumps to the first entry.
cycle_layout also takes an optional direction. The default is forward; pass
"prev" to step backward through the same set, which pairs well with a
Shift variant of the forward bind:
sweets.bind("MOD+w", "cycle_layout")
sweets.bind("MOD+Shift+w", "cycle_layout", "prev")Master position
master_position chooses which side of the screen the master area occupies.
left (default) and right keep a vertical stack beside the master column;
top and bottom rotate the layout so the master is a full-width row with the
stack tiled in a row across the remaining space. The master percentage applies
along the split axis either way (column width for left/right, row height for
top/bottom). The columns layout also honors it as an orientation control —
see its entry above — while the other layouts ignore it.
Master position is per-workspace, seeded from master_position. Change it at
runtime with the master_position and cycle_master_position actions (see
Key bindings). They are not bound by default:
sweets.bind("MOD+m", "cycle_master_position")
sweets.bind("MOD+Left", "master_position", "left")
sweets.bind("MOD+Right", "master_position", "right")
sweets.bind("MOD+Up", "master_position", "top")
sweets.bind("MOD+Down", "master_position", "bottom")new_window
Controls where a freshly opened window lands. master (dwm-style, default)
makes it the new master and pushes the old master into the stack, so the layout
reshuffles on every open. stack keeps the existing master untouched and
appends the window to the bottom of the stack (the first window on an empty
workspace is the master either way). An invalid value is a config error.
reorder_ratio
Tunes how far you must drag a tiled window (with MOD + left drag) before it
takes a neighbor's place on release. It is the fraction of the neighboring
window you must cross, measured from the edge you approach it from, so it behaves
the same in every direction regardless of the master split. Lower values reorder
sooner (a short drag is enough); higher values require dragging deeper into the
neighbor, which avoids accidental swaps. Out-of-range values are a config error.
Keyboard resizing
The default MOD+= and MOD+- bindings grow or shrink the focused tiled window
by changing the master/stack split in 5-percent steps. If the focused window is
the master, grow makes the master area larger; if it is in the stack, grow makes
the stack area larger.
MOD+Shift+= and MOD+Shift+- resize along the other axis instead, transferring
space between the focused stack window and an adjacent stack neighbor. The keypad
KP_Add and KP_Subtract bindings provide the same controls.
The two resize axes follow the master position: the resize key whose direction
matches the master/stack split adjusts the master size, and the cross-axis key
resizes the stack pair. With top/bottom master the vertical keys drive the
master split and the horizontal keys resize the stack. Stack resize has no effect
for the master or when there is only one stack window.
Special workspace
The special workspace shown by MOD+s tiles like ordinary workspaces and starts
in the same default layout and master_position. It is private compositor
state, not one of the numbered workspaces, and it appears as a dimmed overlay on
the active output. Its windows use the global sweets.gaps{ ... } values.
While it is open and focused, the layout actions (layout, cycle_layout,
master_position, cycle_master_position) and the resize controls act on the
special workspace, so it can hold its own arrangement independent of the numbered
workspace beneath it.
The special workspace stacks above regular windows and top-layer surfaces such as panels, but below overlay-layer surfaces. Launchers like rofi (which use the overlay layer by default) open in front of it and stay clickable while it is open; apps launched from them land on the special workspace.
sweets.special{ ... }
Controls the private special workspace overlay.
sweets.special {
dim = "#000000A6",
}| Key | Type | Default | Description |
|---|---|---|---|
dim | string | #000000A6 | Dimmer color behind special workspace windows, #RRGGBB[AA] |
The alpha channel controls the dim strength. For example, #00000080 is a
medium black dim, while #181825CC gives a stronger tinted overlay.
sweets.gaps{ ... }
Controls the spacing around tiled windows.
sweets.gaps {
inner = 8,
outer = 8,
smart = false,
}| Key | Type | Default | Description |
|---|---|---|---|
inner | int | 8 | Pixels between tiled windows, 0–4096 |
outer | int | 8 | Pixels between tiled windows and usable-area edges, 0–4096 |
smart | bool | false | Remove outer gaps when exactly one tiled window is visible |
Smart gaps count tiled windows on the active workspace. Floating windows do not affect the count. With one tiled window, only the outer margin is removed; with two or more, the configured inner and outer gaps apply normally.
sweets.border{ ... }
Controls the border drawn around each window.
sweets.border {
width = 2,
focused = "#C27AFF",
unfocused = "#333338",
urgent = "#F7768E",
}| Key | Type | Default | Description |
|---|---|---|---|
width | int | 2 | Window border thickness in pixels, 0–64 (0 disables) |
focused | string | #C27AFF | Border color of the focused window |
unfocused | string | #333338 | Border color of unfocused windows |
urgent | string | #F7768E | Border color of an unfocused window demanding attention |
A window demanding attention (an X11 window setting the ICCCM urgency hint or
_NET_WM_STATE_DEMANDS_ATTENTION) is drawn with the urgent color instead of
stealing focus. Focusing the window clears the state.
Colors are #RRGGBB or #RRGGBBAA hex (the # is optional); a missing alpha
is opaque.
sweets.tabbar{ ... }
Styles the tab strip drawn by the tabbed layout. It has no effect
on other layouts.
sweets.tabbar {
height = 24,
font = "Sans 10",
active_bg = "#C27AFF",
active_fg = "#FFFFFF",
inactive_bg = "#212127",
inactive_fg = "#B7B7C2",
urgent_bg = "#F7768E",
urgent_fg = "#FFFFFF",
}| Key | Type | Default | Description |
|---|---|---|---|
height | int | 24 | Tab strip height in pixels, 8–256 |
font | string | Sans 10 | Pango font description for tab titles |
active_bg | string | #C27AFF | Background of the focused tab |
active_fg | string | #FFFFFF | Title color of the focused tab |
inactive_bg | string | #212127 | Background of unfocused tabs |
inactive_fg | string | #B7B7C2 | Title color of unfocused tabs |
urgent_bg | string | #F7768E | Background of a tab whose window wants attention |
urgent_fg | string | #FFFFFF | Title color of an urgent tab |
Titles are ellipsized to fit their tab and rendered at the output scale, so
they stay crisp on HiDPI displays. If the usable area is too short to fit the
strip plus a window, the strip is dropped and the layout falls back to a plain
full-area stack. The urgent color applies to a background tab only; focusing it
clears the urgency, so the focused tab always uses active_*.
font is a Pango font description such as "JetBrains Mono 11" or
"Sans Bold 10". Colors are #RRGGBB or #RRGGBBAA hex (the # is
optional); a missing alpha is opaque.