shell: execute authority directives; Settings reads sessiond
SessiondBridge: handle pushed {"directive":"lock"} on the heartbeat line and
raise the lock surface. Unknown directives are console.error — a silent drop
leaves the daemon blanking unlocked when its budget expires.
SessiondPolicy: new singleton, reads/writes DeviceStatePolicy over its own
short-lived connection (not the bridge socket — that EOF is shell-death
detection).
IdleConfig: new "Lock screen (device authority)" section bound to it. SetPolicy
had zero callers, so the old spinboxes moved a JSON file the daemon never read.
Says so in the error colour when sessiond is unreachable.
New file needs a deploy.sh manifest line or the services qmldir fails whole.
This commit is contained in:
parent
6eb87a542d
commit
24ce6d382b
4 changed files with 227 additions and 1 deletions
|
|
@ -111,7 +111,7 @@ ContentPage {
|
|||
|
||||
ContentSection {
|
||||
icon: "timer"
|
||||
title: Translation.tr("Timers")
|
||||
title: Translation.tr("Session timers")
|
||||
|
||||
// These write real Config keys, but they only take EFFECT when the
|
||||
// native coordinator is on. Disabled (greyed) otherwise so the page
|
||||
|
|
@ -146,4 +146,103 @@ ContentPage {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Lock screen timers, owned by sessiond ----------------------------
|
||||
// A separate section because these are a different authority. The two
|
||||
// above are the shell's own IdleMonitors deciding when to dim and lock a
|
||||
// session in use; these are the device state machine deciding how long a
|
||||
// LOCKED, lit panel may burn before it goes dark. That machine has its own
|
||||
// clock and its own actuators, so its numbers must come from it — which is
|
||||
// what SessiondPolicy is for, and what this page did not do until
|
||||
// 2026-07-25 (SetPolicy had zero callers; the daemon ran on its built-in
|
||||
// 15 s while this page showed whatever was in the JSON file).
|
||||
Component.onCompleted: SessiondPolicy.refresh()
|
||||
|
||||
ContentSection {
|
||||
icon: "phonelink_lock"
|
||||
title: Translation.tr("Lock screen (device authority)")
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
color: SessiondPolicy.available
|
||||
? Appearance.colors.colSubtext
|
||||
: Appearance.colors.colError
|
||||
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||
text: SessiondPolicy.available
|
||||
? Translation.tr("Read live from souveraine-sessiond. Changes here go straight to the daemon that blanks the panel.")
|
||||
: Translation.tr("sessiond is not answering — these values are NOT authoritative. %1").arg(SessiondPolicy.lastError)
|
||||
}
|
||||
|
||||
ConfigSpinBox {
|
||||
icon: "timer_off"
|
||||
text: Translation.tr("Blank the lock screen after (seconds, 0 = never)")
|
||||
value: SessiondPolicy.lockBlankAfterSecs
|
||||
from: 0
|
||||
to: 600
|
||||
stepSize: 5
|
||||
enabled: SessiondPolicy.available
|
||||
onValueChanged: {
|
||||
if (SessiondPolicy.available && value !== SessiondPolicy.lockBlankAfterSecs)
|
||||
SessiondPolicy.apply({ lock_blank_after_secs: value });
|
||||
}
|
||||
StyledToolTip {
|
||||
text: Translation.tr("How long a locked, lit screen waits before going dark. 0 keeps it lit forever — the desk-clock case.")
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSpinBox {
|
||||
icon: "back_hand"
|
||||
text: Translation.tr("…when the device is being held (seconds)")
|
||||
value: SessiondPolicy.lockBlankAfterHeldSecs
|
||||
from: 0
|
||||
to: 600
|
||||
stepSize: 5
|
||||
enabled: SessiondPolicy.available
|
||||
onValueChanged: {
|
||||
if (SessiondPolicy.available && value !== SessiondPolicy.lockBlankAfterHeldSecs)
|
||||
SessiondPolicy.apply({ lock_blank_after_held_secs: value });
|
||||
}
|
||||
StyledToolTip {
|
||||
text: Translation.tr("The same budget when the accelerometer says the device is in a hand rather than on a table.")
|
||||
}
|
||||
}
|
||||
|
||||
ConfigSpinBox {
|
||||
icon: "brightness_medium"
|
||||
text: Translation.tr("Dim warning before blanking (seconds)")
|
||||
value: SessiondPolicy.dimGraceSecs
|
||||
from: 1
|
||||
to: 120
|
||||
stepSize: 1
|
||||
enabled: SessiondPolicy.available && SessiondPolicy.dimWarning
|
||||
onValueChanged: {
|
||||
if (SessiondPolicy.available && value !== SessiondPolicy.dimGraceSecs)
|
||||
SessiondPolicy.apply({ dim_grace_secs: value });
|
||||
}
|
||||
StyledToolTip {
|
||||
text: Translation.tr("The panel visibly fades this long before it goes dark. A tap inside the window cancels the blank.")
|
||||
}
|
||||
}
|
||||
|
||||
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 });
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
color: Appearance.colors.colSubtext
|
||||
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||
text: Translation.tr("The screen never goes dark on an unlocked session. sessiond locks first and waits %1s for the compositor to acknowledge; if it cannot, it blanks anyway and records a security error rather than pretending the session locked.")
|
||||
.arg(SessiondPolicy.lockAckBudgetSecs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue