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

Commit 9d63d355 authored by Ming-Shin Lu's avatar Ming-Shin Lu
Browse files

Fix showing keyboard without editor focused in some cases (1-2/2)

As CL[1] mentioned window focus behavior changes from R,
ignoring STATE_VISIBLE or STATE_ALWAYS_VISIBLE request doesn't enough
to fix unexpected keyboard visible issue when same window focused with
the above softInput flag without editor focus, since there is no
additional unspecified window focus to hide the current soft-input
as prior to R's behavior.

To fix that, we introduced new SoftInputShowHideReason to hide
soft-input when the same window focused without valid editor focus
after screen unlock, in order to align with the behavior prior to R.

[1]: I37ae6e30d1de581ba15131c2a90396b3a522a4d6

Bug: 161506356
Test: atest CtsInputMethodTestCases
Change-Id: I20e8076acc5fec3c055af0740e2e2a64b1fb6f0d
parent 770baec3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -610,7 +610,8 @@ public final class InputMethodManager {
        @Override
        public void startInputAsyncOnWindowFocusGain(View focusedView,
                @SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus) {
            final int startInputFlags = getStartInputFlags(focusedView, 0);
            int startInputFlags = getStartInputFlags(focusedView, 0);
            startInputFlags |= StartInputFlags.WINDOW_GAINED_FOCUS;

            final ImeFocusController controller = getFocusController();
            if (controller == null) {
+2 −0
Original line number Diff line number Diff line
@@ -224,6 +224,8 @@ public final class InputMethodDebug {
                return "HIDE_DOCKED_STACK_ATTACHED";
            case SoftInputShowHideReason.HIDE_RECENTS_ANIMATION:
                return "HIDE_RECENTS_ANIMATION";
            case SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR:
                return "HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR";
            default:
                return "Unknown=" + reason;
        }
+15 −1
Original line number Diff line number Diff line
@@ -47,7 +47,8 @@ import java.lang.annotation.Retention;
        SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME,
        SoftInputShowHideReason.HIDE_DOCKED_STACK_ATTACHED,
        SoftInputShowHideReason.HIDE_RECENTS_ANIMATION,
        SoftInputShowHideReason.HIDE_BUBBLES})
        SoftInputShowHideReason.HIDE_BUBBLES,
        SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR})
public @interface SoftInputShowHideReason {
    /** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */
    int SHOW_SOFT_INPUT = 0;
@@ -147,4 +148,17 @@ public @interface SoftInputShowHideReason {
     * switching, or collapsing Bubbles.
     */
    int HIDE_BUBBLES = 19;

    /**
     * Hide soft input when focusing the same window (e.g. screen turned-off and turn-on) which no
     * valid focused editor.
     *
     * Note: From Android R, the window focus change callback is processed by InputDispatcher,
     * some focus behavior changes (e.g. There are an activity with a dialog window, after
     * screen turned-off and turned-on, before Android R the window focus sequence would be
     * the activity first and then the dialog focused, however, in R the focus sequence would be
     * only the dialog focused as it's the latest window with input focus) makes we need to hide
     * soft-input when the same window focused again to align with the same behavior prior to R.
     */
    int HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR = 20;
}
+6 −0
Original line number Diff line number Diff line
@@ -47,4 +47,10 @@ public @interface StartInputFlags {
     * documented hence we probably need to revisit this though.
     */
    int INITIAL_CONNECTION = 4;

    /**
     * The start input happens when the window gained focus to call
     * {@code android.view.inputmethod.InputMethodManager#startInputAsyncOnWindowFocusGain}.
     */
    int WINDOW_GAINED_FOCUS = 8;
}
+20 −8
Original line number Diff line number Diff line
@@ -3463,6 +3463,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub

        final boolean sameWindowFocused = mCurFocusedWindow == windowToken;
        final boolean isTextEditor = (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0;
        final boolean startInputByWinGainedFocus =
                (startInputFlags & StartInputFlags.WINDOW_GAINED_FOCUS) != 0;

        if (sameWindowFocused && isTextEditor) {
            if (DEBUG) {
                Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
@@ -3506,7 +3509,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        InputBindResult res = null;
        switch (softInputMode & LayoutParams.SOFT_INPUT_MASK_STATE) {
            case LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
                if (!isTextEditor || !doAutoShow) {
                if (!sameWindowFocused && (!isTextEditor || !doAutoShow)) {
                    if (LayoutParams.mayUseInputMethod(windowFlags)) {
                        // There is no focus view, and this window will
                        // be behind any soft input window, so hide the
@@ -3555,7 +3558,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                }
                break;
            case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
                if (isImeVisible()) {
                if (!sameWindowFocused) {
                    if (DEBUG) Slog.v(TAG, "Window asks to hide input");
                    hideCurrentInputLocked(mCurFocusedWindow, 0, null,
                            SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE);
@@ -3584,7 +3587,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                if (DEBUG) Slog.v(TAG, "Window asks to always show input");
                if (InputMethodUtils.isSoftInputModeStateVisibleAllowed(
                        unverifiedTargetSdkVersion, startInputFlags)) {
                    if (!isImeVisible()) {
                    if (!sameWindowFocused) {
                        if (attribute != null) {
                            res = startInputUncheckedLocked(cs, inputContext, missingMethods,
                                    attribute, startInputFlags, startInputReason);
@@ -3603,17 +3606,26 @@ public class InputMethodManagerService extends IInputMethodManager.Stub

        if (!didStart) {
            if (attribute != null) {
                if (!DebugFlags.FLAG_OPTIMIZE_START_INPUT.value()
                if (sameWindowFocused) {
                    // On previous platforms, when Dialogs re-gained focus, the Activity behind
                    // would briefly gain focus first, and dismiss the IME.
                    // On R that behavior has been fixed, but unfortunately apps have come
                    // to rely on this behavior to hide the IME when the editor no longer has focus
                    // To maintain compatibility, we are now hiding the IME when we don't have
                    // an editor upon refocusing a window.
                    if (startInputByWinGainedFocus) {
                        hideCurrentInputLocked(mCurFocusedWindow, 0, null,
                                SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR);
                    }
                    res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
                            startInputFlags, startInputReason);
                } else if (!DebugFlags.FLAG_OPTIMIZE_START_INPUT.value()
                        || (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0) {
                    res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
                            startInputFlags, startInputReason);
                } else {
                    res = InputBindResult.NO_EDITOR;
                }
            } else if (sameWindowFocused) {
                return new InputBindResult(
                        InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
                        null, null, null, -1, null);
            } else {
                res = InputBindResult.NULL_EDITOR_INFO;
            }