Table of Contents
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Monitor
Same as Display module, but with a different default output format
| Module type | monitor |
| Default order | 19 (only used by --gen-config) |
| Module source | src/modules/monitor/monitor.c |
| Detection source | src/detection/displayserver/ |
Prints one line per connected display, in a layout built for panels rather than desktops: the native resolution, the refresh rate, and the physical size with the diagonal in inches and the pixel density.
Monitor (HDMI-1): 1920x1080 px @ 60 Hz - 521x293 mm (23.99 inches, 91.79 ppi)
Monitor is the same detection as Display — it calls the same
ffConnectDisplayServer() and walks the same display list — with a different default line and a
different set of format variables. Everything after the resolution is conditional:
@ <n> Hzis printed only when the display reported a refresh rate.- <w>x<h> mm (<inch> inches, <ppi> ppi)is printed only when the physical size is known, and the value is the panel's EDID size in millimetres.[HDR Compatible]is printed when the display supports HDR, or when HDR is enabled.
The key is Monitor (<name>), or a bare Monitor when the display has no name. Unlike Display
there is no (<n>) fallback and no per-display numbering: two nameless displays both print
Monitor.
Platform support
The module layer is platform independent — monitor.c only formats what the shared
displayserver subsystem returns. Detection is therefore identical to
Display: the displayserver subsystem has a real implementation
on all ten platforms (Wayland / XCB / Xlib / DRM / sysfs on Linux and the BSDs, CoreGraphics on
macOS, GDI plus DisplayConfigGetDeviceInfo on Windows, BScreen on Haiku, and the display
service over binder on Android).
Configuration
| Key | Type | Default | Description |
|---|---|---|---|
key |
string | module name + display name | Module key. A single space hides the key and the separator. |
keyColor |
color | – | Overrides display.color.keys |
keyIcon |
string | built-in glyph | Printed when display.key.type includes the icon bit. Any glyph works; "" prints none. |
keyWidth |
integer | – | Overrides display.key.width |
outputColor |
color | – | Overrides display.color.output |
format |
string | – | Custom output format (see below) |
condition |
object | – | Show the module only if the conditions match |
There are no module-specific options — only the standard module arguments. In particular the
three options that shape Display's output are not accepted here: compactType,
preciseRefreshRate and order are rejected with Unknown JSON key …, because
ffParseMonitorJsonObject() only forwards the module arguments. See the pitfalls.
Inside key the available variables are {index}, {name}, {icon} and {module-name}; {index}
is 0 when there is only one display.
Format string
Run fastfetch -h monitor-format for the authoritative list.
| Variable | Description |
|---|---|
{name} |
Display name * |
{width} |
Native resolution width in pixels |
{height} |
Native resolution height in pixels |
{physical-width} |
Physical width in millimetres |
{physical-height} |
Physical height in millimetres |
{inch} |
Physical diagonal in inches |
{ppi} |
Pixels per inch |
{manufacture-year} |
Year of manufacture, 0 when unknown |
{manufacture-week} |
Week of manufacture, 0 when unknown |
{serial} |
Serial number, empty when unknown |
{refresh-rate} |
Refresh rate in Hz |
{hdr-compatible} |
true when the display supports HDR, whether or not it is on |
{name} is the only variable marked *, i.e. also usable in the key format. The list is not a
subset of Display's: {width} / {height} look the same, but Monitor has no {scaled-width},
{type}, {rotation}, {is-primary}, {bit-depth}, {platform-api} or {dpi}, and adds nothing
of its own. {width} and {height} are the same native mode both modules report.
{inch}, {ppi} and {refresh-rate} are floating-point values, so they are formatted with
display.fraction — two decimals by default (31.48, 139.94, 165.00). {manufacture-year} and
{manufacture-week} are integers, and {serial} is a string.
JSON output
The module has no JSON result of its own — it always emits the alias error:
[
{
"type": "Monitor",
"error": "Monitor module is an alias of Display module"
}
]
ffGenerateMonitorJsonResult() writes the error string and returns false without touching the
display list. Use the display module when a structured result is needed; the two read the same
detection, so { "type": "display" } gives exactly the data this module formats.
Examples
// The default line, but only the native resolution
{ "type": "monitor", "format": "{width}x{height}" }
// Panel report: size, density and EDID metadata
{ "type": "monitor", "format": "{name}: {inch}in {ppi}ppi {manufacture-year}-W{manufacture-week} {serial}" }
// Rename the key and print the refresh rate next to the resolution
{ "type": "monitor", "key": "Panel {index}", "format": "{width}x{height} @ {refresh-rate} Hz" }
Pitfalls
- The JSON output is an error object, not a result.
Monitoris declared as an alias ofDisplay, so--format jsonyields{"type":"Monitor","error":"Monitor module is an alias of Display module"}and nothing else. A JSON consumer that wants display data has to ask fordisplay. compactType,preciseRefreshRateandorderare rejected. They belong to thedisplaymodule. Setting any of them on amonitorentry printsUnknown JSON key <name>(and withdisplay.showErrorsoff the rest of the run is unaffected but the line is still formatted with the defaults). TheMonitorlayout is fixed: there is no way to collapse it to one line.- The refresh rate is rendered twice, differently. The default line prints it with
%gafter rounding to three decimals, so165.0Hz shows as165 Hz; the{refresh-rate}variable is a double formatted withdisplay.fraction, so the same panel shows165.00. A format string that reproduces the default line has to round it itself. {inch}here is notDisplay's{inch}. Thedisplaymodule rounds its{inch}to a whole number;Monitorprints the real value withdisplay.fraction(31.48, not31). The default line uses two decimals explicitly (%.2f inches, %.2f ppi).- The physical block vanishes together, but
{ppi}has no guard of its own. The- … mm (… inch … ppi)part is only printed when the diagonal is greater than zero, which comes from the EDID physical size.{ppi}is computed assqrt(width² + height²) / inch, so it follows the same value and is not meaningful when no physical size was reported. [HDR Compatible]is not the same marker asDisplay's[HDR]. Themonitorlayout prints the marker when the status isSupportedorEnabled, so a panel that can do HDR but has it switched off still shows[HDR Compatible].{hdr-compatible}istruein both cases as well.orderset onDisplaydoes not affectMonitor.ffConnectDisplayServer()returns a process-wide static thatDisplaysorts only for its own output, soMonitorprints the displays in detection order unless the machine reports them sorted. Set the layout on each module separately — but note thatMonitorcannot sort at all.- The key is never numbered. With several displays every line carries its own
Monitor (<name>); there is noMonitor 1:/Monitor 2:. Displays without a name are indistinguishable in the output. serialcan look like a hex word. EDID serials are frequently a hexadecimal token rather than a text string; it is reported verbatim as a string.
Implementation
ffPrintMonitor() calls ffConnectDisplayServer() and iterates result->displays. For each display
it derives the diagonal from the EDID size and the density from the resolution:
double inch = sqrt(physicalWidth² + physicalHeight²) / 25.4;
double ppi = sqrt(width² + height²) / inch;
bool hdrCompatible = hdrStatus == FF_DISPLAY_HDR_STATUS_SUPPORTED
|| hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED;
It then builds the key (Monitor, plus (<name>) when the display has one, or the parsed key
format) and prints either the fixed layout or the custom format. Because the detection result is a
singleton shared with every other display module, the strings are deliberately not destroyed.
There is no detection code in the module directory: everything comes from
src/detection/displayserver/, whose per-platform behaviour is described in
Display. One consequence worth repeating here is that
ffdsAppendDisplay() drops any display with a zero width or height and forces a DPI of 96 when the
backend cannot report one, so a Monitor line always has a usable resolution.