import QtQuick import QtQuick.Effects import Quickshell import Quickshell.Wayland import ".." as M WlSessionLockSurface { id: root required property WlSessionLock lock required property LockAuth auth color: "transparent" // Blur screenshot of desktop as background ScreencopyView { id: background anchors.fill: parent captureSource: root.screen opacity: 0 layer.enabled: true layer.effect: MultiEffect { autoPaddingEnabled: false blurEnabled: true blur: 1 blurMax: 64 } NumberAnimation on opacity { to: 1 duration: 400 easing.type: Easing.OutCubic } } // Dim overlay Rectangle { anchors.fill: parent color: Qt.rgba(M.Theme.base00.r, M.Theme.base00.g, M.Theme.base00.b, 0.4) opacity: background.opacity } // Center content Item { id: content anchors.centerIn: parent width: 320 height: _col.height opacity: 0 scale: 0.9 NumberAnimation on opacity { to: 1 duration: 300 easing.type: Easing.OutCubic } NumberAnimation on scale { to: 1 duration: 300 easing.type: Easing.OutCubic } Column { id: _col anchors.horizontalCenter: parent.horizontalCenter spacing: 24 // Clock Text { anchors.horizontalCenter: parent.horizontalCenter text: Qt.formatTime(new Date(), "HH:mm") color: M.Theme.base05 font.pixelSize: 72 font.family: M.Theme.fontFamily font.bold: true Timer { interval: 1000 running: true repeat: true onTriggered: parent.text = Qt.formatTime(new Date(), "HH:mm") } } // Date Text { anchors.horizontalCenter: parent.horizontalCenter text: Qt.formatDate(new Date(), "dddd, d MMMM") color: M.Theme.base04 font.pixelSize: M.Theme.fontSize + 2 font.family: M.Theme.fontFamily Timer { interval: 60000 running: true repeat: true onTriggered: parent.text = Qt.formatDate(new Date(), "dddd, d MMMM") } } // Spacer Item { width: 1 height: 24 } // Password input LockInput { anchors.horizontalCenter: parent.horizontalCenter width: 280 buffer: root.auth.buffer state: root.auth.state } // Error message Text { id: _errorText anchors.horizontalCenter: parent.horizontalCenter text: root.auth.message color: M.Theme.base08 font.pixelSize: M.Theme.fontSize - 1 font.family: M.Theme.fontFamily opacity: root.auth.message ? 1 : 0 height: root.auth.message ? implicitHeight : 0 Behavior on opacity { NumberAnimation { duration: 200 } } Behavior on height { NumberAnimation { duration: 200 easing.type: Easing.OutCubic } } } } } // Keyboard input - focus lives on an Item since WlSessionLockSurface is a window Item { anchors.fill: parent focus: true Keys.onPressed: event => { if (!root._unlocking) root.auth.handleKey(event); } } // Unlock animation property bool _unlocking: false Connections { target: root.lock function onUnlock() { root._unlocking = true; _unlockAnim.start(); } } SequentialAnimation { id: _unlockAnim ParallelAnimation { NumberAnimation { target: content property: "opacity" to: 0 duration: 200 easing.type: Easing.InCubic } NumberAnimation { target: content property: "scale" to: 0.9 duration: 200 easing.type: Easing.InCubic } NumberAnimation { target: background property: "opacity" to: 0 duration: 300 easing.type: Easing.InCubic } } PropertyAction { target: root.lock property: "locked" value: false } } // Shake animation on auth failure SequentialAnimation { id: _shakeAnim NumberAnimation { target: content property: "anchors.horizontalCenterOffset" to: 12 duration: 50 } NumberAnimation { target: content property: "anchors.horizontalCenterOffset" to: -12 duration: 50 } NumberAnimation { target: content property: "anchors.horizontalCenterOffset" to: 8 duration: 50 } NumberAnimation { target: content property: "anchors.horizontalCenterOffset" to: -8 duration: 50 } NumberAnimation { target: content property: "anchors.horizontalCenterOffset" to: 0 duration: 50 } } Connections { target: root.auth function onAuthFailed() { _shakeAnim.restart(); } } }