mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-16 00:04:01 -04:00
* updated dank to support aqueous
* further updates
* aqueous support work
* updated to support workspace options better in aqueous
* added blur to dms shell for aqueous
* added keybinding update
* remove unneeded blur
* clean up per claud review
* swapped to ipc
* aqueous: move IPC integration to QML, delete test fixtures (since we
dont have a QML test structure even setup), delete in-repo docs
* fix staticcheck
* aqueous: consolidate more aqueous specific stuff
* add aqueous logo
---------
Co-authored-by: Zoey <[email protected]>
(cherry picked from commit b9365610c8)
150 lines
6.3 KiB
QML
150 lines
6.3 KiB
QML
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
|
|
import Quickshell
|
|
import qs.Services
|
|
|
|
Singleton {
|
|
id: root
|
|
readonly property var log: Log.scoped("AqueousConfigService")
|
|
property bool busy: false
|
|
|
|
function requireCapabilities(result, required) {
|
|
if (result?.protocol !== 1 || !Array.isArray(result.capabilities))
|
|
throw new Error("unsupported aqueous-config protocol or discovery");
|
|
for (const capability of required) {
|
|
if (!result.capabilities.includes(capability))
|
|
throw new Error("unsupported aqueous-config capability: " + capability);
|
|
}
|
|
}
|
|
|
|
function helper(operation, input, callback) {
|
|
const args = ["aqueous-config", operation, "--shell", "dms"];
|
|
if (input !== null)
|
|
args.push("--request", "-");
|
|
AqueousService.runJson(args, input, (result, error) => {
|
|
if (!error && result?.ok !== true)
|
|
error = result?.code ? result.code + ": " + (result.message || "") : "aqueous-config rejected the request";
|
|
callback(result, error);
|
|
});
|
|
}
|
|
|
|
function request(operation, draft, callback) {
|
|
if (!CompositorService.isAqueous || busy) {
|
|
callback(null, busy ? "busy" : "unavailable");
|
|
return;
|
|
}
|
|
busy = true;
|
|
const complete = (result, error) => {
|
|
busy = false;
|
|
if (error)
|
|
log.warn("helper operation failed:", operation, error);
|
|
callback(error ? null : result, error);
|
|
};
|
|
if (operation === "snapshot") {
|
|
helper("snapshot", null, (result, error) => {
|
|
try {
|
|
if (error)
|
|
throw new Error(error);
|
|
requireCapabilities(result, ["schema_fields", "shell_dms"]);
|
|
if (typeof result.generation !== "string" || !result.generation)
|
|
throw new Error("missing configuration generation");
|
|
complete(result, "");
|
|
} catch (e) {
|
|
complete(null, String(e));
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
if (!["apply", "validate"].includes(operation) || typeof draft?.expected_generation !== "string" || !draft.expected_generation) {
|
|
complete(null, "invalid operation or missing expected_generation; reload configuration");
|
|
return;
|
|
}
|
|
const request = Object.assign({}, draft, {
|
|
protocol: 1
|
|
});
|
|
request.backup_dir = request.backup_dir || (Quickshell.env("XDG_CONFIG_HOME") || Quickshell.env("HOME") + "/.config") + "/DankMaterialShell/aqueous-backups";
|
|
const input = JSON.stringify(request);
|
|
const required = ["validate", "stdin_requests", "generation_check", "atomic_file_replace", "shell_dms"];
|
|
for (const [key, capability] of Object.entries({
|
|
monitor_changes: "monitor_modes",
|
|
custom_keybind_changes: "keybinds",
|
|
sync_cursor: "cursor_sync",
|
|
sync_typography: "typography_sync"
|
|
})) {
|
|
if (Object.prototype.hasOwnProperty.call(request, key))
|
|
required.push(capability);
|
|
}
|
|
helper("version", null, (version, error) => {
|
|
try {
|
|
if (error)
|
|
throw new Error(error);
|
|
requireCapabilities(version, required);
|
|
} catch (e) {
|
|
complete(null, String(e));
|
|
return;
|
|
}
|
|
helper("validate", input, (validated, error) => {
|
|
if (error || operation === "validate") {
|
|
complete(validated, error);
|
|
return;
|
|
}
|
|
helper("apply", input, complete);
|
|
});
|
|
});
|
|
}
|
|
|
|
function buildOutputsConfig(snapshot, outputs, original) {
|
|
if (!snapshot.capabilities?.includes("monitor_modes"))
|
|
throw new Error("unsupported: monitor_modes");
|
|
const raw = (snapshot.raw_files?.outputs || "") + "\n" + (snapshot.raw_files?.wm || "");
|
|
if (/^\s*edid\s*=/m.test(raw))
|
|
throw new Error("unsupported: this aqueous-config version does not expose EDID monitor edits");
|
|
const transforms = ["normal", "90", "180", "270", "flipped", "flipped-90", "flipped-180", "flipped-270"];
|
|
const changes = [];
|
|
if ((snapshot.monitors || []).some(m => /[*?\[]/.test(m.name)))
|
|
throw new Error("unsupported: reconcile wildcard monitor configuration before persisting displays");
|
|
for (const output of outputs) {
|
|
const before = original.find(o => o.name === output.name);
|
|
if (!before)
|
|
throw new Error("conflict: output changed during preview");
|
|
if (output.enabled !== before.enabled)
|
|
throw new Error("unsupported: this aqueous-config version cannot persist output enablement");
|
|
if (output.adaptiveSync !== before.adaptiveSync)
|
|
throw new Error("unsupported: this aqueous-config version cannot persist adaptive sync");
|
|
if (!output.enabled)
|
|
continue;
|
|
const configured = (snapshot.monitors || []).filter(m => m.name === output.name);
|
|
if (configured.length > 1)
|
|
throw new Error("conflict: multiple configured monitor entries");
|
|
const monitor = configured[0];
|
|
if (Math.abs(output.scale - (monitor?.scale ?? 1)) > 0.0001)
|
|
throw new Error("unsupported: this aqueous-config version cannot persist output scale");
|
|
const mode = output.currentMode;
|
|
if (!mode)
|
|
throw new Error("unavailable: output mode");
|
|
changes.push({
|
|
id: monitor?.id || "live:" + output.name,
|
|
name: output.name,
|
|
x: output.x,
|
|
y: output.y,
|
|
transform: transforms[output.transform],
|
|
mode: mode.width + "x" + mode.height + "@" + (mode.refresh / 1000)
|
|
});
|
|
}
|
|
return {
|
|
expected_generation: snapshot.generation,
|
|
monitor_changes: changes,
|
|
create_user_override: true
|
|
};
|
|
}
|
|
|
|
function load(callback) {
|
|
request("snapshot", null, callback);
|
|
}
|
|
|
|
function apply(draft, callback) {
|
|
request("apply", draft, callback);
|
|
}
|
|
}
|