Skip to content

BSP (binary space partitioning)

Recursively splits the screen in half, creating a balanced tree of windows. Each split alternates direction: vertical, then horizontal, then vertical again. Unlike Tall and Wide, BSP has no main window. Every window can be resized individually.

┌───────────────────────────────────────────────────────────┐
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ 1 │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
└───────────────────────────────────────────────────────────┘
┌─────────────────────────────┬─────────────────────────────┐
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ 1 │ 2 │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘
┌─────────────────────────────┬─────────────────────────────┐
│ │ │
│ │ │
│ │ │
│ 1 │ │
│ │ │
│ │ │
│ │ │
│ │ 3 │
├─────────────────────────────┤ │
│ │ │
│ │ │
│ │ │
│ 2 │ │
│ │ │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘
┌─────────────────────────────┬─────────────────────────────┐
│ │ │
│ │ │
│ │ │
│ 1 │ 3 │
│ │ │
│ │ │
│ │ │
│ │ │
├─────────────────────────────┼─────────────────────────────┤
│ │ │
│ │ │
│ │ │
│ 2 │ 4 │
│ │ │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘
┌──────────────┬──────────────┬─────────────────────────────┐
│ │ │ │
│ │ │ │
│ │ │ │
│ 1 │ 2 │ 4 │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
├──────────────┴──────────────┼─────────────────────────────┤
│ │ │
│ │ │
│ │ │
│ 3 │ 5 │
│ │ │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘

Each new window splits an existing space in half, alternating direction at each tree level.

  • Adjustable ratio: No (use per-window resize instead)
  • Adjustable main count: No (no main area concept)
  • Per-window resize: Yes
  • Stateful: Yes - remembers custom ratios

BSP provides resize actions that adjust individual splits:

spoon.Shoji:bindHotkeys({
bsp_shrink_horizontal = { { "ctrl", "cmd" }, "h" },
bsp_expand_horizontal = { { "ctrl", "cmd" }, "l" },
bsp_shrink_vertical = { { "ctrl", "cmd" }, "k" },
bsp_expand_vertical = { { "ctrl", "cmd" }, "j" },
bsp_rotate = { { "ctrl", "cmd" }, "r" },
})

Resize the split containing the focused window:

Before (window 1 focused):

┌─────────────────────────────┬─────────────────────────────┐
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ 1 │ 2 │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘

After expand_horizontal:

┌─────────────────────────────────────────┬─────────────────┐
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ 1 │ 2 │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
└─────────────────────────────────────────┴─────────────────┘

Flip all splits 90 degrees:

Before:

┌─────────────────────────────┬─────────────────────────────┐
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ 1 │ 2 │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘

After:

┌───────────────────────────────────────────────────────────┐
│ │
│ │
│ │
│ 1 │
│ │
│ │
│ │
│ │
├───────────────────────────────────────────────────────────┤
│ │
│ │
│ │
│ 2 │
│ │
│ │
│ │
│ │
└───────────────────────────────────────────────────────────┘

Each split in the BSP tree has an independent ratio (default 0.5, meaning equal halves). The resize actions adjust the nearest split in the specified direction:

Action Effect
bsp_expand_horizontal Increase width of focused window’s vertical split by 0.05
bsp_shrink_horizontal Decrease width of focused window’s vertical split by 0.05
bsp_expand_vertical Increase height of focused window’s horizontal split by 0.05
bsp_shrink_vertical Decrease height of focused window’s horizontal split by 0.05
bsp_rotate Swap all horizontal splits to vertical and vice versa

To reset all split ratios to 0.5, use reset_space (Ctrl+Alt+Shift+0). This clears the BSP tree state and rebuilds it from scratch.

See BSP layout actions for hotkey bindings.

BSP remembers custom split ratios. This state persists:

  • Across retiles within the same macOS Space
  • When switching away and back to the macOS Space
  • When cycling to other layouts and returning

The algorithm builds a binary tree:

  1. First split (depth 0): Left-right (vertical divider)
  2. Second split (depth 1): Top-bottom (horizontal divider)
  3. Third split (depth 2): Left-right again
  4. And so on…

Windows distribute evenly between subtrees, creating balanced layouts regardless of window count.

BSP shines when:

  • Managing many windows (5+) that all need visibility
  • Window importance shifts during work (no fixed main window)
  • Fine-grained control over individual window sizes is needed
  • A symmetric, balanced layout is preferred
Aspect BSP Tall
Main window None Yes (left side)
Resize scope Individual splits Global ratio
State Per-window ratios Stateless
Best for Many equal windows Primary + supporting