/* SPDX-FileCopyrightText: 2016 David Edmundson SPDX-License-Identifier: LGPL-2.0-or-later */ import QtQuick 2.2 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.12 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 import org.kde.kscreenlocker 1.0 as ScreenLocker import org.kde.breeze.components SessionManagementScreen { id: sessionManager readonly property alias mainPasswordBox: passwordBox property bool lockScreenUiVisible: false property alias showPassword: passwordBox.showPassword //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 /* * 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 */ signal passwordResult(string password) onUserSelected: { const nextControl = (passwordBox.visible ? passwordBox : loginButton); // 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. Using TabFocusReason, so that the loginButton gets the // visual highlight. nextControl.forceActiveFocus(Qt.TabFocusReason); } function startLogin() { const password = passwordBox.text // 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(); passwordResult(password); } RowLayout { Layout.fillWidth: true PlasmaExtras.PasswordField { id: passwordBox font.pointSize: Kirigami.Theme.defaultFont.pointSize + 1 Layout.fillWidth: true placeholderText: i18nd("plasma_shell_org.kde.plasma.desktop", "Password") focus: true enabled: !authenticator.graceLocked // In Qt this is implicitly active based on focus rather than visibility // in any other application having a focussed invisible object would be weird // but here we are using to wake out of screensaver mode // We need to explicitly disable cursor flashing to avoid unnecessary renders cursorVisible: visible onAccepted: { if (lockScreenUiVisible) { startLogin(); } } //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: root function onClearPassword() { passwordBox.forceActiveFocus() passwordBox.text = ""; } function onNotificationRepeated() { sessionManager.playHighlightAnimation(); } } } PlasmaComponents3.Button { id: loginButton Accessible.name: i18nd("plasma_shell_org.kde.plasma.desktop", "Unlock") Layout.preferredHeight: passwordBox.implicitHeight Layout.preferredWidth: loginButton.Layout.preferredHeight icon.name: LayoutMirroring.enabled ? "go-previous" : "go-next" onClicked: startLogin() Keys.onEnterPressed: clicked() Keys.onReturnPressed: clicked() } } component FailableLabel : PlasmaComponents3.Label { id: _failableLabel required property int kind required property string label visible: authenticator.authenticatorTypes & kind text: label textFormat: Text.PlainText horizontalAlignment: Text.AlignHCenter Layout.fillWidth: true RejectPasswordAnimation { id: _rejectAnimation target: _failableLabel onFinished: _timer.restart() } Connections { target: authenticator function onNoninteractiveError(kind, authenticator) { if (kind & _failableLabel.kind) { _failableLabel.text = Qt.binding(() => authenticator.errorMessage) _rejectAnimation.start() } } } Timer { id: _timer interval: Kirigami.Units.humanMoment onTriggered: { _failableLabel.text = Qt.binding(() => _failableLabel.label) } } } FailableLabel { kind: ScreenLocker.Authenticator.Fingerprint label: i18nd("plasma_shell_org.kde.plasma.desktop", "(or scan your fingerprint on the reader)") } FailableLabel { kind: ScreenLocker.Authenticator.Smartcard label: i18nd("plasma_shell_org.kde.plasma.desktop", "(or scan your smartcard)") } }