diff --git a/quickshell/Modules/Lock/Keyboard.qml b/quickshell/Modules/Lock/Keyboard.qml index cfc0c6117..b6f53e17b 100644 --- a/quickshell/Modules/Lock/Keyboard.qml +++ b/quickshell/Modules/Lock/Keyboard.qml @@ -25,142 +25,179 @@ Rectangle { property string strClose: "keyboard_hide" property var modelKeyboard: { - "row_1": [{ - "text": 'q', - "symbol": '1', - "width": 1 - }, { - "text": 'w', - "symbol": '2', - "width": 1 - }, { - "text": 'e', - "symbol": '3', - "width": 1 - }, { - "text": 'r', - "symbol": '4', - "width": 1 - }, { - "text": 't', - "symbol": '5', - "width": 1 - }, { - "text": 'y', - "symbol": '6', - "width": 1 - }, { - "text": 'u', - "symbol": '7', - "width": 1 - }, { - "text": 'i', - "symbol": '8', - "width": 1 - }, { - "text": 'o', - "symbol": '9', - "width": 1 - }, { - "text": 'p', - "symbol": '0', - "width": 1 - }], - "row_2": [{ - "text": 'a', - "symbol": '-', - "width": 1 - }, { - "text": 's', - "symbol": '/', - "width": 1 - }, { - "text": 'd', - "symbol": ':', - "width": 1 - }, { - "text": 'f', - "symbol": ';', - "width": 1 - }, { - "text": 'g', - "symbol": '(', - "width": 1 - }, { - "text": 'h', - "symbol": ')', - "width": 1 - }, { - "text": 'j', - "symbol": '€', - "width": 1 - }, { - "text": 'k', - "symbol": '&', - "width": 1 - }, { - "text": 'l', - "symbol": '@', - "width": 1 - }], - "row_3": [{ - "text": strShift, - "symbol": strShift, - "width": 1.5 - }, { - "text": 'z', - "symbol": '.', - "width": 1 - }, { - "text": 'x', - "symbol": ',', - "width": 1 - }, { - "text": 'c', - "symbol": '?', - "width": 1 - }, { - "text": 'v', - "symbol": '!', - "width": 1 - }, { - "text": 'b', - "symbol": "'", - "width": 1 - }, { - "text": 'n', - "symbol": "%", - "width": 1 - }, { - "text": 'm', - "symbol": '"', - "width": 1 - }, { - "text": strBackspace, - "symbol": strBackspace, - "width": 1.5 - }], - "row_4": [{ - "text": strClose, - "symbol": strClose, - "width": 1.5 - }, { - "text": "123", - "symbol": 'ABC', - "width": 1.5 - }, { - "text": ' ', - "symbol": ' ', - "width": 4.5 - }, { - "text": '.', - "symbol": '.', - "width": 1 - }, { - "text": strEnter, - "symbol": strEnter, - "width": 1.5 - }] + "row_1": [ + { + "text": 'q', + "symbol": '1', + "width": 1 + }, + { + "text": 'w', + "symbol": '2', + "width": 1 + }, + { + "text": 'e', + "symbol": '3', + "width": 1 + }, + { + "text": 'r', + "symbol": '4', + "width": 1 + }, + { + "text": 't', + "symbol": '5', + "width": 1 + }, + { + "text": 'y', + "symbol": '6', + "width": 1 + }, + { + "text": 'u', + "symbol": '7', + "width": 1 + }, + { + "text": 'i', + "symbol": '8', + "width": 1 + }, + { + "text": 'o', + "symbol": '9', + "width": 1 + }, + { + "text": 'p', + "symbol": '0', + "width": 1 + } + ], + "row_2": [ + { + "text": 'a', + "symbol": '-', + "width": 1 + }, + { + "text": 's', + "symbol": '/', + "width": 1 + }, + { + "text": 'd', + "symbol": ':', + "width": 1 + }, + { + "text": 'f', + "symbol": ';', + "width": 1 + }, + { + "text": 'g', + "symbol": '(', + "width": 1 + }, + { + "text": 'h', + "symbol": ')', + "width": 1 + }, + { + "text": 'j', + "symbol": '€', + "width": 1 + }, + { + "text": 'k', + "symbol": '&', + "width": 1 + }, + { + "text": 'l', + "symbol": '@', + "width": 1 + } + ], + "row_3": [ + { + "text": strShift, + "symbol": strShift, + "width": 1.5 + }, + { + "text": 'z', + "symbol": '.', + "width": 1 + }, + { + "text": 'x', + "symbol": ',', + "width": 1 + }, + { + "text": 'c', + "symbol": '?', + "width": 1 + }, + { + "text": 'v', + "symbol": '!', + "width": 1 + }, + { + "text": 'b', + "symbol": "'", + "width": 1 + }, + { + "text": 'n', + "symbol": "%", + "width": 1 + }, + { + "text": 'm', + "symbol": '"', + "width": 1 + }, + { + "text": strBackspace, + "symbol": strBackspace, + "width": 1.5 + } + ], + "row_4": [ + { + "text": strClose, + "symbol": strClose, + "width": 1.5 + }, + { + "text": "123", + "symbol": 'ABC', + "width": 1.5 + }, + { + "text": ' ', + "symbol": ' ', + "width": 4.5 + }, + { + "text": '.', + "symbol": '.', + "width": 1 + }, + { + "text": strEnter, + "symbol": strEnter, + "width": 1.5 + } + ] } //Here is the corresponding table between the ascii and the key event @@ -210,9 +247,7 @@ Rectangle { "_;": Qt.Key_Semicolon, "_(": Qt.Key_BracketLeft, "_)": Qt.Key_BracketRight, - "_€": parseInt( - "20ac", - 16) // I didn't find the appropriate Qt event so I used the hex format + "_€": parseInt("20ac", 16) // I didn't find the appropriate Qt event so I used the hex format , "_&": Qt.Key_Ampersand, "_@": Qt.Key_At, @@ -224,121 +259,111 @@ Rectangle { "_'": Qt.Key_Apostrophe, "_%": Qt.Key_Percent, "_*": Qt.Key_Asterisk -} + } -Item { -id: keyboard_container -anchors.left: parent.left -anchors.leftMargin: 5 -anchors.right: parent.right -anchors.top: parent.top -anchors.topMargin: 5 -anchors.bottom: parent.bottom -anchors.bottomMargin: 5 + Item { + id: keyboard_container + anchors.left: parent.left + anchors.leftMargin: 5 + anchors.right: parent.right + anchors.top: parent.top + anchors.topMargin: 5 + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 -//One column which contains 5 rows -Column { -spacing: columnSpacing + //One column which contains 5 rows + Column { + spacing: columnSpacing -Row { -id: row_1 -spacing: rowSpacing -Repeater { -model: modelKeyboard["row_1"] -delegate: CustomButtonKeyboard { -text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase -() : modelData.text -width: modelData.width * keyboard_container.width / columns - rowSpacing -height: keyboard_container.height / rows - columnSpacing + Row { + id: row_1 + spacing: rowSpacing + Repeater { + model: modelKeyboard["row_1"] + delegate: CustomButtonKeyboard { + text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase() : modelData.text + width: modelData.width * keyboard_container.width / columns - rowSpacing + height: keyboard_container.height / rows - columnSpacing -onClicked: root.clicked(text) -} -} -} -Row { -id: row_2 -spacing: rowSpacing -Repeater { -model: modelKeyboard["row_2"] -delegate: CustomButtonKeyboard { -text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase -() : modelData.text -width: modelData.width * keyboard_container.width / columns - rowSpacing -height: keyboard_container.height / rows - columnSpacing + onClicked: root.clicked(text) + } + } + } + Row { + id: row_2 + spacing: rowSpacing + Repeater { + model: modelKeyboard["row_2"] + delegate: CustomButtonKeyboard { + text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase() : modelData.text + width: modelData.width * keyboard_container.width / columns - rowSpacing + height: keyboard_container.height / rows - columnSpacing -onClicked: root.clicked(text) -} -} -} -Row { -id: row_3 -spacing: rowSpacing -Repeater { -model: modelKeyboard["row_3"] -delegate: CustomButtonKeyboard { -text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase -() : modelData.text -width: modelData.width * keyboard_container.width / columns - rowSpacing -height: keyboard_container.height / rows - columnSpacing -isShift: shift && text === strShift + onClicked: root.clicked(text) + } + } + } + Row { + id: row_3 + spacing: rowSpacing + Repeater { + model: modelKeyboard["row_3"] + delegate: CustomButtonKeyboard { + text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase() : modelData.text + width: modelData.width * keyboard_container.width / columns - rowSpacing + height: keyboard_container.height / rows - columnSpacing + isShift: shift && text === strShift -onClicked: root.clicked(text) -} -} -} -Row { -id: row_4 -spacing: rowSpacing -Repeater { -model: modelKeyboard["row_4"] -delegate: CustomButtonKeyboard { -text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase -() : modelData.text -width: modelData.width * keyboard_container.width / columns - rowSpacing -height: keyboard_container.height / rows - columnSpacing + onClicked: root.clicked(text) + } + } + } + Row { + id: row_4 + spacing: rowSpacing + Repeater { + model: modelKeyboard["row_4"] + delegate: CustomButtonKeyboard { + text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase() : modelData.text + width: modelData.width * keyboard_container.width / columns - rowSpacing + height: keyboard_container.height / rows - columnSpacing -onClicked: root.clicked(text) -} -} -} -} -} -signal clicked(string text) + onClicked: root.clicked(text) + } + } + } + } + } + signal clicked(string text) -Connections { -target: root -function onClicked(text) { -if (!keyboard_controller.target) -return -if (text === strShift) { -root.shift = !root.shift -} else if (text === '123') { -root.symbols = true -} else if (text === 'ABC') { -root.symbols = false -} else if (text === strEnter) { -if (keyboard_controller.target.accepted) { -keyboard_controller.target.accepted() -} -} else if (text === strClose) { -root.dismissed() -} else { -if (text === strBackspace) { -var current = keyboard_controller.target.text -keyboard_controller.target.text = current.slice(0, current.length - 1) -} else { -var charToInsert = root.symbols ? text : (root.shift ? text.toUpperCase -() : text) -var current = keyboard_controller.target.text -var cursorPos = keyboard_controller.target.cursorPosition -keyboard_controller.target.text = current.slice(0, -cursorPos) + charToInsert + current.slice(cursorPos) -keyboard_controller.target.cursorPosition = cursorPos + 1 -} + Connections { + target: root + function onClicked(text) { + if (!keyboard_controller.target) + return; + if (text === strShift) { + root.shift = !root.shift; + } else if (text === '123') { + root.symbols = true; + } else if (text === 'ABC') { + root.symbols = false; + } else if (text === strEnter) { + if (keyboard_controller.target.accepted) { + keyboard_controller.target.accepted(); + } + } else if (text === strClose) { + root.dismissed(); + } else { + if (text === strBackspace) { + keyboard_controller.target.backspace(); + } else { + var charToInsert = root.symbols ? text : (root.shift ? text.toUpperCase() : text); + keyboard_controller.target.insertText(charToInsert); + } -if (root.shift && text !== strShift) -root.shift = false -} -} -} + if (root.shift && text !== strShift) + root.shift = false; + } + } + } } diff --git a/quickshell/Modules/Lock/LockScreenContent.qml b/quickshell/Modules/Lock/LockScreenContent.qml index 6dd30bca2..812f553e4 100644 --- a/quickshell/Modules/Lock/LockScreenContent.qml +++ b/quickshell/Modules/Lock/LockScreenContent.qml @@ -46,6 +46,7 @@ Item { } signal unlockRequested + signal passwordEdited(string text) function resetLockState() { lockerReadySent = false; @@ -56,6 +57,12 @@ Item { pam.lockMessage = ""; } + function focusPasswordField() { + if (demoMode || !passwordField) + return; + passwordField.forceActiveFocus(); + } + function currentAuthFeedbackText() { if (!pam) return ""; @@ -799,7 +806,7 @@ Item { FocusScope { id: passwordField - property string text: root.passwordBuffer + readonly property string text: root.passwordBuffer property int cursorPosition: text.length signal accepted @@ -809,7 +816,7 @@ Item { } function clear() { - text = ""; + root.passwordEdited(""); cursorPosition = 0; } @@ -817,23 +824,27 @@ Item { if (value.length === 0) return; clampCursorPosition(); - text = text.slice(0, cursorPosition) + value + text.slice(cursorPosition); - cursorPosition += value.length; + const pos = cursorPosition; + root.passwordEdited(text.slice(0, pos) + value + text.slice(pos)); + cursorPosition = pos + value.length; } function backspace() { clampCursorPosition(); if (cursorPosition === 0) return; - text = text.slice(0, cursorPosition - 1) + text.slice(cursorPosition); - cursorPosition -= 1; + const pos = cursorPosition; + root.passwordEdited(text.slice(0, pos - 1) + text.slice(pos)); + cursorPosition = pos - 1; } function deleteForward() { clampCursorPosition(); if (cursorPosition === text.length) return; - text = text.slice(0, cursorPosition) + text.slice(cursorPosition + 1); + const pos = cursorPosition; + root.passwordEdited(text.slice(0, pos) + text.slice(pos + 1)); + cursorPosition = pos; } function isPrintableText(value) { @@ -868,11 +879,7 @@ Item { focus: true enabled: !demoMode activeFocusOnTab: !demoMode - onTextChanged: { - if (!demoMode) { - root.passwordBuffer = text; - } - } + onTextChanged: cursorPosition = text.length onAccepted: { if (!demoMode && !root.unlocking && !pam.passwd.active && !pam.u2fPending) { pam.passwd.start(); @@ -958,7 +965,7 @@ Item { } onActiveFocusChanged: { - if (!activeFocus && !demoMode && visible && passwordField && !powerMenu.isVisible) { + if (!activeFocus && !demoMode && passwordField && !powerMenu.isVisible) { Qt.callLater(() => { if (passwordField && passwordField.forceActiveFocus) { passwordField.forceActiveFocus(); @@ -968,7 +975,7 @@ Item { } onEnabledChanged: { - if (enabled && !demoMode && visible && passwordField && !powerMenu.isVisible) { + if (enabled && !demoMode && passwordField && !powerMenu.isVisible) { Qt.callLater(() => { if (passwordField && passwordField.forceActiveFocus) { passwordField.forceActiveFocus(); @@ -976,17 +983,6 @@ Item { }); } } - - Connections { - target: root - - function onPasswordBufferChanged() { - if (passwordField.text === root.passwordBuffer) - return; - passwordField.text = root.passwordBuffer; - passwordField.cursorPosition = passwordField.text.length; - } - } } KeyboardController { @@ -1121,8 +1117,7 @@ Item { visible: root.canStartSecurityKeyUnlock() enabled: visible onClicked: { - passwordField.text = ""; - root.passwordBuffer = ""; + passwordField.clear(); pam.u2f.startForAlternativeAuth(); } } @@ -1845,8 +1840,7 @@ Item { function onUnlockRequested() { root.unlocking = true; lockerReadyArmed = false; - passwordField.text = ""; - root.passwordBuffer = ""; + passwordField.clear(); root.unlockRequested(); } @@ -1856,15 +1850,13 @@ Item { return; root.unlocking = false; placeholderDelay.restart(); - passwordField.text = ""; - root.passwordBuffer = ""; + passwordField.clear(); } function onU2fPendingChanged() { if (!root.pam.u2fPending) return; - passwordField.text = ""; - root.passwordBuffer = ""; + passwordField.clear(); if (keyboardController.isKeyboardActive) keyboardController.hide(); } diff --git a/quickshell/Modules/Lock/LockSurface.qml b/quickshell/Modules/Lock/LockSurface.qml index 91057ce0b..d4a88a82e 100644 --- a/quickshell/Modules/Lock/LockSurface.qml +++ b/quickshell/Modules/Lock/LockSurface.qml @@ -40,11 +40,7 @@ FocusScope { focus: !videoScreensaver.active opacity: videoScreensaver.active ? 0 : 1 onUnlockRequested: root.unlockRequested() - onPasswordBufferChanged: { - if (root.sharedPasswordBuffer !== passwordBuffer) { - root.passwordChanged(passwordBuffer); - } - } + onPasswordEdited: text => root.passwordChanged(text) Behavior on opacity { NumberAnimation { @@ -57,6 +53,7 @@ FocusScope { id: videoScreensaver anchors.fill: parent screenName: root.screenName + onDismissed: Qt.callLater(() => lockContent.focusPasswordField()) } Component.onCompleted: forceActiveFocus()