refactor(*): move to x11
This commit is contained in:
+55
-38
@@ -1,7 +1,7 @@
|
||||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
const puppeteer = require('puppeteer-core');
|
||||
const { spawn, exec } = require('child_process');
|
||||
const { spawn, exec, execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
@@ -10,7 +10,7 @@ app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use(bodyParser.json());
|
||||
|
||||
const PORT = process.env.PORT || 5011;
|
||||
const WORKSPACE = process.env.WORKSPACE || '1';
|
||||
const MONITOR = process.env.MONITOR || 'HDMI-1';
|
||||
|
||||
// State variables
|
||||
let browserProcess = null;
|
||||
@@ -23,19 +23,48 @@ let isKiosk = process.env.KIOSK !== '0'; // default 1
|
||||
let isGpu = process.env.GPU !== '0'; // default 1
|
||||
let chromiumFlags = [];
|
||||
|
||||
function getMonitorGeometry(monitorName) {
|
||||
try {
|
||||
const stdout = execSync('xrandr').toString();
|
||||
const lines = stdout.split('\n');
|
||||
for (const line of lines) {
|
||||
if (line.includes(monitorName) && line.includes('connected')) {
|
||||
// Match geometry string like 1920x1080+1920+0
|
||||
const match = line.match(/(\d+)x(\d+)\+(\d+)\+(\d+)/);
|
||||
if (match) {
|
||||
return {
|
||||
width: match[1],
|
||||
height: match[2],
|
||||
x: match[3],
|
||||
y: match[4]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to parse xrandr:', e);
|
||||
}
|
||||
// Fallback geometry if xrandr fails
|
||||
return { width: 1920, height: 1080, x: 0, y: 0 };
|
||||
}
|
||||
|
||||
function buildFlags() {
|
||||
const geometry = getMonitorGeometry(MONITOR);
|
||||
console.log(`Monitor ${MONITOR} resolved to position ${geometry.x},${geometry.y} with size ${geometry.width}x${geometry.height}`);
|
||||
|
||||
const flags = [
|
||||
'--no-sandbox',
|
||||
'--disable-dev-shm-usage',
|
||||
'--remote-debugging-port=9222',
|
||||
'--enable-features=UseOzonePlatform',
|
||||
'--ozone-platform=wayland',
|
||||
`--user-data-dir=/data/chromium-${WORKSPACE}`,
|
||||
'--window-position=0,0'
|
||||
`--user-data-dir=/data/chromium-${MONITOR}`,
|
||||
`--window-position=${geometry.x},${geometry.y}`,
|
||||
`--window-size=${geometry.width},${geometry.height}`
|
||||
];
|
||||
|
||||
if (isKiosk) {
|
||||
flags.push('--kiosk');
|
||||
// To ensure full screen stays on the target monitor
|
||||
flags.push(`--app=${currentUrl}`);
|
||||
}
|
||||
|
||||
if (!isGpu) {
|
||||
@@ -57,24 +86,20 @@ async function startChromium() {
|
||||
}
|
||||
|
||||
const flags = buildFlags();
|
||||
// Start with a specific title so we can target it with swaymsg
|
||||
const initialUrl = `data:text/html,<html><head><title>KioskInit${WORKSPACE}</title></head><body>Loading...</body></html>`;
|
||||
|
||||
console.log('Starting Chromium with flags:', flags.join(' '));
|
||||
|
||||
browserProcess = spawn('/usr/bin/chromium', [...flags, initialUrl], {
|
||||
// If kiosk is enabled, we pass the URL via --app to enforce window boundaries
|
||||
// Otherwise we just pass the URL as a positional argument.
|
||||
const args = [...flags];
|
||||
if (!isKiosk) {
|
||||
args.push(currentUrl);
|
||||
}
|
||||
|
||||
browserProcess = spawn('/usr/bin/chromium', args, {
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
// Wait a bit for the window to appear in Sway
|
||||
setTimeout(() => {
|
||||
console.log(`Assigning window to workspace ${WORKSPACE}...`);
|
||||
exec(`swaymsg "[title=KioskInit${WORKSPACE}] move to workspace ${WORKSPACE}"`, (err, stdout, stderr) => {
|
||||
if (err) console.error('Swaymsg error:', stderr);
|
||||
else console.log('Swaymsg success:', stdout);
|
||||
});
|
||||
}, 2000);
|
||||
|
||||
// Connect Puppeteer
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
@@ -87,8 +112,10 @@ async function startChromium() {
|
||||
const pages = await browser.pages();
|
||||
page = pages.length > 0 ? pages[0] : await browser.newPage();
|
||||
|
||||
console.log(`Navigating to ${currentUrl}`);
|
||||
await page.goto(currentUrl);
|
||||
if (!isKiosk) {
|
||||
console.log(`Navigating to ${currentUrl}`);
|
||||
await page.goto(currentUrl);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Puppeteer connect error:', e);
|
||||
}
|
||||
@@ -128,7 +155,6 @@ app.post('/autorefresh/:interval', (req, res) => {
|
||||
});
|
||||
|
||||
app.post('/scan', (req, res) => {
|
||||
// Stub for local service discovery
|
||||
res.status(200).send('Scanned');
|
||||
});
|
||||
|
||||
@@ -157,7 +183,9 @@ app.post('/url', async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (needRestart) {
|
||||
// If we're in kiosk mode, --app flag is used so changing URL requires restart to stay full screen
|
||||
// If we're not in kiosk mode, we can just navigate the page
|
||||
if (needRestart || isKiosk) {
|
||||
await startChromium();
|
||||
} else if (page) {
|
||||
await page.goto(currentUrl);
|
||||
@@ -205,21 +233,10 @@ app.get('/version', (req, res) => {
|
||||
|
||||
app.get('/screenshot', (req, res) => {
|
||||
const file = `/tmp/screenshot-${Date.now()}.png`;
|
||||
// Using grim instead of scrot for Wayland
|
||||
// We specify the output by workspace name if needed, but grim captures the whole screen if no output is specified.
|
||||
// To capture just the workspace, we can use grim with swaymsg to find the coordinates,
|
||||
// or simply rely on grim which by default captures everything.
|
||||
// To be safe and capture just the output for this workspace:
|
||||
exec(`grim -o HDMI-A-${WORKSPACE} ${file}`, (err) => {
|
||||
if (err) {
|
||||
// Fallback if HDMI-A-X is not found (e.g. testing locally)
|
||||
exec(`grim ${file}`, (err2) => {
|
||||
if (err2) return res.status(500).send('Screenshot failed');
|
||||
res.sendFile(file);
|
||||
});
|
||||
} else {
|
||||
res.sendFile(file);
|
||||
}
|
||||
// We use scrot for X11 screenshots.
|
||||
exec(`scrot ${file}`, (err) => {
|
||||
if (err) return res.status(500).send('Screenshot failed');
|
||||
res.sendFile(file);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -227,5 +244,5 @@ app.get('/screenshot', (req, res) => {
|
||||
startChromium();
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Kiosk API running on port ${PORT}`);
|
||||
console.log(`Kiosk API running on port ${PORT} for monitor ${MONITOR}`);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user