greeter: init greeter

This commit is contained in:
kossLAN 2025-06-20 12:16:19 -04:00
parent be06bf0f86
commit fc9ced0bbe
Signed by: kossLAN
SSH key fingerprint: SHA256:bdV0x+wdQHGJ6LgmstH3KV8OpWY+OOFmJcPcB0wQPV8
6 changed files with 126 additions and 37 deletions

View file

@ -0,0 +1,39 @@
import QtQuick
import Quickshell
import Quickshell.Services.Greetd
import "../lockscreen"
Scope {
id: root
signal launch
property LockState state: LockState {
onTryUnlock: {
this.unlockInProgress = true;
// TODO: env var for user
Greetd.createSession("koss");
}
}
Connections {
target: Greetd
function onAuthMessage(message: string, error: bool, responseRequired: bool, echoResponse: bool) {
if (responseRequired) {
Greetd.respond(root.state.currentText);
} // else ignore - only supporting passwords
}
function onAuthFailure() {
root.state.currentText = "";
root.state.failed();
root.state.unlockInProgress = false;
}
function onReadyToLaunch() {
root.state.unlockInProgress = false;
root.launch();
}
}
}

34
shell/greeter/shell.qml Normal file
View file

@ -0,0 +1,34 @@
pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Wayland
import Quickshell.Services.Greetd
import "../lockscreen"
ShellRoot {
id: root
GreeterContext {
id: context
onLaunch: {
lock.locked = false;
Greetd.launch(["hyprland"]);
}
}
WlSessionLock {
id: lock
locked: true
WlSessionLockSurface {
LockSurface {
state: context.state
// TODO: env var for wallpaper
wallpaper: "root:resources/wallpapers/wallhaven-96y9qk.jpg"
anchors.fill: parent
}
}
}
}

View file

@ -1,9 +1,11 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import ".."
Singleton {
id: root
@ -22,9 +24,15 @@ Singleton {
}
LockContext {
id: passwordContext
id: context
onUnlocked: persist.locked = false
Connections {
target: context.state
function onUnlocked() {
persist.locked = false;
}
}
}
WlSessionLock {
@ -34,11 +42,13 @@ Singleton {
WlSessionLockSurface {
LockSurface {
state: context.state
wallpaper: ShellSettings.settings.wallpaperUrl
anchors.fill: parent
context: passwordContext
}
}
}
function init() {}
function init() {
}
}

View file

@ -1,3 +1,5 @@
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Services.Pam
@ -5,21 +7,14 @@ import Quickshell.Services.Pam
Scope {
id: root
property string currentText: ""
property bool unlockInProgress: false
property bool showFailure: false
signal unlocked
signal failed
property LockState state: LockState {
onTryUnlock: {
if (this.currentText === "")
return;
// Clear the failure text once the user starts typing.
onCurrentTextChanged: showFailure = false
function tryUnlock() {
if (currentText === "")
return;
root.unlockInProgress = true;
pam.start();
this.unlockInProgress = true;
pam.start();
}
}
PamContext {
@ -34,20 +29,20 @@ Scope {
// pam_unix will ask for a response for the password prompt
onPamMessage: {
if (this.responseRequired) {
this.respond(root.currentText);
this.respond(root.state.currentText);
}
}
// pam_unix won't send any important messages so all we need is the completion status.
onCompleted: result => {
if (result == PamResult.Success) {
root.unlocked();
root.currentText = "";
root.state.unlocked();
root.state.currentText = "";
} else {
root.showFailure = true;
root.state.showFailure = true;
}
root.unlockInProgress = false;
root.state.unlockInProgress = false;
}
}
}

View file

@ -0,0 +1,12 @@
import Quickshell
Scope {
property string currentText: ""
property bool unlockInProgress: false
property bool showFailure: false
signal unlocked
signal failed
signal tryUnlock
onCurrentTextChanged: showFailure = false
}

View file

@ -4,19 +4,18 @@ import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
import ".."
Rectangle {
Item {
id: root
color: Window.active ? ShellSettings.colors["surface"] : ShellSettings.colors["surface_dim"]
required property LockContext context
required property LockState state
required property string wallpaper
Item {
anchors.fill: parent
Image {
id: bgImage
source: ShellSettings.settings.wallpaperUrl
source: root.wallpaper
fillMode: Image.PreserveAspectCrop
anchors.fill: parent
visible: false
@ -26,7 +25,7 @@ Rectangle {
anchors.fill: bgImage
source: bgImage
radius: 80
transparentBorder: true
transparentBorder: false
}
Rectangle {
@ -134,27 +133,27 @@ Rectangle {
// password input, should probably split this out into a seperate comp
LoginField {
id: passwordBox
enabled: !root.context.unlockInProgress
enabled: !root.state.unlockInProgress
Layout.preferredWidth: 250
Layout.preferredHeight: 30
Layout.maximumHeight: 30
Layout.alignment: Qt.AlignHCenter
onTextChanged: root.context.currentText = this.text
onAccepted: root.context.tryUnlock()
onTextChanged: root.state.currentText = this.text
onAccepted: root.state.tryUnlock()
Connections {
target: root.context
target: root.state
function onCurrentTextChanged() {
if (!passwordBox.shaking) {
passwordBox.text = root.context.currentText;
passwordBox.text = root.state.currentText;
}
}
function onShowFailureChanged() {
if (root.context.showFailure && !passwordBox.shaking) {
if (root.state.showFailure && !passwordBox.shaking) {
passwordBox.shaking = true;
}
}
@ -185,9 +184,9 @@ Rectangle {
// testing button
Button {
visible: false
visible: true
text: "Emergency Unlock"
onClicked: root.context.unlocked()
onClicked: root.state.unlocked()
anchors {
right: parent.right