Skip to content

Layouts

SamWM supports multiple tiling layout algorithms, configurable per-workspace.

Built-in Layouts

master-stack

Classic master-stack tiling. The first N windows occupy the master area on the left; remaining windows stack vertically on the right.

+----------+------+
|          |  2   |
|   1      |------|
| (master) |  3   |
|          |------|
|          |  4   |
+----------+------+

Configurable via:

  • layout.master_factor — Master area width ratio (0.0–1.0, default 0.55)
  • layout.master_count — Number of master windows (default 1)

dwindle

Hyprland-inspired dwindle layout. Windows recursively split into halves, alternating horizontal and vertical. The most recent window gets a larger portion.

+-------+------+
|       |  2   |
|   1   +--+---+
|       |3 | 4 |
+--+----+--+---+
|5 | 6  |7 | 8 |
+--+----+--+---+

bsp

Binary Space Partitioning inspired by bspwm. Each window splits the available space recursively. Alternates between horizontal and vertical splits at each level.

+-------+-------+
|       |   3   |
|   1   +---+---+
|       | 4 | 5 |
+---+---+---+---+
| 2 | 6 | 7 | 8 |
+---+---+---+---+

columns

Niri-inspired scrollable column layout. Each window gets a full-height column. When columns exceed the output width, they scroll horizontally.

+----+----+----+----+
|    |    |    |    |
| 1  | 2  | 3  | 4  |← scrolls →
|    |    |    |    |
+----+----+----+----+

Column width defaults to output_width / min(window_count, 4), minimum 200px.

floating

No automatic tiling. Windows maintain their positions and sizes.

fullscreen

All windows rendered fullscreen, stacked. Only the focused window is visible.

Switching Layouts

Via Keybindings

SUPER+L  → dwindle
SUPER+T  → master-stack
SUPER+G  → bsp
SUPER+C  → columns

Via Lua Config

samwm.layout({ default = "dwindle" })

Runtime

samwm.switch_layout("bsp")

Custom Layouts via Lua

You can define entirely custom layout algorithms in Lua:

samwm.register_layout("my-layout", function(windows, bounds)
    local result = {}
    local count = 0
    for _, w in pairs(windows) do
        count = count + 1
    end

    local col_width = bounds.width / count
    local i = 0
    for _, w in pairs(windows) do
        table.insert(result, {
            id = w.id,
            x = bounds.x + i * col_width,
            y = bounds.y,
            width = col_width,
            height = bounds.height
        })
        i = i + 1
    end
    return result
end)

The layout function receives:

  • windows — Table of window objects with id, title, class, x, y, width, height
  • bounds — Output bounds with x, y, width, height

Must return a table of placement objects with id, x, y, width, height.

Smart Gaps

When layout.smart_gaps is enabled (default), gaps are disabled when only one window is visible on a workspace.

Gap Configuration

samwm.general({
    gaps_inner = 5,   -- Gap between windows
    gaps_outer = 10,  -- Gap between windows and screen edges
})