lock screen added

This commit is contained in:
2025-12-30 23:15:24 -08:00
parent 9e4198288b
commit 98416e2d27
2 changed files with 179 additions and 35 deletions

View File

@@ -20,7 +20,6 @@ PanelWindow {
function open() { function open() {
visible = true visible = true
list.visible = true list.visible = true
list.modelChanged()
} }
implicitWidth: 800 implicitWidth: 800
@@ -67,7 +66,6 @@ PanelWindow {
} }
} }
// TODO: Swap ListView for ScriptModel
ListView { ListView {
id: list id: list
spacing: 6 spacing: 6
@@ -76,14 +74,8 @@ PanelWindow {
highlightRangeMode: ListView.StrictlyEnforceRange highlightRangeMode: ListView.StrictlyEnforceRange
preferredHighlightBegin: 120 preferredHighlightBegin: 120
preferredHighlightEnd: this.height/2 preferredHighlightEnd: this.height/2
onModelChanged: {
if (searchInput.text === "")
currentIndex = currentApps.findIndex(entry =>
entry.id === lastLaunched
);
}
model: currentApps model: ScriptModel { values: currentApps; objectProp: "id" }
delegate: Button { delegate: Button {
height: entry_height height: entry_height
width: launcher.width + 10 width: launcher.width + 10

204
Lock.qml
View File

@@ -4,28 +4,48 @@ import QtQuick.Effects
import QtQuick.Shapes import QtQuick.Shapes
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Services.Pam
WlSessionLock { WlSessionLock {
id: lock id: lock
readonly property string bgPath: "assets/lockbg.jpg" readonly property string bgPath: "assets/lockbg.jpg"
readonly property string logoPath: "assets/logo.svg" readonly property string logoPath: "assets/logo.svg"
function open() { function open() {
locked = true locked = true
} }
function close() { function close() {
locked = false exitAnimation.start()
} }
locked: false locked: false
component OutQuint300: Behavior {
enabled: lock.secure
PropertyAnimation {
duration: 500
easing.type: Easing.OutQuint
}
}
component Shear5: Shear {
required property real height
xFactor: height * Math.tan(5 * Math.PI/180) / -100
}
surface: WlSessionLockSurface { surface: WlSessionLockSurface {
id: surface id: surface
color: "transparent" color: "transparent"
Item { Item {
id: content id: content
visible: true
layer.enabled: true
anchors.fill: parent anchors.fill: parent
layer.enabled: true
property bool idle: !passInput.text.length
Keys.onReturnPressed: {
idle = false
if (!pam.active) {
pam.start()
}
}
Image { Image {
visible: false
source: lock.bgPath source: lock.bgPath
anchors { anchors {
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
@@ -35,16 +55,136 @@ WlSessionLock {
height: surface.height height: surface.height
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
} }
Item {
anchors {
left: parent.left
right: parent.right
verticalCenter: parent.verticalCenter
}
height: logo.height * 0.3
Rectangle {
anchors {
left: parent.left
right: parent.right
verticalCenter: parent.verticalCenter
}
height: parent.height * !content.idle
opacity: !content.idle
OutQuint300 on height {}
OutQuint300 on opacity {}
color: "#323232"
RectangularShadow {
anchors {
fill: parent
leftMargin: -blur
rightMargin: -blur
}
z: -1
blur: 12
opacity: 0.6
}
}
Item {
anchors.fill: parent
clip: true
RectangularShadow {
anchors {
top: inputBox.top
right: inputBox.right
bottom: inputBox.bottom
topMargin: -blur
bottomMargin: -blur
}
blur: 16
width: blur
opacity: 0.8
transform: Shear5 {height: inputBox.height}
}
Rectangle {
id: inputBox
anchors {
top: parent.top
bottom: parent.bottom
}
antialiasing: true
x: surface.width/3 + (surface.width/4) * content.idle
width: (surface.width/3 + shear.xFactor) * !content.idle
OutQuint300 on x {}
OutQuint300 on width {}
color: "#5F46BB"
transform: Shear5 {height: inputBox.height; id: shear}
}
Column {
anchors {
verticalCenter: inputBox.verticalCenter
left: inputBox.right
leftMargin: surface.width/3 * -1 + logo.width * 0.29
}
width: inputBox.width
clip: true
spacing: 10
Text {
id: prompt
anchors.left: parent.left
anchors.leftMargin: passInputBg.height * 0.15/2
text: "o shit waddup!"
color: "white"
font {
family: "comfortaa"
pixelSize: 20
}
}
Rectangle {
id: passInputBg
anchors.left: parent.left
anchors.leftMargin: height * 0.15
radius: 12
color: Qt.darker(inputBox.color, 1.5)
height: prompt.font.pixelSize + 20
width: surface.width * 0.18
transform: Shear { xFactor: -0.15 }
TextInput {
id: passInput
anchors.fill: passInputBg
anchors.margins: 10
focus: !pam.active
font: prompt.font
color: "white"
echoMode: TextInput.Password
transform: Shear { xFactor: 0.15 }
onTextChanged: content.idle = !text.length
}
}
}
}
}
Item { Item {
id: logo id: logo
anchors { anchors {
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter horizontalCenter: parent.horizontalCenter
} }
width: Math.min(surface.width, surface.height) * 0.6 + borderWidth*2 width: Math.min(surface.width, surface.height) * 0.6
height: width height: width
layer.enabled: true
layer.smooth: true
readonly property real borderWidth: 24 readonly property real borderWidth: width * 0.04
transform: [
Scale {
origin {x: logo.width/2; y: logo.height/2 }
xScale: (content.idle ? 1.0 : 0.5) * (1 + circleHover.hovered * 0.1)
yScale: xScale
OutQuint300 on xScale {}
},
Translate {
x: content.idle ? 0 : (surface.width/6 * -1)
OutQuint300 on x {}
}
]
// Background // Background
Shape { Shape {
@@ -64,16 +204,19 @@ WlSessionLock {
moveToStart: true moveToStart: true
centerX: logo.width/2 centerX: logo.width/2
centerY: logo.height/2 centerY: logo.height/2
radiusX: surface.height * 0.3 + logo.borderWidth/2 radiusX: logo.width * 0.45 + logo.borderWidth/2
radiusY: radiusX radiusY: radiusX
startAngle: 0 startAngle: 0
sweepAngle: 360 sweepAngle: 360
} }
} }
HoverHandler { id: circleHover }
TapHandler {
onTapped: content.idle = !content.idle
}
} }
Item { Item {
id: triangles id: triangles
visible: false
anchors.fill: parent anchors.fill: parent
clip: true clip: true
layer.enabled: true layer.enabled: true
@@ -109,14 +252,13 @@ WlSessionLock {
} }
onObjectAdded: (index, obj) => obj.parent = triangles onObjectAdded: (index, obj) => obj.parent = triangles
} }
} layer.effect: ShaderEffect {
ShaderEffect { property var src: triangles
anchors.fill: parent property var mask: circleBg
property var src: triangles property bool fadeDirection: true
property var mask: circleBg vertexShader: "default.vert.qsb"
property bool fadeDirection: true fragmentShader: "trifade.frag.qsb"
vertexShader: "default.vert.qsb" }
fragmentShader: "trifade.frag.qsb"
} }
// Group border and logo to shadow together // Group border and logo to shadow together
@@ -135,7 +277,7 @@ WlSessionLock {
moveToStart: true moveToStart: true
centerX: logo.width/2 centerX: logo.width/2
centerY: logo.height/2 centerY: logo.height/2
radiusX: surface.height * 0.3 radiusX: logo.height * 0.45
radiusY: radiusX radiusY: radiusX
startAngle: 0 startAngle: 0
sweepAngle: 360 sweepAngle: 360
@@ -147,7 +289,7 @@ WlSessionLock {
anchors { anchors {
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter horizontalCenter: parent.horizontalCenter
verticalCenterOffset: logo.height * 0.05 * -1 verticalCenterOffset: logo.height * 0.065 * -1
} }
width: logo.width * 0.65 width: logo.width * 0.65
height: width height: width
@@ -158,7 +300,6 @@ WlSessionLock {
} }
} }
layer.effect: MultiEffect { layer.effect: MultiEffect {
anchors.fill: parent
blurMax: 48 blurMax: 48
shadowEnabled: true shadowEnabled: true
shadowOpacity: 0.4 shadowOpacity: 0.4
@@ -172,19 +313,13 @@ WlSessionLock {
color: "white" color: "white"
anchors.fill: parent anchors.fill: parent
PropertyAnimation on opacity { PropertyAnimation on opacity {
running: lock.secure
from: 1 from: 1
to: 0 to: 0
easing.type: Easing.Linear
duration: 800 duration: 800
} }
} }
Button {
text: "unlock"
onClicked: lock.locked = false
}
layer.effect: MultiEffect { layer.effect: MultiEffect {
anchors.fill: parent
maskEnabled: true maskEnabled: true
maskSource: contentMask maskSource: contentMask
} }
@@ -208,7 +343,24 @@ WlSessionLock {
duration: 800 duration: 800
easing.type: Easing.OutQuint easing.type: Easing.OutQuint
} }
PropertyAnimation on progress {
id: exitAnimation
running: false
from: 1
to: 0
easing.type: Easing.OutQuint
onStopped: lock.locked = false
}
} }
} }
PamContext {
id: pam
config: "system-auth"
onPamMessage: if (this.responseRequired) this.respond(passInput.text)
onCompleted: result => { switch (result) {
case PamResult.Success:
exitAnimation.start()
}}
}
} }
} }