Index: remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java |
diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java b/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java |
index e6ae76baff7915e64059f84a2fa288be564d169e..b26434b4bb6e0b770aadaea0061e7ff4ccb62fa1 100644 |
--- a/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java |
+++ b/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java |
@@ -18,6 +18,11 @@ public class DesktopCanvas { |
*/ |
private static final float MAX_ZOOM_FACTOR = 100.0f; |
+ /** |
+ * Used to smoothly reduce the amount of padding whle the user is zooming. |
Lambros
2016/09/30 01:59:37
s/whle/while/
joedow
2016/09/30 19:42:57
Done.
|
+ */ |
+ private static final float PADDING_REDUCTION_FACTOR = 0.85f; |
+ |
private final RenderStub mRenderStub; |
private final RenderData mRenderData; |
@@ -41,6 +46,12 @@ public class DesktopCanvas { |
*/ |
private Rect mSystemUiOffsetPixels = new Rect(); |
+ /** |
+ * Represents the additional space, in pixels, for each edge of the desktop image. Used for |
+ * positioning the desktop canvas to allow the user to scroll it below any visible System UI. |
Lambros
2016/09/30 01:59:36
Is this in screen or image coordinates?
Can you ex
joedow
2016/09/30 19:42:56
Added a block of text at the top of the class givi
|
+ */ |
+ private RectF mImagePadding = new RectF(); |
+ |
public DesktopCanvas(RenderStub renderStub, RenderData renderData) { |
mRenderStub = renderStub; |
mRenderData = renderData; |
@@ -169,6 +180,16 @@ public class DesktopCanvas { |
mRenderData.transform.setScale(scale, scale); |
} |
+ // Trim the image padding if the user is zooming out. This prevents cases where the image |
+ // pops to the center when it reaches its minimum size. Note that we do not need to do |
+ // anything when the user is zooming in as the canvas will expand and absorb the padding. |
+ if (scaleFactor < 1.0f) { |
+ mImagePadding.set(mImagePadding.left * PADDING_REDUCTION_FACTOR, |
+ mImagePadding.top * PADDING_REDUCTION_FACTOR, |
+ mImagePadding.right * PADDING_REDUCTION_FACTOR, |
+ mImagePadding.bottom * PADDING_REDUCTION_FACTOR); |
+ } |
+ |
if (centerOnCursor) { |
setCursorPosition(mCursorPosition.x, mCursorPosition.y); |
} else { |
@@ -198,6 +219,9 @@ public class DesktopCanvas { |
// Translate the image so the viewport center is displayed in the middle of the screen. |
mRenderData.transform.postTranslate(viewportTransX, viewportTransY); |
+ // Remove or add image padding based on the new position. |
Lambros
2016/09/30 01:59:37
How is padding based on position?
joedow
2016/09/30 19:42:56
Removed comment since it wan't useful.
|
+ adjustImagePadding(); |
+ |
mRenderStub.setTransformation(mRenderData.transform); |
} |
@@ -223,7 +247,9 @@ public class DesktopCanvas { |
/** Returns a region which defines the set of valid cursor values in image space. */ |
private RectF getImageBounds() { |
- return new RectF(0, 0, mRenderData.imageWidth, mRenderData.imageHeight); |
+ float[] maxPadding = getMaxPadding(); |
+ return new RectF(-maxPadding[0], -maxPadding[1], mRenderData.imageWidth + maxPadding[2], |
Lambros
2016/09/30 01:59:36
If my reading is correct, this is the full image r
joedow
2016/09/30 19:42:56
I'll remove the maxPadding method since it is conf
|
+ mRenderData.imageHeight + maxPadding[3]); |
} |
/** Returns a region which defines the set of valid viewport center values in image space. */ |
@@ -233,23 +259,105 @@ public class DesktopCanvas { |
mRenderData.transform.invert(screenToImage); |
screenToImage.mapVectors(screenVectors); |
- float xAdjust = 0.0f; |
- if (mRenderData.imageWidth < screenVectors[0]) { |
- // Image is narrower than the screen, so adjust the bounds to center it. |
- xAdjust = (screenVectors[0] - mRenderData.imageWidth) / 2.0f; |
- } |
- |
- float yAdjust = 0.0f; |
- if (mRenderData.imageHeight < screenVectors[1]) { |
- // Image is shorter than the screen, so adjust the bounds to center it. |
- yAdjust = (screenVectors[1] - mRenderData.imageHeight) / 2.0f; |
- } |
+ float[] letterBoxPadding = getLetterboxPadding(); |
+ screenToImage.mapVectors(letterBoxPadding); |
// screenCenter values are 1/2 of a particular screen dimension mapped to image space. |
- float screenCenterX = screenVectors[0] / 2.0f; |
- float screenCenterY = screenVectors[1] / 2.0f; |
- return new RectF(screenCenterX - xAdjust, screenCenterY - yAdjust, |
- mRenderData.imageWidth - screenCenterX + xAdjust, |
- mRenderData.imageHeight - screenCenterY + yAdjust); |
+ float screenCenterX = (screenVectors[0] / 2.0f) - letterBoxPadding[0]; |
+ float screenCenterY = (screenVectors[1] / 2.0f) - letterBoxPadding[1]; |
+ RectF imageBounds = getImageBounds(); |
+ return new RectF(imageBounds.left + screenCenterX, imageBounds.top + screenCenterY, |
Lambros
2016/09/30 01:59:36
return imageBounds.inset(screenCenterX, screenCent
joedow
2016/09/30 19:42:57
Done.
|
+ imageBounds.right - screenCenterX, imageBounds.bottom - screenCenterY); |
+ } |
+ |
+ /** Returns the maximum amount of padding per edge (left, top, right, bottom) in image space. */ |
+ private float[] getMaxPadding() { |
+ RectF systemUiOffsetPixels = getAdjustedSystemUiOffsets(); |
+ float[] maxPadding = {Math.max(mImagePadding.left, systemUiOffsetPixels.left), |
+ Math.max(mImagePadding.top, systemUiOffsetPixels.top), |
+ Math.max(mImagePadding.right, systemUiOffsetPixels.right), |
+ Math.max(mImagePadding.bottom, systemUiOffsetPixels.bottom)}; |
+ Matrix screenToImage = new Matrix(); |
+ mRenderData.transform.invert(screenToImage); |
+ screenToImage.mapVectors(maxPadding); |
+ |
+ return maxPadding; |
+ } |
+ |
+ /** Returns the letter box padding needed in each dimension (x and y) in screen coordinates. */ |
Lambros
2016/09/30 01:59:37
Maybe explain in a little more detail:
This is the
joedow
2016/09/30 19:42:57
Explained in detail at the top of the class.
|
+ private float[] getLetterboxPadding() { |
Lambros
2016/09/30 01:59:36
Maybe return PointF ?
joedow
2016/09/30 19:42:57
I had originally left this as a float [] to make t
|
+ float[] imageVectors = {mRenderData.imageWidth, mRenderData.imageHeight}; |
+ mRenderData.transform.mapVectors(imageVectors); |
+ |
+ // 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. |
+ float widthAdjust = |
+ Math.max(0.0f, ((float) mRenderData.screenWidth - imageVectors[0]) / 2.0f); |
+ float heightAdjust = |
+ Math.max(0.0f, ((float) mRenderData.screenHeight - imageVectors[1]) / 2.0f); |
+ |
+ return new float[] {widthAdjust, heightAdjust}; |
+ } |
+ |
+ /** |
+ * Returns the amount of System UI, adjusted for letter boxing, which should be used for |
+ * padding calculations. |
+ */ |
+ private RectF getAdjustedSystemUiOffsets() { |
+ float[] letterBoxPadding = getLetterboxPadding(); |
+ return new RectF(Math.max(mSystemUiOffsetPixels.left - letterBoxPadding[0], 0.0f), |
+ Math.max(mSystemUiOffsetPixels.top - letterBoxPadding[1], 0.0f), |
+ Math.max(mSystemUiOffsetPixels.right - letterBoxPadding[0], 0.0f), |
+ Math.max(mSystemUiOffsetPixels.bottom - letterBoxPadding[1], 0.0f)); |
+ } |
+ |
+ /** Updates the padding used to allow the user to scroll the image out from under System UI. */ |
+ private void adjustImagePadding() { |
+ float[] letterBoxPadding = getLetterboxPadding(); |
+ RectF systemUiOffsetPixels = getAdjustedSystemUiOffsets(); |
+ float[] imagePoints = {0.0f, 0.0f, mRenderData.imageWidth, mRenderData.imageHeight}; |
+ mRenderData.transform.mapPoints(imagePoints); |
+ |
+ mImagePadding.set( |
+ adjustEdge(systemUiOffsetPixels.left, mImagePadding.left, |
+ imagePoints[0] - letterBoxPadding[0]), |
+ adjustEdge(systemUiOffsetPixels.top, mImagePadding.top, |
+ imagePoints[1] - letterBoxPadding[1]), |
+ adjustEdge(systemUiOffsetPixels.right, mImagePadding.right, |
+ mRenderData.screenWidth - imagePoints[2] - letterBoxPadding[0]), |
+ adjustEdge(systemUiOffsetPixels.bottom, mImagePadding.bottom, |
+ mRenderData.screenHeight - imagePoints[3] - letterBoxPadding[1])); |
+ } |
+ |
+ /** |
+ * Update the current edge padding based on the current System UI and image postion state. |
Lambros
2016/09/30 01:59:36
s/postion/position/
joedow
2016/09/30 19:42:56
Done.
|
+ * |
+ * @param systemUiPadding Amount of visible System UI in pixels. |
+ * @param currentPadding Amount of padding used, in pixels, for position calculations. |
+ * @param visiblePixels Amount of padding actually visible, in pixels. |
+ * @return The new value, in pixels, to be used for positioning. |
+ */ |
+ private float adjustEdge(float systemUiPadding, float currentPadding, float visiblePixels) { |
+ float edgeValue; |
+ visiblePixels = Math.max(visiblePixels, 0.0f); |
+ if (systemUiPadding > 0.0f) { |
+ if (systemUiPadding > currentPadding) { |
+ // Add enough padding to allow scrolling the desktop out from under the System UI. |
+ edgeValue = Math.min(systemUiPadding, visiblePixels); |
+ } else if (systemUiPadding < currentPadding) { |
+ // Remove unneeded padding from the canvas. |
+ edgeValue = Math.max(systemUiPadding, Math.min(currentPadding, visiblePixels)); |
+ } else { |
+ // If current and system padding sizes are the same, then keep the visible portion. |
+ edgeValue = Math.min(currentPadding, visiblePixels); |
+ } |
+ } else if (currentPadding > 0.0f) { |
+ // If we have existing padding, then trim if possible, otherwise keep the same value. |
+ edgeValue = Math.min(currentPadding, visiblePixels); |
+ } else { |
+ // Use zero padding if there is no system or current padding specified. |
+ edgeValue = 0.0f; |
+ } |
+ return edgeValue; |
} |
} |