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

Commit 443f9acd authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Compute surface position of scaled child window

This replaces the way commit df46fd52 did. The frames of child
window are still calculated with scaling, but only the surface
scale is ignored. So if the app calls getLocationOnScreen for
a scaled child window, the coordinate base can be consistent
with parent.

Bug: 182362657
Test: atest WindowStateTests#testCompatOverrideScale

Change-Id: I6d4f7dab4949feb488fbcb42ff687a520fe4ca70
parent 9c6e07a7
Loading
Loading
Loading
Loading
+19 −41
Original line number Diff line number Diff line
@@ -259,7 +259,6 @@ import com.android.internal.util.ToBooleanFunction;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.utils.CoordinateTransforms;

import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -1177,14 +1176,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP

    /**
     * @return {@code true} if the application runs in size compatibility mode or has an app level
     * scaling override set. This method always returns {@code false} on child window because it
     * should follow parent's scale.
     * scaling override set.
     * @see CompatModePackages#getCompatScale
     * @see android.content.res.CompatibilityInfo#supportsScreen
     * @see ActivityRecord#hasSizeCompatBounds()
     */
    boolean hasCompatScale() {
        return (mOverrideScale != 1f || hasCompatScale(mAttrs, mActivityRecord)) && !mIsChildWindow;
        return mOverrideScale != 1f || hasCompatScale(mAttrs, mActivityRecord);
    }

    /**
@@ -4478,22 +4476,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            h = Math.min(h, ph);
        }

        if (mIsChildWindow) {
            final WindowState parent = getTopParentWindow();
            if (parent.hasCompatScale()) {
                // Scale the containing and display frames because they are in screen coordinates.
                // The position of frames are already relative to parent so only size is scaled.
                mTmpRect.set(containingFrame);
                containingFrame = mTmpRect;
                CoordinateTransforms.scaleRectSize(containingFrame, parent.mInvGlobalScale);
                if (fitToDisplay) {
                    mTmpRect2.set(displayFrame);
                    displayFrame = mTmpRect2;
                    CoordinateTransforms.scaleRectSize(displayFrame, parent.mInvGlobalScale);
                }
            }
        }

        // Set mFrame
        Gravity.apply(attrs.gravity, w, h, containingFrame,
                (int) (x + attrs.horizontalMargin * pw),
@@ -5124,19 +5106,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        }
    }

    /**
     * Expand the given rectangle by this windows surface insets. This
     * takes you from the 'window size' to the 'surface size'.
     * The surface insets are positive in each direction, so we inset by
     * the inverse.
     */
    void expandForSurfaceInsets(Rect r) {
        r.inset(-mAttrs.surfaceInsets.left,
                -mAttrs.surfaceInsets.top,
                -mAttrs.surfaceInsets.right,
                -mAttrs.surfaceInsets.bottom);
    }

    boolean surfaceInsetsChanging() {
        return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets);
    }
