diff options
Diffstat (limited to 'shared')
| -rw-r--r-- | shared/Status.qml | 58 |
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" } } |
