fix: reliable IME switch on macOS 26 Tahoe (postEvent HID source + timing)#118
Merged
Conversation
Root cause (researched against macism, the reference CJK input switcher):
macOS 26 Tahoe tightened input-event timing. cmd-ime's postEvent() used a
nil CGEventSource and posted key-up immediately after key-down, which Tahoe
now drops — the Eisu/Kana switch silently fails in normal apps (regression
vs. older macOS).
Fix postEvent() to match macism's proven approach:
- real HID event source (CGEventSource(stateID: .hidSystemState)) not nil
- space key-up ~50ms after key-down, dispatched async so the event-tap
callback (main run loop) is never blocked
Also revert the Eisu/Kana switch to a single mechanism (posting the key,
which drives the IME's internal Hiragana/direct mode without stealing focus)
and remove the v2.4.7-2.4.9 TIS special-casing: bare TISSelectInputSource
only moves the menu-bar indicator unless the caller forces activation, and
the focus-stealing window workaround macism uses for its CLI is unacceptable
for a background switcher.
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.
Root cause (researched, not guessed)
Confirmed on-device: macOS 26.5.1 (Tahoe). Reference:
macism, the battle-tested CJK input-source switcher, documents that macOS 26 tightened input-event timing (older macOS needed ~1ms, Tahoe needs much longer).cmd-ime's
postEvent()— which posts the Eisu(102)/Kana(104) key to switch the frontmost app's IME — used two pre-Tahoe patterns that Tahoe now drops:nilCGEventSource (macism uses a realCGEventSource(stateID: .hidSystemState)).Result: on Tahoe the synthesized key is dropped and the switch silently fails in normal apps — the regression the user hit.
Why not TIS:
TISSelectInputSourcealone only moves the menu-bar indicator unless the caller forces activation (the "menu shows あ but types direct" bug — also documented by macism). macism forces it with a focus-stealing temporary window, which is fine for a one-shot CLI but unacceptable for a background switcher that must not yank focus from the app you're typing in. So the correct primitive for cmd-ime is posting the key, done right.Fix
postEvent(): real HID event source + key-up dispatched ~50ms after key-down (async, so the event-tap callback on the main run loop is never blocked).InputSourceSwitcher,isTISSwitchApp, palette-avoidance) — that whole detour was the wrong primitive for a live switcher and caused the palette-window and half-switch regressions.Tests
KeyEventTests: Kana/Eisu remap output passes through on keyDown/keyUp (the key that drives the IME).InputSourceDumpTests: skippable on-device diagnostic (CMDIME_DUMP_INPUT_SOURCES=1) that enumerates installed IMEs' TIS structure — how the Google single-mode-source fact was established.swift buildclean · 32 tests (1 skipped, 0 failures) · swiftlint 0 serious.Needs on-device confirmation (IME switching can't be verified headless): after auto-update, press the switch key in a normal app (メモ/TextEdit) and confirm it actually types Hiragana.
Version 2.4.10.