summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java59
-rw-r--r--core/java/android/inputmethodservice/NavigationBarController.java76
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