fix(ime): keep toggle alive when activeController is lost in IMK lifecycle races - #20
Merged
Merged
Conversation
…cycle races CGEventTap toggle entry points relied solely on the global activeController, which IMK can leave nil or stale during fullscreen/Space transitions. The Shift+Space handler then consumed the event without toggling — a black hole where the key did nothing until the user re-focused the app. Resolve the controller via activeController, falling back to lastController (kept across deactivate) only when Ongeul is the active input source, so a stale controller can't eat another IME's Shift+Space or persist a wrong per-app mode. Consume only when a live client can apply the toggle; otherwise pass through to IMK's correctly-routed handle(). Apply the same resolution to the Vim-escape, CapsLock, modifier-tap, and English-lock entry points.
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.
Problem
Occasionally Shift+Space (Korean/English toggle) does nothing — no toggle, no space — most visibly with a fullscreen app such as VSCode. Switching to another window and back restores it.
Root cause
The CGEventTap toggle path's authority is the global
KeyEventTap.activeController, maintained via IMK'sactivateServer/deactivateServer. During fullscreen/Space transitions IMK can deliver these out of order (activate → deactivateon the same instance) or drop theactivate, leavingactiveControllernil while that controller is still the focused IME. The IMK input path doesn't useactiveController, so typing still works while only the tap-driven toggle dies. Worse, the Shift+Space handler consumed the event unconditionally, so the key was swallowed with no effect (a black hole) until the nextactivateServer.Fix
lastController(preserved acrossdeactivate) andresolvedController = activeController ?? lastController, gated so the fallback only applies when Ongeul is the active input source (TIS) — preventing a stale controller from eating another IME's Shift+Space or persisting a wrong per-app mode.handle()(correct routing + commits in-flight Hangul).Notes / scope
Verification
./scripts/build.sh).toggling [lastController fallback]appearing means the bug condition occurred and was auto-recovered.