Skip to content

Drag-to-swap

Reorder windows by dragging. Drag one tiled window over another and they swap positions. This page focuses on drag-to-swap behavior and examples. For the complete list of configuration options, see Configuration overview.

Enabling

spoon.Shoji:configure({
drag_swap = true,
})

Options

OptionTypeDefaultDescription
drag_swapbooleanfalseEnable drag-to-swap
drag_min_distancenumber40Minimum drag distance (pixels)
drag_swap_sensitivitynumber0How early to trigger (0-1)
drag_enabled_layoutsstring[]{"tall"}Drag-swap layouts

How it works

  1. Start dragging a tiled window
  2. Drag crosses drag_min_distance threshold
  3. Drag enters another window’s area
  4. Windows swap positions in tile order
  5. Layout updates to reflect the new order

Before drag:

┌─────────────────────────────┬─────────────────────────────┐
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ 1 (drag) │ 2 │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘

After swap:

┌─────────────────────────────┬─────────────────────────────┐
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ 2 │ 1 (drop) │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘

Three-window example

Swapping affects tile order. Dragging window 1 onto window 3 swaps their positions in the order, causing the layout to reflow.

Before: Tile order is 1, 2, 3

┌─────────────────────────────┬─────────────────────────────┐
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ 2 │
│ │ │
│ 1 (drag) ├─────────────────────────────┤
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ 3 │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘

After: Tile order is 3, 2, 1

┌─────────────────────────────┬─────────────────────────────┐
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ 2 │
│ │ │
│ 3 ├─────────────────────────────┤
│ │ │
│ │ │
│ │ │
│ │ │
│ │ │
│ │ 1 (drop) │
│ │ │
│ │ │
│ │ │
└─────────────────────────────┴─────────────────────────────┘

Window 3 becomes master (first in order), window 2 stays second, and window 1 moves to third position.

Minimum distance

Prevents accidental swaps from small mouse movements:

spoon.Shoji:configure({
drag_swap = true,
drag_min_distance = 40, -- Must drag 40px before swap activates
})

Higher values require more deliberate dragging. Lower values feel more responsive but may trigger by accident.

Swap sensitivity

Controls when the swap triggers as drag enters another window:

  • 0 (default): Swap when drag reaches target window’s center
  • 0.5: Swap when 25% into the target window
  • 1: Swap immediately upon entering target window
spoon.Shoji:configure({
drag_swap = true,
drag_swap_sensitivity = 0.3, -- Swap at 35% into target window
})

Layout restrictions

Not all layouts work well with drag-swap. Specify which support it:

spoon.Shoji:configure({
drag_swap = true,
drag_enabled_layouts = { "tall", "wide", "grid" },
})

The floating layout is not supported (no fixed positions).

Full example

spoon.Shoji:configure({
drag_swap = true,
drag_min_distance = 30,
drag_swap_sensitivity = 0.2,
drag_enabled_layouts = { "tall", "wide", "bsp", "grid" },
})

Limitations

  • Single-space only (no cross-space dragging)
  • Cross-screen dragging not supported
  • Floating windows cannot participate
  • One swap per drag (release and drag again for multiple swaps)

Performance

Drag detection monitors mouse events, adding some overhead. Leave it disabled if not needed (drag_swap = false is the default).