diff --git a/assets/pam.d/howdy b/assets/pam.d/howdy new file mode 100644 index 000000000..5e5b50396 --- /dev/null +++ b/assets/pam.d/howdy @@ -0,0 +1 @@ +auth required pam_howdy.so diff --git a/modules/lock/Center.qml b/modules/lock/Center.qml index bfd747de2..41524b361 100644 --- a/modules/lock/Center.qml +++ b/modules/lock/Center.qml @@ -9,7 +9,7 @@ ColumnLayout { id: root required property var lock - readonly property real centerScale: Math.min(1, (lock.screen?.height ?? 1440) / 1440) + readonly property real centerScale: Math.min(1, (lock.screen ? lock.screen.height : 1440) / 1440) readonly property int centerWidth: Tokens.sizes.lock.centerWidth * centerScale Layout.preferredWidth: centerWidth diff --git a/modules/lock/Lock.qml b/modules/lock/Lock.qml index f852cb7ff..8c47139bc 100644 --- a/modules/lock/Lock.qml +++ b/modules/lock/Lock.qml @@ -28,7 +28,7 @@ Scope { Loader { asynchronous: true - active: true + active: Quickshell.screens.length > 0 onLoaded: active = false // Force a load of a screencopy so the one in the lock works diff --git a/modules/lock/Pam.qml b/modules/lock/Pam.qml index f4c617473..2d377bef2 100644 --- a/modules/lock/Pam.qml +++ b/modules/lock/Pam.qml @@ -12,10 +12,12 @@ Scope { readonly property alias passwd: passwd readonly property alias fprint: fprint + readonly property alias howdy: howdy + property string lockMessage property string state - property string fprintState - property string buffer + property string fprintState: "" + property string buffer: "" signal flashMsg @@ -23,8 +25,19 @@ Scope { if (passwd.active || state === "max") return; + if (howdy.active && event.key !== Qt.Key_Enter && event.key !== Qt.Key_Return) { + howdy.abort(); + } + if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { - passwd.start(); + if (buffer.length === 0) { + if (howdy.available) + howdy.trigger(); + } else { + if (howdy.active) + howdy.abort(); + passwd.start(); + } } else if (event.key === Qt.Key_Backspace) { if (event.modifiers & Qt.ControlModifier) { buffer = ""; @@ -32,7 +45,6 @@ Scope { buffer = buffer.slice(0, -1); } } else if (/^[^\x00-\x1F\x7F-\x9F]+$/.test(event.text)) { - // Allow anything except control characters buffer += event.text; } } @@ -53,7 +65,6 @@ Scope { onResponseRequiredChanged: { if (!responseRequired) return; - respond(root.buffer); root.buffer = ""; } @@ -61,7 +72,6 @@ Scope { onCompleted: res => { if (res === PamResult.Success) return root.lock.unlock(); - if (res === PamResult.Error) root.state = "error"; else if (res === PamResult.MaxTries) @@ -77,9 +87,9 @@ Scope { PamContext { id: fprint - property bool available - property int tries - property int errorTries + property bool available: false + property int tries: 0 + property int errorTries: 0 function checkAvail(): void { if (!available || !GlobalConfig.lock.enableFprint || !root.lock.secure) { @@ -110,11 +120,8 @@ Scope { errorRetry.restart(); } } else if (res === PamResult.MaxTries) { - // Isn't actually the real max tries as pam only reports completed - // when max tries is reached. tries++; if (tries < GlobalConfig.lock.maxFprintTries) { - // Restart if not actually real max tries root.fprintState = "fail"; start(); } else { @@ -128,20 +135,54 @@ Scope { } } + PamContext { + id: howdy + + property bool available: false + + function trigger(): void { + if (!available || !root.lock.secure) + return; + start(); + } + + config: "howdy" + configDirectory: Quickshell.shellDir + "/assets/pam.d" + + onCompleted: res => { + if (res === PamResult.Success) + return root.lock.unlock(); + else + abort(); + } + } + Process { - id: availProc + id: fprintAvailProc command: ["sh", "-c", "fprintd-list $USER"] - onExited: code => { // qmllint disable signal-handler-parameters + + onExited: (code, exitStatus) => { // qmllint disable signal-handler-parameters fprint.available = code === 0; fprint.checkAvail(); } } + Process { + id: howdyAvailProc + + command: ["sh", "-c", "command -v howdy"] + + onExited: (code, exitStatus) => { // qmllint disable signal-handler-parameters + howdy.available = code === 0; + } + } + Timer { id: errorRetry interval: 800 + onTriggered: fprint.start() } @@ -149,6 +190,7 @@ Scope { id: stateReset interval: 4000 + onTriggered: { if (root.state !== "max") root.state = ""; @@ -159,6 +201,7 @@ Scope { id: fprintStateReset interval: 4000 + onTriggered: { root.fprintState = ""; fprint.errorTries = 0; @@ -168,7 +211,8 @@ Scope { Connections { function onSecureChanged(): void { if (root.lock.secure) { - availProc.running = true; + fprintAvailProc.running = true; + howdyAvailProc.running = true; root.buffer = ""; root.state = ""; root.fprintState = ""; @@ -178,6 +222,8 @@ Scope { function onUnlock(): void { fprint.abort(); + howdy.abort(); + passwd.abort(); } target: root.lock diff --git a/modules/lock/center/InputField.qml b/modules/lock/center/InputField.qml index 90b0c7dea..238dc779a 100644 --- a/modules/lock/center/InputField.qml +++ b/modules/lock/center/InputField.qml @@ -48,6 +48,8 @@ Item { text: { if (root.pam.passwd.active) return qsTr("Loading..."); + if (root.pam.howdy.active) + return qsTr("Scanning face..."); if (root.pam.state === "max") return qsTr("Max tries reached"); return qsTr("Enter your password"); diff --git a/modules/lock/center/PasswordInput.qml b/modules/lock/center/PasswordInput.qml index e93884a27..982ef4ec3 100644 --- a/modules/lock/center/PasswordInput.qml +++ b/modules/lock/center/PasswordInput.qml @@ -65,8 +65,8 @@ StyledRect { AnimLoader { anchors.centerIn: parent - anchors.verticalCenterOffset: sourceComponent === iconComp ? 1 : 0 - sourceComp: root.lock.pam.passwd.active ? loadingComp : iconComp + anchors.verticalCenterOffset: sourceComp === iconComp ? 1 : 0 + sourceComp: (root.lock.pam.passwd.active || root.lock.pam.howdy.active) ? loadingComp : iconComp } Component { @@ -75,6 +75,8 @@ StyledRect { MaterialIcon { animate: true text: { + if (root.lock.pam.howdy.active) + return "face"; if (root.lock.pam.fprint.tries >= GlobalConfig.lock.maxFprintTries) return "fingerprint_off"; if (root.lock.pam.fprint.active) diff --git a/plugin/src/Caelestia/Blobs/CMakeLists.txt b/plugin/src/Caelestia/Blobs/CMakeLists.txt index 9506f7f44..ea4056cda 100644 --- a/plugin/src/Caelestia/Blobs/CMakeLists.txt +++ b/plugin/src/Caelestia/Blobs/CMakeLists.txt @@ -1,11 +1,11 @@ qml_module(caelestia-blobs URI Caelestia.Blobs SOURCES - blobgroup.cpp - blobshape.cpp - blobrect.cpp - blobinvertedrect.cpp - blobmaterial.cpp + blobgroup.hpp blobgroup.cpp + blobshape.hpp blobshape.cpp + blobrect.hpp blobrect.cpp + blobinvertedrect.hpp blobinvertedrect.cpp + blobmaterial.hpp blobmaterial.cpp LIBRARIES Qt::Quick ) diff --git a/plugin/src/Caelestia/Components/CMakeLists.txt b/plugin/src/Caelestia/Components/CMakeLists.txt index ac8ce166e..cb46ea2af 100644 --- a/plugin/src/Caelestia/Components/CMakeLists.txt +++ b/plugin/src/Caelestia/Components/CMakeLists.txt @@ -1,9 +1,9 @@ qml_module(caelestia-components URI Caelestia.Components SOURCES - lazylistview.cpp - wavyline.cpp - buttonrow.cpp + lazylistview.hpp lazylistview.cpp + wavyline.hpp wavyline.cpp + buttonrow.hpp buttonrow.cpp LIBRARIES Qt::Quick ) diff --git a/plugin/src/Caelestia/Config/CMakeLists.txt b/plugin/src/Caelestia/Config/CMakeLists.txt index 15e4b7c2f..739b0d8ba 100644 --- a/plugin/src/Caelestia/Config/CMakeLists.txt +++ b/plugin/src/Caelestia/Config/CMakeLists.txt @@ -1,17 +1,17 @@ qml_module(caelestia-config URI Caelestia.Config SOURCES - config.cpp - configattached.cpp - configobject.cpp - rootconfig.cpp - appearanceconfig.cpp - font.cpp - fontbuilder.cpp - tokens.cpp - tokensattached.cpp - anim.cpp - monitorconfigmanager.cpp + config.hpp config.cpp + configattached.hpp configattached.cpp + configobject.hpp configobject.cpp + rootconfig.hpp rootconfig.cpp + appearanceconfig.hpp appearanceconfig.cpp + font.hpp font.cpp + fontbuilder.hpp fontbuilder.cpp + tokens.hpp tokens.cpp + tokensattached.hpp tokensattached.cpp + anim.hpp anim.cpp + monitorconfigmanager.hpp monitorconfigmanager.cpp backgroundconfig.hpp barconfig.hpp borderconfig.hpp diff --git a/plugin/src/Caelestia/Images/CMakeLists.txt b/plugin/src/Caelestia/Images/CMakeLists.txt index d869667d8..307c4a942 100644 --- a/plugin/src/Caelestia/Images/CMakeLists.txt +++ b/plugin/src/Caelestia/Images/CMakeLists.txt @@ -1,9 +1,9 @@ qml_module(caelestia-images URI Caelestia.Images SOURCES - cachingimageprovider.cpp - imagecacher.cpp - iutils.cpp + cachingimageprovider.hpp cachingimageprovider.cpp + imagecacher.hpp imagecacher.cpp + iutils.hpp iutils.cpp LIBRARIES Qt::Gui Qt::Quick diff --git a/plugin/src/Caelestia/Internal/CMakeLists.txt b/plugin/src/Caelestia/Internal/CMakeLists.txt index abcaf86b4..7b7b12510 100644 --- a/plugin/src/Caelestia/Internal/CMakeLists.txt +++ b/plugin/src/Caelestia/Internal/CMakeLists.txt @@ -1,14 +1,14 @@ qml_module(caelestia-internal URI Caelestia.Internal SOURCES - circularbuffer.cpp - circularindicatormanager.cpp - linearindicatormanager.cpp - hyprdevices.cpp - hyprextras.cpp - logindmanager.cpp - sparklineitem.cpp - visualiserbars.cpp + circularbuffer.hpp circularbuffer.cpp + circularindicatormanager.hpp circularindicatormanager.cpp + linearindicatormanager.hpp linearindicatormanager.cpp + hyprdevices.hpp hyprdevices.cpp + hyprextras.hpp hyprextras.cpp + logindmanager.hpp logindmanager.cpp + sparklineitem.hpp sparklineitem.cpp + visualiserbars.hpp visualiserbars.cpp LIBRARIES Qt::Gui Qt::Quick diff --git a/plugin/src/Caelestia/Services/CMakeLists.txt b/plugin/src/Caelestia/Services/CMakeLists.txt index 5c85ae5f1..f7ee07440 100644 --- a/plugin/src/Caelestia/Services/CMakeLists.txt +++ b/plugin/src/Caelestia/Services/CMakeLists.txt @@ -1,22 +1,22 @@ qml_module(caelestia-services URI Caelestia.Services SOURCES - service.cpp - serviceref.cpp - beattracker.cpp - audiocollector.cpp - audioprovider.cpp - cavaprovider.cpp - tickingservice.cpp - sensorslib.cpp - usagefmt.cpp - cpu.cpp - gpu.cpp - memory.cpp - diskinfo.cpp - storage.cpp - lyriccandidate.cpp - lyrics.cpp + service.hpp service.cpp + serviceref.hpp serviceref.cpp + beattracker.hpp beattracker.cpp + audiocollector.hpp audiocollector.cpp + audioprovider.hpp audioprovider.cpp + cavaprovider.hpp cavaprovider.cpp + tickingservice.hpp tickingservice.cpp + sensorslib.hpp sensorslib.cpp + usagefmt.hpp usagefmt.cpp + cpu.hpp cpu.cpp + gpu.hpp gpu.cpp + memory.hpp memory.cpp + diskinfo.hpp diskinfo.cpp + storage.hpp storage.cpp + lyriccandidate.hpp lyriccandidate.cpp + lyrics.hpp lyrics.cpp LIBRARIES PkgConfig::Pipewire PkgConfig::Aubio