aboutsummaryrefslogtreecommitdiffstats
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/Status.qml58
1 files changed, 50 insertions, 8 deletions
diff --git a/shared/Status.qml b/shared/Status.qml
index 8f80b9a..be090b3 100644
--- a/shared/Status.qml
+++ b/shared/Status.qml
@@ -32,34 +32,71 @@ Singleton {
readonly property bool dnd: dndFile.value
readonly property bool presentation: presFile.value
+ // Stored as "auto-lock disabled", so the missing-file default of off is
+ // the wanted default of locking on. The row inverts it for the label.
+ readonly property bool nolock: nolockFile.value
readonly property int activeCount: (root.dnd ? 1 : 0) + (root.presentation ? 1 : 0)
+ + (root.nolock ? 1 : 0)
// Set once by shell.qml. IdleInhibitor does nothing with a null window,
// and the singleton has no window of its own to offer.
property var inhibitWindow: null
- // What dnd was before presentation mode turned it on, so turning
- // presentation mode off restores it rather than clearing it. Held here
- // rather than in a file: it is meaningful only while presentation mode is
- // on, and presentation mode does not survive a reboot.
+ // What dnd and nolock were before presentation mode drove them, so turning
+ // presentation mode off restores them rather than clearing them. Held here
+ // rather than in a file: they are meaningful only while presentation mode
+ // is on, and presentation mode does not survive a reboot.
//
// Known limit: on a shell restart while presentation is already on,
- // onPresentationChanged can run before the dnd FileView has loaded, so the
- // recorded prior value depends on which file loads first.
+ // onPresentationChanged can run before these FileViews have loaded, so the
+ // recorded prior values depend on which file loads first.
property bool dndBeforePresentation: false
+ property bool nolockBeforePresentation: false
+
+ // Deadline for a timed disable, owned by the singleton rather than the row
+ // because the drawer page (and so the row) is destroyed on close while the
+ // effect has to outlive it. Shell-lifetime only: a restart while a timed
+ // disable is pending leaves the lock off until it is toggled, which is
+ // safe because the user opted into the disable.
+ property double nolockUntil: 0
function setMode(name, on) {
if (name === "dnd") {
dndFile.write(on);
} else if (name === "presentation") {
presFile.write(on);
+ } else if (name === "nolock") {
+ // Any write clears a pending deadline; the timed path sets it back.
+ root.nolockUntil = 0;
+ nolockFile.write(on);
}
}
+ // Disable auto-lock, optionally for a number of minutes. Zero or a
+ // non-number means until toggled back.
+ function disableLockFor(minutes) {
+ const m = Number(minutes);
+ root.setMode("nolock", true);
+ if (m > 0) root.nolockUntil = Date.now() + m * 60000;
+ }
+
function toggleMode(name) {
if (name === "dnd") root.setMode("dnd", !root.dnd);
else if (name === "presentation") root.setMode("presentation", !root.presentation);
+ else if (name === "nolock") root.setMode("nolock", !root.nolock);
+ }
+
+ // The timed disable re-enables itself. Runs only while a deadline is
+ // pending, so no tick burns while the mode is off or permanently on.
+ Timer {
+ id: nolockTimer
+ interval: 1000
+ repeat: true
+ running: root.nolockUntil > 0
+ onTriggered: {
+ if (Date.now() >= root.nolockUntil) root.setMode("nolock", false);
+ }
}
// Effects follow the mode rather than the setter, so a mode set by
@@ -67,10 +104,13 @@ Singleton {
onPresentationChanged: {
if (root.presentation) {
root.dndBeforePresentation = root.dnd;
+ root.nolockBeforePresentation = root.nolock;
root.setMode("dnd", true);
+ root.setMode("nolock", true);
root.runBreaktimer("pause");
} else {
root.setMode("dnd", root.dndBeforePresentation);
+ root.setMode("nolock", root.nolockBeforePresentation);
root.runBreaktimer("resume");
}
}
@@ -94,10 +134,11 @@ Singleton {
// Wayland idle inhibit. The compositor advertises
// zwp_idle_inhibit_manager_v1 and hypridle honours it, so no D-Bus path
- // is needed even though elogind runs here.
+ // is needed even though elogind runs here. nolock is the sole holder;
+ // presentation drives nolock, so it needs no second inhibitor.
IdleInhibitor {
window: root.inhibitWindow
- enabled: root.presentation && root.inhibitWindow !== null
+ enabled: root.nolock && root.inhibitWindow !== null
}
component ModeFile: FileView {
@@ -136,4 +177,5 @@ Singleton {
ModeFile { id: dndFile; path: root.dir + "/status.dnd" }
ModeFile { id: presFile; path: root.dir + "/status.presentation" }
+ ModeFile { id: nolockFile; path: root.dir + "/status.nolock" }
}