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

Commit 1f903c3b authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix issue #5283365: Rotating the device to portrait mode, hides the keyboard partly

PhoneWindowManager now takes full responsibility for deciding where the
navigation bar goes.  This gets rid of a bunch of race conditions with
determining layout while the nav bar is moving itself at the same time
the window manager is computing a new configuration.

Note that this breaks the "nav bar on left" option.  The current nav
bar code could also be cleaned up some more to completely drive its
behavior based on onSizeChanged() happening during relayout.

Change-Id: I1651d74c3464ba0d588aab3049e099c78420146a
parent 4e2134b7
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -478,14 +478,14 @@ public interface WindowManagerPolicy {
     * decorations that can never be removed.  That is, system bar or
     * button bar.
     */
    public int getNonDecorDisplayWidth(int rotation, int fullWidth);
    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation);

    /**
     * Return the display height available after excluding any screen
     * decorations that can never be removed.  That is, system bar or
     * button bar.
     */
    public int getNonDecorDisplayHeight(int rotation, int fullHeight);
    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation);

    /**
     * Return the available screen width that we should report for the
@@ -493,7 +493,7 @@ public interface WindowManagerPolicy {
     * {@link #getNonDecorDisplayWidth(int, int)}; it may be smaller than
     * that to account for more transient decoration like a status bar.
     */
    public int getConfigDisplayWidth(int rotation, int fullWidth);
    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation);

    /**
     * Return the available screen height that we should report for the
@@ -501,7 +501,7 @@ public interface WindowManagerPolicy {
     * {@link #getNonDecorDisplayHeight(int, int)}; it may be smaller than
     * that to account for more transient decoration like a status bar.
     */
    public int getConfigDisplayHeight(int rotation, int fullHeight);
    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation);

    /**
     * Return whether the given window should forcibly hide everything
@@ -671,8 +671,10 @@ public interface WindowManagerPolicy {
     * 
     * @param displayWidth The current full width of the screen.
     * @param displayHeight The current full height of the screen.
     * @param displayRotation The current rotation being applied to the base
     * window.
     */
    public void beginLayoutLw(int displayWidth, int displayHeight);
    public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation);

    /**
     * Called for each window attached to the window manager as layout is
+1 −26
Original line number Diff line number Diff line
@@ -469,20 +469,10 @@ public class PhoneStatusBar extends StatusBar {
    }

    private WindowManager.LayoutParams getNavigationBarLayoutParams() {
        final int rotation = mDisplay.getRotation();
        final boolean sideways = 
            (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);

        final Resources res = mContext.getResources();
        final int size = res.getDimensionPixelSize(R.dimen.navigation_bar_size);

        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                sideways ? size : ViewGroup.LayoutParams.MATCH_PARENT,
                sideways ? ViewGroup.LayoutParams.MATCH_PARENT : size,
                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
                    0
                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
@@ -494,21 +484,6 @@ public class PhoneStatusBar extends StatusBar {
        }

        lp.setTitle("NavigationBar");
        switch (rotation) {
            case Surface.ROTATION_90:
                // device has been turned 90deg counter-clockwise
                lp.gravity = Gravity.RIGHT | Gravity.FILL_VERTICAL;
                break;
            case Surface.ROTATION_270:
                // device has been turned 90deg clockwise
                lp.gravity = (NavigationBarView.NAVBAR_ALWAYS_AT_RIGHT ? Gravity.RIGHT
                                                                       : Gravity.LEFT) 
                             | Gravity.FILL_VERTICAL;
                break;
            default:
                lp.gravity = Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
                break;
        }
        lp.windowAnimations = 0;

        return lp;
+37 −35
Original line number Diff line number Diff line
@@ -345,6 +345,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    static final Rect mTmpDisplayFrame = new Rect();
    static final Rect mTmpContentFrame = new Rect();
    static final Rect mTmpVisibleFrame = new Rect();
    static final Rect mTmpNavigationFrame = new Rect();
    
    WindowState mTopFullscreenOpaqueWindowState;
    WindowState mTopAppWindowState;
@@ -1125,27 +1126,27 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        return mStatusBarCanHide;
    }

    public int getNonDecorDisplayWidth(int rotation, int fullWidth) {
    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
        // Assumes that the navigation bar appears on the side of the display in landscape.
        final boolean horizontal
            = (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90);
        return fullWidth - (horizontal ? mNavigationBarWidth : 0);
        if (fullWidth > fullHeight) {
            return fullWidth - mNavigationBarWidth;
        }
        return fullWidth;
    }

    public int getNonDecorDisplayHeight(int rotation, int fullHeight) {
        final boolean horizontal
            = (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90);
    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
        // Assumes the navigation bar appears on the bottom of the display in portrait.
        return fullHeight
            - (mStatusBarCanHide ? 0 : mStatusBarHeight)
            - (horizontal ? 0 : mNavigationBarHeight);
            - ((fullWidth > fullHeight) ? 0 : mNavigationBarHeight);
    }

    public int getConfigDisplayWidth(int rotation, int fullWidth) {
        return getNonDecorDisplayWidth(rotation, fullWidth);
    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation);
    }

    public int getConfigDisplayHeight(int rotation, int fullHeight) {
        return getNonDecorDisplayHeight(rotation, fullHeight);
    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
        return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation);
    }

    public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
@@ -1687,7 +1688,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    }
    
    /** {@inheritDoc} */
    public void beginLayoutLw(int displayWidth, int displayHeight) {
    public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) {
        mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
        mUnrestrictedScreenWidth = displayWidth;
        mUnrestrictedScreenHeight = displayHeight;
@@ -1713,30 +1714,31 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        if (mStatusBar != null) {
            Rect navr = null;
            if (mNavigationBar != null) {
                mNavigationBar.computeFrameLw(pf, df, vf, vf);
                // Force the navigation bar to its appropriate place and
                // size.  We need to do this directly, instead of relying on
                // it to bubble up from the nav bar, because this needs to
                // change atomically with screen rotations.
                if (displayWidth < displayHeight) {
                    // Portrait screen; nav bar goes on bottom.
                    mTmpNavigationFrame.set(0, displayHeight-mNavigationBarHeight,
                            displayWidth, displayHeight);
                    if (mNavigationBar.isVisibleLw()) {
                    navr = mNavigationBar.getFrameLw();

                    if (navr.top == 0) {
                        // Navigation bar is vertical
                        if (mDockLeft == navr.left) {
                            mDockLeft = navr.right;
                        } else if (mDockRight == navr.right) {
                            mDockRight = navr.left;
                        mDockBottom = mTmpNavigationFrame.top;
                    }
                } else {
                        // Navigation bar horizontal, at bottom
                        if (mDockBottom == navr.bottom) {
                            mDockBottom = navr.top;
                        }
                    // Landscape screen; nav bar goes to the right.
                    mTmpNavigationFrame.set(displayWidth-mNavigationBarWidth, 0,
                            displayWidth, displayHeight);
                    if (mNavigationBar.isVisibleLw()) {
                        mDockRight = mTmpNavigationFrame.left;
                    }
                }
                mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
                        mTmpNavigationFrame, mTmpNavigationFrame);
                if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
            }
            if (DEBUG_LAYOUT) {
                Log.i(TAG, "mNavigationBar frame: " + navr);
                Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
            if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
                    mDockLeft, mDockTop, mDockRight, mDockBottom));
            }

            // apply navigation bar insets
            pf.left = df.left = vf.left = mDockLeft;
@@ -1862,7 +1864,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
            WindowState attached) {
        // we've already done the status bar
        if (win == mStatusBar) {
        if (win == mStatusBar || win == mNavigationBar) {
            return;
        }

+15 −13
Original line number Diff line number Diff line
@@ -5701,8 +5701,8 @@ public class WindowManagerService extends IWindowManager.Stub
        return config;
    }

    private int reduceConfigWidthSize(int curSize, int rotation, float density, int dw) {
        int size = (int)(mPolicy.getConfigDisplayWidth(rotation, dw) / density);
    private int reduceConfigWidthSize(int curSize, int rotation, float density, int dw, int dh) {
        int size = (int)(mPolicy.getConfigDisplayWidth(dw, dh, rotation) / density);
        if (size < curSize) {
            curSize = size;
        }
@@ -5722,17 +5722,17 @@ public class WindowManagerService extends IWindowManager.Stub
            unrotDw = dw;
            unrotDh = dh;
        }
        int sw = reduceConfigWidthSize(unrotDw, Surface.ROTATION_0, density, unrotDw);
        sw = reduceConfigWidthSize(sw, Surface.ROTATION_90, density, unrotDh);
        sw = reduceConfigWidthSize(sw, Surface.ROTATION_180, density, unrotDw);
        sw = reduceConfigWidthSize(sw, Surface.ROTATION_270, density, unrotDh);
        int sw = reduceConfigWidthSize(unrotDw, Surface.ROTATION_0, density, unrotDw, unrotDh);
        sw = reduceConfigWidthSize(sw, Surface.ROTATION_90, density, unrotDw, unrotDh);
        sw = reduceConfigWidthSize(sw, Surface.ROTATION_180, density, unrotDw, unrotDh);
        sw = reduceConfigWidthSize(sw, Surface.ROTATION_270, density, unrotDw, unrotDh);
        return sw;
    }

    private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
            int dw, int dh) {
        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(rotation, dw);
        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(rotation, dh);
        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
        float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
        int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
        if (curSize == 0 || size < curSize) {
@@ -5809,15 +5809,17 @@ public class WindowManagerService extends IWindowManager.Stub

        // Update application display metrics.
        final DisplayMetrics dm = mDisplayMetrics;
        mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
        mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
        mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
        mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
        mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight);

        mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
                mCompatDisplayMetrics);

        config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(mRotation, dw) / dm.density);
        config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(mRotation, dh) / dm.density);
        config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
                / dm.density);
        config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
                / dm.density);
        config.smallestScreenWidthDp = computeSmallestWidth(rotated, dw, dh, dm.density);

        config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
@@ -7151,7 +7153,7 @@ public class WindowManagerService extends IWindowManager.Stub
        if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed="
                + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
        
        mPolicy.beginLayoutLw(dw, dh);
        mPolicy.beginLayoutLw(dw, dh, mRotation);

        int seq = mLayoutSeq+1;
        if (seq < 0) seq = 0;