Skip to content

Clean up hidutil remaps on shutdown, signal, and panic - #10

Merged
mitchelljphayes merged 1 commit into
mainfrom
hidutil-cleanup-on-exit
Mar 16, 2026
Merged

Clean up hidutil remaps on shutdown, signal, and panic#10
mitchelljphayes merged 1 commit into
mainfrom
hidutil-cleanup-on-exit

Conversation

@mitchelljphayes

Copy link
Copy Markdown
Owner

Summary

  • Clear hidutil UserKeyMapping on every exit path so the keyboard returns to its default state when Switcheroo stops
  • Wire up signal-hook (was already a dep, unused) to catch SIGTERM/SIGINT, stop the CFRunLoop, and trigger cleanup
  • Install a panic hook that clears hidutil before the default handler runs
  • Track whether hidutil remaps are active with an AtomicBool to avoid unnecessary cleanup calls

Why

The hidutil modifier remaps (e.g. Caps Lock → Ctrl) are kernel-level and persist after Switcheroo exits. This means stopping the daemon leaves stale remaps — confusing if you're debugging or if the daemon crashes. Since the LaunchAgent re-applies them on boot anyway, cleanup on exit is the right default.

Exit paths covered

Scenario Cleanup mechanism
Ctrl+C / SIGINT Signal handler stops CFRunLoop → normal cleanup
launchctl bootout / SIGTERM Same signal handler
Panic Custom panic hook calls clear_modifier_remaps()
Error in run() main() error path calls clear_modifier_remaps()
SIGKILL Not possible to handle — only uncleanable exit

Wire up signal-hook (already a dependency, previously unused) to handle
SIGTERM and SIGINT by stopping the CFRunLoop, allowing graceful cleanup.

On any exit path — normal shutdown, signal, panic, or error — clear the
hidutil UserKeyMapping so the keyboard returns to its default state.
The LaunchAgent re-applies remaps on next boot, so there's no gap.

- Add hidutil::clear_modifier_remaps() to reset UserKeyMapping to empty
- Extract run_hidutil_set() helper to share between apply and clear
- Install panic hook that clears hidutil before the default handler runs
- Spawn signal listener thread that stops CFRunLoop on SIGINT/SIGTERM
- Track hidutil state with AtomicBool to avoid unnecessary cleanup calls
- Clean up on error path in main() as a final safety net
@mitchelljphayes
mitchelljphayes merged commit 08dec59 into main Mar 16, 2026
3 checks passed
@mitchelljphayes
mitchelljphayes deleted the hidutil-cleanup-on-exit branch March 16, 2026 19:14
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.

1 participant