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