From 713ba1efbb0bbb39ffaf93f6413db03d92e0b5d8 Mon Sep 17 00:00:00 2001 From: bbedward Date: Tue, 28 Apr 2026 10:12:35 -0400 Subject: [PATCH] idle/lock: add option to turn off monitors after lock explicitly --- quickshell/Modules/Lock/Lock.qml | 8 ++ quickshell/Modules/Lock/LockScreenContent.qml | 79 ++++++++----------- quickshell/Modules/Lock/LockSurface.qml | 2 + quickshell/Modules/Lock/Pam.qml | 48 +++++------ quickshell/assets/pam/fprint | 2 +- 5 files changed, 70 insertions(+), 69 deletions(-) diff --git a/quickshell/Modules/Lock/Lock.qml b/quickshell/Modules/Lock/Lock.qml index 9a5a00fb..1b06c690 100644 --- a/quickshell/Modules/Lock/Lock.qml +++ b/quickshell/Modules/Lock/Lock.qml @@ -147,6 +147,13 @@ Scope { } } + Pam { + id: sharedPam + lockSecured: root.shouldLock + buffer: root.sharedPasswordBuffer + onUnlockRequested: root.unlock() + } + WlSessionLock { id: sessionLock @@ -170,6 +177,7 @@ Scope { anchors.fill: parent visible: lockSurface.isActiveScreen lock: sessionLock + pam: sharedPam sharedPasswordBuffer: root.sharedPasswordBuffer screenName: lockSurface.currentScreenName isLocked: shouldLock diff --git a/quickshell/Modules/Lock/LockScreenContent.qml b/quickshell/Modules/Lock/LockScreenContent.qml index 3a7f0ab2..de8f0d54 100644 --- a/quickshell/Modules/Lock/LockScreenContent.qml +++ b/quickshell/Modules/Lock/LockScreenContent.qml @@ -23,6 +23,7 @@ Item { property string passwordBuffer: "" property bool demoMode: false + property var pam: demoPam property string screenName: "" property bool unlocking: false property string pamState: "" @@ -52,20 +53,18 @@ Item { return I18n.tr("Touch your security key..."); if (pam.lockMessage && pam.lockMessage.length > 0) return pam.lockMessage; - if (pam.fprintState === "error") { - const detail = (pam.fprint.message || "").trim(); - return detail.length > 0 ? I18n.tr("Fingerprint error: %1").arg(detail) : I18n.tr("Fingerprint error"); - } - if (pam.fprintState === "max") - return I18n.tr("Maximum fingerprint attempts reached. Please use password."); - if (pam.fprintState === "fail") - return I18n.tr("Fingerprint not recognized (%1/%2). Please try again or use password.").arg(pam.fprint.tries).arg(SettingsData.maxFprintTries); if (root.pamState === "error") return I18n.tr("Authentication error - try again"); if (root.pamState === "max") return I18n.tr("Too many attempts - locked out"); if (root.pamState === "fail") return I18n.tr("Incorrect password - try again"); + if (pam.fprintState === "error") + return I18n.tr("Fingerprint error"); + if (pam.fprintState === "max") + return I18n.tr("Maximum fingerprint attempts reached. Please use password."); + if (pam.fprintState === "fail") + return I18n.tr("Fingerprint not recognized (%1/%2). Please try again or use password.").arg(pam.fprint.tries).arg(SettingsData.maxFprintTries); return ""; } @@ -745,13 +744,6 @@ Item { easing.type: Theme.standardEasing } } - - Behavior on color { - ColorAnimation { - duration: Theme.shortDuration - easing.type: Theme.standardEasing - } - } } } @@ -1639,49 +1631,46 @@ Item { } Pam { - id: pam - lockSecured: !demoMode - onUnlockRequested: { + id: demoPam + lockSecured: false + } + + Connections { + target: root.pam + + function onUnlockRequested() { root.unlocking = true; lockerReadyArmed = false; passwordField.text = ""; root.passwordBuffer = ""; root.unlockRequested(); } - onStateChanged: { - root.pamState = state; - if (state !== "") { - root.unlocking = false; - placeholderDelay.restart(); - passwordField.text = ""; - root.passwordBuffer = ""; - } - } - onU2fPendingChanged: { - if (u2fPending) { - passwordField.text = ""; - root.passwordBuffer = ""; - if (keyboardController.isKeyboardActive) - keyboardController.hide(); - } - } - } - Connections { - target: pam + function onStateChanged() { + root.pamState = root.pam.state; + if (root.pam.state === "") + return; + root.unlocking = false; + placeholderDelay.restart(); + passwordField.text = ""; + root.passwordBuffer = ""; + } + + function onU2fPendingChanged() { + if (!root.pam.u2fPending) + return; + passwordField.text = ""; + root.passwordBuffer = ""; + if (keyboardController.isKeyboardActive) + keyboardController.hide(); + } function onUnlockInProgressChanged() { - if (!pam.unlockInProgress && root.unlocking) + if (!root.pam.unlockInProgress && root.unlocking) root.unlocking = false; } } - Binding { - target: pam - property: "buffer" - value: root.passwordBuffer - } - Timer { id: placeholderDelay diff --git a/quickshell/Modules/Lock/LockSurface.qml b/quickshell/Modules/Lock/LockSurface.qml index b8a5cf8b..0eba8bac 100644 --- a/quickshell/Modules/Lock/LockSurface.qml +++ b/quickshell/Modules/Lock/LockSurface.qml @@ -7,6 +7,7 @@ Rectangle { id: root required property WlSessionLock lock + required property var pam required property string sharedPasswordBuffer required property string screenName required property bool isLocked @@ -21,6 +22,7 @@ Rectangle { anchors.fill: parent demoMode: false + pam: root.pam passwordBuffer: root.sharedPasswordBuffer screenName: root.screenName onUnlockRequested: root.unlockRequested() diff --git a/quickshell/Modules/Lock/Pam.qml b/quickshell/Modules/Lock/Pam.qml index 0a772e5d..8064cb30 100644 --- a/quickshell/Modules/Lock/Pam.qml +++ b/quickshell/Modules/Lock/Pam.qml @@ -179,6 +179,8 @@ Scope { abort(); return; } + if (active) + return; tries = 0; errorTries = 0; @@ -192,22 +194,23 @@ Scope { if (!available) return; - if (res === PamResult.Success) { + switch (res) { + case PamResult.Success: if (!root.unlockInProgress) { passwd.abort(); root.proceedAfterPrimaryAuth(); } return; - } - - if (res === PamResult.Error) { - root.fprintState = "error"; + case PamResult.Error: errorTries++; - if (errorTries < 5) { + if (errorTries < 200) { abort(); errorRetry.restart(); + return; } - } else if (res === PamResult.MaxTries) { + abort(); + return; + case PamResult.MaxTries: tries++; if (tries < SettingsData.maxFprintTries) { root.fprintState = "fail"; @@ -216,6 +219,9 @@ Scope { root.fprintState = "max"; abort(); } + break; + default: + return; } root.flashMsg(); @@ -294,7 +300,7 @@ Scope { Timer { id: errorRetry - interval: 800 + interval: 1500 onTriggered: fprint.start() } @@ -346,26 +352,22 @@ Scope { id: fprintStateReset interval: 4000 - onTriggered: { - root.fprintState = ""; - fprint.errorTries = 0; - } + onTriggered: root.fprintState = "" } onLockSecuredChanged: { - if (lockSecured) { - SettingsData.refreshAuthAvailability(); - root.state = ""; - root.fprintState = ""; - root.u2fState = ""; - root.u2fPending = false; - root.lockMessage = ""; - root.resetAuthFlows(); - fprint.checkAvail(); - u2f.checkAvail(); - } else { + if (!lockSecured) { root.resetAuthFlows(); + return; } + root.state = ""; + root.fprintState = ""; + root.u2fState = ""; + root.u2fPending = false; + root.lockMessage = ""; + root.resetAuthFlows(); + fprint.checkAvail(); + u2f.checkAvail(); } Connections { diff --git a/quickshell/assets/pam/fprint b/quickshell/assets/pam/fprint index 770a8a4f..a0f41d7c 100644 --- a/quickshell/assets/pam/fprint +++ b/quickshell/assets/pam/fprint @@ -1,3 +1,3 @@ #%PAM-1.0 -auth required pam_fprintd.so max-tries=1 timeout=5 +auth required pam_fprintd.so max-tries=5