Skip to content

fix: re-register keyboard hooks after Windows session unlock (#1213)#1301

Draft
ChristophNoetel wants to merge 3 commits intocjpais:mainfrom
ChristophNoetel:fix/1213-session-reregister
Draft

fix: re-register keyboard hooks after Windows session unlock (#1213)#1301
ChristophNoetel wants to merge 3 commits intocjpais:mainfrom
ChristophNoetel:fix/1213-session-reregister

Conversation

@ChristophNoetel
Copy link
Copy Markdown
Contributor

Summary

Fixes #1213 -- Windows screen lock (Win+L) kills handy-keys keyboard shortcuts because the Winlogon desktop switch invalidates low-level hooks, and the manager thread never re-registers them.

This PR adds:

  • ReregisterAll command to the handy-keys manager thread that drops the old HotkeyManager, creates a fresh one, and re-registers all bindings
  • Public reregister_all() method on HandyKeysState for triggering re-registration

Coming next (will push before marking ready):

  • Windows session event listener (WTS_SESSION_UNLOCK) that automatically triggers reregister_all() after lock/unlock

See my root cause analysis on the issue.

Test plan

  • cargo check / cargo clippy pass (CI)
  • Handy Keys survives Win+L lock/unlock (core fix)
  • Sleep/wake still works (regression test)
  • Push-to-talk (hold to record, release to stop) still works
  • Repeated lock/unlock (3+ times) -- hooks survive each time
  • Clean shutdown after lock/unlock -- no zombie process

Add infrastructure to re-create the HotkeyManager and re-register all
bindings on demand. This is needed to recover from events that
invalidate low-level keyboard hooks (e.g., Windows session lock).

- Add ReregisterAll variant to ManagerCommand enum
- Implement do_reregister_all() that drops the old manager, creates a
  fresh one, and re-registers all existing bindings
- Handle ReregisterAll in the manager thread with fallback recovery
- Expose public reregister_all() method on HandyKeysState
…1213)

When Windows switches to the secure desktop (Win+L), low-level keyboard
hooks installed by handy-keys are silently invalidated. This adds a
session watcher thread that:

- Creates a hidden message-only window
- Registers for WTS_SESSION_UNLOCK notifications
- Triggers ReregisterAll to recreate hooks when the user unlocks

Cleanup is handled via WM_CLOSE in HandyKeysState::drop.
@ChristophNoetel ChristophNoetel force-pushed the fix/1213-session-reregister branch from b43aa63 to 5a45223 Compare April 19, 2026 17:07
@cjpais
Copy link
Copy Markdown
Owner

cjpais commented Apr 20, 2026

Just wondering if this should be done in Handykeys itself rather than the app level.

…el watcher

Moves session-unlock hook re-registration from the Handy app into the
handy-keys library (handy-computer/handy-keys#19). The library's
Windows listener thread now automatically detects WTS_SESSION_UNLOCK
and re-installs hooks transparently.

This removes ~170 lines of app-level session watcher code:
- start_session_watcher() function and wndproc_stub callback
- ReregisterAll command, do_reregister_all(), reregister_all()
- session_watcher_hwnd field and Drop cleanup
- Win32_System_RemoteDesktop feature from Handy's Cargo.toml

The handy-keys dependency now points at the fork branch temporarily
until the upstream PR is merged and published to crates.io.

Addresses cjpais's review feedback on cjpais#1301.
@ChristophNoetel
Copy link
Copy Markdown
Contributor Author

ChristophNoetel commented Apr 23, 2026

Good call -- you're right that hook lifecycle is a library concern. I've moved the session recovery into handy-keys itself: handy-computer/handy-keys#19.

The library's Windows listener thread already runs a message pump, good fit^^ . On startup it creates a message-only window, registers for WTS_SESSION_UNLOCK notifications, and when session unlock is detected it unhooks the old hooks and installs fresh ones -- all transparent to consumers, no API changes.

This PR now just points handy-keys at the fork branch (1-line Cargo.toml change, -247 lines of app code). Once the upstream PR is merged and published to crates.io, I'll switch back to a version pin.

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.

[BUG] Windows 11 after sleep mode stuck on "transcribing"

2 participants