Skip to content

fix: re-install keyboard hooks after Windows session unlock#19

Open
ChristophNoetel wants to merge 1 commit intohandy-computer:mainfrom
ChristophNoetel:fix/session-recovery
Open

fix: re-install keyboard hooks after Windows session unlock#19
ChristophNoetel wants to merge 1 commit intohandy-computer:mainfrom
ChristophNoetel:fix/session-recovery

Conversation

@ChristophNoetel
Copy link
Copy Markdown

Summary

  • Automatically re-installs low-level keyboard and mouse hooks after a Windows session unlock (Win+L -> sign back in)
  • Windows silently invalidates WH_KEYBOARD_LL / WH_MOUSE_LL hooks when the user locks their session because the Winlogon secure desktop switch detaches hooks from the interactive desktop
  • This is transparent to consumers -- no API changes, no new public types

How it works

The hook thread already runs a message pump (MsgWaitForMultipleObjects + PeekMessageW). This PR adds:

  1. A message-only window (HWND_MESSAGE) created on the hook thread at startup
  2. WTSRegisterSessionNotification() to receive session change events
  3. Detection of WM_WTSSESSION_CHANGE + WTS_SESSION_UNLOCK in the existing message drain loop
  4. On unlock: UnhookWindowsHookEx on old hooks, SetWindowsHookExW to install fresh ones
  5. Proper cleanup (WTSUnRegisterSessionNotification + DestroyWindow) on thread exit

Session notification setup is non-fatal -- if it fails, hooks still work normally, they just won't auto-recover after lock/unlock.

Context

This fixes cjpais/Handy#1213. The fix was originally implemented at the app level in cjpais/Handy#1301, but @cjpais suggested moving it into handy-keys itself since hook lifecycle is a library concern.

Changes

  • Cargo.toml: add Win32_System_RemoteDesktop feature
  • src/platform/windows/listener.rs: session watcher + hook re-installation

Test plan

  • cargo check / cargo clippy pass
  • Existing tests pass (cargo test)
  • Manual: run basic example, Win+L lock/unlock, verify hotkeys still fire
  • Manual: repeated lock/unlock (3+ cycles) -- hooks survive each time
  • Manual: clean shutdown after lock/unlock -- no zombie process

Windows low-level hooks (WH_KEYBOARD_LL, WH_MOUSE_LL) are silently
invalidated when the user locks their session (Win+L) because Windows
switches to the Winlogon secure desktop. After unlocking, the hooks
never fire again.

Fix this by registering for WTS_SESSION_UNLOCK notifications via a
message-only window on the hook thread. When session unlock is detected,
the old hooks are removed and fresh ones are installed. This is
transparent to consumers -- no API changes needed.

Closes cjpais/Handy#1213
ChristophNoetel added a commit to ChristophNoetel/Handy that referenced this pull request Apr 23, 2026
…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.
@cjpais
Copy link
Copy Markdown
Contributor

cjpais commented Apr 27, 2026

Thank you! I will test and pull this in when I get a chance

Have you tested and validated on your own machine @ChristophNoetel, I will do the same, I just want to get confirmation it works

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