Rebuild Displays around the canvas, and let the transaction keep color

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-24 10:44:11 -04:00
parent 1f694b00b6
commit 9bc68ba358
29 changed files with 3065 additions and 388 deletions
@@ -10,9 +10,53 @@ ShellRoot {
{ name: "HDMI-A-1", width: 2560, height: 1440, scale: 1, transform: 1, x: 3140, y: 80, primary: false }
]
// The same two displays, with the second mirroring the first. A mirrored
// display has no position of its own: the compositor puts it on top of its
// target, so its stored coordinates are stale the moment mirroring is on.
readonly property var mirrored: [
{ name: "DP-2", width: 4500, height: 3000, scale: 1.5, transform: 0, x: 140, y: 80, primary: true, mirrorOf: "" },
{ name: "HDMI-A-1", width: 2560, height: 1440, scale: 1, transform: 0, x: 3140, y: 80, primary: false, mirrorOf: "DP-2" }
]
IpcHandler {
target: "display-layout-test"
function mirror(): string {
const normalized = DisplayLayout.normalize(mirrored);
const canvas = DisplayLayout.canvasRects(normalized, 800, 500, 20);
return JSON.stringify({
valid: DisplayLayout.validate(mirrored),
normalized: normalized.map(record => ({
name: record.name, x: record.x, y: record.y,
primary: record.primary, mirrorOf: record.mirrorOf ?? ""
})),
bounds: canvas.bounds,
rects: canvas.rects
});
}
function invalidMirrors(): string {
const base = mirrored.map(record => Object.assign({}, record));
const cases = [];
const add = layout => cases.push(DisplayLayout.validate(layout));
// Mirroring itself.
add([base[0], Object.assign({}, base[1], { mirrorOf: "HDMI-A-1" })]);
// Mirroring an output that is not in the layout.
add([base[0], Object.assign({}, base[1], { mirrorOf: "NOPE-1" })]);
// The primary may not mirror: the desktop is anchored on it.
add([Object.assign({}, base[0], { mirrorOf: "HDMI-A-1" }), base[1]]);
// No chains. Hyprland resolves a mirror to one target, and a chain
// is a question nobody can answer from the canvas.
add([
base[0],
Object.assign({}, base[1], { mirrorOf: "DP-3" }),
{ name: "DP-3", width: 1920, height: 1080, scale: 1, transform: 0, x: 6000, y: 0, primary: false, mirrorOf: "DP-2" }
]);
// Not a name at all.
add([base[0], Object.assign({}, base[1], { mirrorOf: 5 })]);
return JSON.stringify(cases);
}
function status(): string {
const normalized = DisplayLayout.normalize(fixture);
const canvas = DisplayLayout.canvasRects(normalized, 800, 500, 20);