How to Set Up Multiple Monitors with Hyprland: A Complete Configuration Guide

Configure multiple displays in Hyprland by defining hl.monitor blocks in your ~/.config/hypr/hyprland.lua file, specifying output names, resolutions, positions, and scales to build your virtual desktop layout.

Setting up multiple monitors with Hyprland involves a sophisticated configuration pipeline that transforms Lua-based display rules into live Wayland monitor objects. According to the hyprwm/Hyprland source code, the compositor processes your monitor declarations through a dedicated parsing and layout system, allowing precise control over multi-display arrangements ranging from simple laptop-plus-external setups to complex multi-head workstations.

How Hyprland Processes Monitor Configuration

When Hyprland initializes, it reads your configuration file and processes each hl.monitor declaration through a specialized architecture designed to validate rules and compute final display positions.

Parsing and Rule Validation

The monitor rule parser (src/config/shared/monitor/Parser.hpp) handles the initial configuration reading. This component, implemented in CMonitorRuleParser, validates fields such as output, mode, position, scale, and transform. It converts string values like "1920x1080@60" into internal CMode structures and resolves output identifiers (e.g., "DP-1").

Rule Collection and Management

After parsing, the monitor rule manager (src/config/shared/monitor/MonitorRuleManager.cpp) collects all CMonitorRule objects into a registry. This manager supports advanced features including monitor mirroring and disabling specific outputs, providing lookup utilities that the compositor queries during initialization.

Runtime State and Layout Calculation

The monitor state tracker (src/state/MonitorStateTracker.cpp) iterates over the stored rules to instantiate live CMonitor objects. Once these objects exist, the monitor layout controller (src/state/MonitorLayoutController.cpp) calculates final positions using either explicit coordinates or automatic placement keywords, applying scaling and transformations to complete the virtual desktop arrangement.

Basic Two-Monitor Setup

For a typical laptop with an external display, use automatic placement keywords to position the secondary monitor relative to the primary.

-- Primary monitor (built-in laptop display)
hl.monitor({
    output   = "eDP-1",
    mode     = "1920x1080@60",
    position = "auto",
    scale    = "1",
})

-- Secondary monitor (external display to the right)
hl.monitor({
    output   = "DP-1",
    mode     = "2560x1440@144",
    position = "auto-right",
    scale    = "1.5",
})

The auto-right keyword instructs MonitorLayoutController to place this display immediately to the right of the previously configured monitor, creating a seamless extended desktop.

Advanced Layout Strategies

Explicit Coordinate Positioning

For precise control over complex arrangements, specify exact pixel coordinates ("x y") relative to the origin (0,0):

-- Left ultrawide monitor
hl.monitor({
    output   = "HDMI-A-1",
    mode     = "3440x1440@100",
    position = "0 0",
    scale    = "auto",
})

-- Center monitor (positioned at the right edge of the left monitor)
hl.monitor({
    output   = "DP-1",
    mode     = "2560x1440@144",
    position = "3440 0",
    scale    = "auto",
})

-- Right monitor (continuing the horizontal span)
hl.monitor({
    output   = "DP-2",
    mode     = "1920x1080@60",
    position = "6000 0",
    scale    = "auto",
})

This configuration creates a 10,960-pixel wide workspace where MonitorLayoutController respects your exact positioning without automatic adjustments.

Automatic Placement Keywords

Hyprland supports several placement directives for dynamic layouts:

  • auto – Places the monitor at the first available space (typically used for the primary display)
  • auto-left – Positions to the left of the previously placed monitor
  • auto-right – Positions to the right (ideal for standard dual-monitor setups)
  • auto-up – Places above the previous monitor
  • auto-down – Places below the previous monitor

Disabling Unused Outputs

To ignore a specific output (useful for handling disconnected docks or disabling broken panels), set the disabled flag:

hl.monitor({
    output   = "DP-3",
    disabled = true,
})

This rule is processed by CMonitorRuleParser::setDisabled(), which excludes the monitor from the active list during state creation.

Mirroring Displays

Clone one monitor's output to another device using the mirror field:

-- Primary display
hl.monitor({
    output   = "DP-1",
    mode     = "1920x1080@60",
    position = "auto",
})

-- Mirrored display (shows identical content to DP-1)
hl.monitor({
    output   = "HDMI-A-1",
    mirror   = "DP-1",
})

The CMonitorRuleParser::setMirror() function links the secondary framebuffer to the primary output, implemented in src/config/shared/monitor/MonitorRule.hpp.

Organizing Your Configuration

For maintainability, split monitor definitions into separate Lua files and require them in your main configuration:

-- In ~/.config/hypr/monitors.lua
hl.monitor({ output = "eDP-1", mode = "preferred", position = "auto", scale = "auto" })
hl.monitor({ output = "DP-1", mode = "2560x1440@144", position = "auto-right", scale = "1.25" })

-- In ~/.config/hypr/hyprland.lua
require("monitors")

Because MonitorRuleManager processes hl.monitor calls in the order they appear, loading external files preserves your intended placement sequence while keeping your main configuration file clean.

Summary

  • Configuration Location: Define monitors in ~/.config/hypr/hyprland.lua using the hl.monitor Lua API.
  • Core Components: The system uses CMonitorRuleParser (validation), MonitorRuleManager (storage), and MonitorLayoutController (position calculation).
  • Positioning Options: Use "x y" for explicit coordinates or auto-* keywords for relative placement.
  • Advanced Features: Disable outputs with disabled = true or clone displays using the mirror field referencing another output name.
  • Scaling: Set scale to "auto" for DPI detection or specific values like "1.5" for high-DPI displays.

Frequently Asked Questions

How do I find the correct output name for my monitor?

Hyprland uses the names reported by the underlying Wayland backend (typically matching wlr-randr or xrandr output). Common prefixes include eDP-1 for internal laptop panels, DP- for DisplayPort connections, and HDMI-A- for HDMI ports. Run hyprctl monitors from a terminal to list currently detected outputs and their names.

Can I use automatic scaling instead of fixed values?

Yes. Set scale = "auto" in your hl.monitor block to let Hyprland automatically detect and apply the appropriate DPI scaling based on the monitor's physical dimensions and resolution. This is handled during the layout calculation phase in MonitorLayoutController.

What happens if I disconnect a monitor configured with explicit coordinates?

If a monitor defined with explicit position coordinates becomes unavailable, Hyprland removes it from the active layout but preserves the virtual desktop space. Windows previously on that display may need redistribution. The MonitorStateTracker monitors connection events and updates the compositor state accordingly.

How do I rotate a monitor 90 degrees?

Use the transform field with a rotation value: transform = "90" for 90 degrees clockwise, "180" for upside-down, or "270" for 90 degrees counter-clockwise. The layout controller applies this transformation after positioning, affecting both the display orientation and how input coordinates are mapped.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →