import QtQuick import Quickshell import Quickshell.Wayland import Quickshell.Services.Pam QtObject { id: root required property WlSessionLock lock // Auth state: "", "busy", "fail", "error", "max" property string state: "" property string message: "" property string buffer: "" signal authFailed function handleKey(event) { if (_passwd.active || state === "max") return; if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { if (buffer.length > 0) _passwd.start(); } else if (event.key === Qt.Key_Backspace) { if (event.modifiers & Qt.ControlModifier) buffer = ""; else buffer = buffer.slice(0, -1); } else if (event.key === Qt.Key_Escape) { buffer = ""; } else if (event.text && event.text.length === 1) { const c = event.text; // Accept printable ASCII if (c.charCodeAt(0) >= 32 && c.charCodeAt(0) < 127) buffer += c; } } property PamContext _passwd: PamContext { config: "nova-shell" configDirectory: Quickshell.shellDir + "/assets/pam.d" onActiveChanged: { if (active) root.state = "busy"; } onResponseRequiredChanged: { if (!responseRequired) return; respond(root.buffer); root.buffer = ""; } onCompleted: res => { if (res === PamResult.Success) { root.state = ""; root.message = ""; root.lock.unlock(); return; } if (res === PamResult.Error) { root.state = "error"; root.message = "Authentication error"; } else if (res === PamResult.MaxTries) { root.state = "max"; root.message = "Too many attempts"; } else if (res === PamResult.Failed) { root.state = "fail"; root.message = "Wrong password"; } root.authFailed(); _stateReset.restart(); } onMessageChanged: { if (message.startsWith("The account is locked")) root.message = message; } } property Timer _stateReset: Timer { interval: 3000 onTriggered: { if (root.state !== "max") root.state = ""; } } // Reset state when lock becomes secure (freshly locked) property Connections _lockConn: Connections { target: root.lock function onSecureChanged() { if (root.lock.secure) { root.buffer = ""; root.state = ""; root.message = ""; } } } }