Skip to content

Commit 3e52fc2

Browse files
author
Dianne Hackborn
committed
Fix some issues with updating the offsets of a window.
- Apply the correct crop rect at this point. - Apply the correct position by taking into account the frame left/top. - Don't directly apply the new values if the window is currently animating, since we need to go through the whole animation step to determine what the correct position is (taking into account any transformations). Change-Id: I15d79354d9779867c49c7c0880faccdead7b021d
1 parent a7ea0d3 commit 3e52fc2

File tree

1 file changed

+73
-53
lines changed

1 file changed

+73
-53
lines changed

services/java/com/android/server/wm/WindowStateAnimator.java

Lines changed: 73 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,59 @@ void computeShownFrameLocked() {
935935
mDtDy = mWin.mGlobalScale;
936936
}
937937

938+
void updateSurfaceWindowCrop(final boolean recoveringMemory) {
939+
final WindowState w = mWin;
940+
941+
// Need to recompute a new system decor rect each time.
942+
if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
943+
// Currently can't do this cropping for scaled windows. We'll
944+
// just keep the crop rect the same as the source surface.
945+
w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
946+
} else if (w.mLayer >= mService.mSystemDecorLayer) {
947+
// Above the decor layer is easy, just use the entire window.
948+
w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
949+
w.mCompatFrame.height());
950+
} else {
951+
final Rect decorRect = mService.mSystemDecorRect;
952+
// Compute the offset of the window in relation to the decor rect.
953+
final int offX = w.mXOffset + w.mFrame.left;
954+
final int offY = w.mYOffset + w.mFrame.top;
955+
// Initialize the decor rect to the entire frame.
956+
w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height());
957+
// Intersect with the decor rect, offsetted by window position.
958+
w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY,
959+
decorRect.right-offX, decorRect.bottom-offY);
960+
// If size compatibility is being applied to the window, the
961+
// surface is scaled relative to the screen. Also apply this
962+
// scaling to the crop rect. We aren't using the standard rect
963+
// scale function because we want to round things to make the crop
964+
// always round to a larger rect to ensure we don't crop too
965+
// much and hide part of the window that should be seen.
966+
if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
967+
final float scale = w.mInvGlobalScale;
968+
w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
969+
w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
970+
w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
971+
w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
972+
}
973+
}
974+
975+
if (!w.mSystemDecorRect.equals(w.mLastSystemDecorRect)) {
976+
w.mLastSystemDecorRect.set(w.mSystemDecorRect);
977+
try {
978+
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
979+
"CROP " + w.mSystemDecorRect.toShortString(), null);
980+
mSurface.setWindowCrop(w.mSystemDecorRect);
981+
} catch (RuntimeException e) {
982+
Slog.w(TAG, "Error setting crop surface of " + w
983+
+ " crop=" + w.mSystemDecorRect.toShortString(), e);
984+
if (!recoveringMemory) {
985+
mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true);
986+
}
987+
}
988+
}
989+
}
990+
938991
void setSurfaceBoundaries(final boolean recoveringMemory) {
939992
final WindowState w = mWin;
940993
int width, height;
@@ -1003,54 +1056,7 @@ void setSurfaceBoundaries(final boolean recoveringMemory) {
10031056
}
10041057
}
10051058

1006-
// Need to recompute a new system decor rect each time.
1007-
if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
1008-
// Currently can't do this cropping for scaled windows. We'll
1009-
// just keep the crop rect the same as the source surface.
1010-
w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
1011-
} else if (w.mLayer >= mService.mSystemDecorLayer) {
1012-
// Above the decor layer is easy, just use the entire window.
1013-
w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
1014-
w.mCompatFrame.height());
1015-
} else {
1016-
final Rect decorRect = mService.mSystemDecorRect;
1017-
// Compute the offset of the window in relation to the decor rect.
1018-
final int offX = w.mXOffset + w.mFrame.left;
1019-
final int offY = w.mYOffset + w.mFrame.top;
1020-
// Initialize the decor rect to the entire frame.
1021-
w.mSystemDecorRect.set(0, 0, w.mFrame.width(), w.mFrame.height());
1022-
// Intersect with the decor rect, offsetted by window position.
1023-
w.mSystemDecorRect.intersect(decorRect.left-offX, decorRect.top-offY,
1024-
decorRect.right-offX, decorRect.bottom-offY);
1025-
// If size compatibility is being applied to the window, the
1026-
// surface is scaled relative to the screen. Also apply this
1027-
// scaling to the crop rect. We aren't using the standard rect
1028-
// scale function because we want to round things to make the crop
1029-
// always round to a larger rect to ensure we don't crop too
1030-
// much and hide part of the window that should be seen.
1031-
if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
1032-
final float scale = w.mInvGlobalScale;
1033-
w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
1034-
w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
1035-
w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
1036-
w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
1037-
}
1038-
}
1039-
1040-
if (!w.mSystemDecorRect.equals(w.mLastSystemDecorRect)) {
1041-
w.mLastSystemDecorRect.set(w.mSystemDecorRect);
1042-
try {
1043-
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1044-
"CROP " + w.mSystemDecorRect.toShortString(), null);
1045-
mSurface.setWindowCrop(w.mSystemDecorRect);
1046-
} catch (RuntimeException e) {
1047-
Slog.w(TAG, "Error setting crop surface of " + w
1048-
+ " crop=" + w.mSystemDecorRect.toShortString(), e);
1049-
if (!recoveringMemory) {
1050-
mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true);
1051-
}
1052-
}
1053-
}
1059+
updateSurfaceWindowCrop(recoveringMemory);
10541060
}
10551061

10561062
public void prepareSurfaceLocked(final boolean recoveringMemory) {
@@ -1181,17 +1187,31 @@ void setTransparentRegionHint(final Region region) {
11811187
}
11821188

11831189
void setWallpaperOffset(int left, int top) {
1190+
mSurfaceX = left;
1191+
mSurfaceY = top;
1192+
if (mAnimating) {
1193+
// If this window (or its app token) is animating, then the position
1194+
// of the surface will be re-computed on the next animation frame.
1195+
// We can't poke it directly here because it depends on whatever
1196+
// transformation is being applied by the animation.
1197+
return;
1198+
}
1199+
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
1200+
">>> OPEN TRANSACTION setWallpaperOffset");
11841201
Surface.openTransaction();
11851202
try {
1186-
mSurfaceX = left;
1187-
mSurfaceY = top;
1188-
mSurface.setPosition(left, top);
1189-
mSurface.setWindowCrop(null);
1203+
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
1204+
"POS " + left + ", " + top, null);
1205+
mSurface.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top);
1206+
updateSurfaceWindowCrop(false);
11901207
} catch (RuntimeException e) {
11911208
Slog.w(TAG, "Error positioning surface of " + mWin
11921209
+ " pos=(" + left + "," + top + ")", e);
1210+
} finally {
1211+
Surface.closeTransaction();
1212+
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
1213+
"<<< CLOSE TRANSACTION setWallpaperOffset");
11931214
}
1194-
Surface.closeTransaction();
11951215
}
11961216

11971217
// This must be called while inside a transaction.

0 commit comments

Comments
 (0)