ported some quickshell stuff from rivendell-hyprdots

This commit is contained in:
Tomas Rivera
2026-03-10 16:22:35 +01:00
parent 4b442dd121
commit b9e3f35abe
80 changed files with 4462 additions and 9 deletions
+56
View File
@@ -0,0 +1,56 @@
import QtQuick
import Quickshell
import Quickshell.Services.Pam
Scope {
id: root
signal pamSuccess
signal unlocked
signal failed
// These properties are in the context and not individual lock surfaces
// so all surfaces can share the same state.
property string currentText: ""
property bool unlockInProgress: false
property bool showFailure: false
// Clear the failure text once the user starts typing.
onCurrentTextChanged: showFailure = false
function tryUnlock() {
if (currentText === "")
return;
root.unlockInProgress = true;
pam.start();
}
PamContext {
id: pam
// Its best to have a custom pam config for quickshell, as the system one
// might not be what your interface expects, and break in some way.
// This particular example only supports passwords.
configDirectory: "pam"
config: "password.conf"
// pam_unix will ask for a response for the password prompt
onPamMessage: {
if (this.responseRequired) {
this.respond(root.currentText);
}
}
// pam_unix won't send any important messages so all we need is the completion status.
onCompleted: result => {
if (result == PamResult.Success) {
root.pamSuccess();
} else {
root.currentText = "";
root.showFailure = true;
}
root.unlockInProgress = false;
}
}
}
+47
View File
@@ -0,0 +1,47 @@
pragma Singleton
pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import QtQuick
import "." as Lock
Singleton {
Process {
id: screencopyCmd
running: false
command: ["grim", "-s", "0.5", "-t", "jpeg", "/tmp/lock_screencopy.jpeg"]
onExited: lock.locked = true
}
IpcHandler {
target: "lockscreen"
function lock(): void {
screencopyCmd.running = true;
}
}
WlSessionLock {
id: lock
locked: false
WlSessionLockSurface {
id: lockSurface
color: "transparent"
Lock.Surface {
anchors.fill: parent
context: lockContext
}
}
}
Lock.Context {
id: lockContext
onUnlocked: lock.locked = false
}
// Empty function to define first reference to singleton
function init() {
}
}
+281
View File
@@ -0,0 +1,281 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import QtQuick.Effects
import QtQuick.Controls.Fusion
import Quickshell.Wayland
import Quickshell
import "." as Lock
Rectangle {
id: root
required property Lock.Context context
color: "black"
Image {
id: chest
anchors.centerIn: parent
source: "../assets/chest.png"
sourceClipRect: Qt.rect(32, 0, 32, 32)
smooth: false
height: width
// Rectangles
RowLayout {
visible: passwordBox.enabled
anchors.centerIn: parent
anchors.verticalCenterOffset: 31
spacing: 31
Repeater {
model: 6
delegate: Rectangle {
id: r
required property var modelData
color: root.context.showFailure ? "#D6568F" : "#6BCBF3"
implicitWidth: 31
implicitHeight: 31
MultiEffect {
id: glow
source: parent
anchors.fill: parent
brightness: passwordBox.length > r.modelData ? 0.7 : 0
blur: passwordBox.length > r.modelData ? 2.0 : 0
blurEnabled: true
}
}
}
}
Image {
id: screencopy
anchors.centerIn: parent
source: "/tmp/lock_screencopy.jpeg"
height: width * (9 / 16) // Width is animated below
}
Image {
id: chestInFront
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: parent.width / 2
source: "../assets/chest.png"
sourceClipRect: Qt.rect(32, 16, 32, 16)
smooth: false
visible: false
z: 9999
}
}
// Enter anim
// ------------
// Screencopy anim
NumberAnimation {
target: screencopy
property: "width"
from: 1920
to: 250
duration: 700
easing.type: Easing.OutBack
easing.overshoot: 0.9
running: true
}
SequentialAnimation {
id: screencopyAnim
running: true
NumberAnimation {
target: screencopy
property: "anchors.verticalCenterOffset"
to: -150
duration: 500
easing.type: Easing.OutBack
}
PauseAnimation {
duration: 200
}
PropertyAction {
target: chestInFront
property: "visible"
value: true
}
NumberAnimation {
target: screencopy
property: "anchors.verticalCenterOffset"
to: 100
duration: 300
easing.type: Easing.Linear
}
}
// Chest anim
SequentialAnimation {
id: chestAnim
running: true
NumberAnimation {
target: chest
property: "width"
from: 2000
to: 500
duration: 500
easing.type: Easing.OutBack
running: true
}
PauseAnimation {
duration: 500
}
PropertyAction {
target: chest
property: "sourceClipRect.x"
value: 0
}
PropertyAction {
target: chestInFront
property: "visible"
value: false
}
PropertyAction {
target: screencopy
property: "visible"
value: false
}
NumberAnimation {
onStarted: screencopy.visible = false
target: chest
property: "anchors.verticalCenterOffset"
to: 50
duration: 100
easing.type: Easing.OutBack
}
NumberAnimation {
target: chest
property: "anchors.verticalCenterOffset"
to: 0
duration: 100
easing.type: Easing.OutBack
}
}
// Exit anim
// ------------
// Screencopy anim
SequentialAnimation {
id: screencopyAnimExit
running: false
PropertyAction {
target: chestInFront
property: "visible"
value: true
}
NumberAnimation {
target: screencopy
property: "anchors.verticalCenterOffset"
to: -150
duration: 200
easing.type: Easing.OutBack
}
PropertyAction {
target: chestInFront
property: "visible"
value: false
}
NumberAnimation {
target: screencopy
property: "anchors.verticalCenterOffset"
to: 0
duration: 400
easing.type: Easing.OutBack
}
NumberAnimation {
target: screencopy
property: "width"
to: 1920
duration: 400
easing.type: Easing.OutBack
running: true
}
onFinished: () => root.context.unlocked()
}
// Chest anim
SequentialAnimation {
id: chestAnimExit
running: false
PropertyAction {
target: chest
property: "sourceClipRect.x"
value: 32
}
PropertyAction {
target: screencopy
property: "visible"
value: true
}
NumberAnimation {
target: chest
property: "anchors.verticalCenterOffset"
to: -50
duration: 100
easing.type: Easing.OutBack
}
NumberAnimation {
target: chest
property: "anchors.verticalCenterOffset"
to: 0
duration: 200
easing.type: Easing.OutBack
}
}
TextField {
id: passwordBox
implicitWidth: 400
font.pointSize: 50
color: "transparent"
cursorVisible: false
background: Rectangle {
color: "transparent"
}
focus: true
enabled: !screencopyAnim.running && !chestAnim.running && !screencopyAnimExit.running && !chestAnimExit.running && !root.context.unlockInProgress
opacity: 0
echoMode: TextInput.Password
inputMethodHints: Qt.ImhSensitiveData
onTextChanged: () => {
if (text != "") {
root.context.showFailure = false;
}
}
onAccepted: () => {
root.context.currentText = text;
root.context.tryUnlock();
}
Connections {
target: root.context
function onUnlockInProgressChanged() {
if (root.context.unlockInProgress == false) {
passwordBox.text = "";
}
}
function onPamSuccess() {
screencopyAnimExit.running = true;
chestAnimExit.running = true;
}
}
}
// Button {
// text: "Its not working, let me out"
// onClicked: root.context.unlocked()
// }
}
+2
View File
@@ -0,0 +1,2 @@
auth required pam_unix.so