feat(macos): release keyboard grab on lock screen and user switch#2016
Merged
jtroo merged 1 commit intojtroo:mainfrom Apr 11, 2026
Merged
feat(macos): release keyboard grab on lock screen and user switch#2016jtroo merged 1 commit intojtroo:mainfrom
jtroo merged 1 commit intojtroo:mainfrom
Conversation
f69f44e to
604c10f
Compare
Contributor
Author
|
@jtroo I resolved the conflict |
604c10f to
f6dc3d1
Compare
Contributor
Author
|
Resolved again |
Owner
|
The approach looks sensible to me. I think this needs to be configurable though. I presume there are users who are the sole users of their machines that prefer the current always-grab even on lockscreen behaviour - without configurability this change would break their workflows. The default should IMO preserve the current behaviour. With respect to implementation, a CLI argument seems more fitting for this type of functionality as opposed to a config item, but that is a weakly held opinion. |
Contributor
Author
|
Yea, I was thinking the same some time after I made the PR, does |
Owner
|
Name sounds good! |
Address jtroo#1743 Poll CGSession state from a small background thread and pause kanata's global IOKit grab whenever the screen locks or kanata's session loses the console. Resume the grab once the session recovers Key the fast-user-switching check on `kCGSSessionOnConsoleKey`, since `CGSessionCopyCurrentDictionary` returns the *caller's* session — a username comparison against a launch-time snapshot would never trip. Read the undocumented `CGSSessionScreenIsLocked` boolean for the lock signal. Fall back to "do not pause" on a NULL dict so root LaunchDaemon installs (no Quartz GUI session) keep working Re-check the pause flag right after `kb.read()` returns, not just at the top of the loop. `wait_key` blocks on a `read(2)`, so the typical lock path catches kanata mid-read with the new user's first keystroke already seized by IOKit. Drop that event without remapping or emitting it — trade one lost keystroke for never producing a wrong one
f6dc3d1 to
8a213d9
Compare
jtroo
approved these changes
Apr 11, 2026
Owner
|
Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Address #1743
Poll CGSession state from a small background thread and pause kanata's
global IOKit grab whenever the screen locks or kanata's session loses
the console. Resume the grab once the session recovers
Key the fast-user-switching check on
kCGSSessionOnConsoleKey, sinceCGSessionCopyCurrentDictionaryreturns the caller's session — ausername comparison against a launch-time snapshot would never trip.
Read the undocumented
CGSSessionScreenIsLockedboolean for the locksignal. Fall back to "do not pause" on a NULL dict so root LaunchDaemon
installs (no Quartz GUI session) keep working
Re-check the pause flag right after
kb.read()returns, not just at thetop of the loop.
wait_keyblocks on aread(2), so the typical lockpath catches kanata mid-read with the new user's first keystroke already
seized by IOKit. Drop that event without remapping or emitting it —
trade one lost keystroke for never producing a wrong one
Checklist