Warning, /plasma/plasma-workspace/lookandfeel/sddm-theme/Main.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2016 David Edmundson <davidedmundson@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 import QtQuick 2.15 0008 import QtQuick.Layouts 1.15 0009 import QtQuick.Controls 2.15 as QQC2 0010 import Qt5Compat.GraphicalEffects 0011 0012 import org.kde.plasma.components 3.0 as PlasmaComponents3 0013 import org.kde.plasma.private.keyboardindicator as KeyboardIndicator 0014 import org.kde.kirigami 2.20 as Kirigami 0015 0016 import org.kde.breeze.components 0017 0018 // TODO: Once SDDM 0.19 is released and we are setting the font size using the 0019 // SDDM KCM's syncing feature, remove the `config.fontSize` overrides here and 0020 // the fontSize properties in various components, because the theme's default 0021 // font size will be correctly propagated to the login screen 0022 0023 Item { 0024 id: root 0025 0026 // If we're using software rendering, draw outlines instead of shadows 0027 // See https://bugs.kde.org/show_bug.cgi?id=398317 0028 readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software 0029 0030 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary 0031 Kirigami.Theme.inherit: false 0032 0033 width: 1600 0034 height: 900 0035 0036 property string notificationMessage 0037 0038 LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft 0039 LayoutMirroring.childrenInherit: true 0040 0041 KeyboardIndicator.KeyState { 0042 id: capsLockState 0043 key: Qt.Key_CapsLock 0044 } 0045 0046 Item { 0047 id: wallpaper 0048 anchors.fill: parent 0049 Repeater { 0050 model: screenModel 0051 0052 Background { 0053 x: geometry.x; y: geometry.y; width: geometry.width; height: geometry.height 0054 sceneBackgroundType: config.type 0055 sceneBackgroundColor: config.color 0056 sceneBackgroundImage: config.background 0057 } 0058 } 0059 } 0060 0061 RejectPasswordAnimation { 0062 id: rejectPasswordAnimation 0063 target: mainStack 0064 } 0065 0066 MouseArea { 0067 id: loginScreenRoot 0068 anchors.fill: parent 0069 0070 property bool uiVisible: true 0071 property bool blockUI: mainStack.depth > 1 || userListComponent.mainPasswordBox.text.length > 0 || inputPanel.keyboardActive || config.type !== "image" 0072 0073 hoverEnabled: true 0074 drag.filterChildren: true 0075 onPressed: uiVisible = true; 0076 onPositionChanged: uiVisible = true; 0077 onUiVisibleChanged: { 0078 if (blockUI) { 0079 fadeoutTimer.running = false; 0080 } else if (uiVisible) { 0081 fadeoutTimer.restart(); 0082 } 0083 } 0084 onBlockUIChanged: { 0085 if (blockUI) { 0086 fadeoutTimer.running = false; 0087 uiVisible = true; 0088 } else { 0089 fadeoutTimer.restart(); 0090 } 0091 } 0092 0093 Keys.onPressed: event => { 0094 uiVisible = true; 0095 event.accepted = false; 0096 } 0097 0098 //takes one full minute for the ui to disappear 0099 Timer { 0100 id: fadeoutTimer 0101 running: true 0102 interval: 60000 0103 onTriggered: { 0104 if (!loginScreenRoot.blockUI) { 0105 userListComponent.mainPasswordBox.showPassword = false; 0106 loginScreenRoot.uiVisible = false; 0107 } 0108 } 0109 } 0110 WallpaperFader { 0111 visible: config.type === "image" 0112 anchors.fill: parent 0113 state: loginScreenRoot.uiVisible ? "on" : "off" 0114 source: wallpaper 0115 mainStack: mainStack 0116 footer: footer 0117 clock: clock 0118 } 0119 0120 DropShadow { 0121 id: clockShadow 0122 anchors.fill: clock 0123 source: clock 0124 visible: !softwareRendering 0125 radius: 6 0126 samples: 14 0127 spread: 0.3 0128 color : "black" // shadows should always be black 0129 Behavior on opacity { 0130 OpacityAnimator { 0131 duration: Kirigami.Units.veryLongDuration * 2 0132 easing.type: Easing.InOutQuad 0133 } 0134 } 0135 } 0136 0137 Clock { 0138 id: clock 0139 property Item shadow: clockShadow 0140 visible: y > 0 0141 anchors.horizontalCenter: parent.horizontalCenter 0142 y: (userListComponent.userList.y + mainStack.y)/2 - height/2 0143 Layout.alignment: Qt.AlignBaseline 0144 } 0145 0146 QQC2.StackView { 0147 id: mainStack 0148 anchors { 0149 left: parent.left 0150 right: parent.right 0151 } 0152 height: root.height + Kirigami.Units.gridUnit * 3 0153 0154 // If true (depends on the style and environment variables), hover events are always accepted 0155 // and propagation stopped. This means the parent MouseArea won't get them and the UI won't be shown. 0156 // Disable capturing those events while the UI is hidden to avoid that, while still passing events otherwise. 0157 // One issue is that while the UI is visible, mouse activity won't keep resetting the timer, but when it 0158 // finally expires, the next event should immediately set uiVisible = true again. 0159 hoverEnabled: loginScreenRoot.uiVisible ? undefined : false 0160 0161 focus: true //StackView is an implicit focus scope, so we need to give this focus so the item inside will have it 0162 0163 Timer { 0164 //SDDM has a bug in 0.13 where even though we set the focus on the right item within the window, the window doesn't have focus 0165 //it is fixed in 6d5b36b28907b16280ff78995fef764bb0c573db which will be 0.14 0166 //we need to call "window->activate()" *After* it's been shown. We can't control that in QML so we use a shoddy timer 0167 //it's been this way for all Plasma 5.x without a huge problem 0168 running: true 0169 repeat: false 0170 interval: 200 0171 onTriggered: mainStack.forceActiveFocus() 0172 } 0173 0174 initialItem: Login { 0175 id: userListComponent 0176 userListModel: userModel 0177 loginScreenUiVisible: loginScreenRoot.uiVisible 0178 userListCurrentIndex: userModel.lastIndex >= 0 ? userModel.lastIndex : 0 0179 lastUserName: userModel.lastUser 0180 showUserList: { 0181 if (!userListModel.hasOwnProperty("count") 0182 || !userListModel.hasOwnProperty("disableAvatarsThreshold")) { 0183 return false 0184 } 0185 0186 if (userListModel.count === 0 ) { 0187 return false 0188 } 0189 0190 if (userListModel.hasOwnProperty("containsAllUsers") && !userListModel.containsAllUsers) { 0191 return false 0192 } 0193 0194 return userListModel.count <= userListModel.disableAvatarsThreshold 0195 } 0196 0197 notificationMessage: { 0198 const parts = []; 0199 if (capsLockState.locked) { 0200 parts.push(i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Caps Lock is on")); 0201 } 0202 if (root.notificationMessage) { 0203 parts.push(root.notificationMessage); 0204 } 0205 return parts.join(" • "); 0206 } 0207 0208 actionItemsVisible: !inputPanel.keyboardActive 0209 actionItems: [ 0210 ActionButton { 0211 iconSource: "system-suspend" 0212 text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Suspend to RAM", "Sleep") 0213 fontSize: parseInt(config.fontSize) + 1 0214 onClicked: sddm.suspend() 0215 enabled: sddm.canSuspend 0216 }, 0217 ActionButton { 0218 iconSource: "system-reboot" 0219 text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Restart") 0220 fontSize: parseInt(config.fontSize) + 1 0221 onClicked: sddm.reboot() 0222 enabled: sddm.canReboot 0223 }, 0224 ActionButton { 0225 iconSource: "system-shutdown" 0226 text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Shut Down") 0227 fontSize: parseInt(config.fontSize) + 1 0228 onClicked: sddm.powerOff() 0229 enabled: sddm.canPowerOff 0230 }, 0231 ActionButton { 0232 iconSource: "system-user-prompt" 0233 text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "For switching to a username and password prompt", "Other…") 0234 fontSize: parseInt(config.fontSize) + 1 0235 onClicked: mainStack.push(userPromptComponent) 0236 enabled: true 0237 visible: !userListComponent.showUsernamePrompt 0238 }] 0239 0240 onLoginRequest: { 0241 root.notificationMessage = "" 0242 sddm.login(username, password, sessionButton.currentIndex) 0243 } 0244 } 0245 0246 Behavior on opacity { 0247 OpacityAnimator { 0248 duration: Kirigami.Units.longDuration 0249 } 0250 } 0251 0252 readonly property real zoomFactor: 1.5 0253 0254 popEnter: Transition { 0255 ScaleAnimator { 0256 from: mainStack.zoomFactor 0257 to: 1 0258 duration: Kirigami.Units.veryLongDuration 0259 easing.type: Easing.OutCubic 0260 } 0261 OpacityAnimator { 0262 from: 0 0263 to: 1 0264 duration: Kirigami.Units.veryLongDuration 0265 easing.type: Easing.OutCubic 0266 } 0267 } 0268 0269 popExit: Transition { 0270 ScaleAnimator { 0271 from: 1 0272 to: 1 / mainStack.zoomFactor 0273 duration: Kirigami.Units.veryLongDuration 0274 easing.type: Easing.OutCubic 0275 } 0276 OpacityAnimator { 0277 from: 1 0278 to: 0 0279 duration: Kirigami.Units.veryLongDuration 0280 easing.type: Easing.OutCubic 0281 } 0282 } 0283 0284 pushEnter: Transition { 0285 ScaleAnimator { 0286 from: 1 / mainStack.zoomFactor 0287 to: 1 0288 duration: Kirigami.Units.veryLongDuration 0289 easing.type: Easing.OutCubic 0290 } 0291 OpacityAnimator { 0292 from: 0 0293 to: 1 0294 duration: Kirigami.Units.veryLongDuration 0295 easing.type: Easing.OutCubic 0296 } 0297 } 0298 0299 pushExit: Transition { 0300 ScaleAnimator { 0301 from: 1 0302 to: mainStack.zoomFactor 0303 duration: Kirigami.Units.veryLongDuration 0304 easing.type: Easing.OutCubic 0305 } 0306 OpacityAnimator { 0307 from: 1 0308 to: 0 0309 duration: Kirigami.Units.veryLongDuration 0310 easing.type: Easing.OutCubic 0311 } 0312 } 0313 } 0314 0315 VirtualKeyboardLoader { 0316 id: inputPanel 0317 0318 z: 1 0319 0320 screenRoot: root 0321 mainStack: mainStack 0322 mainBlock: userListComponent 0323 passwordField: userListComponent.mainPasswordBox 0324 } 0325 0326 Component { 0327 id: userPromptComponent 0328 Login { 0329 showUsernamePrompt: true 0330 notificationMessage: root.notificationMessage 0331 loginScreenUiVisible: loginScreenRoot.uiVisible 0332 fontSize: parseInt(config.fontSize) + 2 0333 0334 // using a model rather than a QObject list to avoid QTBUG-75900 0335 userListModel: ListModel { 0336 ListElement { 0337 name: "" 0338 icon: "" 0339 } 0340 Component.onCompleted: { 0341 // as we can't bind inside ListElement 0342 setProperty(0, "name", i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Type in Username and Password")); 0343 setProperty(0, "icon", Qt.resolvedUrl("faces/.face.icon")) 0344 } 0345 } 0346 0347 onLoginRequest: { 0348 root.notificationMessage = "" 0349 sddm.login(username, password, sessionButton.currentIndex) 0350 } 0351 0352 actionItemsVisible: !inputPanel.keyboardActive 0353 actionItems: [ 0354 ActionButton { 0355 iconSource: "system-suspend" 0356 text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Suspend to RAM", "Sleep") 0357 fontSize: parseInt(config.fontSize) + 1 0358 onClicked: sddm.suspend() 0359 enabled: sddm.canSuspend 0360 }, 0361 ActionButton { 0362 iconSource: "system-reboot" 0363 text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Restart") 0364 fontSize: parseInt(config.fontSize) + 1 0365 onClicked: sddm.reboot() 0366 enabled: sddm.canReboot 0367 }, 0368 ActionButton { 0369 iconSource: "system-shutdown" 0370 text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Shut Down") 0371 fontSize: parseInt(config.fontSize) + 1 0372 onClicked: sddm.powerOff() 0373 enabled: sddm.canPowerOff 0374 }, 0375 ActionButton { 0376 iconSource: "system-user-list" 0377 text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "List Users") 0378 fontSize: parseInt(config.fontSize) + 1 0379 onClicked: mainStack.pop() 0380 } 0381 ] 0382 } 0383 } 0384 0385 DropShadow { 0386 id: logoShadow 0387 anchors.fill: logo 0388 source: logo 0389 visible: !softwareRendering && config.showlogo === "shown" 0390 horizontalOffset: 1 0391 verticalOffset: 1 0392 radius: 6 0393 samples: 14 0394 spread: 0.3 0395 color : "black" // shadows should always be black 0396 opacity: loginScreenRoot.uiVisible ? 0 : 1 0397 Behavior on opacity { 0398 //OpacityAnimator when starting from 0 is buggy (it shows one frame with opacity 1)" 0399 NumberAnimation { 0400 duration: Kirigami.Units.longDuration 0401 easing.type: Easing.InOutQuad 0402 } 0403 } 0404 } 0405 0406 Image { 0407 id: logo 0408 visible: config.showlogo === "shown" 0409 source: config.logo 0410 anchors.horizontalCenter: parent.horizontalCenter 0411 anchors.bottom: footer.top 0412 anchors.bottomMargin: Kirigami.Units.largeSpacing 0413 asynchronous: true 0414 sourceSize.height: height 0415 opacity: loginScreenRoot.uiVisible ? 0 : 1 0416 fillMode: Image.PreserveAspectFit 0417 height: Math.round(Kirigami.Units.gridUnit * 3.5) 0418 Behavior on opacity { 0419 // OpacityAnimator when starting from 0 is buggy (it shows one frame with opacity 1)" 0420 NumberAnimation { 0421 duration: Kirigami.Units.longDuration 0422 easing.type: Easing.InOutQuad 0423 } 0424 } 0425 } 0426 0427 // Note: Containment masks stretch clickable area of their buttons to 0428 // the screen edges, essentially making them adhere to Fitts's law. 0429 // Due to virtual keyboard button having an icon, buttons may have 0430 // different heights, so fillHeight is required. 0431 // 0432 // Note for contributors: Keep this in sync with LockScreenUi.qml footer. 0433 RowLayout { 0434 id: footer 0435 anchors { 0436 bottom: parent.bottom 0437 left: parent.left 0438 right: parent.right 0439 margins: Kirigami.Units.smallSpacing 0440 } 0441 spacing: Kirigami.Units.smallSpacing 0442 0443 Behavior on opacity { 0444 OpacityAnimator { 0445 duration: Kirigami.Units.longDuration 0446 } 0447 } 0448 0449 PlasmaComponents3.ToolButton { 0450 id: virtualKeyboardButton 0451 0452 text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Button to show/hide virtual keyboard", "Virtual Keyboard") 0453 font.pointSize: config.fontSize 0454 icon.name: inputPanel.keyboardActive ? "input-keyboard-virtual-on" : "input-keyboard-virtual-off" 0455 onClicked: { 0456 // Otherwise the password field loses focus and virtual keyboard 0457 // keystrokes get eaten 0458 userListComponent.mainPasswordBox.forceActiveFocus(); 0459 inputPanel.showHide() 0460 } 0461 visible: inputPanel.status === Loader.Ready 0462 0463 Layout.fillHeight: true 0464 containmentMask: Item { 0465 parent: virtualKeyboardButton 0466 anchors.fill: parent 0467 anchors.leftMargin: -footer.anchors.margins 0468 anchors.bottomMargin: -footer.anchors.margins 0469 } 0470 } 0471 0472 KeyboardButton { 0473 id: keyboardButton 0474 0475 font.pointSize: config.fontSize 0476 0477 onKeyboardLayoutChanged: { 0478 // Otherwise the password field loses focus and virtual keyboard 0479 // keystrokes get eaten 0480 userListComponent.mainPasswordBox.forceActiveFocus(); 0481 } 0482 0483 Layout.fillHeight: true 0484 containmentMask: Item { 0485 parent: keyboardButton 0486 anchors.fill: parent 0487 anchors.leftMargin: virtualKeyboardButton.visible ? 0 : -footer.anchors.margins 0488 anchors.bottomMargin: -footer.anchors.margins 0489 } 0490 } 0491 0492 SessionButton { 0493 id: sessionButton 0494 0495 font.pointSize: config.fontSize 0496 0497 onSessionChanged: { 0498 // Otherwise the password field loses focus and virtual keyboard 0499 // keystrokes get eaten 0500 userListComponent.mainPasswordBox.forceActiveFocus(); 0501 } 0502 0503 Layout.fillHeight: true 0504 containmentMask: Item { 0505 parent: sessionButton 0506 anchors.fill: parent 0507 anchors.leftMargin: virtualKeyboardButton.visible || keyboardButton.visible 0508 ? 0 : -footer.anchors.margins 0509 anchors.bottomMargin: -footer.anchors.margins 0510 } 0511 } 0512 0513 Item { 0514 Layout.fillWidth: true 0515 } 0516 0517 Battery { 0518 fontSize: config.fontSize 0519 } 0520 } 0521 } 0522 0523 Connections { 0524 target: sddm 0525 function onLoginFailed() { 0526 notificationMessage = i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Login Failed") 0527 footer.enabled = true 0528 mainStack.enabled = true 0529 userListComponent.userList.opacity = 1 0530 rejectPasswordAnimation.start() 0531 } 0532 function onLoginSucceeded() { 0533 //note SDDM will kill the greeter at some random point after this 0534 //there is no certainty any transition will finish, it depends on the time it 0535 //takes to complete the init 0536 mainStack.opacity = 0 0537 footer.opacity = 0 0538 } 0539 } 0540 0541 onNotificationMessageChanged: { 0542 if (notificationMessage) { 0543 notificationResetTimer.start(); 0544 } 0545 } 0546 0547 Timer { 0548 id: notificationResetTimer 0549 interval: 3000 0550 onTriggered: notificationMessage = "" 0551 } 0552 }