fix(indicator): don't flash indicator when app switch keeps the same input source - #130
Open
doggy8088 wants to merge 1 commit into
Open
fix(indicator): don't flash indicator when app switch keeps the same input source#130doggy8088 wants to merge 1 commit into
doggy8088 wants to merge 1 commit into
Conversation
…input source Switching between two apps that resolve to the same input source (via a cached keyboard, a per-app specified keyboard, or the system-wide default) still called TISSelectInputSource and popped up the switch indicator every time, even though the input method never actually changed. Users going from an app in EN state to another app in EN state saw the indicator flash on every app switch. Root cause: IndicatorVM always selected the resolved keyboard on app changes, and stateChangesPublisher emitted .appChanges for every app-kind change, which IndicatorWindowController unconditionally treated as "show the indicator". Changes: - ActivateEvent.appChanges now carries inputSourceDidChange so the indicator layer can tell real keyboard switches from no-op ones; add isAppChangesWithUnchangedInputSource helper - IndicatorVM skips the redundant TIS select (and the CJKV fix dance) when the target keyboard equals the current one and marks the state as .noChanges; keyboard cache learning (restore previously used keyboard) still runs for the new app - IndicatorWindowController routes unchanged-keyboard app switches to the hide path instead of showing the indicator - autoShowPublisher suppresses its initial activation for unchanged keyboards while keeping the freshly rebuilt focus-detection watcher active, so focus-based show/hide keeps working - Add ActivateEventInputSourceChangeTests covering the new event flag Behavior notes: - Different-keyboard app switches still announce the indicator as before - The always-on indicator keeps receiving .appChanges, so it no longer flickers on same-keyboard app switches - isHideWhenSwitchAppWithForceKeyboard now consistently hides the indicator when the keyboard is unchanged (previously "cached" sources would still show); nothing switched, so there is nothing to announce - No new preference keys, no localization or settings backup changes Fixes runjuu#126
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped, updates all relevant call sites consistently, and includes targeted unit tests for the new event-flag behavior.
Pull request overview
This PR prevents the indicator from “announcing” app switches that resolve to the same active input source by (1) detecting whether an app switch actually changed the input source (via persistent identifiers) and (2) routing unchanged-input-source app switches through non-show/hide paths so the indicator doesn’t flash.
Changes:
- Extend
IndicatorVM.ActivateEvent.appChangesto include aninputSourceDidChangeflag and add a helper to detect unchanged-input-source app switches. - Skip redundant
TISSelectInputSourceon.appChangedwhen the resolved input source is already active, marking the reason as.noChanges. - Update indicator activation/show-hide routing to suppress popups on unchanged-input-source app switches, and add unit tests for the new event flag.
File summaries
| File | Description |
|---|---|
| Tests/ActivateEventInputSourceChangeTests.swift | Adds tests validating unchanged/changed input-source flags on .appChanges. |
| Input Source Pro/Models/IndicatorVM+Triggers.swift | Adds inputSourceDidChange to app-change events and exposes isAppChangesWithUnchangedInputSource. |
| Input Source Pro/Models/IndicatorVM.swift | Skips redundant input-source selection when persistent identifiers match; records .noChanges. |
| Input Source Pro/Controllers/IndicatorWindowController.swift | Routes unchanged-input-source app switches to justHidePublisher() to prevent indicator popups. |
| Input Source Pro/Controllers/IndicatorWindowController+Activation.swift | Suppresses initial auto-show activation on unchanged-input-source app switches while keeping focus detection active. |
| Input Source Pro.xcodeproj/project.pbxproj | Registers the new test file in the Tests target sources and project groups. |
Review details
- Files reviewed: 6/6 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Purpose
When switching from one app to another that resolves to the same input source (a cached keyboard, a per-app specified keyboard, or the system-wide default), Input Source Pro still selected the source and flashed the switch indicator — even though nothing actually changed. Going from an app in EN state to another app in EN state showed the indicator on every app switch.
This PR makes the indicator announce real input-source changes only, and skips the redundant
TISSelectInputSourcecall when the target keyboard is already active.Closes #126
Summary of changes
IndicatorVM+Triggers.swift—.appChangesactivate events now carry aninputSourceDidChangeflag (computed from the input sources' persistent identifiers) so the indicator layer can distinguish real keyboard switches from no-op app switches. Added anisAppChangesWithUnchangedInputSourcehelper and updated pattern matches / log description.IndicatorVM.swift— in the.appChangedaction, when the resolved keyboard equals the current one, skipinputSourceVM.select(no redundant TIS select and no CJKV fix dance) and record the state reason as.noChanges. Keyboard cache learning ("restore previously used keyboard") still runs for the new app.IndicatorWindowController.swift— unchanged-keyboard app switches route to the hide path instead ofautoHidePublisher, so the indicator no longer pops up.IndicatorWindowController+Activation.swift—autoShowPublishersuppresses its initial activation for unchanged keyboards while keeping the freshly rebuilt focus-detection watcher active, so focus-based show/hide keeps working.Tests/ActivateEventInputSourceChangeTests.swift(new, registered in the Tests target) — unit tests for the new event flag.Behavior notes
.appChanges, so it stays steady (no hide/re-show flicker) on same-keyboard app switches.Testing notes
xcodebuild -scheme "Input Source Pro" -configuration Debug build→ BUILD SUCCEEDEDxcodebuild -scheme "Input Source Pro" -configuration Debug test→ TEST SUCCEEDED (all suites, including the 3 new tests inActivateEventInputSourceChangeTests)Screenshots
No UI changes — behavior-only fix for the scenario shown in #126 (comment) (EN → EN app switch previously always flashed the indicator).