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

Commit 77414fab authored by Tiger Huang's avatar Tiger Huang
Browse files

Make IME source frame not smaller than nav bar frame

In gesture navigation, nav bar frame is larger than frame to calculate
insets. IME should not provide frame which is smaller than the nav bar
frame. Otherwise, nav bar might be overlapped with the content of the
client when IME is shown.

Fix: 142218188
Test: atest DisplayPolicyTests
Change-Id: Ie5edcd1a0f73440623e85aa4a020d16b4266f747
parent 21ebdf80
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3317,7 +3317,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                    mInputMethodWindow.getDisplayId());
        }
        mInsetsStateController.getSourceProvider(ITYPE_IME).setWindow(win,
                null /* frameProvider */, null /* imeFrameProvider */);
                mDisplayPolicy.getImeSourceFrameProvider(), null /* imeFrameProvider */);
        computeImeTarget(true /* updateImeTarget */);
        updateImeControlTarget();
    }
+18 −0
Original line number Diff line number Diff line
@@ -1106,6 +1106,24 @@ public class DisplayPolicy {
        }
    }

    TriConsumer<DisplayFrames, WindowState, Rect> getImeSourceFrameProvider() {
        return (displayFrames, windowState, inOutFrame) -> {
            if (mNavigationBar != null && navigationBarPosition(displayFrames.mDisplayWidth,
                    displayFrames.mDisplayHeight,
                    displayFrames.mRotation) == NAV_BAR_BOTTOM) {
                // In gesture navigation, nav bar frame is larger than frame to calculate insets.
                // IME should not provide frame which is smaller than the nav bar frame. Otherwise,
                // nav bar might be overlapped with the content of the client when IME is shown.
                sTmpRect.set(inOutFrame);
                sTmpRect.intersectUnchecked(mNavigationBar.getFrameLw());
                inOutFrame.inset(windowState.getGivenContentInsetsLw());
                inOutFrame.union(sTmpRect);
            } else {
                inOutFrame.inset(windowState.getGivenContentInsetsLw());
            }
        };
    }

    private static void enforceSingleInsetsTypeCorrespondingToWindowType(int[] insetsTypes) {
        int count = 0;
        for (int insetsType : insetsTypes) {
+37 −0
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.server.wm;

import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.Surface.ROTATION_0;
import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -56,7 +58,10 @@ import static org.mockito.Mockito.when;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.DisplayInfo;
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.WindowInsets.Side;
import android.view.WindowManager;

import androidx.test.filters.SmallTest;
@@ -352,4 +357,36 @@ public class DisplayPolicyTests extends WindowTestsBase {
        insetsPolicy.updateBarControlTarget(mAppWindow);
        assertNull(displayPolicy.mInputConsumer);
    }

    @Test
    public void testImeMinimalSourceFrame() {
        final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
        final DisplayInfo displayInfo = new DisplayInfo();
        displayInfo.logicalWidth = 1000;
        displayInfo.logicalHeight = 2000;
        displayInfo.rotation = ROTATION_0;
        mDisplayContent.mDisplayFrames = new DisplayFrames(mDisplayContent.getDisplayId(),
                displayInfo, null /* displayCutout */);

        displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
        mNavBarWindow.getControllableInsetProvider().setServerVisible(true);

        mDisplayContent.setInputMethodWindowLocked(mImeWindow);
        mImeWindow.mAttrs.setFitInsetsSides(Side.all() & ~Side.BOTTOM);
        mImeWindow.getGivenContentInsetsLw().set(0, displayInfo.logicalHeight, 0, 0);
        mImeWindow.getControllableInsetProvider().setServerVisible(true);

        displayPolicy.beginLayoutLw(mDisplayContent.mDisplayFrames, 0 /* UI mode */);
        displayPolicy.layoutWindowLw(mImeWindow, null, mDisplayContent.mDisplayFrames);

        final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
        final InsetsSource imeSource = state.peekSource(ITYPE_IME);
        final InsetsSource navBarSource = state.peekSource(ITYPE_NAVIGATION_BAR);

        assertNotNull(imeSource);
        assertNotNull(navBarSource);
        assertFalse(imeSource.getFrame().isEmpty());
        assertFalse(navBarSource.getFrame().isEmpty());
        assertTrue(imeSource.getFrame().contains(navBarSource.getFrame()));
    }
}