Skip to content

fix(monitor): Only switch input method for the frontmost app#6

Merged
cuiko merged 1 commit into
mainfrom
fix/foreground-only-switch
Jun 5, 2026
Merged

fix(monitor): Only switch input method for the frontmost app#6
cuiko merged 1 commit into
mainfrom
fix/foreground-only-switch

Conversation

@cuiko

@cuiko cuiko commented Jun 5, 2026

Copy link
Copy Markdown
Owner

Summary

A backgrounded terminal could switch the input method of whatever app was actually in front. Reproed cleanly: with Claude Code running in a background Ghostty tab (its braille-spinner title constantly animating), focusing Obsidian would flip the IM — first to Obsidian's own rule, then immediately to the terminal rule's language.

Root cause

handleWindowFocus is driven by AX window / focused-element / title notifications, which fire even while the observed app is in the background. Claude Code's animated title (✳ … , ⠂ … , ⠐ … ) emits a steady stream of title-change events on the background terminal; the matcher acted on each one and applied the terminal's title rule globally — regardless of which app was frontmost.

Log excerpt while the user was in Obsidian:

md.obsidian            source=nil via=global-default        # TermIMS leaves Obsidian alone
ghostty TITLE RULE HIT ✳ TermIMS → wetype.pinyin            # background terminal switches IM anyway

Fix

  • Guard handleWindowFocus to ignore events whose app isn't NSWorkspace.frontmostApplication.
  • Re-check frontmost inside the 0.15s debounce timer, in case focus moved during the window.
  • activated is left unguarded — an activation notification is itself the signal that the app is now frontmost.

Test plan

  • make build clean
  • Claude Code animating in a background Ghostty tab; focus Obsidian and type → IM stays on Obsidian's setting, no flip to the terminal language
  • Switch to the Ghostty tab → terminal rules still apply (foreground case unaffected)
  • Rapidly activate Ghostty then switch to Obsidian within ~0.15s → no stale switch from the debounce

AX window, focused-element, and title notifications fire even while an
app is in the background. A terminal whose foreground program animates
its title — Claude Code's braille spinner being the worst offender —
emits a steady stream of these events, and handleWindowFocus acted on
every one. The result: a backgrounded terminal's rule reached across
and switched the input method of whatever app was actually in front, so
typing in Obsidian (or a browser) kept getting yanked to the terminal's
configured language.

Guard handleWindowFocus so it ignores events whose app isn't frontmost,
and re-check frontmost inside the debounce timer in case focus moved
during the 0.15s window. activated stays unguarded since an activation
notification is itself the signal that the app is now frontmost.
@cuiko
cuiko merged commit 3e570db into main Jun 5, 2026
1 check passed
@cuiko
cuiko deleted the fix/foreground-only-switch branch June 5, 2026 14:06
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