reload the cursor position from text field when in doubt

This commit is contained in:
Helium314 2024-06-18 00:38:07 +02:00
parent 9efb22bd0c
commit 0b9fb7334d
3 changed files with 29 additions and 12 deletions

View file

@ -997,7 +997,7 @@ public class LatinIME extends InputMethodService implements
// didn't move (the keyboard having been closed with the back key),
// initialSelStart and initialSelEnd sometimes are lying. Make a best effort to
// work around this bug.
mInputLogic.mConnection.tryFixLyingCursorPosition();
mInputLogic.mConnection.tryFixIncorrectCursorPosition();
if (mInputLogic.mConnection.isCursorTouchingWord(currentSettingsValues.mSpacingAndPunctuations, true)) {
mHandler.postResumeSuggestions(true /* shouldDelay */);
}

View file

@ -227,14 +227,21 @@ public final class RichInputConnection implements PrivateCommandPerformer {
*/
public boolean resetCachesUponCursorMoveAndReturnSuccess(final int newSelStart,
final int newSelEnd, final boolean shouldFinishComposition) {
mExpectedSelStart = newSelStart;
mExpectedSelEnd = newSelEnd;
mComposingText.setLength(0);
final boolean didReloadTextSuccessfully = reloadTextCache();
if (!didReloadTextSuccessfully) {
Log.d(TAG, "Will try to retrieve text later.");
// selection is set to INVALID_CURSOR_POSITION if reloadTextCache return false
return false;
}
if (mExpectedSelStart != newSelStart || mExpectedSelEnd != newSelEnd) {
mExpectedSelStart = newSelStart;
mExpectedSelEnd = newSelEnd;
reloadTextCache();
if (mExpectedSelStart != newSelStart || mExpectedSelEnd != newSelEnd) {
Log.i(TAG, "resetCachesUponCursorMove: tried to set "+newSelStart+"/"+newSelEnd+", but input field has "+mExpectedSelStart+"/"+mExpectedSelEnd);
}
}
if (isConnected() && shouldFinishComposition) {
mIC.finishComposingText();
}
@ -272,6 +279,14 @@ public final class RichInputConnection implements PrivateCommandPerformer {
return true;
}
private void reloadCursorPosition() {
if (!isConnected()) return;
final ExtractedText et = mIC.getExtractedText(new ExtractedTextRequest(), 0);
if (et == null) return;
mExpectedSelStart = et.selectionStart + et.startOffset;
mExpectedSelEnd = et.selectionEnd + et.startOffset;
}
private void checkBatchEdit() {
if (mNestLevel != 1) {
// TODO: exception instead
@ -458,10 +473,7 @@ public final class RichInputConnection implements PrivateCommandPerformer {
if (result != null) {
if (!checkTextBeforeCursorConsistency(result)) {
Log.w(TAG, "cached text out of sync, reloading");
ExtractedTextRequest r = new ExtractedTextRequest();
final ExtractedText et = mIC.getExtractedText(r, 0);
mExpectedSelStart = et.selectionStart + et.startOffset;
mExpectedSelEnd = et.selectionEnd + et.startOffset;
reloadCursorPosition();
if (!DebugLogUtils.getStackTrace(2).contains("reloadTextCache")) // clunky bur effective protection against circular reference
reloadTextCache();
}
@ -1130,8 +1142,10 @@ public final class RichInputConnection implements PrivateCommandPerformer {
* means to get the real value, try at least to ask the text view for some characters and
* detect the most damaging cases: when the cursor position is declared to be much smaller
* than it really is.
* (renamed the method, because we clearly ask the editorInfo to provide initial selection, no reason to complain about it
* being initial and thus possibly outdated)
*/
public void tryFixLyingCursorPosition() {
public void tryFixIncorrectCursorPosition() {
mIC = mParent.getCurrentInputConnection();
final CharSequence textBeforeCursor = getTextBeforeCursor(
Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
@ -1167,6 +1181,9 @@ public final class RichInputConnection implements PrivateCommandPerformer {
if (wasEqual || mExpectedSelStart > mExpectedSelEnd) {
mExpectedSelEnd = mExpectedSelStart;
}
} else {
// better re-read the correct position instead of guessing from incomplete data
reloadCursorPosition();
}
}
}

View file

@ -148,9 +148,9 @@ public final class InputLogic {
mRecapitalizeStatus.disable(); // Do not perform recapitalize until the cursor is moved once
mCurrentlyPressedHardwareKeys.clear();
mSuggestedWords = SuggestedWords.getEmptyInstance();
// In some cases (namely, after rotation of the device) editorInfo.initialSelStart is lying
// so we try using some heuristics to find out about these and fix them.
mConnection.tryFixLyingCursorPosition();
// In some cases (e.g. after rotation of the device, or when scrolling the text before bringing up keyboard)
// editorInfo.initialSelStart is not the actual cursor position, so we try using some heuristics to find the correct position.
mConnection.tryFixIncorrectCursorPosition();
cancelDoubleSpacePeriodCountdown();
if (InputLogicHandler.NULL_HANDLER == mInputLogicHandler) {
mInputLogicHandler = new InputLogicHandler(mLatinIME, this);
@ -2380,7 +2380,7 @@ public final class InputLogic {
// If remainingTries is 0, we should stop waiting for new tries, however we'll still
// return true as we need to perform other tasks (for example, loading the keyboard).
}
mConnection.tryFixLyingCursorPosition();
mConnection.tryFixIncorrectCursorPosition();
if (tryResumeSuggestions) {
handler.postResumeSuggestions(true /* shouldDelay */);
}