diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index f77b6f2a11de1..068ff5f58aa8b 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -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 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 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 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 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 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 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 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; diff --git a/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java b/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java index 6d8e07a919ccd..a2f37a56598dd 100644 --- a/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java +++ b/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java @@ -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); - } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index a8a9188a04246..ca2b4aebc736e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -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();