Commit 0a840142 authored by Yuwei Huang's avatar Yuwei Huang Committed by Commit Bot

[Remoting Android] Fix cutout bugs

CL 1174982 only fixes layout issues when the screen has two cutouts that
cancels each other when calculating the center of the safe area. We
still have layout issues in single cutout scenario. This CL fixes these
bugs:

* Fix the calculation of the safe area center. It should be
  (width + inset.left - inset.right) / 2 instead of
  width / 2 + inset.left - inset.right. Same thing for y coordinate
  calculation.
* The letterbox padding doesn't need to account for the safe insets
  since GetViewportScreenCenter() and GetViewportBounds() already
  account for that. Undoing the letterbox changes.
* The SystemUIRect already takes cutouts into consideration. Since we
  no longer include safe insets in the letterbox padding, this CL makes
  DesktopCanvas ignore safe insets during calculation when the
  SystemUIRect is provided so that we don't double-apply the adjustment.

Scenarios manually tested:
{no cutout, 1 cutout, 2 symmetrical cutouts on top and bottom} x
{portrait mode, landscape mode} x
{touch input mode, trackpad input mode} x
{desktop < screen (letterboxes showing),
 desktop >= screen (no letterbox)} x
{keyboard showing, keyboard not showing}

Bug: 831670
Change-Id: I0ad192b2a199c8c1d4d7740b52d4b074c3626640
Reviewed-on: https://chromium-review.googlesource.com/1185631Reviewed-by: default avatarJoe Downing <joedow@chromium.org>
Commit-Queue: Yuwei Huang <yuweih@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585277}
parent 7fa5613c
...@@ -174,8 +174,7 @@ public class DesktopCanvas { ...@@ -174,8 +174,7 @@ public class DesktopCanvas {
} }
float widthRatio = getSafeScreenWidth() / mRenderData.imageWidth; float widthRatio = getSafeScreenWidth() / mRenderData.imageWidth;
float heightRatio = float heightRatio = getSafeScreenHeight() / mRenderData.imageHeight;
calculateSafeScreenHeight(mRenderData.screenHeight) / mRenderData.imageHeight;
float screenToImageScale = Math.max(widthRatio, heightRatio); float screenToImageScale = Math.max(widthRatio, heightRatio);
// If the image is smaller than the screen in either dimension, then we want to scale it // If the image is smaller than the screen in either dimension, then we want to scale it
...@@ -216,12 +215,11 @@ public class DesktopCanvas { ...@@ -216,12 +215,11 @@ public class DesktopCanvas {
float[] imageSize = {mRenderData.imageWidth, mRenderData.imageHeight}; float[] imageSize = {mRenderData.imageWidth, mRenderData.imageHeight};
mRenderData.transform.mapVectors(imageSize); mRenderData.transform.mapVectors(imageSize);
if (imageSize[0] < getSafeScreenWidth() if (imageSize[0] < getSafeScreenWidth() && imageSize[1] < getSafeScreenHeight()) {
&& imageSize[1] < calculateSafeScreenHeight(mRenderData.screenHeight)) {
// Displayed image is too small in both directions, so apply the minimum zoom // Displayed image is too small in both directions, so apply the minimum zoom
// level needed to fit either the width or height. // level needed to fit either the width or height.
float scale = Math.min(getSafeScreenWidth() / mRenderData.imageWidth, float scale = Math.min(getSafeScreenWidth() / mRenderData.imageWidth,
calculateSafeScreenHeight(mRenderData.screenHeight) / mRenderData.imageHeight); getSafeScreenHeight() / mRenderData.imageHeight);
mRenderData.transform.setScale(scale, scale); mRenderData.transform.setScale(scale, scale);
} }
...@@ -230,7 +228,7 @@ public class DesktopCanvas { ...@@ -230,7 +228,7 @@ public class DesktopCanvas {
} else { } else {
// Find the new screen center (it probably changed during the zoom operation) and update // Find the new screen center (it probably changed during the zoom operation) and update
// the viewport to smoothly track the zoom gesture. // the viewport to smoothly track the zoom gesture.
PointF safeScreenCenter = calculateSafeScreenCenterPoint(mRenderData.screenHeight); PointF safeScreenCenter = getSafeScreenCenterPoint();
float[] mappedPoints = { float[] mappedPoints = {
safeScreenCenter.x - mViewportOffset.x, safeScreenCenter.y - mViewportOffset.y}; safeScreenCenter.x - mViewportOffset.x, safeScreenCenter.y - mViewportOffset.y};
Matrix screenToImage = new Matrix(); Matrix screenToImage = new Matrix();
...@@ -264,7 +262,7 @@ public class DesktopCanvas { ...@@ -264,7 +262,7 @@ public class DesktopCanvas {
// Find the center point of the viewport on the screen. // Find the center point of the viewport on the screen.
adjustedScreenHeight = mSystemUiScreenRect.bottom; adjustedScreenHeight = mSystemUiScreenRect.bottom;
} else { } else {
adjustedScreenHeight = ((float) mRenderData.screenHeight); adjustedScreenHeight = getSafeScreenHeight();
} }
return adjustedScreenHeight; return adjustedScreenHeight;
...@@ -275,7 +273,7 @@ public class DesktopCanvas { ...@@ -275,7 +273,7 @@ public class DesktopCanvas {
* account. * account.
*/ */
private PointF getViewportScreenCenter() { private PointF getViewportScreenCenter() {
return calculateSafeScreenCenterPoint(getAdjustedScreenHeight()); return getAdjustedScreenCenterPoint();
} }
/** /**
...@@ -332,21 +330,18 @@ public class DesktopCanvas { ...@@ -332,21 +330,18 @@ public class DesktopCanvas {
Matrix screenToImage = new Matrix(); Matrix screenToImage = new Matrix();
mRenderData.transform.invert(screenToImage); mRenderData.transform.invert(screenToImage);
PointF viewportCenter = getViewportScreenCenter(); float[] screenVectors = {getSafeScreenWidth() / 2, getAdjustedScreenHeight() / 2};
float[] screenVectors = {viewportCenter.x, viewportCenter.y};
screenToImage.mapVectors(screenVectors); screenToImage.mapVectors(screenVectors);
RectF letterboxPadding = getLetterboxPadding(); PointF letterboxPadding = getLetterboxPadding();
float[] letterboxPaddingLeftTop = {letterboxPadding.left, letterboxPadding.top}; float[] letterboxPaddingVectors = {letterboxPadding.x, letterboxPadding.y};
float[] letterboxPaddingRightBottom = {letterboxPadding.right, letterboxPadding.bottom}; screenToImage.mapVectors(letterboxPaddingVectors);
screenToImage.mapVectors(letterboxPaddingLeftTop);
screenToImage.mapVectors(letterboxPaddingRightBottom);
// screenCenter values are 1/2 of a particular screen dimension mapped to image space.
float screenCenterX = screenVectors[0] - letterboxPaddingVectors[0];
float screenCenterY = screenVectors[1] - letterboxPaddingVectors[1];
RectF imageBounds = getImageBounds(); RectF imageBounds = getImageBounds();
imageBounds.left += screenVectors[0] - letterboxPaddingLeftTop[0]; imageBounds.inset(screenCenterX, screenCenterY);
imageBounds.top += screenVectors[1] - letterboxPaddingLeftTop[1];
imageBounds.right -= screenVectors[0] - letterboxPaddingRightBottom[0];
imageBounds.bottom -= screenVectors[1] - letterboxPaddingRightBottom[1];
return imageBounds; return imageBounds;
} }
...@@ -373,25 +368,18 @@ public class DesktopCanvas { ...@@ -373,25 +368,18 @@ public class DesktopCanvas {
} }
/** /**
* Provides the amount of padding needed to center the image content on the screen. Safe insets * Provides the amount of padding needed to center the image content on the screen.
* are fixed constant letterbox padding that exist even when the image is not smaller than the
* screen.
*/ */
private RectF getLetterboxPadding() { private PointF getLetterboxPadding() {
float[] imageVectors = {mRenderData.imageWidth, mRenderData.imageHeight}; float[] imageVectors = {mRenderData.imageWidth, mRenderData.imageHeight};
mRenderData.transform.mapVectors(imageVectors); mRenderData.transform.mapVectors(imageVectors);
// We want to letterbox when the image is smaller than the screen in a specific dimension. // We want to letterbox when the image is smaller than the screen in a specific dimension.
// Since we center the image, split the difference so it is equally distributed. // Since we center the image, split the difference so it is equally distributed.
float widthAdjust = Math.max((getSafeScreenWidth() - imageVectors[0]) / 2, 0); float widthAdjust = Math.max((getSafeScreenWidth() - imageVectors[0]) / 2, 0);
float heightAdjust = Math.max( float heightAdjust = Math.max((getAdjustedScreenHeight() - imageVectors[1]) / 2, 0);
(calculateSafeScreenHeight(getAdjustedScreenHeight()) - imageVectors[1]) / 2, 0);
// Add the safe insets.
RectF padding = new RectF(widthAdjust + mSafeInsets.left, heightAdjust + mSafeInsets.top,
widthAdjust + mSafeInsets.right, heightAdjust + mSafeInsets.bottom);
return padding; return new PointF(widthAdjust, heightAdjust);
} }
/** /**
...@@ -408,14 +396,12 @@ public class DesktopCanvas { ...@@ -408,14 +396,12 @@ public class DesktopCanvas {
// between the System UI and the remote desktop image. // between the System UI and the remote desktop image.
// Note: Ignore negative padding (clamp to 0) since that means no overlap exists. // Note: Ignore negative padding (clamp to 0) since that means no overlap exists.
float adjustedScreenHeight = getAdjustedScreenHeight(); float adjustedScreenHeight = getAdjustedScreenHeight();
RectF letterboxPadding = getLetterboxPadding(); PointF letterboxPadding = getLetterboxPadding();
return new RectF(Math.max(mSystemUiScreenRect.left - letterboxPadding.left, 0.0f), return new RectF(Math.max(mSystemUiScreenRect.left - letterboxPadding.x, 0.0f),
Math.max(mSystemUiScreenRect.top - letterboxPadding.top, 0.0f), Math.max(mSystemUiScreenRect.top - letterboxPadding.y, 0.0f),
Math.max(mRenderData.screenWidth - mSystemUiScreenRect.right Math.max(mRenderData.screenWidth - mSystemUiScreenRect.right - letterboxPadding.x,
- letterboxPadding.right,
0.0f), 0.0f),
Math.max( Math.max(adjustedScreenHeight - mSystemUiScreenRect.bottom - letterboxPadding.y,
adjustedScreenHeight - mSystemUiScreenRect.bottom - letterboxPadding.bottom,
0.0f)); 0.0f));
} }
...@@ -501,29 +487,47 @@ public class DesktopCanvas { ...@@ -501,29 +487,47 @@ public class DesktopCanvas {
} }
/** /**
* @return Screen width inset by {@link #mSafeInsets}. * @return Screen width inset by {@link #mSafeInsets} if {@link #mSystemUiScreenRect} is empty,
* otherwise just the screen width.
*/ */
private float getSafeScreenWidth() { private float getSafeScreenWidth() {
if (!mSystemUiScreenRect.isEmpty()) {
return mRenderData.screenWidth;
}
return mRenderData.screenWidth - mSafeInsets.left - mSafeInsets.right; return mRenderData.screenWidth - mSafeInsets.left - mSafeInsets.right;
} }
/** /**
* @param height The height to be used to calculate the safe screen height. Generally either * @return Screen height inset by {@link #mSafeInsets} if {@link #mSystemUiScreenRect} is empty,
* {@link #getAdjustedScreenHeight()} or mRenderData.screenHeight. * otherwise just the screen height.
* @return Screen height inset by {@link #mSafeInsets}.
*/ */
private float calculateSafeScreenHeight(float height) { private float getSafeScreenHeight() {
return height - mSafeInsets.top - mSafeInsets.bottom; if (!mSystemUiScreenRect.isEmpty()) {
return mRenderData.screenHeight;
}
return mRenderData.screenHeight - mSafeInsets.top - mSafeInsets.bottom;
} }
/** /**
* @param height The height to be used to calculate the safe screen height. Generally either * @return Center point of the screen area inset by {@link #mSafeInsets} if {@link
* {@link #getAdjustedScreenHeight()} or mRenderData.screenHeight. * #mSystemUiScreenRect} is empty, otherwise just the center of the screen.
* @return Center of the safe area on the screen inset by {@link #mSafeInsets}.
*/ */
private PointF calculateSafeScreenCenterPoint(float height) { private PointF getSafeScreenCenterPoint() {
return new PointF( if (!mSystemUiScreenRect.isEmpty()) {
(float) mRenderData.screenWidth / 2 + mSafeInsets.left - mSafeInsets.right, return new PointF(mRenderData.screenWidth / 2.f, mRenderData.screenHeight / 2.f);
height / 2 + mSafeInsets.top - mSafeInsets.bottom); }
return new PointF((mRenderData.screenWidth + mSafeInsets.left - mSafeInsets.right) / 2.f,
(mRenderData.screenHeight + mSafeInsets.top - mSafeInsets.bottom) / 2.f);
}
/**
* @return Same as {@link #getSafeScreenCenterPoint()} if {@link #mSystemUiScreenRect} is empty,
* otherwise return (screenWidth / 2, adjustedScreenHeight / 2).
*/
private PointF getAdjustedScreenCenterPoint() {
if (mSystemUiScreenRect.isEmpty()) {
return getSafeScreenCenterPoint();
}
return new PointF(mRenderData.screenWidth / 2.f, getAdjustedScreenHeight() / 2.f);
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment