1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 21:42:51 -05:00

common: add Proc.runCommand helper

This commit is contained in:
bbedward
2025-10-14 15:14:20 -04:00
parent 5bb5cd296d
commit 9ff0d7405f
2 changed files with 86 additions and 28 deletions

69
Common/Proc.qml Normal file
View File

@@ -0,0 +1,69 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
Singleton {
id: root
property int defaultDebounceMs: 50
property var _procDebouncers: ({}) // id -> { timer, command, callback, waitMs }
function runCommand(id, command, callback, debounceMs) {
const wait = (typeof debounceMs === "number" && debounceMs >= 0) ? debounceMs : defaultDebounceMs
if (!_procDebouncers[id]) {
const t = Qt.createQmlObject('import QtQuick; Timer { repeat: false }', root)
t.triggered.connect(function() { _launchProc(id) })
_procDebouncers[id] = { timer: t, command: command, callback: callback, waitMs: wait }
} else {
_procDebouncers[id].command = command
_procDebouncers[id].callback = callback
_procDebouncers[id].waitMs = wait
}
const entry = _procDebouncers[id]
entry.timer.interval = entry.waitMs
entry.timer.restart()
}
function _launchProc(id) {
const entry = _procDebouncers[id]
if (!entry) return
const proc = Qt.createQmlObject('import Quickshell.Io; Process { running: false }', root)
const out = Qt.createQmlObject('import Quickshell.Io; StdioCollector {}', proc)
const err = Qt.createQmlObject('import Quickshell.Io; StdioCollector {}', proc)
proc.stdout = out
proc.stderr = err
proc.command = entry.command
let capturedOut = ""
let exitSeen = false
let exitCodeValue = -1
out.streamFinished.connect(function() {
capturedOut = out.text || ""
maybeComplete()
})
proc.exited.connect(function(code) {
exitSeen = true
exitCodeValue = code
maybeComplete()
})
function maybeComplete() {
if (!exitSeen) return
if (typeof entry.callback === "function") {
try { entry.callback(capturedOut, exitCodeValue) } catch (e) { console.warn("runCommand callback error:", e) }
}
try { proc.destroy() } catch (_) {}
}
proc.running = true
}
}

View File

@@ -59,33 +59,6 @@ Singleton {
onTriggered: root.doGenerateNiriLayoutConfig()
}
Process {
id: outputsProcess
command: ["niri", "msg", "-j", "outputs"]
stdout: StdioCollector {
onStreamFinished: {
try {
const outputsData = JSON.parse(text)
outputs = outputsData
console.log("NiriService: Loaded", Object.keys(outputsData).length, "outputs")
updateDisplayScales()
if (windows.length > 0) {
windows = sortWindowsByLayout(windows)
}
} catch (e) {
console.warn("NiriService: Failed to parse outputs:", e)
}
}
}
onExited: exitCode => {
if (exitCode !== 0) {
console.warn("NiriService: Failed to fetch outputs, exit code:", exitCode)
}
}
}
Process {
id: validateProcess
command: ["niri", "validate"]
@@ -168,7 +141,23 @@ Singleton {
function fetchOutputs() {
if (!CompositorService.isNiri) return
outputsProcess.running = true
Proc.runCommand("niri-fetch-outputs", ["niri", "msg", "-j", "outputs"], (output, exitCode) => {
if (exitCode !== 0) {
console.warn("NiriService: Failed to fetch outputs, exit code:", exitCode)
return
}
try {
const outputsData = JSON.parse(output)
outputs = outputsData
console.log("NiriService: Loaded", Object.keys(outputsData).length, "outputs")
updateDisplayScales()
if (windows.length > 0) {
windows = sortWindowsByLayout(windows)
}
} catch (e) {
console.warn("NiriService: Failed to parse outputs:", e)
}
})
}
function updateDisplayScales() {