-
Notifications
You must be signed in to change notification settings - Fork 0
Multi Monitor
Configuring multiple displays in NullOS with Hyprland.
Hyprland supports multi-monitor setups with per-monitor configuration for:
- Resolution and refresh rate
- Position and rotation
- Scale and transform
- Wallpapers
- Workspaces
Hyprland auto-detects monitors:
# List connected monitors
hyprctl monitors
# Sample output:
# Monitor eDP-1 (ID 0):
# 1920x1080@60Hz at 0x0
# scale: 1.00
# ...In home/hyprland/settings.nix:
monitor = [
"eDP-1,1920x1080@60,0x0,1"
"HDMI-A-1,1920x1080@60,1920x0,1"
];Format: name,resolution@rate,position,scale
# While displays are connected
hyprctl monitors
# Shows:
# Monitor HDMI-A-1 (ID 1):
# ...Laptops:
-
eDP-1- Internal laptop display -
eDP-2- Less common second internal display
External:
-
HDMI-A-1,HDMI-A-2- HDMI ports -
DP-1,DP-2,DP-3- DisplayPort -
DVI-D-1- DVI port -
VGA-1- VGA port (rare)
NVIDIA:
When using NVIDIA, names may include HDMI-1-0 format.
monitor = [
"HDMI-A-1,1920x1080@60,auto,1"
];monitor = [
"DP-1,2560x1440@144,auto,1"
];monitor = [
"HDMI-A-1,3840x2160@60,auto,1.5" # With scaling
];# Get supported resolutions/rates
hyprctl monitors | grep -A 20 "Monitor HDMI-A-1"Or use GUI tool:
nwg-displaysmonitor = [
"eDP-1,1920x1080@60,auto,1"
"HDMI-A-1,1920x1080@60,auto,1"
];Hyprland arranges monitors automatically.
monitor = [
# Laptop screen at 0,0
"eDP-1,1920x1080@60,0x0,1"
# External monitor to the right
"HDMI-A-1,1920x1080@60,1920x0,1"
];Coordinates:
-
0x0- Top-left corner -
1920x0- 1920 pixels to the right -
0x1080- 1080 pixels down
monitor = [
# Top monitor
"HDMI-A-1,1920x1080@60,0x0,1"
# Bottom monitor
"HDMI-A-2,1920x1080@60,0x1080,1"
];monitor = [
# Center main display
"DP-1,2560x1440@144,0x0,1"
# Left vertical display
"HDMI-A-1,1920x1080@60,-1080x0,1,transform,1"
# Right display
"HDMI-A-2,1920x1080@60,2560x0,1"
];monitor = [
# 1.5x scaling for 4K
"HDMI-A-1,3840x2160@60,auto,1.5"
# 2x scaling for very high DPI
"eDP-1,2880x1800@60,auto,2"
];Common scales:
-
1- No scaling (1080p, 1440p) -
1.25- Small increase (2K on 24") -
1.5- Recommended for 4K 27" -
2- Apple Retina style (4K 24")
Different monitors can have different scales:
monitor = [
"eDP-1,1920x1080@60,0x0,1" # Laptop: no scaling
"HDMI-A-1,3840x2160@60,1920x0,1.5" # 4K: scaled
];monitor = [
"HDMI-A-1,1920x1080@60,auto,1,transform,1"
];Transform values:
-
0- Normal -
1- 90° clockwise -
2- 180° -
3- 270° clockwise -
4- Flipped -
5- Flipped + 90° -
6- Flipped + 180° -
7- Flipped + 270°
monitor = [
# Main horizontal
"DP-1,2560x1440@144,0x0,1"
# Side vertical
"HDMI-A-1,1920x1080@60,2560x0,1,transform,1"
];Note: Position uses rotated dimensions.
monitor = [
"eDP-1,1920x1080@60,0x0,1"
"HDMI-A-1,1920x1080@60,0x0,1,mirror,eDP-1"
];monitor = [
"eDP-1,1920x1080@60,0x0,1"
"HDMI-A-1,3840x2160@60,0x0,2,mirror,eDP-1"
];monitor = [
"eDP-1,disable" # Turn off laptop screen
"HDMI-A-1,1920x1080@60,0x0,1"
];# When lid closed, disable laptop screen
bindl = [
",switch:on:Lid Switch,exec,hyprctl keyword monitor eDP-1,disable"
",switch:off:Lid Switch,exec,hyprctl keyword monitor eDP-1,1920x1080@60,0x0,1"
];With hyprpaper:
# hyprpaper.conf
preload = ~/wallpapers/wall1.png
preload = ~/wallpapers/wall2.png
wallpaper = eDP-1,~/wallpapers/wall1.png
wallpaper = HDMI-A-1,~/wallpapers/wall2.png
Bind workspaces to specific monitors:
workspace = [
"1, monitor:eDP-1"
"2, monitor:eDP-1"
"3, monitor:HDMI-A-1"
"4, monitor:HDMI-A-1"
];Or default monitor per workspace:
workspace = [
"1, monitor:eDP-1, default:true"
"3, monitor:HDMI-A-1, default:true"
];# Change resolution
hyprctl keyword monitor HDMI-A-1,1920x1080@60,auto,1
# Disable monitor
hyprctl keyword monitor eDP-1,disable
# Enable monitor
hyprctl keyword monitor eDP-1,preferred,auto,1Hyprland automatically handles monitor connection/disconnection.
Auto-enable:
monitor = [
",preferred,auto,1" # Catch-all for unknown monitors
];monitor = [
# Disable laptop screen when docked
"eDP-1,disable"
# Use external monitors
"HDMI-A-1,2560x1440@144,0x0,1"
"HDMI-A-2,1920x1080@60,2560x0,1"
];monitor = [
# Only laptop screen
"eDP-1,1920x1080@60,0x0,1"
];monitor = [
# Mirror to projector
"eDP-1,1920x1080@60,0x0,1"
"HDMI-A-1,1920x1080@60,0x0,1,mirror,eDP-1"
];monitor = [
"DP-1,2560x1440@165,0x0,1"
];
# In Hyprland config
misc {
vrr = 1 # Variable refresh rate (G-Sync/FreeSync)
}
env = [
"WLR_DRM_NO_ATOMIC,1" # If screen tearing
];Install via home/nwg-displays.nix:
nwg-displaysFeatures:
- Visual monitor positioning
- Resolution/refresh rate selection
- Generates Hyprland config
- Test before applying
Alternative tool:
nix-shell -p wdisplays --run wdisplaysmonitor = [
# Left monitor (vertical)
"DP-1,1920x1080@60,0x180,1,transform,3"
# Center main monitor
"HDMI-A-1,2560x1440@144,1080x0,1"
# Right monitor
"DP-2,1920x1080@60,3640x180,1"
];
workspace = [
"1, monitor:HDMI-A-1, default:true" # Main on center
"2, monitor:HDMI-A-1"
"3, monitor:DP-1" # Code on left
"4, monitor:DP-2" # Chat on right
];monitor = [
# Left
"HDMI-A-1,1920x1080@60,0x0,1"
# Center (main gaming)
"DP-1,2560x1440@165,1920x0,1"
# Right
"HDMI-A-2,1920x1080@60,4480x0,1"
];
workspace = [
"1, monitor:DP-1, default:true" # Game
"2, monitor:HDMI-A-1, default:true" # Discord
"3, monitor:HDMI-A-2, default:true" # Music/Browser
];monitor = [
# Ultrawide main
"DP-1,3440x1440@144,0x0,1"
# Laptop below
"eDP-1,1920x1080@60,760x1440,1"
];
workspace = [
"1, monitor:DP-1"
"2, monitor:DP-1"
"3, monitor:DP-1"
"9, monitor:eDP-1" # Monitoring workspace
"10, monitor:eDP-1" # Music
];# In waybar config
{
"output": "HDMI-A-1",
"layer": "top",
...
}Multiple configs:
# waybar-main.json for DP-1
# waybar-secondary.json for HDMI-A-1
# Launch both
exec-once = [
"waybar -c ~/.config/waybar/main.json"
"waybar -c ~/.config/waybar/secondary.json"
];env = [
# Force monitor for specific apps
"WLR_DRM_DEVICES,/dev/dri/card1:/dev/dri/card0"
];env = [
"WLR_DRM_NO_ATOMIC,1"
"LIBVA_DRIVER_NAME,nvidia"
"GBM_BACKEND,nvidia-drm"
"__GLX_VENDOR_LIBRARY_NAME,nvidia"
];See NVIDIA for complete NVIDIA setup.
# Check available outputs
hyprctl monitors all
# Force detect
hyprctl reload
# Check kernel detection
ls /sys/class/drm/# List supported modes
hyprctl monitors | grep "available modes" -A 20
# Try preferred mode
monitor = HDMI-A-1,preferred,auto,1
# Force specific mode
monitor = HDMI-A-1,1920x1080@60,auto,1# Enable VRR
misc {
vrr = 1
}
# Or disable atomic (NVIDIA)
env = WLR_DRM_NO_ATOMIC,1# Use GUI to visualize
nwg-displays
# Check current positions
hyprctl monitors | grep -E "(Monitor|at)"# Try integer scaling first
monitor = HDMI-A-1,3840x2160@60,auto,2
# If blurry, disable fractional
render {
explicit_sync = 1
}# Boot to terminal (Ctrl+Alt+F2)
# Check monitors
DISPLAY=:0 hyprctl monitors
# Try safe mode
monitor = ,preferred,auto,1# Different mouse sensitivity per monitor
input {
# Not directly supported, but workaround:
}
# Use scripts to change on workspace focus
workspace = [
"1, monitor:eDP-1, on-created-empty:set-high-sens"
"3, monitor:HDMI-A-1, on-created-empty:set-low-sens"
];Create scripts for different setups:
# ~/.config/hypr/scripts/monitor-laptop.sh
hyprctl keyword monitor eDP-1,1920x1080@60,0x0,1
hyprctl keyword monitor HDMI-A-1,disable
# ~/.config/hypr/scripts/monitor-desk.sh
hyprctl keyword monitor eDP-1,disable
hyprctl keyword monitor HDMI-A-1,2560x1440@144,0x0,1
hyprctl keyword monitor HDMI-A-2,1920x1080@60,2560x0,1Bind to keys:
bind = [
"$mod SHIFT, F7, exec, ~/.config/hypr/scripts/monitor-laptop.sh"
"$mod SHIFT, F8, exec, ~/.config/hypr/scripts/monitor-desk.sh"
];- Use Preferred Mode - Let Hyprland auto-detect when possible
- Integer Scaling - Avoid fractional scaling if possible for clarity
- Consistent Refresh Rates - Mixing can cause issues
-
Test Before Committing - Use
hyprctlruntime commands first - Document Layout - Comment your monitor positions
# home/hyprland/monitors.nix
{ config, pkgs, vars, ... }:
{
wayland.windowManager.hyprland.settings = {
monitor = [
# Primary 1440p gaming monitor
"DP-1,2560x1440@165,1080x0,1"
# Left vertical coding monitor
"HDMI-A-1,1920x1080@60,0x180,1,transform,3"
# Right communication monitor
"HDMI-A-2,1920x1080@60,3640x180,1"
# Laptop screen (disabled when docked)
"eDP-1,disable"
# Catch-all for unknown monitors
",preferred,auto,1"
];
workspace = [
# Main monitor - gaming/primary work
"1, monitor:DP-1, default:true"
"2, monitor:DP-1"
# Left monitor - code/terminals
"3, monitor:HDMI-A-1, default:true"
"4, monitor:HDMI-A-1"
# Right monitor - communication
"5, monitor:HDMI-A-2, default:true"
"6, monitor:HDMI-A-2"
];
# Enable VRR for gaming
misc = {
vrr = 1;
};
};
}- Hyprland - Full Hyprland configuration
- Waybar - Status bar per monitor
- NVIDIA - NVIDIA multi-monitor setup
- Customization Guide - Advanced customization