import Quickshell import Quickshell.Wayland import Quickshell.Widgets import Quickshell.Io import Quickshell.Services.Pam import QtQuick import QtQuick.Controls import QtQuick.Effects WlSessionLock { id: lock locked: false required property bool animate WlSessionLockSurface { id: surface color: "transparent" Component.onCompleted: console.log("done") Rectangle { id: content anchors.fill: parent opacity: !lock.animate || capture.ready color: "#141414" Rectangle { anchors { bottom: parent.bottom horizontalCenter: parent.horizontalCenter bottomMargin: surface.height/6 - this.height/2 } width: 300 height: 40 radius: height/2 color: "#222222" TextInput { id: input x: (parent.width - this.width)/2 Behavior on x { NumberAnimation { duration: 300 easing.type: Easing.OutQuint }} anchors.verticalCenter: parent.verticalCenter focus: true color: "white" font.pixelSize: 20 echoMode: TextInput.Password cursorDelegate: Item {} Keys.onReturnPressed: pam.start() } Text { anchors { horizontalCenter: parent.horizontalCenter top: parent.bottom topMargin: 10 } color: "white" font.pixelSize: 14 text: pam.message } } } ClippingRectangle { anchors.fill: parent color: "white" opacity: lock.animate radius: 0 RectangularShadow { anchors.fill: parent spread: 2 blur: 10 } ScreencopyView { id: capture anchors.fill: parent captureSource: surface.screen readonly property bool ready: { lock.animate && lock.secure && capture.hasContent } Connections { target: lock function onLockedChanged() {capture.captureFrame()} } } transform: Scale { origin { x: width/2; y: height/2 } xScale: 1 yScale: xScale NumberAnimation on xScale { running: capture.ready to: 0.80 duration: 800 easing.type: Easing.InQuint } NumberAnimation on xScale { id: exit running: false from: 0.8 to: 1 duration: 800 easing.type: Easing.OutQuint onStarted: { capture.parent.visible = true } onFinished: lock.locked = false } } SequentialAnimation on opacity { running: capture.ready PauseAnimation {duration: 500} NumberAnimation { duration: 300 to: 0 } } NumberAnimation on opacity { duration: 300 running: exit.running from: 0 to: 1 } NumberAnimation on radius { running: capture.ready duration: 800 to: 32 } NumberAnimation on radius { running: exit.running to: 0 duration: 800 } } PamContext { id: pam config: "pam.conf" configDirectory: "." onPamMessage: if (this.responseRequired) this.respond(input.text) onCompleted: result => { switch (result) { case PamResult.Success: exit.start() break; case PamResult.Failed: case PamResult.Error: case PamResult.MaxTries: input.clear() fail.start(); break; }} } } }