feat(lock): add fingerprint support

Credit to @wooze-pao for providing the required code in #2162
This commit is contained in:
0blivi0nis
2025-10-26 14:50:50 -07:00
parent 437b2020b7
commit 3aa1d5f1ed
4 changed files with 79 additions and 0 deletions
@@ -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) {
@@ -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
@@ -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")
@@ -0,0 +1 @@
auth sufficient pam_fprintd.so