Integrate complete display layouts

This commit is contained in:
Gabriel Brown
2026-08-18 15:00:18 -04:00
parent 0c3935f818
commit d2898d8806
10 changed files with 220 additions and 31 deletions
@@ -41,6 +41,10 @@ Singleton {
property var readDisplays: function() { return DesktopPreferences.get("displays"); }
property var protectDisplays: function(value) { return DesktopPreferences.set("displays", value); }
property var displayBusy: function() { return Displays.busy || Displays.awaitingConfirmation; }
property var readLiveDisplayLayout: function() { return Displays.currentLayout(); }
property var applyDisplayLayout: function(layout) { return Displays.applyProtectedLayout(layout); }
property var displayCanConfirm: function() { return Displays.canConfirm; }
property var confirmDisplayLayout: function() { return Displays.confirm(); }
property var setDisplayBlocked: function(blocked) { Displays.externalChangeBlocked = blocked; }
property var applyCompositor: function() { SystemSettings.applyPersistedDisplayPolicy(); }
property var reloadKeybinds: function() { Keybinds.applyReload(); }
@@ -52,9 +56,11 @@ Singleton {
property var lockBusy: function() { return LockScreen.busy; }
property var reloadShell: function() { Quickshell.reload(false); }
property var protectedDisplays: ({})
property var protectedDisplayLayout: []
property var pendingRestoredLayout: null
readonly property bool busy: listQuery.running || actionRun.running
|| applyRestoredState.running || settleReload.running
|| settleDisplayRestore.running || applyRestoredState.running || settleReload.running
Process {
id: listQuery
@@ -89,18 +95,21 @@ Singleton {
if (actionRun.restoring) {
root.setDisplayBlocked(false);
root.protectedDisplays = ({});
root.protectedDisplayLayout = [];
}
return;
}
root.lastAction = actionRun.restoring ? "restored" : "saved";
if (actionRun.restoring) {
const homeReloaded = root.handleRestoreOutput(actionRun.outputText);
root.lastError = homeReloaded
? ""
: "Desktop settings were restored, but Home favourites could not be reloaded.";
if (!homeReloaded) {
const restoreAccepted = root.handleRestoreOutput(actionRun.outputText);
if (restoreAccepted)
root.lastError = "";
else if (root.lastError === "")
root.lastError = "Desktop settings were restored, but Home favourites could not be reloaded.";
if (!restoreAccepted) {
root.setDisplayBlocked(false);
root.protectedDisplays = ({});
root.protectedDisplayLayout = [];
}
} else
root.lastError = "";
@@ -108,6 +117,28 @@ Singleton {
}
}
Timer {
id: settleDisplayRestore
property int attempts: 0
interval: 100
repeat: true
onTriggered: {
attempts++;
if (root.displayCanConfirm()) {
stop();
if (!root.confirmDisplayLayout()) {
root.failDisplayRestore("The restored display layout could not be confirmed.");
return;
}
root.pendingRestoredLayout = null;
root.beginRestoredStateReplay();
} else if (!root.displayBusy() || attempts >= 180) {
stop();
root.failDisplayRestore("The restored display layout could not be verified.");
}
}
}
Timer {
id: applyRestoredState
interval: 80
@@ -141,6 +172,7 @@ Singleton {
stop();
root.setDisplayBlocked(false);
root.protectedDisplays = ({});
root.protectedDisplayLayout = [];
root.reloadShell();
}
}
@@ -179,12 +211,77 @@ Singleton {
if (!root.reloadHomeState(text))
return false;
root.reloadDesktop();
if (!root.protectDisplays(root.protectedDisplays))
return false;
applyRestoredState.restart();
const restoredLayout = root.layoutFromStoredDisplays(root.readDisplays());
if (restoredLayout === null || root.layoutsEqual(
restoredLayout, root.protectedDisplayLayout)) {
root.beginRestoredStateReplay();
return true;
}
root.pendingRestoredLayout = restoredLayout;
if (!root.applyDisplayLayout(restoredLayout))
return root.failDisplayRestore("The restored display layout was rejected.");
settleDisplayRestore.attempts = 0;
settleDisplayRestore.restart();
return true;
}
function beginRestoredStateReplay(): void {
applyRestoredState.restart();
}
function layoutFromStoredDisplays(stored: var): var {
if (!stored || typeof stored !== "object")
return null;
const current = root.readLiveDisplayLayout();
if (!Array.isArray(current) || current.length === 0)
return null;
const layout = [];
for (const live of current) {
const entry = stored[live.name];
const match = String(entry?.mode ?? "").match(
/^(\d+)x(\d+)@(\d+(?:\.\d+)?)$/);
if (!entry || !match || !Number.isFinite(entry.scale) || entry.scale <= 0
|| !Number.isInteger(entry.transform)
|| entry.transform < 0 || entry.transform > 3
|| !Number.isInteger(entry.x) || !Number.isInteger(entry.y)
|| typeof entry.primary !== "boolean")
return null;
layout.push(Object.assign({}, live, {
width: Number(match[1]),
height: Number(match[2]),
refreshRate: Number(match[3]),
mode: entry.mode,
scale: entry.scale,
transform: entry.transform,
x: entry.x,
y: entry.y,
primary: entry.primary
}));
}
return layout.filter(record => record.primary).length === 1 ? layout : null;
}
function layoutsEqual(left: var, right: var): bool {
if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length)
return false;
const fields = ["name", "mode", "scale", "transform", "x", "y", "primary"];
const a = Array.from(left).sort((x, y) => x.name.localeCompare(y.name));
const b = Array.from(right).sort((x, y) => x.name.localeCompare(y.name));
return a.every((record, index) => fields.every(
field => record[field] === b[index][field]));
}
function failDisplayRestore(message: string): bool {
root.pendingRestoredLayout = null;
if (!root.protectDisplays(root.protectedDisplays))
message += " The original display preference also could not be restored.";
root.setDisplayBlocked(false);
root.protectedDisplays = ({});
root.protectedDisplayLayout = [];
root.lastError = message;
return false;
}
// Restore output carries the canonical Home state. Reconstructing through
// these methods keeps validation and persistence inside HomePreferences;
// this service never mutates its aliases or private FileView directly.
@@ -252,6 +349,8 @@ Singleton {
const currentDisplays = root.readDisplays();
root.protectedDisplays = JSON.parse(JSON.stringify(
currentDisplays && typeof currentDisplays === "object" ? currentDisplays : {}));
root.protectedDisplayLayout = JSON.parse(JSON.stringify(
root.readLiveDisplayLayout() ?? []));
root.setDisplayBlocked(true);
actionRun.restoring = true;
actionRun.exec([root.helperPath, "restore", name]);