Skip to content

Multi-Monitor

SamWM supports multiple monitors with per-output workspace assignment.

Basic Configuration

samwm.general({
    -- Enable multi-monitor support
    multi_monitor = true,
})

Output Configuration

Configure each monitor separately:

samwm.output("DP-1", {
    -- Resolution
    resolution = "1920x1080",

    -- Refresh rate
    refresh = 144,

    -- Position relative to other outputs
    position = { x = 0, y = 0 },

    -- Scale factor
    scale = 1.0,

    -- Transform
    transform = "normal", -- normal, 90, 180, 270, flipped-*

    -- Custom mode
    mode = "1920x1080@144",

    -- Enable/disable
    enabled = true,
})

Output Layout

-- Layout with two monitors side by side
samwm.output("DP-1", {
    position = { x = 0, y = 0 },
})

samwm.output("HDMI-1", {
    position = { x = 1920, y = 0 }, -- Next to DP-1
})

Per-Output Workspaces

Bind workspaces to specific outputs:

-- DP-1: Workspaces 1-5
samwm.output_workspace("DP-1", { 1, 2, 3, 4, 5 })

-- HDMI-1: Workspaces 6-10
samwm.output_workspace("HDMI-1", { 6, 7, 8, 9, 10 })

Automatic Assignment

samwm.general({
    -- Auto-assign new workspaces to current output
    auto_assign_workspace = true,

    -- Or: use per-output workspace pools
    workspace_pools = true,
})

Moving Between Monitors

-- Keybindings to move workspace between monitors
samwm.bind("SUPER+CONTROL", "right", "workspace move +1", "Next monitor")
samwm.bind("SUPER+CONTROL", "left", "workspace move -1", "Previous monitor")

-- Or move the focused window
samwm.bind("SUPER+SHIFT", "right", "window move +1", "Move window to next monitor")
samwm.bind("SUPER+SHIFT", "left", "window move -1", "Move window to prev monitor")

Movement Actions

Action Description
workspace move +1 Move workspace to next monitor
workspace move -1 Move workspace to prev monitor
window move +1 Move window to next monitor
window move -1 Move window to prev monitor
focus +1 Focus next monitor
focus -1 Focus previous monitor

Output Detection

SamWM automatically detects connected outputs on startup and when monitors are plugged/unplugged.

Hotplug Behavior

  • New monitor: Create output, show workspaces
  • Disconnected monitor: Move windows to remaining outputs
  • Resolution change: Auto-adjust layout

Workspace Assignment

Control which workspace appears on which monitor:

-- Default: all workspaces visible on all monitors (cloned)
-- Better: each workspace on one monitor

samwm.workspace_monitor(1, "DP-1")  -- WS 1 on DP-1
samwm.workspace_monitor(2, "HDMI-1") -- WS 2 on HDMI-1

-- Or use workspace groups
samwm.workspace_group("left", { 1, 3, 5, 7, 9 })
samwm.workspace_group("right", { 2, 4, 6, 8, 10 })

Keybindings for Monitor Control

-- Switch active monitor
samwm.bind("SUPER", "right", "focus output", "Focus right monitor")
samwm.bind("SUPER", "left", "focus output", "Focus left monitor")

-- Move workspace to active monitor
samwm.bind("SUPER+SHIFT", "right", "workspace move output", "Move workspace to right")

-- Mirror outputs
samwm.bind("SUPER", "M", "output mirror all", "Mirror all outputs")

Output Properties

Each output exposes properties:

local status = samwm.get_output("DP-1")
print(status.name)       -- "DP-1"
print(status.resolution)  -- "1920x1080"
print(status.position)   -- { x = 0, y = 0 }
print(status.scale)       -- 1.0
print(status.refresh)     -- 144
print(status.connected)   -- true

Per-Monitor Appearance

-- Different wallpaper per output
samwm.output("DP-1", {
    wallpaper = "~/.config/samwm/wallpaper1.png",
})

samwm.output("HDMI-1", {
    wallpaper = "~/.config/samwm/wallpaper2.png",
})

-- Different gaps per output
samwm.output("DP-1", {
    gaps = { top = 0, right = 0, bottom = 0, left = 0 },
})

samwm.output("HDMI-1", {
    gaps = { top = 30, right = 0, bottom = 0, left = 0 }, -- Waybar offset
})

EDID Configuration

Override monitor EDID for custom names:

samwm.output("DP-1", {
    edid = {
        vendor = "SAM",
        model = "U28R55",
        serial = "ABC123",
    }
})

Troubleshooting

Black screen on one monitor

  • Check if output is enabled in config
  • Verify cable connection
  • Try samwm-msg outputs to see detected outputs

Windows on wrong monitor

  • Check workspace assignment: samwm.workspace_monitor(ws, output)
  • Use window move +1 to relocate

Resolution not correct

  • Set explicit mode: mode = "1920x1080@144"
  • Check xrandr or wlr-randr for available modes