mirror of
https://github.com/tomasriveral/nixos.git
synced 2026-08-12 10:30:44 +02:00
ported some quickshell stuff from rivendell-hyprdots
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
auth required pam_unix.so
|
||||
|
||||
Reference in New Issue
Block a user