-
-
Notifications
You must be signed in to change notification settings - Fork 899
Print the window manager name and version
| Module type | wm |
| Default order | 22 (only used by --gen-config) |
| Module source | src/modules/wm/wm.c |
| Detection source |
src/detection/displayserver/ (the name), src/detection/wm/ (version and plugin) |
Prints the window manager or Wayland compositor that owns the session, its version, the display protocol in use, and any recognised tiling add-on.
Window Manager: KWin (X11)
Window Manager: Hyprland 0.48.1 (Wayland)
Window Manager: Quartz Compositor 1.600.0 (with Rectangle 0.80)
Window Manager: dwm.exe 10.0.22621.2506
| Platform | WM name | Version probe | Plugin probe |
|---|---|---|---|
| Linux | displayserver_linux.c |
wm_linux.c |
not supported |
| Android | displayserver_android.c |
wm_linux.c |
not supported |
| FreeBSD / NetBSD / OpenBSD | displayserver_linux.c |
wm_linux.c |
not supported |
| GNU/Hurd | displayserver_linux.c |
wm_linux.c |
not supported |
| Solaris / illumos | displayserver_linux.c |
wm_nosupport.c |
not supported |
| Haiku | displayserver_haiku.cpp |
wm_nosupport.c |
not supported |
| macOS | displayserver_apple.c |
wm_apple.m |
wm_apple.m |
| Windows | displayserver_windows.c |
wm_windows.c |
wm_windows.c |
wm_nosupport.c is registered in the Solaris and Haiku blocks, so the module reports no
version there. This is the mirror image of the DE module, which is unsupported on macOS,
Windows and Haiku instead — no platform has both.
Solaris and Haiku still print a window manager name; only {version} stays empty.
| Key | Type | Default | Description |
|---|---|---|---|
detectPlugin |
boolean | true |
Scan for a recognised tiling window manager add-on. |
key |
string | module name | Module key. A single space hides the key and the separator. |
keyColor |
color | – | Overrides display.color.keys. |
keyWidth |
integer | – | Overrides display.key.width. |
keyIcon |
string | built-in glyph | Printed when display.key.type includes the icon bit. Any glyph works; "" prints none. |
outputColor |
color | – | Overrides display.color.output. |
format |
string | – | Custom output format (see below). |
condition |
object | – | Show the module only if the conditions match. |
Version detection is controlled by the global general.detectVersion setting.
detectPlugin is accepted on every platform, but only macOS and Windows have a plugin probe —
on the other eight it is silently ignored, because the Linux implementation of
ffDetectWMPlugin() returns Not supported on this platform without touching the buffer.
Run fastfetch -h wm-format for the authoritative list.
| Variable | Description |
|---|---|
{process-name} |
The session process, e.g. kwin_wayland or dwm.exe
|
{pretty-name} |
The display name, e.g. KWin
|
{protocol-name} |
X11, Wayland, TTY or SurfaceFlinger
|
{plugin-name} |
Recognised tiling add-on, when one was found |
{version} |
Version string, when one could be determined |
{protocol-name} is empty on macOS, Windows and Haiku — only the Linux/BSD/Solaris display
server layer records a protocol.
On failure the object is { "type": "WM", "error": "No WM found" }.
{ "type": "wm", "key": "WM", "format": "{pretty-name} {version} ({protocol-name})" }{ "type": "wm", "detectPlugin": false, "format": "{process-name}" }-
Most window managers get no version. The Linux version probe knows exactly eleven names
—
Hyprland,sway,labwc,niri,umbriel,weston,WSLg,i3,ctwm,fvwmandOpenbox— and returnsUnsupported WMfor everything else. KWin, Mutter, Muffin, Marco, Xfwm4, dwm, bspwm, Qtile, IceWM and the rest print a name with no version. macOS only knowsWindowServerand Windows only knowsdwm.exe. -
The probe matches the process name, not the pretty name. The dispatch compares against
wmProcessName, which for a Wayland session is whatever/proc/<pid>/commreported for the socket owner. A compositor started through a wrapper or renamed binary therefore falls through toUnsupported WM. -
{plugin-name}is a tiling add-on, not a window manager plugin. It is only ever set for Rectangle, yabai, AeroSpace, Amethyst and GlazeWM on macOS, and for FancyWM, GlazeWM and Komorebi on Windows. On Linux and BSD the field is always empty. -
The plugin probe's errors are swallowed.
ffDetectWMPlugin()returns a status string, but both the text and the JSON paths ignore it — a failed process enumeration simply produces an empty{plugin-name}with no diagnostic. -
On macOS the plugin probe requires a parent PID of 1. Only processes whose
e_ppidis 1 are considered, so a tiling add-on started by a session manager or a terminal is missed. -
The plugin name is capitalised by hand. On macOS, when no
Info.plistversion can be read, the first character of the process name is upper-cased in place — soyabaiis reported asYabaiandrectangleasRectangle. -
{pretty-name}can be an arbitrary string. An unrecognised window manager falls back to its raw process name, and an unrecognisedXDG_CURRENT_DESKTOPcan be promoted into the WM slot by the display-server layer, so{pretty-name}is not restricted to the known names. -
detectPlugin: falsedoes not stop the process scan. It only skips the plugin probe; the window manager name itself still comes from a full process-table walk when the display server connection could not supply it. -
Version detection runs external commands.
sway,labwc,niri,umbriel,weston,i3,ctwm,fvwmandOpenboxare all executed with--versionwhen the binary string scan fails. Setgeneral.detectVersiontofalseto keep fastfetch side-effect free.
ffPrintWM() and ffGenerateWMJsonResult() both ask ffConnectDisplayServer() for the cached
FFDisplayServerResult, error out when wmPrettyName is empty, then optionally call
ffDetectWMPlugin() and ffDetectWMVersion(). The version call is gated on
instance.config.general.detectVersion inside the module itself.
The display-server layer fills wmProcessName, wmPrettyName and wmProtocolName. On Linux,
Android, BSD and Solaris, ffdsDetectWMDE() in wmde.c first uses whatever the display-server
connection already produced, otherwise the environment value from parseEnv(), and then falls
back to a process scan. applyPrettyNameIfWM() maps about twenty process names to pretty names
with case-insensitive matching, including the kwin_*, cinnamon-* and -kwin_wayland prefix
and suffix forms. Anything unrecognised keeps its raw process name as the pretty name.
wmProtocolName is set by the display-server backends, not by the WM module: Wayland, X11
or TTY on Linux, and SurfaceFlinger on Android. On Android the whole detection is skipped
when the protocol is SurfaceFlinger, since only the X11 path can report a window manager.
ffDetectWMVersion() is an if/else if chain over the process name:
-
Hyprland — reads
#define GIT_TAGfrom<pkg base>/include/hyprland/src/version.h, then scans theHyprlandbinary for av<major>.<minor>.<patch>string, then runsHyprland --versionand prefers aTag: v...line over the first field of the output. -
sway — scans the
swaybinary for a line starting withsway version, and also recognises the SwayFX formswayfx version <v> (based on sway <v>), which is rendered as<sway> [swayfx <swayfx>]. Falls back tosway --version. -
labwc / ctwm / fvwm / Openbox — share
extractCommonWmVersion(), which scans the binary for a<major>.<minor>.<patch>string. The command fallbacks differ:labwc --versionkeeps the second field, the other three keep the last field of the first line, and fvwm is invoked with-versionrather than--version. -
niri / umbriel — run
<name> --versionand keep the text between the first space and the last(. -
weston — runs
weston --versionand keeps the last field of the first line. -
WSLg — parses
/mnt/wslg/versions.txt, handling both theWSLg: <v>form used from WSL 2.9.3 on and the olderWSLg <v>+<build>: <v>form. -
i3 — scans the
i3binary for a<major>.<minor>string, then runsi3 --versionand takes the token afterversion. -
macOS — only for
WindowServer: readsCFBundleShortVersionStringfrom the SkyLightversion.plist, falling back to the CoreGraphics one. -
Windows — only for
dwm.exe: reads the file version of%SystemRoot%\dwm.exe.
Binary string scanning is preferred over spawning processes because it avoids the fork; the
scans use ffBinaryExtractStrings() with a sscanf-based matcher that only accepts a string
starting with a full version number, and the minimum-length argument is set to the length of a
representative sample (v0.0.0, sway version 0.0.0, 0.0, …) so that unrelated strings are
rejected early.
The macOS probe walks sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) and considers only
processes whose parent is PID 1. The Windows probe walks the process table with
SystemBasicProcessInformation (smaller entries, so one query suffices) and falls back to
SystemProcessInformation with up to five buffer retries. Both then match against a fixed list
and, when general.detectVersion is on, append the add-on's own version — from
Info.plist via ffGetAppNameAndVersion() on macOS, from ffGetFileVersion() or
komorebi --version on Windows.
{ "type": "WM", "result": { "processName": "WindowServer", "prettyName": "Quartz Compositor", "protocolName": "", "pluginName": "", "version": "1.600.0" } }