Floor batch-edit depth at zero for unbalanced endBatchEdit - #35
Merged
Conversation
Some IMEs (Huawei Celia, SwiftKey) call endBatchEdit without a matching beginBatchEdit, driving the InputConnection batch depth negative. Once negative, the drain condition batchDepth == 0 never fires and queued edit commands are silently dropped, swallowing typed characters. Floor the depth at zero, matching PlatformTextEditorExtensions which already floors, and add Android host tests for the InputConnection batch-edit behavior. Fixes #33
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 8 |
| Duplication | 1 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
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
Some IMEs call
endBatchEdit()without a matchingbeginBatchEdit()— Huawei Celia does this consistently, Microsoft SwiftKey intermittently.TextEditorInputConnection.endBatchEditInternaldecrementedbatchDepthunconditionally, so a stray end drove the depth to-1. After that:addEditCommandWithBatch(begin: -1 → 0, queue, end: 0 → -1), so the drain conditionbatchDepth == 0is never true at the end of the wrapper. The edit command is queued and never applied — typed characters silently vanish, and the IME rebuilds its composition from the wrong buffer state, swallowing the first character of words (downstream report: Strange Android IME behavior hammer-editor#759).PlatformTextEditorExtensions.batchEditDepth) already floors at 0, so the two counters permanently desynced, breaking the "drain runs withisInBatchEdit == false" invariant thatImeCursorSyncdepends on.This is the same IME misbehavior AndroidX guards against in
StatelessInputConnection, which floors its batch depth at zero.Fix
batchDepth = (batchDepth - 1).coerceAtLeast(0)inendBatchEditInternal, keeping the connection counter in lockstep with the platform counter. An unbalanced end at depth 0 with an empty queue is now a harmless no-op, andendBatchEdit()'s return contract (true iff a batch is still in progress) is unchanged.Tests
Added an
androidHostTestsource set (viawithHostTestBuilder) and madeTextEditorInputConnectioninternal(@VisibleForTesting) so the real class is testable. NewTextEditorInputConnectionBatchTestcovers:endBatchEdit()followed bysetComposingText/commitText— all text lands in the document (fails without the fix)PlatformTextEditorExtensions.isInBatchEditendBatchEdit()return value contract (fails without the fix)Verified: 3 of the 6 new tests fail without the one-line fix and all pass with it;
desktopTeststill green.Fixes #33
🤖 Generated with Claude Code