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

Commit 5f05965f authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Keep IMM#mCurRootView synchronized with the actual window focus.

Currently IMM#mCurRootView is always cleared every time when
IMM#finishInputLocked() is called.  We have been doing this since
Iad09cf5dbb7f6f156fd39ed243431432e00f8945 so as not to hold the
strong reference to a DecorView so long time (Bug 6413553).

Strictly speaking, the attached window may continue holding
input focus even after IMM#finishInputLocked() is called.
In this state IMM#focusIn() might have unexpectedly rejected
focus-in event but presumably this might not be obvious, or might
not occur at all because in some situations IMM#finishInputLocked()
has never been called even when the attached view loses input
focus.

In order to fix Issue 20820914, however, we need to call
IMM#finishInputLocked() exactly when the attached view loses
input focus.  To make it easier to diagnose any unexpected
regressions, this CL only changes the handling of
IMM#mCurRootView, while the next CL Id6afc8fc64512225578c62557b96
plumbs IMM#focusOut() to IMM#finishInputLocked().

Manually tested following scenarios.
- Repro steps in Bug 6413553.  Made sure that IMM#mCurRootView
  is cleared after switching back from the current application to
  the previous application with back key.
- Test application that calls WebView#showFindDialog(). Made sure
  that LatinIME works fine when switching text fields.  This is
  non-trivial because android.webkit.FindActionModeCallback is
  changed in this CL.
- Repro steps in Bug 21144633.  Made sure that we can enter
  recipient's name in the messaging app.

Bug: 20820914
Change-Id: I219394178e4172bc47864297f1418e677dba25e5
parent 92847c96
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -2015,8 +2015,8 @@ public final class ViewRootImpl implements ViewParent,
                mLastWasImTarget = imTarget;
                InputMethodManager imm = InputMethodManager.peekInstance();
                if (imm != null && imTarget) {
                    imm.startGettingWindowFocus(mView);
                    imm.onWindowFocus(mView, mView.findFocus(),
                    imm.onPreWindowFocus(mView, true /* hasWindowFocus */);
                    imm.onPostWindowFocus(mView, mView.findFocus(),
                            mWindowAttributes.softInputMode,
                            !mHasHadWindowFocus, mWindowAttributes.flags);
                }
@@ -3321,11 +3321,10 @@ public final class ViewRootImpl implements ViewParent,
                            .mayUseInputMethod(mWindowAttributes.flags);

                    InputMethodManager imm = InputMethodManager.peekInstance();
                    if (mView != null) {
                        if (hasWindowFocus && imm != null && mLastWasImTarget &&
                                !isInLocalFocusMode()) {
                            imm.startGettingWindowFocus(mView);
                    if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
                        imm.onPreWindowFocus(mView, hasWindowFocus);
                    }
                    if (mView != null) {
                        mAttachInfo.mKeyDispatchState.reset();
                        mView.dispatchWindowFocusChanged(hasWindowFocus);
                        mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
@@ -3335,7 +3334,7 @@ public final class ViewRootImpl implements ViewParent,
                    // so all of the view state is set up correctly.
                    if (hasWindowFocus) {
                        if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
                            imm.onWindowFocus(mView, mView.findFocus(),
                            imm.onPostWindowFocus(mView, mView.findFocus(),
                                    mWindowAttributes.softInputMode,
                                    !mHasHadWindowFocus, mWindowAttributes.flags);
                        }
+20 −7
Original line number Diff line number Diff line
@@ -1392,7 +1392,7 @@ public final class InputMethodManager {
     * Called by ViewAncestor when its window gets input focus.
     * @hide
     */
    public void onWindowFocus(View rootView, View focusedView, int softInputMode,
    public void onPostWindowFocus(View rootView, View focusedView, int softInputMode,
            boolean first, int windowFlags) {
        boolean forceNewFocus = false;
        synchronized (mH) {
@@ -1443,9 +1443,22 @@ public final class InputMethodManager {
    }

    /** @hide */
    public void startGettingWindowFocus(View rootView) {
    public void onPreWindowFocus(View rootView, boolean hasWindowFocus) {
        synchronized (mH) {
            if (rootView == null) {
                mCurRootView = null;
            } if (hasWindowFocus) {
                mCurRootView = rootView;
            } else if (rootView == mCurRootView) {
                // If the mCurRootView is losing window focus, release the strong reference to it
                // so as not to prevent it from being garbage-collected.
                mCurRootView = null;
            } else {
                if (DEBUG) {
                    Log.v(TAG, "Ignoring onPreWindowFocus()."
                            + " mCurRootView=" + mCurRootView + " rootView=" + rootView);
                }
            }
        }
    }

+3 −3
Original line number Diff line number Diff line
@@ -154,10 +154,10 @@ public class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
    }

    public void showSoftInput() {
        mInput.startGettingWindowFocus(mEditText.getRootView());
        mInput.focusIn(mEditText);
        if (mEditText.requestFocus()) {
            mInput.showSoftInput(mEditText, 0);
        }
    }

    public void updateMatchCount(int matchIndex, int matchCount, boolean isEmptyFind) {
        if (!isEmptyFind) {