blob: e5c529f0093762e7796e45a44374885ba4ea7de2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
//
// UDT SDDM greeter. The root item spans every screen. The wallpaper is drawn
// once per screen; the login card is pinned to one screen (config uiScreen,
// else the primary screen); input wakes the card after it fades.
import QtQuick
import "components"
Item {
id: root
// SDDM sizes the greeter to the union of every screen.
readonly property var union: screenModel.geometry(-1)
width: union.width
height: union.height
// Palette. Values come from theme.conf, overridden live by theme.conf.user.
readonly property string baseColor: config.stringValue("base")
readonly property int cardRadius: 10
readonly property string wallpaperUrl:
config.stringValue("background") === ""
? ""
: "file://" + config.stringValue("background")
readonly property string wantedScreen: config.stringValue("uiScreen")
property var primaryGeometry: screenModel.geometry(screenModel.primary >= 0 ? screenModel.primary : 0)
property var namedGeometry: primaryGeometry
readonly property var cardGeometry: wantedScreen === "" ? primaryGeometry : namedGeometry
// The Image delegate of the screen the card sits on. The frosted card
// samples it. Null until the model has populated.
property Item cardScreenImage: null
Repeater {
id: screens
model: screenModel
delegate: Item {
x: geometry.x
y: geometry.y
width: geometry.width
height: geometry.height
Image {
id: screenImage
anchors.fill: parent
source: root.wallpaperUrl
fillMode: Image.PreserveAspectCrop
sourceSize.width: parent.width
sourceSize.height: parent.height
smooth: true
asynchronous: true
}
// Scrim so the card and text read on any wallpaper.
Rectangle {
anchors.fill: parent
color: root.baseColor
opacity: 0.45
}
readonly property string screenName: name
Component.onCompleted: root.registerScreen(index, screenName, screenImage, geometry)
}
}
// Filled as the model populates: the primary screen's name, and the
// wallpaper image plus geometry of whichever screen owns the card.
property string primaryName: ""
function registerScreen(index, screenName, image, geom) {
if (index === screenModel.primary)
root.primaryName = screenName
if (screenName === root.cardScreenName()) {
root.cardScreenImage = image
root.namedGeometry = geom
}
}
function cardScreenName() {
return root.wantedScreen !== "" ? root.wantedScreen : root.primaryName
}
// Idle: fade the card after fadeoutMs, restore on any input.
property bool uiVisible: true
Timer {
id: idle
interval: config.intValue("fadeoutMs") > 0 ? config.intValue("fadeoutMs") : 60000
running: root.uiVisible
repeat: false
onTriggered: root.uiVisible = false
}
function wake() {
root.uiVisible = true
idle.restart()
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onPressed: root.wake()
onPositionChanged: root.wake()
}
Keys.onPressed: event => {
root.wake()
event.accepted = false
}
LoginCard {
id: card
x: root.cardGeometry.x + (root.cardGeometry.width - width) / 2 + card.shakeOffset
y: root.cardGeometry.y + (root.cardGeometry.height - height) / 2
backdropSource: root.cardScreenImage
visible: opacity > 0
opacity: root.uiVisible ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 260; easing.type: Easing.OutCubic } }
onWake: root.wake()
}
}
|