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

Commit d0244216 authored by Cosmin Băieș's avatar Cosmin Băieș
Browse files

Include IME navigation bar in IME insets

Check if the IME navigation bar is visible, and make sure the computed
IME insets are at least as big as it is.

When an IME is in floating mode, the computed IME insets would be zero,
but the IME navigation bar would be shown (in gesture nav), so the app
content would be slightly covered by it. As a workaround, IMEs always
include the navigation bar insets size in their override for computing
the IME insets size.

With the introduction of the ability to hide the IME navigation bar in
[1], this lead to a problem where apps that want to inset their content
by the IME insets size, when an IME is in floating mode and requested to
hide the IME navigation bar, would still receive non-zero insets equal
to the size of the system gesture navigation bar (drag handle).

This ensures the IME insets size will always include the IME navigation
bar size when necessary, enabling IMEs to remove their workaround,
solving the non-zero insets problem described above.

  [1]: I8793db69fb846046300d5a56b3b0060138ef4cd5

Bug: 336335471
Test: atest InputMethodServiceTest#testImeNavigationBarInsets
Change-Id: Id252731ac8b5138cccd1164197ff3ece3a5f3cf8
parent dc295013
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -720,6 +720,7 @@ public class InputMethodService extends AbstractInputMethodService {

    final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = info -> {
        onComputeInsets(mTmpInsets);
        mNavigationBarController.updateInsets(mTmpInsets);
        if (!mViewsCreated) {
            // The IME views are not ready, keep visible insets untouched.
            mTmpInsets.visibleTopInsets = 0;
+31 −0
Original line number Diff line number Diff line
@@ -58,6 +58,10 @@ import java.util.Objects;
final class NavigationBarController {

    private interface Callback {

        default void updateInsets(@NonNull InputMethodService.Insets originalInsets) {
        }

        default void updateTouchableInsets(@NonNull InputMethodService.Insets originalInsets,
                @NonNull ViewTreeObserver.InternalInsetsInfo dest) {
        }
@@ -96,6 +100,15 @@ final class NavigationBarController {
                ? new Impl(inputMethodService) : Callback.NOOP;
    }

    /**
     * Update the given insets to be at least as big as the IME navigation bar, when visible.
     *
     * @param originalInsets the insets to check and modify to include the IME navigation bar.
     */
    void updateInsets(@NonNull InputMethodService.Insets originalInsets) {
        mImpl.updateInsets(originalInsets);
    }

    void updateTouchableInsets(@NonNull InputMethodService.Insets originalInsets,
            @NonNull ViewTreeObserver.InternalInsetsInfo dest) {
        mImpl.updateTouchableInsets(originalInsets, dest);
@@ -269,6 +282,24 @@ final class NavigationBarController {
            mNavigationBarFrame = null;
        }

        @Override
        public void updateInsets(@NonNull InputMethodService.Insets originalInsets) {
            if (!mImeDrawsImeNavBar || mNavigationBarFrame == null
                    || mNavigationBarFrame.getVisibility() != View.VISIBLE
                    || mService.isFullscreenMode()) {
                return;
            }

            final int[] loc = new int[2];
            mNavigationBarFrame.getLocationInWindow(loc);
            if (originalInsets.contentTopInsets > loc[1]) {
                originalInsets.contentTopInsets = loc[1];
            }
            if (originalInsets.visibleTopInsets > loc[1]) {
                originalInsets.visibleTopInsets = loc[1];
            }
        }

        @Override
        public void updateTouchableInsets(@NonNull InputMethodService.Insets originalInsets,
                @NonNull ViewTreeObserver.InternalInsetsInfo dest) {