This commit is contained in:
2026-01-09 18:51:22 +00:00
parent de10e1dd1f
commit 3125b77020
7 changed files with 106 additions and 30 deletions

View File

@@ -149,6 +149,7 @@ export class EcoDaemon {
async getDisplays(): Promise<DisplayInfo[]> {
if (this.swayStatus.state !== 'running') {
this.log(`[displays] Sway not running (state: ${this.swayStatus.state}), skipping display query`);
return [];
}
const uid = await this.getUserUid();

View File

@@ -28,11 +28,39 @@ export class ProcessManager {
private user: string;
private swayProcess: Deno.ChildProcess | null = null;
private browserProcess: Deno.ChildProcess | null = null;
private swaySocket: string | null = null;
constructor(user: string) {
this.user = user;
}
/**
* Find the Sway IPC socket path in the runtime directory
* Sway creates sockets like: sway-ipc.$UID.$PID.sock
*/
async findSwaySocket(runtimeDir: string): Promise<string | null> {
try {
for await (const entry of Deno.readDir(runtimeDir)) {
if (entry.name.startsWith('sway-ipc.') && entry.name.endsWith('.sock')) {
const socketPath = `${runtimeDir}/${entry.name}`;
console.log(`[sway] Found IPC socket: ${socketPath}`);
return socketPath;
}
}
} catch (error) {
console.error(`[sway] Error finding socket: ${error}`);
}
return null;
}
getSwaySocket(): string | null {
return this.swaySocket;
}
setSwaySocket(socket: string | null): void {
this.swaySocket = socket;
}
/**
* Generate Sway configuration content for kiosk mode
*/
@@ -146,9 +174,19 @@ for_window [app_id="chromium-browser"] fullscreen enable
* Run a swaymsg command to control Sway
*/
async swaymsg(config: { runtimeDir: string; waylandDisplay: string }, command: string): Promise<boolean> {
// Find socket if not already found
if (!this.swaySocket) {
this.swaySocket = await this.findSwaySocket(config.runtimeDir);
}
if (!this.swaySocket) {
console.error('[swaymsg] No Sway IPC socket found');
return false;
}
const env: Record<string, string> = {
XDG_RUNTIME_DIR: config.runtimeDir,
WAYLAND_DISPLAY: config.waylandDisplay,
SWAYSOCK: this.swaySocket,
};
const envString = Object.entries(env)
@@ -292,6 +330,7 @@ for_window [app_id="chromium-browser"] fullscreen enable
// Process may already be dead
}
this.swayProcess = null;
this.swaySocket = null; // Reset socket so we find new one on restart
}
}
@@ -311,9 +350,19 @@ for_window [app_id="chromium-browser"] fullscreen enable
* Get connected displays via swaymsg
*/
async getDisplays(config: { runtimeDir: string; waylandDisplay: string }): Promise<DisplayInfo[]> {
// Find socket if not already found
if (!this.swaySocket) {
this.swaySocket = await this.findSwaySocket(config.runtimeDir);
}
if (!this.swaySocket) {
console.error('[displays] No Sway IPC socket found');
return [];
}
const env: Record<string, string> = {
XDG_RUNTIME_DIR: config.runtimeDir,
WAYLAND_DISPLAY: config.waylandDisplay,
SWAYSOCK: this.swaySocket,
};
const envString = Object.entries(env)
@@ -329,7 +378,8 @@ for_window [app_id="chromium-browser"] fullscreen enable
try {
const result = await cmd.output();
if (!result.success) {
console.error('[displays] Failed to get outputs');
const stderr = new TextDecoder().decode(result.stderr);
console.error(`[displays] Failed to get outputs: ${stderr}`);
return [];
}
@@ -427,6 +477,7 @@ for_window [app_id="chromium-browser"] fullscreen enable
console.log(`[${name}] Process exited with code ${status.code}`);
if (name === 'sway' && this.swayProcess === process) {
this.swayProcess = null;
this.swaySocket = null; // Reset socket so we find new one on restart
} else if (name === 'chromium' && this.browserProcess === process) {
this.browserProcess = null;
}

View File

@@ -1 +1 @@
export const VERSION = "0.3.9";
export const VERSION = "0.4.2";