Skip to content

Commit a64b477

Browse files
committed
lockscreen: replace lockscreen example
The new one uses the pam module and looks much nicer.
1 parent c30a4fa commit a64b477

File tree

9 files changed

+190
-126
lines changed

9 files changed

+190
-126
lines changed

lockscreen/AuthContext.qml

Lines changed: 0 additions & 43 deletions
This file was deleted.

lockscreen/LockContext.qml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import QtQuick
2+
import Quickshell
3+
import Quickshell.Services.Pam
4+
5+
Scope {
6+
id: root
7+
signal unlocked()
8+
signal failed()
9+
10+
// These properties are in the context and not individual lock surfaces
11+
// so all surfaces can share the same state.
12+
property string currentText: ""
13+
property bool unlockInProgress: false
14+
property bool showFailure: false
15+
16+
// Clear the failure text once the user starts typing.
17+
onCurrentTextChanged: showFailure = false;
18+
19+
function tryUnlock() {
20+
if (currentText === "") return;
21+
22+
root.unlockInProgress = true;
23+
pam.start();
24+
}
25+
26+
PamContext {
27+
id: pam
28+
29+
// Its best to have a custom pam config for quickshell, as the system one
30+
// might not be what your interface expects, and break in some way.
31+
// This particular example only supports passwords.
32+
configDirectory: "pam"
33+
config: "password.conf"
34+
35+
// pam_unix will ask for a response for the password prompt
36+
onPamMessage: {
37+
if (this.responseRequired) {
38+
this.respond(root.currentText);
39+
}
40+
}
41+
42+
// pam_unix won't send any important messages so all we need is the completion status.
43+
onCompleted: result => {
44+
if (result == PamResult.Success) {
45+
root.unlocked();
46+
} else {
47+
root.currentText = "";
48+
root.showFailure = true;
49+
}
50+
51+
root.unlockInProgress = false;
52+
}
53+
}
54+
}

lockscreen/LockSurface.qml

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import QtQuick
2+
import QtQuick.Layouts
3+
import QtQuick.Controls.Fusion
4+
import Quickshell.Wayland
5+
6+
Rectangle {
7+
id: root
8+
required property LockContext context
9+
readonly property ColorGroup colors: Window.active ? palette.active : palette.inactive
10+
11+
color: colors.window
12+
13+
Button {
14+
text: "Its not working, let me out"
15+
onClicked: context.unlocked();
16+
}
17+
18+
Label {
19+
id: clock
20+
property var date: new Date()
21+
22+
anchors {
23+
horizontalCenter: parent.horizontalCenter
24+
top: parent.top
25+
topMargin: 100
26+
}
27+
28+
// The native font renderer tends to look nicer at large sizes.
29+
renderType: Text.NativeRendering
30+
font.pointSize: 80
31+
32+
// updates the clock every second
33+
Timer {
34+
running: true
35+
repeat: true
36+
interval: 1000
37+
38+
onTriggered: clock.date = new Date();
39+
}
40+
41+
// updated when the date changes
42+
text: {
43+
const hours = this.date.getHours().toString().padStart(2, '0');
44+
const minutes = this.date.getMinutes().toString().padStart(2, '0');
45+
return `${hours}:${minutes}`;
46+
}
47+
}
48+
49+
ColumnLayout {
50+
// Uncommenting this will make the password entry invisible except on the active monitor.
51+
// visible: Window.active
52+
53+
anchors {
54+
horizontalCenter: parent.horizontalCenter
55+
top: parent.verticalCenter
56+
}
57+
58+
RowLayout {
59+
TextField {
60+
id: passwordBox
61+
62+
implicitWidth: 400
63+
padding: 10
64+
65+
focus: true
66+
enabled: !root.context.unlockInProgress
67+
echoMode: TextInput.Password
68+
inputMethodHints: Qt.ImhSensitiveData
69+
70+
// Update the text in the context when the text in the box changes.
71+
onTextChanged: root.context.currentText = this.text;
72+
73+
// Try to unlock when enter is pressed.
74+
onAccepted: root.context.tryUnlock();
75+
76+
// Update the text in the box to match the text in the context.
77+
// This makes sure multiple monitors have the same text.
78+
Connections {
79+
target: root.context
80+
81+
function onCurrentTextChanged() {
82+
passwordBox.text = root.context.currentText;
83+
}
84+
}
85+
}
86+
87+
Button {
88+
text: "Unlock"
89+
padding: 10
90+
91+
// don't steal focus from the text box
92+
focusPolicy: Qt.NoFocus
93+
94+
enabled: !root.context.unlockInProgress && root.context.currentText !== "";
95+
onClicked: root.context.tryUnlock();
96+
}
97+
}
98+
99+
Label {
100+
visible: root.context.showFailure
101+
text: "Incorrect password"
102+
}
103+
}
104+
}

lockscreen/Lockscreen.qml

Lines changed: 0 additions & 52 deletions
This file was deleted.

lockscreen/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Lockscreen
22

3-
This is a barebones lockscreen with a password input box.
4-
Note that you MUST have `pamtester` installed or you won't be able to log in.
3+
This is a simple but functional lockscreen that follows the system color scheme.
4+
The only authentication method it supports is a password.
55

66
You can run the lockscreen with `quickshell -p shell.qml`.
77

lockscreen/image.png

-670 Bytes
Loading

lockscreen/pam/password.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
auth required pam_unix.so

lockscreen/shell.qml

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,31 @@
1-
import QtQuick
2-
import QtQuick.Controls.Basic
31
import Quickshell
42
import Quickshell.Wayland
53

64
ShellRoot {
7-
AuthContext {
8-
id: authContext
9-
onUnlocked: lock.locked = false
5+
// This stores all the information shared between the lock surfaces on each screen.
6+
LockContext {
7+
id: lockContext
8+
9+
onUnlocked: {
10+
// Unlock the screen before exiting, or the compositor will display a
11+
// fallback lock you can't interact with.
12+
lock.locked = false;
13+
14+
Qt.quit();
15+
}
1016
}
1117

1218
WlSessionLock {
1319
id: lock
14-
locked: true
1520

16-
onLockedChanged: {
17-
if (!locked) Qt.quit();
18-
}
21+
// Lock the session immediately when quickshell starts.
22+
locked: true
1923

2024
WlSessionLockSurface {
21-
// You probably want to replace this with an image.
22-
color: "#303030"
23-
24-
// For your own sanity you should probably keep this
25-
// while working on the lockscreen.
26-
Button {
27-
text: "Help! I misconfigured my lockscreen!"
28-
onClicked: lock.locked = false
29-
}
30-
31-
Lockscreen {
25+
LockSurface {
3226
anchors.fill: parent
33-
context: authContext
27+
context: lockContext
3428
}
3529
}
3630
}
37-
3831
}

lockscreen/test.qml

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,24 @@ import QtQuick
22
import Quickshell
33

44
ShellRoot {
5-
AuthContext {
6-
id: authContext
7-
onUnlocked: Qt.quit()
5+
LockContext {
6+
id: lockContext
7+
onUnlocked: Qt.quit();
88
}
99

1010
FloatingWindow {
11-
color: "#303030"
12-
13-
Lockscreen {
11+
LockSurface {
1412
anchors.fill: parent
15-
context: authContext
13+
context: lockContext
14+
}
15+
}
16+
17+
// exit the example if the window closes
18+
Connections {
19+
target: Quickshell
20+
21+
function onLastWindowClosed() {
22+
Qt.quit();
1623
}
1724
}
1825
}

0 commit comments

Comments
 (0)