From 3aa1d5f1ed23e0b857e1bd895f2979612d500696 Mon Sep 17 00:00:00 2001 From: 0blivi0nis <182329535+0blivi0nis@users.noreply.github.com> Date: Sun, 26 Oct 2025 14:50:50 -0700 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20feat(lock):=20add=20fingerprint?= =?UTF-8?q?=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Credit to @wooze-pao for providing the required code in #2162 --- .../quickshell/ii/modules/lock/Lock.qml | 10 ++++ .../ii/modules/lock/LockContext.qml | 46 +++++++++++++++++++ .../ii/modules/lock/LockSurface.qml | 22 +++++++++ .../ii/modules/lock/pam/fprintd.conf | 1 + 4 files changed, 79 insertions(+) create mode 100644 dots/.config/quickshell/ii/modules/lock/pam/fprintd.conf diff --git a/dots/.config/quickshell/ii/modules/lock/Lock.qml b/dots/.config/quickshell/ii/modules/lock/Lock.qml index 15950093c..5cfc12d72 100644 --- a/dots/.config/quickshell/ii/modules/lock/Lock.qml +++ b/dots/.config/quickshell/ii/modules/lock/Lock.qml @@ -32,6 +32,16 @@ Scope { } } + Connections { + target: GlobalStates + function onScreenLockedChanged() { + if (GlobalStates.screenLocked) { + lockContext.reset(); + lockContext.tryFingerUnlock(); + } + } + } + onUnlocked: (targetAction) => { // Perform the target action if it's not just unlocking if (targetAction == LockContext.ActionEnum.Poweroff) { diff --git a/dots/.config/quickshell/ii/modules/lock/LockContext.qml b/dots/.config/quickshell/ii/modules/lock/LockContext.qml index 7d030fc42..8a1bd5854 100644 --- a/dots/.config/quickshell/ii/modules/lock/LockContext.qml +++ b/dots/.config/quickshell/ii/modules/lock/LockContext.qml @@ -2,6 +2,7 @@ import qs import qs.modules.common import QtQuick import Quickshell +import Quickshell.Io import Quickshell.Services.Pam Scope { @@ -18,8 +19,13 @@ Scope { property string currentText: "" property bool unlockInProgress: false property bool showFailure: false + property bool fingerprintsConfigured: false property var targetAction: LockContext.ActionEnum.Unlock + Component.onCompleted: { + fingerprintCheckProcess.running = true; + } + function resetTargetAction() { root.targetAction = LockContext.ActionEnum.Unlock; } @@ -37,6 +43,46 @@ Scope { root.clearText(); root.unlockInProgress = false; } + + function tryFingerUnlock() { + fingerPam.start(); + } + + function stopPam() { + fingerPam.abort(); + } + + Process { + id: fingerprintCheckProcess + command: ["bash", "-c", "fprintd-list $(whoami)"] + stdout: StdioCollector { + id: fingerprintOutputCollector + onStreamFinished: { + root.fingerprintsConfigured = fingerprintOutputCollector.text.includes("Fingerprints for user"); + } + } + onExited: (exitCode, exitStatus) => { + if (exitCode !== 0) { + console.warn("fprintd-list command exited with error:", exitCode, exitStatus); + root.fingerprintsConfigured = false; + } + } + } + + PamContext { + id: fingerPam + + configDirectory: "pam" + config: "fprintd.conf" + + onCompleted: result => { + if (result == PamResult.Success) { + root.unlocked(root.targetAction); + } else if (result == PamResult.Error){ // if timeout or etc.. + tryFingerUnlock() + } + } + } Timer { id: passwordClearTimer diff --git a/dots/.config/quickshell/ii/modules/lock/LockSurface.qml b/dots/.config/quickshell/ii/modules/lock/LockSurface.qml index 5feba6c72..1f7c47c75 100644 --- a/dots/.config/quickshell/ii/modules/lock/LockSurface.qml +++ b/dots/.config/quickshell/ii/modules/lock/LockSurface.qml @@ -98,6 +98,28 @@ MouseArea { scale: root.toolbarScale opacity: root.toolbarOpacity + // Fingerprint + Loader { + Layout.leftMargin: 10 + Layout.alignment: Qt.AlignVCenter + active: root.context.fingerprintsConfigured // Bind to actual fingerprint availability + visible: root.context.fingerprintsConfigured + + sourceComponent: Row { + spacing: 8 + + MaterialSymbol { + id: fingerprintIcon + anchors.verticalCenter: parent.verticalCenter + fill: 1 + text: "fingerprint" + iconSize: Appearance.font.pixelSize.huge + color: Appearance.colors.colOnSurfaceVariant + animateChange: true + } + } + } + ToolbarTextField { id: passwordBox placeholderText: GlobalStates.screenUnlockFailed ? Translation.tr("Incorrect password") : Translation.tr("Enter password") diff --git a/dots/.config/quickshell/ii/modules/lock/pam/fprintd.conf b/dots/.config/quickshell/ii/modules/lock/pam/fprintd.conf new file mode 100644 index 000000000..73d9cc725 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/lock/pam/fprintd.conf @@ -0,0 +1 @@ +auth sufficient pam_fprintd.so \ No newline at end of file From 9610baf903a346ef1bbb98a87ddcbae086021b0b Mon Sep 17 00:00:00 2001 From: 0blivi0nis <182329535+0blivi0nis@users.noreply.github.com> Date: Sun, 26 Oct 2025 23:05:45 -0700 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=90=9B=20fix(lock):=20remove=20duplic?= =?UTF-8?q?ate=20connection,=20only=20start=20if=20configured,=20stop=20on?= =?UTF-8?q?=20unlock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quickshell/ii/modules/lock/Lock.qml | 7 -- .../ii/modules/lock/LockContext.qml | 85 ++++++++++--------- 2 files changed, 44 insertions(+), 48 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/lock/Lock.qml b/dots/.config/quickshell/ii/modules/lock/Lock.qml index 5cfc12d72..12ba1a2eb 100644 --- a/dots/.config/quickshell/ii/modules/lock/Lock.qml +++ b/dots/.config/quickshell/ii/modules/lock/Lock.qml @@ -25,13 +25,6 @@ Scope { LockContext { id: lockContext - Connections { - target: GlobalStates - function onScreenLockedChanged() { - if (GlobalStates.screenLocked) lockContext.reset(); - } - } - Connections { target: GlobalStates function onScreenLockedChanged() { diff --git a/dots/.config/quickshell/ii/modules/lock/LockContext.qml b/dots/.config/quickshell/ii/modules/lock/LockContext.qml index 8a1bd5854..8b245237b 100644 --- a/dots/.config/quickshell/ii/modules/lock/LockContext.qml +++ b/dots/.config/quickshell/ii/modules/lock/LockContext.qml @@ -2,7 +2,7 @@ import qs import qs.modules.common import QtQuick import Quickshell -import Quickshell.Io +import Quickshell.Io // Required for StdioCollector import Quickshell.Services.Pam Scope { @@ -43,46 +43,6 @@ Scope { root.clearText(); root.unlockInProgress = false; } - - function tryFingerUnlock() { - fingerPam.start(); - } - - function stopPam() { - fingerPam.abort(); - } - - Process { - id: fingerprintCheckProcess - command: ["bash", "-c", "fprintd-list $(whoami)"] - stdout: StdioCollector { - id: fingerprintOutputCollector - onStreamFinished: { - root.fingerprintsConfigured = fingerprintOutputCollector.text.includes("Fingerprints for user"); - } - } - onExited: (exitCode, exitStatus) => { - if (exitCode !== 0) { - console.warn("fprintd-list command exited with error:", exitCode, exitStatus); - root.fingerprintsConfigured = false; - } - } - } - - PamContext { - id: fingerPam - - configDirectory: "pam" - config: "fprintd.conf" - - onCompleted: result => { - if (result == PamResult.Success) { - root.unlocked(root.targetAction); - } else if (result == PamResult.Error){ // if timeout or etc.. - tryFingerUnlock() - } - } - } Timer { id: passwordClearTimer @@ -106,6 +66,33 @@ Scope { pam.start(); } + function tryFingerUnlock() { + if (root.fingerprintsConfigured) { + fingerPam.start(); + } + } + + function stopFingerPam() { + fingerPam.abort(); + } + + Process { + id: fingerprintCheckProcess + command: ["bash", "-c", "fprintd-list $(whoami)"] + stdout: StdioCollector { + id: fingerprintOutputCollector + onStreamFinished: { + root.fingerprintsConfigured = fingerprintOutputCollector.text.includes("Fingerprints for user"); + } + } + onExited: (exitCode, exitStatus) => { + if (exitCode !== 0) { + console.warn("fprintd-list command exited with error:", exitCode, exitStatus); + root.fingerprintsConfigured = false; + } + } + } + PamContext { id: pam @@ -120,6 +107,7 @@ Scope { onCompleted: result => { if (result == PamResult.Success) { root.unlocked(root.targetAction); + stopFingerPam(); } else { root.clearText(); root.unlockInProgress = false; @@ -129,4 +117,19 @@ Scope { } } + PamContext { + id: fingerPam + + configDirectory: "pam" + config: "fprintd.conf" + + onCompleted: result => { + if (result == PamResult.Success) { + root.unlocked(root.targetAction); + stopFingerPam(); + } else if (result == PamResult.Error){ // if timeout or etc.. + tryFingerUnlock() + } + } + } } From 175379dfdba0c51675ac1cbdd12f3f1b893d9177 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 30 Oct 2025 09:03:11 +0100 Subject: [PATCH 3/4] locksurface: adjust fingerprint icon size/spacing --- .../ii/modules/lock/LockSurface.qml | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/lock/LockSurface.qml b/dots/.config/quickshell/ii/modules/lock/LockSurface.qml index 1f7c47c75..8a3a73f60 100644 --- a/dots/.config/quickshell/ii/modules/lock/LockSurface.qml +++ b/dots/.config/quickshell/ii/modules/lock/LockSurface.qml @@ -101,22 +101,17 @@ MouseArea { // Fingerprint Loader { Layout.leftMargin: 10 + Layout.rightMargin: 6 Layout.alignment: Qt.AlignVCenter - active: root.context.fingerprintsConfigured // Bind to actual fingerprint availability - visible: root.context.fingerprintsConfigured + active: root.context.fingerprintsConfigured + visible: active - sourceComponent: Row { - spacing: 8 - - MaterialSymbol { - id: fingerprintIcon - anchors.verticalCenter: parent.verticalCenter - fill: 1 - text: "fingerprint" - iconSize: Appearance.font.pixelSize.huge - color: Appearance.colors.colOnSurfaceVariant - animateChange: true - } + sourceComponent: MaterialSymbol { + id: fingerprintIcon + fill: 1 + text: "fingerprint" + iconSize: Appearance.font.pixelSize.hugeass + color: Appearance.colors.colOnSurfaceVariant } } From e3db8372a7f1d8de4c2d0ff311c468e3db2248c4 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 30 Oct 2025 09:04:58 +0100 Subject: [PATCH 4/4] lock: remove useless comment, declare fingerprint check proc running directly --- dots/.config/quickshell/ii/modules/lock/LockContext.qml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/lock/LockContext.qml b/dots/.config/quickshell/ii/modules/lock/LockContext.qml index 8b245237b..dcfd9a85d 100644 --- a/dots/.config/quickshell/ii/modules/lock/LockContext.qml +++ b/dots/.config/quickshell/ii/modules/lock/LockContext.qml @@ -2,7 +2,7 @@ import qs import qs.modules.common import QtQuick import Quickshell -import Quickshell.Io // Required for StdioCollector +import Quickshell.Io import Quickshell.Services.Pam Scope { @@ -22,10 +22,6 @@ Scope { property bool fingerprintsConfigured: false property var targetAction: LockContext.ActionEnum.Unlock - Component.onCompleted: { - fingerprintCheckProcess.running = true; - } - function resetTargetAction() { root.targetAction = LockContext.ActionEnum.Unlock; } @@ -77,7 +73,8 @@ Scope { } Process { - id: fingerprintCheckProcess + id: fingerprintCheckProc + running: true command: ["bash", "-c", "fprintd-list $(whoami)"] stdout: StdioCollector { id: fingerprintOutputCollector