Watch
1
0
Fork
You've already forked souveraine
0

settings: one Brightness dimming section, one blank timeout

The page asked the same question twice because two daemons answer it, and
split the blank budget by held-vs-resting — which makes the user arbitrate a
guess the accelerometer is making. Held-ness belongs in the confidence
arithmetic as an adjustment to one budget, not as a second budget here.
This commit is contained in:
Fimeg 2026-07-26 18:11:01 -04:00
commit c7c92d2680

View file

@ -58,23 +58,38 @@ ContentPage {
{ displayName: Translation.tr("5 min"), icon: "timer", value: 300 }, { displayName: Translation.tr("5 min"), icon: "timer", value: 300 },
{ displayName: Translation.tr("10 min"), icon: "timer", value: 600 } { displayName: Translation.tr("10 min"), icon: "timer", value: 600 }
] ]
// How long before the lock the dim starts. Wider range than the // ONE dim setting, for both authorities.
// lock-screen grace below: this one has a whole idle-to-lock budget to sit //
// inside, and 300 with a 10-minute lock is Casey's "the 15s dim starts at // This used to be two: a session dim (15s5min, before the lock) and a
// 9:45" shape at a larger scale. // separate lock-screen dim grace (520s, before the blank). They are two
readonly property var dimGracePresets: [ // daemons, but they are not two questions the user is answering "how
{ displayName: Translation.tr("15s"), icon: "brightness_medium", value: 15 }, // much warning do I get before the screen goes away", once. Splitting it
// made the page describe our architecture instead of their screen.
//
// Written to both: the shell's dimBeforeLockSeconds and sessiond's
// dim_grace_secs. The lock-screen side is clamped below, because a dim
// longer than the blank budget is a dim that never shows.
readonly property var dimPresets: [
{ displayName: Translation.tr("5s"), icon: "brightness_medium", value: 5 },
{ displayName: Translation.tr("10s"), icon: "brightness_medium", value: 10 },
{ displayName: Translation.tr("30s"), icon: "brightness_medium", value: 30 }, { displayName: Translation.tr("30s"), icon: "brightness_medium", value: 30 },
{ displayName: Translation.tr("1 min"), icon: "brightness_medium", value: 60 }, { displayName: Translation.tr("1 min"), icon: "brightness_medium", value: 60 },
{ displayName: Translation.tr("3 min"), icon: "brightness_medium", value: 180 }, { displayName: Translation.tr("3 min"), icon: "brightness_medium", value: 180 }
{ displayName: Translation.tr("5 min"), icon: "brightness_medium", value: 300 }
]
readonly property var gracePresets: [
{ displayName: Translation.tr("5s"), icon: "brightness_medium", value: 5 },
{ displayName: Translation.tr("10s"), icon: "brightness_medium", value: 10 },
{ displayName: Translation.tr("20s"), icon: "brightness_medium", value: 20 }
] ]
// The lock screen cannot warn for longer than it waits. Clamp rather than
// refuse: the user picked a warning length, and the honest reading of
// "30s warning, 15s blank" is "warn as early as this screen allows".
function applyDim(v) {
Config.options.lock.idle.dimBeforeLockSeconds = v;
if (!SessiondPolicy.available)
return;
const blank = SessiondPolicy.lockBlankAfterSecs;
SessiondPolicy.apply({
dim_grace_secs: blank > 0 ? Math.max(1, Math.min(v, blank - 1)) : v
});
}
// "2 min" reads better than "120 s" in a sentence about when things happen. // "2 min" reads better than "120 s" in a sentence about when things happen.
function clockText(secs) { function clockText(secs) {
if (secs >= 60 && secs % 60 === 0) if (secs >= 60 && secs % 60 === 0)
@ -171,22 +186,48 @@ ContentPage {
options: page.idlePresets options: page.idlePresets
} }
// Relative, not absolute. The two used to be independent seconds StyledText {
// values and nothing stopped a dim set past the lock, which produced Layout.fillWidth: true
// a dim that silently never fired. Choosing "how long before" makes visible: !Config.options.lock.idle.nativeCoordinatorEnabled
// the relationship the thing the user sets, so moving the lock moves wrapMode: Text.WordWrap
// the dim with it. color: Appearance.colors.colError
font.pixelSize: Appearance.font.pixelSize.smaller
text: Translation.tr("The native coordinator is off, so these do not run.")
}
}
// --- Brightness dimming, one question ---------------------------------
// Deliberately not split by authority. Two daemons own the actuation, and
// the page used to say so by giving each its own dim control which made
// the user answer the same question twice and left them to work out that
// the two interact. One control, written to both. See applyDim().
ContentSection {
icon: "brightness_medium"
title: Translation.tr("Brightness dimming")
ConfigSwitch {
buttonIcon: "brightness_low"
text: Translation.tr("Dim before the screen goes away")
checked: SessiondPolicy.dimWarning
enabled: SessiondPolicy.available
onCheckedChanged: {
if (SessiondPolicy.available && checked !== SessiondPolicy.dimWarning)
SessiondPolicy.apply({ dim_warning: checked });
}
}
ContentSubsectionLabel { ContentSubsectionLabel {
text: Translation.tr("Start dimming this long before locking") text: Translation.tr("Start dimming this long before")
} }
ConfigSelectionArray { ConfigSelectionArray {
currentValue: Config.options.lock.idle.dimBeforeLockSeconds currentValue: Config.options.lock.idle.dimBeforeLockSeconds
onSelected: v => Config.options.lock.idle.dimBeforeLockSeconds = v onSelected: v => page.applyDim(v)
options: page.dimGracePresets options: page.dimPresets
} }
// Say what the pair actually does. A relationship the user has to // Say what it actually does, on both surfaces, in one sentence each.
// compute in their head is one they will get wrong. // A relationship the user has to compute in their head is one they
// will get wrong.
StyledText { StyledText {
Layout.fillWidth: true Layout.fillWidth: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
@ -196,7 +237,7 @@ ContentPage {
const lock = Config.options.lock.idle.lockAfterSeconds; const lock = Config.options.lock.idle.lockAfterSeconds;
const grace = Config.options.lock.idle.dimBeforeLockSeconds; const grace = Config.options.lock.idle.dimBeforeLockSeconds;
const dimAt = Math.max(1, Math.min(lock - 1, lock - grace)); const dimAt = Math.max(1, Math.min(lock - 1, lock - grace));
return Translation.tr("Dims at %1, locks at %2.") return Translation.tr("In use: dims at %1, locks at %2.")
.arg(page.clockText(dimAt)) .arg(page.clockText(dimAt))
.arg(page.clockText(lock)); .arg(page.clockText(lock));
} }
@ -204,11 +245,19 @@ ContentPage {
StyledText { StyledText {
Layout.fillWidth: true Layout.fillWidth: true
visible: !Config.options.lock.idle.nativeCoordinatorEnabled visible: SessiondPolicy.available
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
color: Appearance.colors.colError color: Appearance.colors.colSubtext
font.pixelSize: Appearance.font.pixelSize.smaller font.pixelSize: Appearance.font.pixelSize.smaller
text: Translation.tr("The native coordinator is off, so these do not run.") text: {
const blank = SessiondPolicy.lockBlankAfterSecs;
if (blank === 0)
return Translation.tr("On the lock screen: never blanks, so nothing dims.");
const g = SessiondPolicy.dimGraceSecs;
return Translation.tr("On the lock screen: dims %1 before blanking at %2.")
.arg(page.clockText(g))
.arg(page.clockText(blank));
}
} }
} }
@ -245,51 +294,32 @@ ContentPage {
// desk-clock case" and nobody reasons about a lock screen in // desk-clock case" and nobody reasons about a lock screen in
// 5-second increments. Values are still seconds on the wire; the // 5-second increments. Values are still seconds on the wire; the
// daemon's vocabulary does not change because the UI got legible. // daemon's vocabulary does not change because the UI got legible.
// One blank timeout, not two.
//
// The daemon still has a separate held-vs-resting budget, and it is
// still the right idea a phone in your hand should not blank on the
// same schedule as one face-up on a desk. It is not a *setting*
// though. Asking the user to pick two numbers made them responsible
// for arbitrating a guess the accelerometer was making on their
// behalf, and the machine already has a better vocabulary for that:
// §4's confidence arithmetic. Held-ness belongs there, as an
// adjustment to one budget, not as a second budget on this page.
//
// Until that lands, both fields get the same value, so the behaviour
// is uniform and predictable rather than silently forking on a sensor
// reading nothing surfaces.
ContentSubsectionLabel { ContentSubsectionLabel {
text: Translation.tr("Blank after — on a table") text: Translation.tr("Blank after")
} }
ConfigSelectionArray { ConfigSelectionArray {
currentValue: SessiondPolicy.lockBlankAfterSecs currentValue: SessiondPolicy.lockBlankAfterSecs
onSelected: v => SessiondPolicy.apply({ lock_blank_after_secs: v }) onSelected: v => SessiondPolicy.apply({
lock_blank_after_secs: v,
lock_blank_after_held_secs: v
})
options: page.blankPresets options: page.blankPresets
} }
ContentSubsectionLabel {
text: Translation.tr("Blank after — in your hand")
}
StyledText {
Layout.fillWidth: true
wrapMode: Text.WordWrap
color: Appearance.colors.colSubtext
font.pixelSize: Appearance.font.pixelSize.smaller
text: Translation.tr("Used when the accelerometer says the device is being held rather than resting.")
}
ConfigSelectionArray {
currentValue: SessiondPolicy.lockBlankAfterHeldSecs
onSelected: v => SessiondPolicy.apply({ lock_blank_after_held_secs: v })
options: page.blankPresets
}
ContentSubsectionLabel {
text: Translation.tr("Dim warning before blanking")
}
ConfigSelectionArray {
currentValue: SessiondPolicy.dimGraceSecs
onSelected: v => SessiondPolicy.apply({ dim_grace_secs: v })
options: page.gracePresets
}
ConfigSwitch {
buttonIcon: "brightness_low"
text: Translation.tr("Show the dim warning")
checked: SessiondPolicy.dimWarning
enabled: SessiondPolicy.available
onCheckedChanged: {
if (SessiondPolicy.available && checked !== SessiondPolicy.dimWarning)
SessiondPolicy.apply({ dim_warning: checked });
}
}
// Only claim the ordering guarantee when the daemon actually reports // Only claim the ordering guarantee when the daemon actually reports
// the field. An older sessiond has no lock_ack_budget_secs, and // the field. An older sessiond has no lock_ack_budget_secs, and
// rendering that absence as "waits 0s" would be the page inventing a // rendering that absence as "waits 0s" would be the page inventing a