import org.kde.breeze.components import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 as QQC2 import org.kde.plasma.components 3.0 as PlasmaComponents3 import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kirigami 2.20 as Kirigami SessionManagementScreen { id: root property Item mainPasswordBox: passwordBox property bool showUsernamePrompt: !showUserList property string lastUserName property bool loginScreenUiVisible: false //the y position that should be ensured visible when the on screen keyboard is visible property int visibleBoundary: mapFromItem(loginButton, 0, 0).y onHeightChanged: visibleBoundary = mapFromItem(loginButton, 0, 0).y + loginButton.height + Kirigami.Units.smallSpacing property real fontSize: Kirigami.Theme.defaultFont.pointSize signal loginRequest(string username, string password) onShowUsernamePromptChanged: { if (!showUsernamePrompt) { lastUserName = "" } } onUserSelected: { // Don't startLogin() here, because the signal is connected to the // Escape key as well, for which it wouldn't make sense to trigger // login. focusFirstVisibleFormControl(); } QQC2.StackView.onActivating: { // Controls are not visible yet. Qt.callLater(focusFirstVisibleFormControl); } function focusFirstVisibleFormControl() { const nextControl = (userNameInput.visible ? userNameInput : (passwordBox.visible ? passwordBox : loginButton)); // Using TabFocusReason, so that the loginButton gets the visual highlight. nextControl.forceActiveFocus(Qt.TabFocusReason); } /* * Login has been requested with the following username and password * If username field is visible, it will be taken from that, otherwise from the "name" property of the currentIndex */ function startLogin() { const username = showUsernamePrompt ? userNameInput.text : userList.selectedUser const password = passwordBox.text footer.enabled = false mainStack.enabled = false userListComponent.userList.opacity = 0.5 // This is partly because it looks nicer, but more importantly it // works round a Qt bug that can trigger if the app is closed with a // TextField focused. // // See https://bugreports.qt.io/browse/QTBUG-55460 loginButton.forceActiveFocus(); loginRequest(username, password); } PlasmaComponents3.TextField { id: userNameInput font.pointSize: fontSize + 1 Layout.fillWidth: true text: lastUserName visible: showUsernamePrompt focus: showUsernamePrompt && !lastUserName //if there's a username prompt it gets focus first, otherwise password does placeholderText: i18nd("plasma-desktop-sddm-theme", "Username") onAccepted: { if (root.loginScreenUiVisible) { passwordBox.forceActiveFocus() } } } RowLayout { Layout.fillWidth: true PlasmaExtras.PasswordField { id: passwordBox font.pointSize: fontSize + 1 Layout.fillWidth: true placeholderText: i18nd("plasma-desktop-sddm-theme", "Password") focus: !showUsernamePrompt || lastUserName // Disable reveal password action because SDDM does not have the breeze icon set loaded rightActions: [] onAccepted: { if (root.loginScreenUiVisible) { startLogin(); } } visible: root.showUsernamePrompt || userList.currentItem.needsPassword Keys.onEscapePressed: { mainStack.currentItem.forceActiveFocus(); } //if empty and left or right is pressed change selection in user switch //this cannot be in keys.onLeftPressed as then it doesn't reach the password box Keys.onPressed: event => { if (event.key === Qt.Key_Left && !text) { userList.decrementCurrentIndex(); event.accepted = true } if (event.key === Qt.Key_Right && !text) { userList.incrementCurrentIndex(); event.accepted = true } } Connections { target: sddm function onLoginFailed() { passwordBox.selectAll() passwordBox.forceActiveFocus() } } } PlasmaComponents3.Button { id: loginButton Accessible.name: i18nd("plasma-desktop-sddm-theme", "Log In") Layout.preferredHeight: passwordBox.implicitHeight Layout.preferredWidth: text.length === 0 ? loginButton.Layout.preferredHeight : -1 icon.name: text.length === 0 ? (root.LayoutMirroring.enabled ? "go-previous" : "go-next") : "" text: root.showUsernamePrompt || userList.currentItem.needsPassword ? "" : i18n("Log In") onClicked: startLogin() Keys.onEnterPressed: clicked() Keys.onReturnPressed: clicked() } } }