mirror of
https://github.com/zoriya/ags.git
synced 2026-06-08 20:35:40 +00:00
feature: add subprocess util
this would be the equivalent of deflisten in eww
This commit is contained in:
+40
-88
@@ -1,7 +1,6 @@
|
||||
import GLib from 'gi://GLib';
|
||||
import Gio from 'gi://Gio';
|
||||
import Service from './service.js';
|
||||
import { error, execAsync, warning } from '../utils.js';
|
||||
import { error, execAsync, subprocess } from '../utils.js';
|
||||
|
||||
const HIS = GLib.getenv('HYPRLAND_INSTANCE_SIGNATURE');
|
||||
|
||||
@@ -44,13 +43,6 @@ type Active = {
|
||||
workspace: ActiveWorkspace
|
||||
}
|
||||
|
||||
type HyprlandState = {
|
||||
active: Active
|
||||
monitors: Map<string, Monitor>
|
||||
workspaces: Map<number, Workspace>
|
||||
clients: Map<string, Client>
|
||||
}
|
||||
|
||||
class HyprlandService extends Service {
|
||||
static {
|
||||
Service.register(this, {
|
||||
@@ -59,55 +51,59 @@ class HyprlandService extends Service {
|
||||
});
|
||||
}
|
||||
|
||||
_state!: HyprlandState;
|
||||
_active: Active;
|
||||
_monitors: Map<string, Monitor>;
|
||||
_workspaces: Map<number, Workspace>;
|
||||
_clients: Map<string, Client>;
|
||||
|
||||
constructor() {
|
||||
if (!HIS)
|
||||
error('Hyprland is not running');
|
||||
|
||||
super();
|
||||
this._state = {
|
||||
active: {
|
||||
client: {
|
||||
address: '',
|
||||
title: '',
|
||||
class: '',
|
||||
},
|
||||
monitor: '',
|
||||
workspace: {
|
||||
id: 0,
|
||||
name: '',
|
||||
},
|
||||
this._active = {
|
||||
client: {
|
||||
address: '',
|
||||
title: '',
|
||||
class: '',
|
||||
},
|
||||
monitor: '',
|
||||
workspace: {
|
||||
id: 0,
|
||||
name: '',
|
||||
},
|
||||
monitors: new Map(),
|
||||
workspaces: new Map(),
|
||||
clients: new Map(),
|
||||
};
|
||||
|
||||
this._monitors = new Map();
|
||||
this._workspaces = new Map();
|
||||
this._clients = new Map();
|
||||
this._sync();
|
||||
this._startSocat();
|
||||
|
||||
const socat = `socat -U - UNIX-CONNECT:/tmp/hypr/${HIS}/.socket2.sock`;
|
||||
subprocess(['bash', '-c', socat], line => {
|
||||
this._onEvent(line);
|
||||
});
|
||||
}
|
||||
|
||||
async _sync() {
|
||||
try {
|
||||
const monitors = await execAsync('hyprctl -j monitors');
|
||||
this._state.monitors = new Map();
|
||||
this._monitors = new Map();
|
||||
(JSON.parse(monitors as string) as Monitor[]).forEach(monitor => {
|
||||
this._state.monitors.set(monitor.name, monitor);
|
||||
this._monitors.set(monitor.name, monitor);
|
||||
if (monitor.focused) {
|
||||
this._state.active.monitor = monitor.name;
|
||||
this._state.active.workspace = monitor.activeWorkspace;
|
||||
this._active.monitor = monitor.name;
|
||||
this._active.workspace = monitor.activeWorkspace;
|
||||
}
|
||||
});
|
||||
|
||||
const workspaces = await execAsync('hyprctl -j workspaces');
|
||||
this._state.workspaces = new Map();
|
||||
this._workspaces = new Map();
|
||||
(JSON.parse(workspaces as string) as Workspace[]).forEach(ws => {
|
||||
this._state.workspaces.set(ws.id, ws);
|
||||
this._workspaces.set(ws.id, ws);
|
||||
});
|
||||
|
||||
const clients = await execAsync('hyprctl -j clients');
|
||||
this._state.clients = new Map();
|
||||
this._clients = new Map();
|
||||
(JSON.parse(clients as string) as Client[]).forEach(c => {
|
||||
const {
|
||||
address,
|
||||
@@ -119,7 +115,7 @@ class HyprlandService extends Service {
|
||||
floating,
|
||||
} = c;
|
||||
|
||||
this._state.clients.set(address.substring(2), {
|
||||
this._clients.set(address.substring(2), {
|
||||
address,
|
||||
pid,
|
||||
workspace,
|
||||
@@ -145,16 +141,16 @@ class HyprlandService extends Service {
|
||||
|
||||
switch (e) {
|
||||
case 'activewindow':
|
||||
this._state.active.client.class = argv[0];
|
||||
this._state.active.client.title = argv[1];
|
||||
this._active.client.class = argv[0];
|
||||
this._active.client.title = argv[1];
|
||||
break;
|
||||
|
||||
case 'activewindowv2':
|
||||
this._state.active.client.address = argv[0];
|
||||
this._active.client.address = argv[0];
|
||||
break;
|
||||
|
||||
case 'closewindow':
|
||||
this._state.active.client = {
|
||||
this._active.client = {
|
||||
class: '',
|
||||
title: '',
|
||||
address: '',
|
||||
@@ -172,7 +168,7 @@ class HyprlandService extends Service {
|
||||
break;
|
||||
}
|
||||
case 'changefloating': {
|
||||
const client = this._state.clients.get(argv[0]);
|
||||
const client = this._clients.get(argv[0]);
|
||||
if (client)
|
||||
client.floating = argv[1] === '1';
|
||||
break;
|
||||
@@ -184,50 +180,6 @@ class HyprlandService extends Service {
|
||||
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
_startSocat() {
|
||||
try {
|
||||
const socat = `
|
||||
socat -U - UNIX-CONNECT:/tmp/hypr/${HIS}/.socket2.sock | while read lines
|
||||
do
|
||||
echo $lines
|
||||
done`;
|
||||
|
||||
const proc = Gio.Subprocess.new(
|
||||
['bash', '-c', socat],
|
||||
Gio.SubprocessFlags.STDOUT_PIPE,
|
||||
);
|
||||
|
||||
const pipe = proc.get_stdout_pipe();
|
||||
if (!pipe) {
|
||||
warning('socat error');
|
||||
return;
|
||||
}
|
||||
|
||||
const stdout = new Gio.DataInputStream({
|
||||
base_stream: pipe,
|
||||
close_base_stream: true,
|
||||
});
|
||||
|
||||
this._readSocat(stdout);
|
||||
} catch (e) {
|
||||
logError(e as Error);
|
||||
}
|
||||
}
|
||||
|
||||
_readSocat(stdout: Gio.DataInputStream) {
|
||||
stdout.read_line_async(GLib.PRIORITY_LOW, null, (stdout, res) => {
|
||||
try {
|
||||
const line = stdout?.read_line_finish_utf8(res)[0];
|
||||
if (line) {
|
||||
this._onEvent(line);
|
||||
this._readSocat(stdout);
|
||||
}
|
||||
} catch (e) {
|
||||
logError(e as Error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default class Hyprland {
|
||||
@@ -239,10 +191,10 @@ export default class Hyprland {
|
||||
return Hyprland._instance;
|
||||
}
|
||||
|
||||
static get active() { return Hyprland.instance._state.active; }
|
||||
static get monitors() { return Hyprland.instance._state.monitors; }
|
||||
static get workspaces() { return Hyprland.instance._state.workspaces; }
|
||||
static get clients() { return Hyprland.instance._state.clients; }
|
||||
static get active() { return Hyprland.instance._active; }
|
||||
static get monitors() { return Hyprland.instance._monitors; }
|
||||
static get workspaces() { return Hyprland.instance._workspaces; }
|
||||
static get clients() { return Hyprland.instance._clients; }
|
||||
|
||||
static HyprctlGet(cmd: string): unknown | object {
|
||||
const [success, out, err] =
|
||||
|
||||
+42
-4
@@ -222,11 +222,8 @@ export function isRunning(dbusName: string) {
|
||||
}
|
||||
|
||||
export function execAsync(cmd: string | string[]) {
|
||||
if (typeof cmd === 'string')
|
||||
cmd = cmd.split(' ');
|
||||
|
||||
const proc = Gio.Subprocess.new(
|
||||
cmd,
|
||||
typeof cmd === 'string' ? cmd.split(' ') : cmd,
|
||||
Gio.SubprocessFlags.STDOUT_PIPE |
|
||||
Gio.SubprocessFlags.STDERR_PIPE,
|
||||
);
|
||||
@@ -258,3 +255,44 @@ export function exec(cmd: string) {
|
||||
|
||||
return decoder.decode(out).trim();
|
||||
}
|
||||
|
||||
export function subprocess(
|
||||
cmd: string | string[],
|
||||
callback: (out: string) => void,
|
||||
onError = logError,
|
||||
) {
|
||||
try {
|
||||
const read = (stdout: Gio.DataInputStream) => {
|
||||
stdout.read_line_async(GLib.PRIORITY_LOW, null, (stdout, res) => {
|
||||
try {
|
||||
const output = stdout?.read_line_finish_utf8(res)[0];
|
||||
if (output) {
|
||||
callback(output);
|
||||
read(stdout);
|
||||
}
|
||||
} catch (e) {
|
||||
return onError(e as Error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const proc = Gio.Subprocess.new(
|
||||
typeof cmd === 'string' ? cmd.split(' ') : cmd,
|
||||
Gio.SubprocessFlags.STDOUT_PIPE |
|
||||
Gio.SubprocessFlags.STDERR_PIPE,
|
||||
);
|
||||
|
||||
const pipe = proc.get_stdout_pipe();
|
||||
if (!pipe)
|
||||
return onError(new Error(`subprocess ${cmd} stdout pipe is null`));
|
||||
|
||||
const stdout = new Gio.DataInputStream({
|
||||
base_stream: pipe,
|
||||
close_base_stream: true,
|
||||
});
|
||||
|
||||
read(stdout);
|
||||
} catch (e) {
|
||||
return onError(e as Error);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user