@@ -5454,6 +5423,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }

    private void updateScaleIfNeeded() {
        if (mIsChildWindow) {
            // Child window follows parent's scale.
            return;
        }
        float newHScale = mHScale * mGlobalScale * mWallpaperScale;
        float newVScale = mVScale * mGlobalScale * mWallpaperScale;
        if (mLastHScale != newHScale ||
@@ -5537,15 +5510,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        // If changed, also adjust getTransformationMatrix
        final WindowContainer parentWindowContainer = getParent();
        if (isChildWindow()) {
            // TODO: This probably falls apart at some point and we should
            // actually compute relative coordinates.

            final WindowState parent = getParentWindow();
            outPoint.offset(-parent.mWindowFrames.mFrame.left, -parent.mWindowFrames.mFrame.top);
            // Undo the scale of window position because the relative coordinates for child are
            // based on the scaled parent.
            if (mInvGlobalScale != 1f) {
                outPoint.x = (int) (outPoint.x * mInvGlobalScale + 0.5f);
                outPoint.y = (int) (outPoint.y * mInvGlobalScale + 0.5f);
            }
            // Since the parent was outset by its surface insets, we need to undo the outsetting
            // with insetting by the same amount.
            final WindowState parent = getParentWindow();
            transformSurfaceInsetsPosition(mTmpPoint, parent.mAttrs.surfaceInsets);
            outPoint.offset(-parent.mWindowFrames.mFrame.left + mTmpPoint.x,
                    -parent.mWindowFrames.mFrame.top + mTmpPoint.y);
            outPoint.offset(mTmpPoint.x, mTmpPoint.y);
        } else if (parentWindowContainer != null) {
            final Rect parentBounds = isStartingWindowAssociatedToTask()
                    ? mStartingData.mAssociatedTask.getBounds()
@@ -5564,7 +5540,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
            outPoint.offset(outset, outset);
        }

        // Expand for surface insets. See WindowState.expandForSurfaceInsets.
        // The surface size is larger than the window if the window has positive surface insets.
        transformSurfaceInsetsPosition(mTmpPoint, mAttrs.surfaceInsets);
        outPoint.offset(-mTmpPoint.x, -mTmpPoint.y);

@@ -5576,7 +5552,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
     * scaled, the insets also need to be scaled for surface position in global coordinate.
     */
    private void transformSurfaceInsetsPosition(Point outPos, Rect surfaceInsets) {
        if (!hasCompatScale()) {
        // Ignore the scale for child window because its insets have been scaled with the
        // parent surface.
        if (mGlobalScale == 1f || mIsChildWindow) {
            outPos.x = surfaceInsets.left;
            outPos.y = surfaceInsets.top;
            return;
+0 −6
Original line number Diff line number Diff line
@@ -152,10 +152,4 @@ public class CoordinateTransforms {
        transform.mapRect(tmp);
        inOutRect.set((int) tmp.left, (int) tmp.top, (int) tmp.right, (int) tmp.bottom);
    }

    /** Scales the rect without changing its position. */
    public static void scaleRectSize(Rect inOutRect, float scale) {
        inOutRect.right = inOutRect.left + (int) (inOutRect.width() * scale + .5f);
        inOutRect.bottom = inOutRect.top + (int) (inOutRect.height() * scale + .5f);
    }
}
+17 −11
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ import static org.mockito.Mockito.when;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
@@ -563,7 +564,7 @@ public class WindowStateTests extends WindowTestsBase {
        final WindowState child = createWindow(w, TYPE_APPLICATION_PANEL, "child");

        assertTrue(w.hasCompatScale());
        assertFalse(child.hasCompatScale());
        assertTrue(child.hasCompatScale());

        makeWindowVisible(w, child);
        w.setRequestedSize(100, 200);
@@ -574,21 +575,26 @@ public class WindowStateTests extends WindowTestsBase {
        w.mAttrs.gravity = Gravity.TOP | Gravity.LEFT;
        child.mAttrs.gravity = Gravity.CENTER;
        DisplayContentTests.performLayout(mDisplayContent);
        final Rect parentFrame = w.getFrame();
        final Rect childFrame = child.getFrame();

        // Frame on screen = 200x400 (200, 200 - 400, 600). Compat frame on client = 100x200.
        final Rect unscaledCompatFrame = new Rect(w.getWindowFrames().mCompatFrame);
        unscaledCompatFrame.scale(overrideScale);
        final Rect parentFrame = w.getFrame();
        assertEquals(w.getWindowFrames().mFrame, unscaledCompatFrame);
        assertEquals(parentFrame, unscaledCompatFrame);

        final Rect childFrame = child.getFrame();
        assertEquals(childFrame, child.getWindowFrames().mCompatFrame);
        // Child frame = 50x100 (225, 250 - 275, 350) according to Gravity.CENTER.
        final int childX = parentFrame.left + child.mRequestedWidth / 2;
        final int childY = parentFrame.top + child.mRequestedHeight / 2;
        final Rect expectedChildFrame = new Rect(childX, childY, childX + child.mRequestedWidth,
                childY + child.mRequestedHeight);
        assertEquals(expectedChildFrame, childFrame);
        // Frame on screen = 100x200 (250, 300 - 350, 500). Compat frame on client = 50x100.
        unscaledCompatFrame.set(child.getWindowFrames().mCompatFrame);
        unscaledCompatFrame.scale(overrideScale);
        assertEquals(childFrame, unscaledCompatFrame);

        // The position of child is relative to parent. So the local coordinates should be scaled.
        final Point expectedChildPos = new Point(
                (int) ((childFrame.left - parentFrame.left) / overrideScale),
                (int) ((childFrame.top - parentFrame.top) / overrideScale));
        final Point childPos = new Point();
        child.transformFrameToSurfacePosition(childFrame.left, childFrame.top, childPos);
        assertEquals(expectedChildPos, childPos);

        // Surface should apply the scale.
        w.prepareSurfaces();