Files
omarchycn/test/shell.d/fixtures/lock-password-overflow/shell.qml
T
David Heinemeier HanssonandClaude Fable 5 12dc7ae558 Shrink lock screen password dots to fit the field
Long passwords used to overflow the input field and clip with no
feedback that typing was still registering. Scale the dot size and
letter spacing down as the password grows, like macOS, so every
keystroke stays visible.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 11:03:00 -07:00

85 lines
2.6 KiB
QML

import QtQuick
import Quickshell
import qs.Commons
ShellRoot {
id: root
readonly property string resultPath: Quickshell.env("OMARCHY_QML_TEST_RESULT")
readonly property string rootPath: Quickshell.env("OMARCHY_PATH")
property var failures: []
function fail(message) {
failures.push(String(message))
}
function assertTrue(condition, message) {
if (!condition) fail(message)
}
function shellQuote(value) {
return "'" + String(value).replace(/'/g, "'\\''") + "'"
}
function writeResult() {
var payload = JSON.stringify({
ok: failures.length === 0,
failures: failures
})
if (resultPath) {
Quickshell.execDetached(["bash", "-lc", "printf '%s' " + shellQuote(payload) + " > " + shellQuote(resultPath)])
}
}
Item { id: host; width: 800; height: 600 }
TextMetrics {
id: probe
font.family: Style.font.family
}
Timer {
interval: 1
running: true
repeat: false
onTriggered: {
try {
var component = Qt.createComponent("file://" + root.rootPath + "/shell/plugins/lock/LockView.qml", Component.PreferSynchronous)
if (component.status !== Component.Ready) {
root.fail("LockView failed to load: " + component.errorString())
return
}
var view = component.createObject(host, { width: 800, height: 600, loadBackground: false })
if (!view) {
root.fail("LockView failed to instantiate: " + component.errorString())
return
}
view.passwordText = "x".repeat(6)
root.assertTrue(view.passwordDotScale === 1, "short passwords keep full-size dots, got scale " + view.passwordDotScale)
view.passwordText = "x".repeat(40)
var longScale = view.passwordDotScale
root.assertTrue(longScale > 0 && longScale < 1, "overflowing passwords shrink the dots, got scale " + longScale)
view.passwordText = "x".repeat(80)
var longerScale = view.passwordDotScale
root.assertTrue(longerScale < longScale, "dots keep shrinking as the password grows, got " + longerScale + " vs " + longScale)
probe.font.pixelSize = Math.max(1, Math.floor(view.passwordDotFontSize * longerScale))
probe.font.letterSpacing = view.passwordDotLetterSpacing * longerScale
probe.text = "●".repeat(80)
root.assertTrue(probe.advanceWidth <= view.fieldWidth, "all 80 dots fit inside the field, need " + probe.advanceWidth + "px of " + view.fieldWidth)
view.destroy()
} catch (error) {
root.fail("lock password overflow fixture threw: " + error)
} finally {
root.writeResult()
}
}
}
}