Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a35ebcf8 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Fix stale EditorInfo upon EditText#setText()

This is a follow up to our previous CL [1], which added initial
surrounding text support into EditorInfo and let TextView support it.

What we overlooked was that calling TextView#setText() would trigger

  TextView#onCreateInputConnection()

before TextView#mText is updated to the new value.  As a result,
EditorInfo is initialized with a stale surrounding text information.

With this CL, EditorInfo will correctly be initialized with the new
text specified to TextView#setText().

One complicated thing in this CL is InputMethodManager also has some
issues about how to drop spurious

  InputMethodService#onUpdateSelection()

while InputConnection is being replaced with a new instance.  I ended
up having to introduce a hacky boolean

  Editor#mHasPendingRestartInputForSetText

to work around this in the TextView/EditText. This workaround is
expected to be removed/revisited as part of Bug 186582769.

 [1]: Ie04f2349b1157408aa8ed9044aea12ce99132cb4
      c486acc4

Fix: 161330778
Test: atest CtsInputMethodTestCases:EditTextImeSupportTest
Change-Id: Iee3b754eea319861b2eb955d6cc95ba13006b55e
parent 3dfc4cd4
Loading
Loading
Loading
Loading
+39 −1
Original line number Diff line number Diff line
@@ -259,6 +259,20 @@ public class Editor {
    // Used to highlight a word when it is corrected by the IME
    private CorrectionHighlighter mCorrectionHighlighter;

    /**
     * {@code true} when {@link TextView#setText(CharSequence, TextView.BufferType, boolean, int)}
     * is being executed and {@link InputMethodManager#restartInput(View)} is scheduled to be
     * called.
     *
     * <p>This is also used to avoid an unnecessary invocation of
     * {@link InputMethodManager#updateSelection(View, int, int, int, int)} when
     * {@link InputMethodManager#restartInput(View)} is scheduled to be called already
     * See bug 186582769 for details.</p>
     *
     * <p>TODO(186582769): Come up with better way.</p>
     */
    private boolean mHasPendingRestartInputForSetText = false;

    InputContentType mInputContentType;
    InputMethodState mInputMethodState;

@@ -1825,6 +1839,29 @@ public class Editor {
        }
    }

    /**
     * Called from {@link TextView#setText(CharSequence, TextView.BufferType, boolean, int)} to
     * schedule {@link InputMethodManager#restartInput(View)}.
     */
    void scheduleRestartInputForSetText() {
        mHasPendingRestartInputForSetText = true;
    }

    /**
     * Called from {@link TextView#setText(CharSequence, TextView.BufferType, boolean, int)} to
     * actually call {@link InputMethodManager#restartInput(View)} if it's scheduled.  Does nothing
     * otherwise.
     */
    void maybeFireScheduledRestartInputForSetText() {
        if (mHasPendingRestartInputForSetText) {
            final InputMethodManager imm = getInputMethodManager();
            if (imm != null) {
                imm.restartInput(mTextView);
            }
            mHasPendingRestartInputForSetText = false;
        }
    }

    static final int EXTRACT_NOTHING = -2;
    static final int EXTRACT_UNKNOWN = -1;

@@ -1958,7 +1995,8 @@ public class Editor {
    }

    private void sendUpdateSelection() {
        if (null != mInputMethodState && mInputMethodState.mBatchEditNesting <= 0) {
        if (null != mInputMethodState && mInputMethodState.mBatchEditNesting <= 0
                && !mHasPendingRestartInputForSetText) {
            final InputMethodManager imm = getInputMethodManager();
            if (null != imm) {
                final int selectionStart = mTextView.getSelectionStart();
+7 −4
Original line number Diff line number Diff line
@@ -6285,11 +6285,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                || needEditableForNotification) {
            createEditorIfNeeded();
            mEditor.forgetUndoRedo();
            mEditor.scheduleRestartInputForSetText();
            Editable t = mEditableFactory.newEditable(text);
            text = t;
            setFilters(t, mFilters);
            InputMethodManager imm = getInputMethodManager();
            if (imm != null) imm.restartInput(this);
        } else if (precomputed != null) {
            if (mTextDir == null) {
                mTextDir = getTextDirectionHeuristic();
@@ -6408,8 +6407,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            notifyListeningManagersAfterTextChanged();
        }
        if (mEditor != null) {
            // SelectionModifierCursorController depends on textCanBeSelected, which depends on text
        if (mEditor != null) mEditor.prepareCursorControllers();
            mEditor.prepareCursorControllers();
            mEditor.maybeFireScheduledRestartInputForSetText();
        }
    }
    /**