Skip to content

Fix lock password field auto-focus - #11643

Closed
Bekkenes wants to merge 1 commit into
omacom:quattrofrom
Bekkenes:fix/lock-focus-retry
Closed

Bekkenes wants to merge 1 commit into
omacom:quattrofrom
Bekkenes:fix/lock-focus-retry

Conversation

@Bekkenes

Copy link
Copy Markdown

Problem

The Quickshell lock screen password field does not auto-focus. After locking (cold lock, idle timeout, or suspend/resume), typing does nothing until the field is clicked. Reported as #6858 (and #7467).

Root cause

LockView.qml grabbed focus once with Qt.callLater(forcePasswordFocus) from Component.onCompleted and onInputEnabledChanged. The WlSessionLockSurface is created before Hyprland maps it and hands over keyboard focus, so that single grab lands while the window is still inactive and is never re-applied when the surface activates. Focus is also lost again, with nothing to reclaim it, in three further paths:

  • suspend/resume — the surface survives the suspend and inputEnabled (lockRequested) stays true across it, so neither hook re-fires;
  • idle auto-lock — the screensaver holds keyboard focus at lock time and is killed up to a second after the single grab has run;
  • failed password — the field is disabled while PAM runs and nothing refocuses it when authenticatingPassword clears.

Fix

Replace the single-shot grab with a retry timer whose running binding keys off focus state, so it re-arms on every later focus loss:

Timer {
  interval: 100
  repeat: true
  running: root.inputEnabled && !root.authenticatingPassword && !root.displaysBlank && !passwordInput.activeFocus
  onTriggered: root.forcePasswordFocus()
}

The !root.displaysBlank term idles the timer while the display is blanked. That bounds the one surface that can never converge — a monitor hotplugged mid-lock has a null screen and cannot win keyboard focus however many times it is asked — so it does not spin at 10 Hz for the whole lock.

Verification

  • qmllint on LockView.qml is clean.
  • New regression test test/shell.d/lock-focus-retry-test.sh asserts the retry invariant.
  • Existing lock and video-background tests pass, including the compositor-gated lock-password-overflow and lock-fingerprint-indicator tests that load and instantiate LockView.qml in a live Quickshell process.

Notes

  • This covers cold-lock, suspend/resume, idle-lock screensaver death, and post-password refocus. It intentionally does not add keyboard-wake for a blanked screen (that is Wake the blanked lock screen from the keyboard #7471's separate concern, and the blanked wake path is already reachable via pointer).
  • Third-party lock views that cloned the stock LockView.qml won't pick this up automatically; that is inherent to cloning.

The lock surface is created before Hyprland maps it and hands over keyboard focus, so the single forceActiveFocus() from Component.onCompleted landed while the window was still inactive and never re-applied. Focus is also dropped on suspend/resume, after the idle screensaver dies, and when a failed password re-enables the field. Retry until the field holds focus; the timer's running binding re-arms on every later focus loss, and idles while the display is blanked so a surface that can never take focus (monitor hotplugged mid-lock) does not spin all night.

Fixes omacom#6858

@csfh csfh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment in the implementation is unnecessarily long.

I am wondering if it wouldn't be better to resolve the underlying problem in shell.

@paulogeyer paulogeyer left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for #12587.

Verified test/shell.d/lock-focus-retry-test.sh green on PR head (3/3); stock tip lacks the focus-retry Timer. Matches the DPMS-blank → wake path: timer idles while displays are blank, then retries forcePasswordFocus() until the password field has keyboard focus — so typing works without a click after wake, without flipping global mouse_refocus.

Prefer this over the mouse_refocus = false workaround and over stale #7471. Complements #12435 for the suspend/resume focus path.

@paulogeyer

paulogeyer commented Sep 20, 2026 •

Copy link
Copy Markdown

Verified on my laptop (ASUS Vivobook, Intel Arc)

Live soak of the LockView focus-retry Timer against #12587:

  1. Lock session
  2. Wait for DPMS blank (~5s idle blank / displaysBlank)
  3. Wake with mouse
  4. Type password without clicking the field → unlocked

Stock tip fails this path (one-shot Qt.callLater(forcePasswordFocus) never reclaims after compositor focus loss). With the retry timer, keys land immediately after wake.

Structural harness test/shell.d/lock-focus-retry-test.sh also green earlier.

+1 — prefer this over draft #12614 for the DPMS-blank-while-locked case: surface stays mounted, so window active/activeFocusItem signals alone are a weaker fit; the timer that idles on displaysBlank matches the bug.

Non-blocking follow-ups (optional before or after merge)

  1. Event + timer: keep the 100ms timer as backstop; also Connections on Window.window (activeChanged / activeFocusItemChanged) → ensurePasswordFocus() gated on window.active for instant reclaim on resume/refocus (idea from Fix lock password focus after resume #12614 without dropping the timer).
  2. Stronger test: regex contract is fine as a guard; a small QML fixture that steals focus and asserts recovery (and toggles displaysBlank to check the timer idles/re-arms) would catch regressions the regex misses.
  3. PR body: cite Lock screen password field loses keyboard focus after DPMS wake #12587 explicitly (DPMS wake on an already-locked session), not only the older cold-lock cluster.

Not a substitute: global mouse_refocus=false, or suspend-only reclaim PRs — complementary at best.

@bjarneo

bjarneo commented Sep 21, 2026

Copy link
Copy Markdown
Member

Automated duplication check: this pull request looks similar to #8560, which covers the same lock focus restore on resume. I keep that one open and close this one to consolidate review.

If you feel this is the wrong decision, please open the PR again with a note on the difference.

@bjarneo bjarneo closed this Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants