Loading core/java/android/view/inputmethod/InputMethodManager.java +2 −1 Original line number Diff line number Diff line Loading @@ -611,7 +611,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) { Loading core/java/com/android/internal/inputmethod/InputMethodDebug.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java +15 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } core/java/com/android/internal/inputmethod/StartInputFlags.java +6 −0 Original line number Diff line number Diff line Loading @@ -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; } services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +42 −13 Original line number Diff line number Diff line Loading @@ -3275,6 +3275,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { if (mCurClient == null || mCurClient.curSession == null) { return false; } if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0 && (mShowExplicitlyRequested || mShowForced)) { if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide"); Loading Loading @@ -3459,7 +3462,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // pre-rendering not supported on low-ram devices. cs.shouldPreRenderIme = DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() && !mIsLowRam; if (mCurFocusedWindow == windowToken) { 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 + " attribute=" + attribute + ", token = " + windowToken Loading @@ -3474,6 +3482,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY, null, null, null, -1, null); } mCurFocusedWindow = windowToken; mCurFocusedWindowSoftInputMode = softInputMode; mCurFocusedWindowClient = cs; Loading @@ -3491,7 +3500,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub == LayoutParams.SOFT_INPUT_ADJUST_RESIZE || mRes.getConfiguration().isLayoutSizeAtLeast( Configuration.SCREENLAYOUT_SIZE_LARGE); final boolean isTextEditor = (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0; // We want to start input before showing the IME, but after closing // it. We want to do this after closing it to help the IME disappear Loading @@ -3502,7 +3510,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 Loading Loading @@ -3551,9 +3559,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } break; case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN: if (!sameWindowFocused) { if (DEBUG) Slog.v(TAG, "Window asks to hide input"); hideCurrentInputLocked(mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE); } break; case LayoutParams.SOFT_INPUT_STATE_VISIBLE: if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { Loading @@ -3578,6 +3588,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.v(TAG, "Window asks to always show input"); if (InputMethodUtils.isSoftInputModeStateVisibleAllowed( unverifiedTargetSdkVersion, startInputFlags)) { if (!sameWindowFocused) { if (attribute != null) { res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute, startInputFlags, startInputReason); Loading @@ -3585,6 +3596,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null, SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE); } } else { Slog.e(TAG, "SOFT_INPUT_STATE_ALWAYS_VISIBLE is ignored because" + " there is no focused view that also returns true from" Loading @@ -3595,7 +3607,20 @@ 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); Loading @@ -3609,6 +3634,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return res; } private boolean isImeVisible() { return (mImeWindowVis & InputMethodService.IME_VISIBLE) != 0; } private boolean canShowInputMethodPickerLocked(IInputMethodClient client) { // TODO(yukawa): multi-display support. final int uid = Binder.getCallingUid(); Loading Loading
core/java/android/view/inputmethod/InputMethodManager.java +2 −1 Original line number Diff line number Diff line Loading @@ -611,7 +611,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) { Loading
core/java/com/android/internal/inputmethod/InputMethodDebug.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading
core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java +15 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; }
core/java/com/android/internal/inputmethod/StartInputFlags.java +6 −0 Original line number Diff line number Diff line Loading @@ -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; }
services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +42 −13 Original line number Diff line number Diff line Loading @@ -3275,6 +3275,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) { if (mCurClient == null || mCurClient.curSession == null) { return false; } if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0 && (mShowExplicitlyRequested || mShowForced)) { if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide"); Loading Loading @@ -3459,7 +3462,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // pre-rendering not supported on low-ram devices. cs.shouldPreRenderIme = DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() && !mIsLowRam; if (mCurFocusedWindow == windowToken) { 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 + " attribute=" + attribute + ", token = " + windowToken Loading @@ -3474,6 +3482,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY, null, null, null, -1, null); } mCurFocusedWindow = windowToken; mCurFocusedWindowSoftInputMode = softInputMode; mCurFocusedWindowClient = cs; Loading @@ -3491,7 +3500,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub == LayoutParams.SOFT_INPUT_ADJUST_RESIZE || mRes.getConfiguration().isLayoutSizeAtLeast( Configuration.SCREENLAYOUT_SIZE_LARGE); final boolean isTextEditor = (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0; // We want to start input before showing the IME, but after closing // it. We want to do this after closing it to help the IME disappear Loading @@ -3502,7 +3510,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 Loading Loading @@ -3551,9 +3559,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } break; case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN: if (!sameWindowFocused) { if (DEBUG) Slog.v(TAG, "Window asks to hide input"); hideCurrentInputLocked(mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE); } break; case LayoutParams.SOFT_INPUT_STATE_VISIBLE: if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { Loading @@ -3578,6 +3588,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.v(TAG, "Window asks to always show input"); if (InputMethodUtils.isSoftInputModeStateVisibleAllowed( unverifiedTargetSdkVersion, startInputFlags)) { if (!sameWindowFocused) { if (attribute != null) { res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute, startInputFlags, startInputReason); Loading @@ -3585,6 +3596,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null, SoftInputShowHideReason.SHOW_STATE_ALWAYS_VISIBLE); } } else { Slog.e(TAG, "SOFT_INPUT_STATE_ALWAYS_VISIBLE is ignored because" + " there is no focused view that also returns true from" Loading @@ -3595,7 +3607,20 @@ 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); Loading @@ -3609,6 +3634,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return res; } private boolean isImeVisible() { return (mImeWindowVis & InputMethodService.IME_VISIBLE) != 0; } private boolean canShowInputMethodPickerLocked(IInputMethodClient client) { // TODO(yukawa): multi-display support. final int uid = Binder.getCallingUid(); Loading