mangowmmangowm

Monitors

Manage display outputs, resolution, scaling, and tearing.

Monitor Rules

You can configure each display output individually using the monitorrule keyword.

Syntax:

monitorrule=name:Values,Parameter:Values,Parameter:Values

Info: If any of the matching fields (name, make, model, serial) are set, all of the set ones must match to be considered a match. Use wlr-randr to get your monitor's name, make, model, and serial.

Parameters

ParameterTypeValuesDescription
namestringAnyMatch by monitor name (supports regex)
makestringAnyMatch by monitor manufacturer
modelstringAnyMatch by monitor model
serialstringAnyMatch by monitor serial number
widthinteger0-9999Monitor width
heightinteger0-9999Monitor height
refreshfloat0.001-9999.0Monitor refresh rate
xinteger0-99999X position
yinteger0-99999Y position
scalefloat0.01-100.0Monitor scale
vrrinteger0, 1Enable variable refresh rate
hdrinteger0, 1Enable hdr support
hdr_min_lumfloat0.0-10000.0Mastering display minimum luminance, cd/m² (0 = unset)
hdr_max_lumfloat0.0-10000.0Mastering display peak luminance, also sent as max_cll, cd/m² (0 = unset)
hdr_max_avg_lumfloat0.0-10000.0Max frame-average light level (max_fall), cd/m² (0 = unset)
hdr_forceinteger0, 1Enable HDR even when the EDID does not advertise BT.2020/PQ
iccstring-Path to an ICC profile applied as the output color transform (e.g. /usr/share/color/icc/MyDisplay.icc). Mutually exclusive with hdr: when both are set, HDR takes precedence and the ICC profile is ignored. Set hdr:0 to use the ICC profile
rrinteger0-7Monitor transform
custominteger0, 1Enable custom mode (not supported on all displays — may cause black screen)
disableinteger0, 1Disable the monitor

Transform Values

ValueRotation
0No transform
190° counter-clockwise
2180° counter-clockwise
3270° counter-clockwise
4180° vertical flip
5Flip + 90° counter-clockwise
6Flip + 180° counter-clockwise
7Flip + 270° counter-clockwise

Critical: If you use XWayland applications, never use negative coordinates for your monitor positions. This is a known XWayland bug that causes click events to malfunction. Always arrange your monitors starting from 0,0 and extend into positive coordinates.

Note: that "name" is a regular expression. If you want an exact match, you need to add ^ and $ to the beginning and end of the expression, for example, ^eDP-1$ matches exactly the string eDP-1.

Examples

# Laptop display: 1080p, 60Hz, positioned at origin
monitorrule=name:^eDP-1$,width:1920,height:1080,refresh:60,x:0,y:10

# Match by make and model instead of name
monitorrule=make:Chimei Innolux Corporation,model:0x15F5,width:1920,height:1080,refresh:60,x:0,y:0

# Virtual monitor with pattern matching
monitorrule=name:HEADLESS-.*,width:1920,height:1080,refresh:60,x:1926,y:0,scale:1,rr:0,vrr:0

Monitor Spec Format

Several commands (focusmon, tagmon, disable_monitor, enable_monitor, toggle_monitor, viewcrossmon, tagcrossmon) accept a monitor_spec string to identify a monitor.

Format:

name:xxx&&make:xxx&&model:xxx&&serial:xxx
  • Any field can be omitted and there is no order requirement.
  • If all fields are omitted, the string is treated as the monitor name directly (e.g., eDP-1).
  • Use wlr-randr to find your monitor's name, make, model, and serial.

Examples:

# By name (shorthand)
mmsg dispatch toggle_monitor,eDP-1

# By make and model
mmsg dispatch toggle_monitor,make:Chimei Innolux Corporation&&model:0x15F5

# By serial
mmsg dispatch toggle_monitor,serial:12345678

Tearing (Game Mode)

Tearing allows games to bypass the compositor's VSync for lower latency.

SettingDefaultDescription
allow_tearing0Global tearing control: 0 (Disable), 1 (Enable), 2 (Fullscreen only).

HDR

HDR is only supported in wl-only branch, since it requires the vulkan renderer but scenefx is not supported yet.

SettingDefaultDescription
hdr_depth2Set the hdr depth for the current display. 0 is Default, 1 is HDR8, 2 is HDR10.
  • you should enable HDR in monitorrule first, refer to Monitors — Monitor Rules
  • you must set env=WLR_RENDERER,vulkan before mango starts.

for example(must relogin once after setting):

env=WLR_RENDERER,vulkan
monitorrule=name:eDP-1,model:0x15F5,width:1920,height:1080,refresh:60,x:0,y:0,scale:1,vrr:0,rr:0:hdr:1

Toggling HDR at runtime

monitorrule sets the state at startup; togglehdr changes it without a config reload, the way sway's output <name> hdr on|off|toggle does.

