Skip to content

feat: switch input source during prefix mode (macOS, opt-in)#434

Merged
ogulcancelik merged 2 commits into
ogulcancelik:masterfrom
sf-jin-ku:issue/400-prefix-ime-ascii-input-source
Jun 3, 2026
Merged

feat: switch input source during prefix mode (macOS, opt-in)#434
ogulcancelik merged 2 commits into
ogulcancelik:masterfrom
sf-jin-ku:issue/400-prefix-ime-ascii-input-source

Conversation

@sf-jin-ku

@sf-jin-ku sf-jin-ku commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

What this does

Implements #400. While prefix mode is active on macOS, switch the system input source to the current ASCII-capable layout, then put back whatever was active once prefix mode ends. Off by default, behind [experimental] switch_ascii_input_source_in_prefix.

The problem: with a Korean (or any non-Latin) IME active, hitting the prefix key works, but the next key often gets composed by the IME instead of read as a command. So prefix commands are unreliable unless you switch to English first.

How it works

The switch hangs off the Mode transition rather than any new state. After each event is handled, I compare the previous mode against the current one: entering prefix switches to ASCII (only when the flag is on), and leaving prefix — for any reason, including cancel — restores. Keeping it on the mode edge means there's no second flag that can drift out of sync, and every exit path restores through the same point.

AppState only carries the bool; the actual macOS call lives in the runtime, so state stays pure. The macOS side is all in src/platform/macos.rs behind a small PrefixInputSource trait, so the rest of the app never sees the Carbon/CoreFoundation FFI and non-macOS just compiles a no-op. The saved source is held in a struct whose Drop does the restore + CFRelease, so it can't leak on an early return.

It uses TISCopyCurrentASCIICapableKeyboardLayoutInputSource, so it picks up whatever ASCII layout you already have — no hard-coded ABC/US. If the current source is already ASCII-capable (compared with CFEqual) or any TIS call fails, it does nothing and input keeps working.

Testing

PrefixInputSource is a trait so the transitions are covered with a fake — enter/leave, flag off, and the already-ASCII / failed-switch case where the later restore has to stay harmless. There's also a dispatch-level test that Esc out of prefix restores, since the exit is decided below handle_key.

just ci passes; I also ran the wider just check (clippy -D warnings + the python unittests). Verified by hand on macOS with a Korean IME: prefix commands land mid-composition, and my IME comes back when prefix mode ends.

Docs

New [experimental] option, so I updated docs/next/website/src/content/docs/configuration.mdx for the next release. Left docs/next/CHANGELOG.md alone (maintainers handle that at release), and didn't touch root README/CHANGELOG or the released website docs.

@sf-jin-ku sf-jin-ku force-pushed the issue/400-prefix-ime-ascii-input-source branch 2 times, most recently from 8d47c96 to aae513c Compare June 3, 2026 01:10
On macOS, opt-in under [experimental], temporarily switch the host input
source to the current ASCII-capable layout while prefix mode is active so
prefix commands register even when a CJK IME is composing, then restore the
previous input source when prefix mode exits or is cancelled. No-op when the
current source is already ASCII-capable, on non-macOS platforms, or when any
input source call fails. Pane text input is unaffected.

Also pin next_resize_poll in next_loop_deadline_includes_selection_autoscroll_deadline
so the selection autoscroll deadline stays the earliest; the default resize
poll could otherwise beat it and flake the assertion.

refs ogulcancelik#400
@sf-jin-ku sf-jin-ku force-pushed the issue/400-prefix-ime-ascii-input-source branch from aae513c to 4828fe1 Compare June 3, 2026 01:30
@ogulcancelik

Copy link
Copy Markdown
Owner

lgtm ty!

@ogulcancelik ogulcancelik merged commit f5e66b2 into ogulcancelik:master Jun 3, 2026
3 checks passed
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.

2 participants