From 1221ac804ccaa8bd39cbd2ea0a02cd61f231393d Mon Sep 17 00:00:00 2001 From: charlotte whittleman Date: Sat, 28 Mar 2026 11:51:09 -0500 Subject: [PATCH 1/4] feat(lockscreen): add fprintd fingerprint authentication --- modules/lockscreen/LockScreen.qml | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/modules/lockscreen/LockScreen.qml b/modules/lockscreen/LockScreen.qml index e3f48446..b41a99d7 100644 --- a/modules/lockscreen/LockScreen.qml +++ b/modules/lockscreen/LockScreen.qml @@ -22,6 +22,8 @@ WlSessionLockSurface { property bool authenticating: false property string errorMessage: "" property int failLockSecondsLeft: 0 + property bool fingerprintAvailable: false + property bool fingerprintScanning: false // Always transparent - blur background handles the visuals color: "transparent" @@ -525,6 +527,12 @@ WlSessionLockSurface { if (passwordInput.text.trim() === "") return; + // Stop fingerprint scan while password auth runs + if (fprintdVerify.running) { + fprintdVerify.running = false; + fingerprintScanning = false; + } + // Guardar contraseña y limpiar campo inmediatamente authPasswordHolder.password = passwordInput.text; passwordInput.text = ""; @@ -578,6 +586,11 @@ WlSessionLockSurface { passwordInput.text = ""; authenticating = false; passwordInputBox.showError = false; + // Resume fingerprint scanning after failed password attempt + if (fingerprintAvailable) { + fprintdVerify.running = true; + fingerprintScanning = true; + } } } } @@ -662,6 +675,58 @@ WlSessionLockSurface { } } + // Fingerprint authentication via fprintd + // Step 1: check if user has any enrolled fingers + Process { + id: fprintdCheckProc + command: ["bash", "-c", `fprintd-list '${usernameCollector.text.trim()}' 2>/dev/null`] + running: false + + stdout: StdioCollector { + onStreamFinished: { + // fprintd-list output contains "finger" for each enrolled finger + if (text.trim() !== "" && text.indexOf("finger") >= 0) { + fingerprintAvailable = true; + fprintdVerify.running = true; + fingerprintScanning = true; + } + } + } + } + + // Step 2: run fprintd-verify and watch for match + Process { + id: fprintdVerify + command: ["fprintd-verify", usernameCollector.text.trim()] + running: false + + stdout: StdioCollector { + id: fprintdVerifyOut + onStreamFinished: { + fingerprintScanning = false; + if (text.indexOf("verify-match") >= 0) { + // Fingerprint matched — trigger the same unlock flow as password success + startAnim = false; + unlockTimer.start(); + errorMessage = ""; + authenticating = false; + } + // On failure or timeout, do nothing — user can still type password + } + } + } + + // Start fingerprint check once the username is known + Connections { + target: usernameCollector + function onTextChanged() { + const user = usernameCollector.text.trim(); + if (user !== "" && startAnim && !fprintdCheckProc.running && !fingerprintAvailable) { + fprintdCheckProc.running = true; + } + } + } + // PAM authentication process PamContext { id: pamAuth @@ -746,5 +811,11 @@ WlSessionLockSurface { // Start animations startAnim = true; passwordInput.forceActiveFocus(); + + // If username is already available (whoami finished), start fingerprint check now. + // Otherwise the Connections on usernameCollector will trigger it. + if (usernameCollector.text.trim() !== "") { + fprintdCheckProc.running = true; + } } } From bdf5faa7daa7bdc3887d3623075cc71ef9987a9e Mon Sep 17 00:00:00 2001 From: charlotte whittleman Date: Sat, 28 Mar 2026 11:55:00 -0500 Subject: [PATCH 2/4] feat(lockscreen): add fingerprint icon and scanning animation --- modules/lockscreen/LockScreen.qml | 30 +++++++++++++++++++++++++++--- modules/theme/Icons.qml | 1 + 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/modules/lockscreen/LockScreen.qml b/modules/lockscreen/LockScreen.qml index b41a99d7..1e83d4b8 100644 --- a/modules/lockscreen/LockScreen.qml +++ b/modules/lockscreen/LockScreen.qml @@ -454,10 +454,10 @@ WlSessionLockSurface { anchors.rightMargin: 32 spacing: 8 - // User icon / Spinner + // User icon / Spinner / Fingerprint Text { id: userIcon - text: authenticating ? Icons.circleNotch : Icons.user + text: authenticating ? Icons.circleNotch : (fingerprintScanning ? Icons.fingerprint : Icons.user) font.family: Icons.font font.pixelSize: 24 color: passwordFieldBg.item @@ -475,6 +475,7 @@ WlSessionLockSurface { } } + // Spinner for password auth Timer { id: spinnerTimer interval: 100 @@ -485,10 +486,33 @@ WlSessionLockSurface { } } + // Breathing pulse for fingerprint scanning + SequentialAnimation { + running: fingerprintScanning && !authenticating + loops: Animation.Infinite + NumberAnimation { + target: userIcon + property: "opacity" + to: 0.35 + duration: 900 + easing.type: Easing.InOutSine + } + NumberAnimation { + target: userIcon + property: "opacity" + to: 1.0 + duration: 900 + easing.type: Easing.InOutSine + } + } + onTextChanged: { - if (userIcon.text === Icons.user) { + if (userIcon.text !== Icons.circleNotch) { userIcon.rotation = 0; } + if (userIcon.text !== Icons.fingerprint) { + userIcon.opacity = 1.0; + } } } diff --git a/modules/theme/Icons.qml b/modules/theme/Icons.qml index c6a690a5..b6b89a58 100644 --- a/modules/theme/Icons.qml +++ b/modules/theme/Icons.qml @@ -179,6 +179,7 @@ QtObject { readonly property string sunDim: "" readonly property string moon: "" readonly property string user: "" + readonly property string fingerprint: "" readonly property string spinnerGap: "" readonly property string circleNotch: "" readonly property string file: "" From a5541b50c89f864bb5a0b46d1e4e7f2ae3246c22 Mon Sep 17 00:00:00 2001 From: charlotte whittleman Date: Sat, 28 Mar 2026 12:22:05 -0500 Subject: [PATCH 3/4] fix(lockscreen): tighten fprintd enrollment check to avoid false positives --- modules/lockscreen/LockScreen.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lockscreen/LockScreen.qml b/modules/lockscreen/LockScreen.qml index 1e83d4b8..1ad65eb1 100644 --- a/modules/lockscreen/LockScreen.qml +++ b/modules/lockscreen/LockScreen.qml @@ -709,7 +709,7 @@ WlSessionLockSurface { stdout: StdioCollector { onStreamFinished: { // fprintd-list output contains "finger" for each enrolled finger - if (text.trim() !== "" && text.indexOf("finger") >= 0) { + if (text.indexOf("-finger") >= 0) { fingerprintAvailable = true; fprintdVerify.running = true; fingerprintScanning = true; From 58af1c4544bd69cb2ba104b55047fe25e72a9bf5 Mon Sep 17 00:00:00 2001 From: charlotte whittleman Date: Sat, 28 Mar 2026 12:35:00 -0500 Subject: [PATCH 4/4] fix(lockscreen): slow down fingerprint pulse animation by 30% --- modules/lockscreen/LockScreen.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/lockscreen/LockScreen.qml b/modules/lockscreen/LockScreen.qml index 1ad65eb1..1ef8bc43 100644 --- a/modules/lockscreen/LockScreen.qml +++ b/modules/lockscreen/LockScreen.qml @@ -494,14 +494,14 @@ WlSessionLockSurface { target: userIcon property: "opacity" to: 0.35 - duration: 900 + duration: 1170 easing.type: Easing.InOutSine } NumberAnimation { target: userIcon property: "opacity" to: 1.0 - duration: 900 + duration: 1170 easing.type: Easing.InOutSine } }