Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ Full function reference with examples can be found at
| | uefi | X | X | X | X | | OS started via UEFI |
| | hypervisor | | | | X | | hyper-v enabled? (win only) |
| | remoteSession | | | | X | | runs in remote session (win only) |
| | displayServer | X | X | X | X | X | display server e.g. wayland, x11, quartz, dwm, surfaceflinger or '' (headless) |
| si.uuid(cb) | {...} | X | X | X | X | X | object of several UUIDs |
| | os | X | X | X | X | | os specific UUID |
| | hardware | X | X | X | X | | hardware specific UUID |
Expand Down
13 changes: 12 additions & 1 deletion docs/os.html
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,16 @@ <h2>Operating System, Shell, Versions, Users</h2>
<td></td>
<td>runs in remote session (win only)</td>
</tr>
<tr>
<td></td>
<td>displayServer</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>display server: wayland, x11, quartz, dwm, tty</td>
</tr>
<tr class="example">
<td></td>
<td colspan="7">
Expand All @@ -257,7 +267,8 @@ <h5>Example</h5>
serial: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
build: '19D76',
servicepack: '',
uefi: true
uefi: true,
displayServer: 'quartz'
}</pre>
</td>
</tr>
Expand Down
13 changes: 12 additions & 1 deletion docs/v4/os.html
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,16 @@ <h2>Operating System, Shell, Versions, Users</h2>
<td></td>
<td>OS uses UEFI on startup</td>
</tr>
<tr>
<td></td>
<td>displayServer</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>display server: wayland, x11, quartz, dwm, tty</td>
</tr>
<tr class="example">
<td></td>
<td colspan="7">
Expand All @@ -237,7 +247,8 @@ <h5>Example</h5>
serial: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
build: '19D76',
servicepack: '',
uefi: true
uefi: true,
displayServer: 'quartz'
}</pre>
</td>
</tr>
Expand Down
1 change: 1 addition & 0 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ export namespace Systeminformation {
uefi: boolean | null;
hypervizor?: boolean;
remoteSession?: boolean;
displayServer: string;
}

interface UuidData {
Expand Down
83 changes: 82 additions & 1 deletion lib/osinfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,81 @@ function getFQDN() {
return fqdn;
}

// --------------------------
// Display Server Detection

function getDisplayServer() {
let result = '';

// Linux and BSD systems can use X11, Wayland, or run headless (tty)
// Android uses SurfaceFlinger
if (_linux || _freebsd || _openbsd || _netbsd || _sunos) {
// Check for Android's SurfaceFlinger first
if (_platform === 'android') {
try {
// Check if surfaceflinger process is running
const stdout = execSync('pgrep -f surfaceflinger 2>/dev/null || ps -A 2>/dev/null | grep surfaceflinger', { encoding: 'utf8' });
if (stdout && stdout.trim()) {
result = 'surfaceflinger';
}
} catch {
// If check fails, still might be Android but headless or termux environment
result = '';
}
} else {
// Primary method: XDG_SESSION_TYPE is the most reliable
const sessionType = process.env.XDG_SESSION_TYPE || '';
if (sessionType) {
result = sessionType.toLowerCase();
} else {
// Fallback: check for display environment variables
if (process.env.WAYLAND_DISPLAY) {
result = 'wayland';
} else if (process.env.DISPLAY) {
result = 'x11';
} else {
// No GUI - TTY/console session or headless
result = '';
}
}
}
}

// macOS uses Quartz Compositor when GUI is active
if (_darwin) {
try {
// Try to verify WindowServer is running
const stdout = execSync('pgrep WindowServer 2>/dev/null', { encoding: 'utf8' });
// If output exists, WindowServer is running
if (stdout && stdout.trim()) {
result = 'quartz';
}
} catch {
// If pgrep fails or WindowServer not found, assume headless
result = '';
}
}

// Windows uses DWM (Desktop Window Manager) when GUI is active
// Note: WSL2/WSLg is detected as Linux, not Windows
if (_windows) {
try {
// Check if dwm.exe process exists using simpler tasklist approach
const stdout = execSync('tasklist /NH /FI "IMAGENAME eq dwm.exe"', util.execOptsWin);
const output = stdout.toString().toLowerCase();
// If dwm.exe in output, GUI is running
if (output && output.indexOf('dwm.exe') !== -1) {
result = 'dwm';
}
} catch {
// If tasklist fails or dwm.exe not found, assume headless
result = '';
}
}

return result;
}

// --------------------------
// OS Information

Expand All @@ -237,7 +312,8 @@ function osInfo(callback) {
serial: '',
build: '',
servicepack: '',
uefi: false
uefi: false,
displayServer: ''
};

if (_linux) {
Expand Down Expand Up @@ -273,6 +349,7 @@ function osInfo(callback) {
result.codename = codename;
result.codepage = util.getCodepage();
result.build = (release.BUILD_ID || '').replace(/"/g, '').trim();
result.displayServer = getDisplayServer();
isUefiLinux().then((uefi) => {
result.uefi = uefi;
uuid().then((data) => {
Expand Down Expand Up @@ -302,6 +379,7 @@ function osInfo(callback) {
result.codename = '';
result.codepage = util.getCodepage();
result.uefi = uefi || null;
result.displayServer = getDisplayServer();
if (callback) {
callback(result);
}
Expand Down Expand Up @@ -337,6 +415,7 @@ function osInfo(callback) {
result.codename = result.release.startsWith('26.') ? 'Tahoe' : result.codename;
result.uefi = true;
result.codepage = util.getCodepage();
result.displayServer = getDisplayServer();
if (callback) {
callback(result);
}
Expand All @@ -349,6 +428,7 @@ function osInfo(callback) {
const lines = stdout.toString().split('\n');
result.distro = lines[0];
result.logofile = getLogoFile(result.distro);
result.displayServer = getDisplayServer();
if (callback) {
callback(result);
}
Expand Down Expand Up @@ -383,6 +463,7 @@ function osInfo(callback) {
result.codename = getWindowsRelease(buildNum);
}
result.remoteSession = term.toString().toLowerCase().indexOf('true') >= 0;
result.displayServer = getDisplayServer();
isUefiWindows().then((uefi) => {
result.uefi = uefi;
if (callback) {
Expand Down