mmsg dispatch togglehdr              # toggle the focused monitor
mmsg dispatch togglehdr,on           # force on
mmsg dispatch togglehdr,off,eDP-1    # a named output
mmsg dispatch togglehdr,toggle,all   # every output at once

With no argument it toggles the focused monitor. Reloading the config re-applies monitorrule and overrides whatever togglehdr last set.

all applies to every enabled output. In toggle mode it makes one decision for all of them — if anything is on, everything goes off — rather than flipping each output against its own state. Outputs that cannot do HDR are skipped without their state being touched.

Mastering display metadata

hdr:1 alone declares BT.2020 primaries and the PQ transfer function, but leaves the mastering display fields at zero, so the panel has nothing to tone-map against. Set them to your panel's values:

monitorrule=name:eDP-1,...,hdr:1,hdr_max_lum:616,hdr_max_avg_lum:400

di-edid-decode prints them under HDR Static Metadata Data Block. hdr_max_lum is sent both as the mastering peak and as max_cll. Leaving any of the three at 0 leaves that field unset, which is the previous behaviour.

hdr_min_lum has no effect on wlroots 0.20.x: the minimum was scaled the wrong way in backend/drm/atomic.c and every value underflowed to 0. Fixed upstream by wlroots commit f6a01b40, not backported to the 0.20 branch.

Panels whose EDID hides the HDR block

Some panels declare HDR only inside a DisplayID 2.0 extension, with the CTA-861 blocks nested in a container (tag 0x81). This is legal EDID 1.4, but wlroots reads HDR capability through libdisplay-info's CTA path and comes back empty, so hdr:1 is silently ignored on a panel that handles PQ.

hdr_force:1 skips the two EDID-derived checks:

monitorrule=name:eDP-1,...,hdr:1,hdr_force:1,hdr_max_lum:616,hdr_max_avg_lum:400

It does not skip the renderer check: output colour transforms only exist in the Vulkan renderer, so WLR_RENDERER=vulkan is still required.

Configuration

Enable Globally:

allow_tearing=1

Enable per Window:

Use a window rule to force tearing for specific games.

windowrule=force_tearing:1,title:vkcube

Tearing Behavior Matrix

force_tearing \ allow_tearingDISABLED (0)ENABLED (1)FULLSCREEN_ONLY (2)
UNSPECIFIED (0)Not AllowedFollows tearing_hintOnly fullscreen follows tearing_hint
ENABLED (1)Not AllowedAllowedOnly fullscreen allowed
DISABLED (2)Not AllowedNot AllowedNot Allowed

Graphics Card Compatibility

Warning: Some graphics cards require setting the WLR_DRM_NO_ATOMIC environment variable before mango starts to successfully enable tearing.

Add this to config and relogin mango:

env=WLR_DRM_NO_ATOMIC,1

GPU Compatibility

If mango cannot display correctly or shows a black screen, try selecting a specific GPU:

# Use a single GPU
WLR_DRM_DEVICES=/dev/dri/card1 mango

# Use multiple GPUs
WLR_DRM_DEVICES=/dev/dri/card0:/dev/dri/card1 mango

Some GPUs have compatibility issues with syncobj_enable=1 — it may crash apps like kitty that use syncobj. Set env=WLR_DRM_NO_ATOMIC,1 in config.conf and relogin to resolve this.


Power Management

You can control monitor power using the mmsg IPC tool.

Notice: This sleep command does not remove the monitor, it only turns the power off.

# Turn power off
mmsg dispatch sleep_monitor,eDP-1

# Turn power on
mmsg dispatch wakeup_monitor,eDP-1

# Toggle power
mmsg dispatch sleep_toggle_monitor,eDP-1

You can also use wlr-randr for monitor management:

# remove a monitor
mmsg dispatch disable_monitor,eDP-1

# add a monitor
mmsg dispatch enable_monitor,eDP-1

# Show all monitors spec
wlr-randr

Screen Scale(1.5 scale example)

# don't scale xwayland in global to avoid blurry
xwayland_ignore_scale=1
# scale:1.5 to scale native wayland app
monitorrule=name:eDP-1,width:1920,height:1080,refresh:60,x:0,y:0,scale:1.5
# use dpi to scale xwayland(1.5 * 96 = 144)
exec-once=echo "Xft.dpi: 144" | xrdb -merge

Virtual Monitors

You can create and manage virtual displays through IPC commands:

# Create virtual output
mmsg dispatch create_virtual_output

# Destroy all virtual outputs
mmsg dispatch destroy_all_virtual_output

You can configure virtual monitors using wlr-randr:

# Show all monitors
wlr-randr

# Configure virtual monitor
wlr-randr --output HEADLESS-1 --pos 1921,0 --scale 1 --custom-mode 1920x1080@60Hz

Virtual monitors can be used for screen sharing with tools like Sunshine and Moonlight, allowing other devices to act as extended monitors.

On this page