Harden display apply and recovery

This commit is contained in:
Gabriel Brown
2026-08-18 02:55:43 -04:00
parent 5671324eb2
commit 2d4b126f14
7 changed files with 422 additions and 64 deletions
@@ -110,7 +110,7 @@ Column {
onTapped: Displays.apply(
root.monitor.name,
rate.modelData.mode,
root.monitor.scale,
Displays.nearestCleanScale(rate.modelData.mode, root.monitor.scale),
root.monitor.transform)
}
}
@@ -21,6 +21,9 @@ SettingsPage {
lede: SystemSettings.monitorDescription || "Reading the active display…"
readonly property var monitor: Displays.monitors.length > 0 ? Displays.monitors[0] : null
readonly property string currentMode: root.monitor
? `${root.monitor.width}x${root.monitor.height}@${Math.round(root.monitor.refreshRate)}`
: ""
// The confirmation sits above everything, because while it is counting down
// it is the only thing that matters on this page.
@@ -76,6 +79,7 @@ SettingsPage {
id: keepButton
anchors.verticalCenter: parent.verticalCenter
text: "Keep"
enabled: Displays.canConfirm
onClicked: Displays.confirm()
}
}
@@ -131,7 +135,8 @@ SettingsPage {
width: parent.width
label: "Scale"
detail: "Fractional scales that do not divide the resolution into whole pixels are rejected by the compositor, so only clean ones are offered."
options: Displays.scales.map(scale => ({ value: scale, label: scale.toFixed(2) + "×" }))
options: Displays.scalesForMode(root.currentMode)
.map(scale => ({ value: scale, label: scale.toFixed(2) + "×" }))
current: root.monitor ? root.monitor.scale : 1
enabled: !Displays.awaitingConfirmation && !Displays.busy
onPicked: value => root.applyWith({ scale: value })
@@ -167,11 +172,14 @@ SettingsPage {
function applyWith(change: var): void {
if (!root.monitor)
return;
const current = `${root.monitor.width}x${root.monitor.height}@${Math.round(root.monitor.refreshRate)}`;
const mode = change.mode ?? root.currentMode;
const requestedScale = change.scale ?? root.monitor.scale;
Displays.apply(
root.monitor.name,
change.mode ?? current,
change.scale ?? root.monitor.scale,
mode,
Displays.isScaleClean(mode, requestedScale)
? requestedScale
: Displays.nearestCleanScale(mode, requestedScale),
change.transform ?? root.monitor.transform);
}
}
@@ -28,11 +28,31 @@ Item {
// scrolls -- the Appearance page pins its live preview here.
property Component header: null
Loader {
id: pinnedHeader
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.leftMargin: 34
anchors.rightMargin: 34
anchors.topMargin: 30
active: root.header !== null
sourceComponent: root.header
z: 1
}
Flickable {
anchors.fill: parent
id: pageScroll
anchors.left: parent.left
anchors.right: parent.right
anchors.top: pinnedHeader.active ? pinnedHeader.bottom : parent.top
anchors.bottom: parent.bottom
anchors.topMargin: pinnedHeader.active ? 16 : 0
clip: true
contentWidth: width
contentHeight: layout.implicitHeight + 64
contentHeight: layout.implicitHeight + (pinnedHeader.active ? 34 : 64)
boundsBehavior: Flickable.StopAtBounds
Column {
@@ -40,15 +60,9 @@ Item {
width: parent.width - 68
x: 34
y: 30
y: pinnedHeader.active ? 0 : 30
spacing: 16
Loader {
width: parent.width
active: root.header !== null
sourceComponent: root.header
}
Text {
width: parent.width
visible: root.title !== ""