diff options
| -rw-r--r-- | core/java/android/inputmethodservice/InputMethodService.java | 59 | ||||
| -rw-r--r-- | core/java/android/inputmethodservice/NavigationBarController.java | 76 |
2 files changed, 83 insertions, 52 deletions
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 84d96bd1e155..3d6da5452ad2 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -435,6 +435,11 @@ public class InputMethodService extends AbstractInputMethodService { } /** + * Cached value of {@link #canImeRenderGesturalNavButtons}, as it doesn't change at runtime. + */ + private final boolean mCanImeRenderGesturalNavButtons = canImeRenderGesturalNavButtons(); + + /** * Allows the system to optimize the back button affordance based on the presence of software * keyboard. * @@ -564,6 +569,9 @@ public class InputMethodService extends AbstractInputMethodService { private final NavigationBarController mNavigationBarController = new NavigationBarController(this); + /** Whether a custom IME Switcher button was requested to be visible. */ + private boolean mCustomImeSwitcherButtonRequestedVisible; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) int mTheme = 0; @@ -783,7 +791,7 @@ public class InputMethodService extends AbstractInputMethodService { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal"); mPrivOps.set(params.privilegedOperations); InputMethodPrivilegedOperationsRegistry.put(params.token, mPrivOps); - mNavigationBarController.onNavButtonFlagsChanged(params.navigationBarFlags); + onNavButtonFlagsChanged(params.navigationBarFlags); attachToken(params.token); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } @@ -893,7 +901,7 @@ public class InputMethodService extends AbstractInputMethodService { public final void dispatchStartInput(@Nullable InputConnection inputConnection, @NonNull IInputMethod.StartInputParams params) { mPrivOps.reportStartInputAsync(params.startInputToken); - mNavigationBarController.onNavButtonFlagsChanged(params.navigationBarFlags); + onNavButtonFlagsChanged(params.navigationBarFlags); if (params.restarting) { restartInput(inputConnection, params.editorInfo); } else { @@ -918,6 +926,20 @@ public class InputMethodService extends AbstractInputMethodService { @Override public void onNavButtonFlagsChanged(@InputMethodNavButtonFlags int navButtonFlags) { mNavigationBarController.onNavButtonFlagsChanged(navButtonFlags); + if (!mCanImeRenderGesturalNavButtons) { + final boolean showImeSwitcher = (navButtonFlags + & InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN) != 0; + // The IME cannot draw the IME nav bar, so this will never be visible. In this case + // the system nav bar hosts the IME buttons. + // The system nav bar will be hidden when the IME is shown and the config is set. + final boolean navBarNotVisible = getApplicationContext().getResources() + .getBoolean(com.android.internal.R.bool.config_hideNavBarForKeyboard); + final boolean visible = showImeSwitcher && navBarNotVisible; + if (visible != mCustomImeSwitcherButtonRequestedVisible) { + mCustomImeSwitcherButtonRequestedVisible = visible; + onCustomImeSwitcherButtonRequestedVisible(visible); + } + } } /** @@ -4473,28 +4495,27 @@ public class InputMethodService extends AbstractInputMethodService { /** * Called when the requested visibility of a custom IME Switcher button changes. * - * <p>When the system provides an IME navigation bar, it may decide to show an IME Switcher - * button inside this bar. However, the IME can request hiding the bar provided by the system - * with {@code getWindowInsetsController().hide(captionBar())} (the IME navigation bar provides - * {@link Type#captionBar() captionBar} insets to the IME window). If the request is successful, - * then it becomes the IME's responsibility to provide a custom IME Switcher button in its - * input view, with equivalent functionality.</p> + * <p>When this method is called with {@code true} by the system, the IME must show a button + * within its UI to switch IMEs. When it is called with {@code false}, it must hide this button. + * + * <p>Normally, the system provides a button for switching to a different IME when that is + * appropriate. Under certain circumstances, namely when the IME successfully asks to hide the + * system-provided navigation bar (with {@code getWindowInsetsController().hide(captionBar())}), + * providing this button is delegated to the IME through this callback. * - * <p>This custom button is only requested to be visible when the system provides the IME - * navigation bar, both the bar and the IME Switcher button inside it should be visible, - * but the IME successfully requested to hide the bar. This does not depend on the current - * visibility of the IME. It could be called with {@code true} while the IME is hidden, in - * which case the IME should prepare to show the button as soon as the IME itself is shown.</p> + * <p>This does not depend on the current visibility of the IME. It could be called with + * {@code true} while the IME is hidden, in which case the IME should prepare to show the button + * as soon as the IME itself is shown. * * <p>This is only called when the requested visibility changes. The default value is * {@code false} and as such, this will not be called initially if the resulting value is - * {@code false}.</p> + * {@code false}. * * <p>This can be called at any time after {@link #onCreate}, even if the IME is not currently - * visible. However, this is not guaranteed to be called before the IME is shown, as it depends - * on when the IME requested hiding the IME navigation bar. If the request is sent during - * the showing flow (e.g. during {@link #onStartInputView}), this will be called shortly after - * {@link #onWindowShown}, but before the first IME frame is drawn.</p> + * visible. However, this is not guaranteed to be called before the IME is shown, as it may + * depend on the IME requesting to hide the system-provided navigation bar. If the request is + * sent during the showing flow (e.g. during {@link #onStartInputView}), this will be called + * shortly after {@link #onWindowShown}, but before the first IME frame is drawn. * * @param visible whether the button is requested visible or not. */ @@ -4686,6 +4707,8 @@ public class InputMethodService extends AbstractInputMethodService { + " touchableRegion=" + mTmpInsets.touchableRegion); p.println(" mSettingsObserver=" + mSettingsObserver); p.println(" mNavigationBarController=" + mNavigationBarController.toDebugString()); + p.println(" mCustomImeSwitcherButtonRequestedVisible=" + + mCustomImeSwitcherButtonRequestedVisible); } private final ImeTracing.ServiceDumper mDumper = new ImeTracing.ServiceDumper() { diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java index 7da053d0010e..f1dee89b0b1d 100644 --- a/core/java/android/inputmethodservice/NavigationBarController.java +++ b/core/java/android/inputmethodservice/NavigationBarController.java @@ -170,6 +170,9 @@ final class NavigationBarController { private boolean mShouldShowImeSwitcherWhenImeIsShown; + /** Whether a custom IME Switcher button should be visible. */ + private boolean mCustomImeSwitcherButtonRequestedVisible; + @Appearance private int mAppearance; @@ -181,9 +184,6 @@ final class NavigationBarController { private boolean mDrawLegacyNavigationBarBackground; - /** Whether a custom IME Switcher button should be visible. */ - private boolean mCustomImeSwitcherVisible; - private final Rect mTempRect = new Rect(); private final int[] mTempPos = new int[2]; @@ -275,7 +275,9 @@ final class NavigationBarController { // IME navigation bar. boolean visible = insets.isVisible(captionBar()); mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.GONE); - checkCustomImeSwitcherVisibility(); + checkCustomImeSwitcherButtonRequestedVisible( + mShouldShowImeSwitcherWhenImeIsShown, mImeDrawsImeNavBar, + !visible /* imeNavBarNotVisible */); } return view.onApplyWindowInsets(insets); }); @@ -502,33 +504,31 @@ final class NavigationBarController { mShouldShowImeSwitcherWhenImeIsShown; mShouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherWhenImeIsShown; - checkCustomImeSwitcherVisibility(); - mService.mWindow.getWindow().getDecorView().getWindowInsetsController() .setImeCaptionBarInsetsHeight(getImeCaptionBarHeight(imeDrawsImeNavBar)); if (imeDrawsImeNavBar) { installNavigationBarFrameIfNecessary(); - if (mNavigationBarFrame == null) { - return; - } - if (mShouldShowImeSwitcherWhenImeIsShown - == prevShouldShowImeSwitcherWhenImeIsShown) { - return; - } - final NavigationBarView navigationBarView = mNavigationBarFrame.findViewByPredicate( - NavigationBarView.class::isInstance); - if (navigationBarView != null) { - // TODO(b/213337792): Support InputMethodService#setBackDisposition(). - // TODO(b/213337792): Set NAVBAR_IME_VISIBLE only when necessary. - final int flags = NAVBAR_BACK_DISMISS_IME | NAVBAR_IME_VISIBLE - | (mShouldShowImeSwitcherWhenImeIsShown - ? NAVBAR_IME_SWITCHER_BUTTON_VISIBLE : 0); - navigationBarView.setNavbarFlags(flags); + if (mNavigationBarFrame != null && mShouldShowImeSwitcherWhenImeIsShown + != prevShouldShowImeSwitcherWhenImeIsShown) { + final NavigationBarView navigationBarView = mNavigationBarFrame + .findViewByPredicate(NavigationBarView.class::isInstance); + if (navigationBarView != null) { + // TODO(b/213337792): Support InputMethodService#setBackDisposition(). + // TODO(b/213337792): Set NAVBAR_IME_VISIBLE only when necessary. + final int flags = NAVBAR_BACK_DISMISS_IME | NAVBAR_IME_VISIBLE + | (mShouldShowImeSwitcherWhenImeIsShown + ? NAVBAR_IME_SWITCHER_BUTTON_VISIBLE : 0); + navigationBarView.setNavbarFlags(flags); + } } } else { uninstallNavigationBarFrameIfNecessary(); } + + // Check custom IME Switcher button visibility after (un)installing nav bar frame. + checkCustomImeSwitcherButtonRequestedVisible(shouldShowImeSwitcherWhenImeIsShown, + imeDrawsImeNavBar, !isShown() /* imeNavBarNotVisible */); } @Override @@ -631,22 +631,29 @@ final class NavigationBarController { } /** - * Checks if a custom IME Switcher button should be visible, and notifies the IME when this - * state changes. This can only be {@code true} if three conditions are met: + * Checks if a custom IME Switcher button should be requested visible, and notifies the IME + * when this state changes. This is only {@code true} when the IME Switcher button is + * requested visible, and the navigation bar is not requested visible. * - * <li>The IME should draw the IME navigation bar.</li> - * <li>The IME Switcher button should be visible when the IME is visible.</li> - * <li>The IME navigation bar should be visible, but was requested hidden by the IME.</li> + * @param buttonVisible whether the IME Switcher button is requested visible. + * @param shouldDrawImeNavBar whether the IME navigation bar should be drawn. + * @param imeNavBarNotVisible whether the IME navigation bar is not requested visible. This + * will be {@code true} if it is requested hidden or not + * installed. */ - private void checkCustomImeSwitcherVisibility() { + private void checkCustomImeSwitcherButtonRequestedVisible(boolean buttonVisible, + boolean shouldDrawImeNavBar, boolean imeNavBarNotVisible) { if (!Flags.imeSwitcherRevampApi()) { return; } - final boolean visible = mImeDrawsImeNavBar && mShouldShowImeSwitcherWhenImeIsShown - && mNavigationBarFrame != null && !isShown(); - if (visible != mCustomImeSwitcherVisible) { - mCustomImeSwitcherVisible = visible; - mService.onCustomImeSwitcherButtonRequestedVisible(mCustomImeSwitcherVisible); + // The system nav bar will be hidden when the IME is shown and the config is set. + final boolean navBarNotVisible = shouldDrawImeNavBar ? imeNavBarNotVisible + : mService.getResources().getBoolean( + com.android.internal.R.bool.config_hideNavBarForKeyboard); + final boolean visible = buttonVisible && navBarNotVisible; + if (visible != mCustomImeSwitcherButtonRequestedVisible) { + mCustomImeSwitcherButtonRequestedVisible = visible; + mService.onCustomImeSwitcherButtonRequestedVisible(visible); } } @@ -656,7 +663,8 @@ final class NavigationBarController { + " mNavigationBarFrame=" + mNavigationBarFrame + " mShouldShowImeSwitcherWhenImeIsShown=" + mShouldShowImeSwitcherWhenImeIsShown - + " mCustomImeSwitcherVisible=" + mCustomImeSwitcherVisible + + " mCustomImeSwitcherButtonRequestedVisible=" + + mCustomImeSwitcherButtonRequestedVisible + " mAppearance=0x" + Integer.toHexString(mAppearance) + " mDarkIntensity=" + mDarkIntensity + " mDrawLegacyNavigationBarBackground=" + mDrawLegacyNavigationBarBackground |