Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Unified Diff: remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java

Issue 2375113003: Allow Desktop Canvas to be scrolled out from under System UI. (Closed)
Patch Set: Addressing CR feedback Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..778c395267e875f75548e8ff8aa6acc33aa484e0 100644
--- a/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java
+++ b/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java
@@ -14,32 +14,49 @@ import android.graphics.RectF;
*/
public class DesktopCanvas {
/**
- * Maximum allowed zoom level - see {@link #repositionImageWithZoom()}.
+ * Maximum allowed zoom level - see {@link #scaleAndRepositionImage()}.
*/
private static final float MAX_ZOOM_FACTOR = 100.0f;
+ /**
+ * Used to smoothly reduce the amount of padding while the user is zooming.
+ */
+ private static final float PADDING_REDUCTION_FACTOR = 0.85f;
+
private final RenderStub mRenderStub;
private final RenderData mRenderData;
/**
- * Represents the actual center of the viewport. This value needs to be a pair of floats so the
- * desktop image can be positioned with sub-pixel accuracy for smoother panning animations at
- * high zoom levels.
+ * Represents the actual center of the viewport in image space. This value needs to be a pair
+ * of floats so the desktop image can be positioned with sub-pixel accuracy for smoother panning
+ * animations at high zoom levels.
*/
+ // TODO(joedow): See if we can collapse Viewport and Cursor position members. They were needed
+ // in the past due to how we calculated the center positions but may not be needed now.
private PointF mViewportPosition = new PointF();
/**
- * Represents the desired center of the viewport. This value may not represent the actual
- * center of the viewport as adjustments are made to ensure as much of the desktop is visible as
- * possible. This value needs to be a pair of floats so the desktop image can be positioned
- * with sub-pixel accuracy for smoother panning animations at high zoom levels.
+ * Represents the desired center of the viewport in image space. This value may not represent
+ * the actual center of the viewport as adjustments are made to ensure as much of the desktop is
+ * visible as possible. This value needs to be a pair of floats so the desktop image can be
+ * positioned with sub-pixel accuracy for smoother panning animations at high zoom levels.
+ * Note: The internal cursor position may be placed outside of the image boundary, however the
+ * cursor position we inject on the host side is restricted to the actual image dimensions.
*/
private PointF mCursorPosition = new PointF();
/**
- * Represents the amount of space, in pixels, used by System UI.
+ * Represents the amount of space, in pixels, used by System UI on each edge of the screen.
+ */
+ // TODO(joedow): Update usage of this member so it is a true Rect instead of a set of offsets.
+ private Rect mSystemUiScreenSize = new Rect();
+
+ /**
+ * Represents the amount of padding, in screen pixels, added to each edge of the desktop image.
+ * This extra space allows the user to reveal portions of the desktop image which are obscured
+ * by System UI.
*/
- private Rect mSystemUiOffsetPixels = new Rect();
+ private RectF mVisibleImagePadding = new RectF();
public DesktopCanvas(RenderStub renderStub, RenderData renderData) {
mRenderStub = renderStub;
@@ -104,12 +121,12 @@ public class DesktopCanvas {
* @param bottom The space used by System UI on the bottom edge of the screen.
*/
public void setSystemUiOffsetValues(int left, int top, int right, int bottom) {
- mSystemUiOffsetPixels.set(left, top, right, bottom);
+ mSystemUiScreenSize.set(left, top, right, bottom);
}
/** Called to indicate that no System UI is visible. */
public void clearSystemUiOffsets() {
- mSystemUiOffsetPixels.setEmpty();
+ mSystemUiScreenSize.setEmpty();
}
/** Resizes the image by zooming it such that the image is displayed without borders. */
@@ -169,6 +186,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) {
+ mVisibleImagePadding.set(mVisibleImagePadding.left * PADDING_REDUCTION_FACTOR,
+ mVisibleImagePadding.top * PADDING_REDUCTION_FACTOR,
+ mVisibleImagePadding.right * PADDING_REDUCTION_FACTOR,
+ mVisibleImagePadding.bottom * PADDING_REDUCTION_FACTOR);
+ }
+
if (centerOnCursor) {
setCursorPosition(mCursorPosition.x, mCursorPosition.y);
} else {
@@ -198,6 +225,8 @@ public class DesktopCanvas {
// Translate the image so the viewport center is displayed in the middle of the screen.
mRenderData.transform.postTranslate(viewportTransX, viewportTransY);
+ updateVisibleImagePadding();
+
mRenderStub.setTransformation(mRenderData.transform);
}
@@ -221,35 +250,97 @@ public class DesktopCanvas {
}
}
- /** Returns a region which defines the set of valid cursor values in image space. */
+ /** Returns a region which defines the set of valid cursor positions in image space. */
private RectF getImageBounds() {
- return new RectF(0, 0, mRenderData.imageWidth, mRenderData.imageHeight);
+ // The set of valid cursor positions includes any point on the image as well as the padding.
+ // Padding is additional space added to the image which is the larger value of:
+ // - Potential overlap of the System UI and image content
+ // - Actual amount of padding already being used
+ //
+ // By expanding the area, we allow the user to move the cursor 'under' the System UI which
+ // pulls the content out from under it and allows it to be visible. Once the System UI has
+ // been dismissed or changes size, we use the actual padding value instead which prevents
+ // the desktop image from 'snapping' back to pre-System UI state.
+ RectF systemUiOverlap = getSystemUiOverlap();
+ float[] padding = {Math.max(mVisibleImagePadding.left, systemUiOverlap.left),
+ Math.max(mVisibleImagePadding.top, systemUiOverlap.top),
+ Math.max(mVisibleImagePadding.right, systemUiOverlap.right),
+ Math.max(mVisibleImagePadding.bottom, systemUiOverlap.bottom)};
+ Matrix screenToImage = new Matrix();
+ mRenderData.transform.invert(screenToImage);
+ screenToImage.mapVectors(padding);
+
+ return new RectF(-padding[0], -padding[1], mRenderData.imageWidth + padding[2],
+ mRenderData.imageHeight + padding[3]);
}
/** Returns a region which defines the set of valid viewport center values in image space. */
private RectF getViewportBounds() {
- float[] screenVectors = {(float) mRenderData.screenWidth, (float) mRenderData.screenHeight};
+ // The region of allowable viewport values is the imageBound rect, inset by the size of the
+ // viewport itself. This prevents over and under panning of the viewport while still
+ // allowing the user to see and interact with all pixels one the desktop image.
Matrix screenToImage = new Matrix();
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[] screenVectors = {(float) mRenderData.screenWidth, (float) mRenderData.screenHeight};
+ screenToImage.mapVectors(screenVectors);
- 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;
- }
+ PointF letterboxPadding = getLetterboxPadding();
+ float[] letterboxPaddingVectors = {letterboxPadding.x, letterboxPadding.y};
+ screenToImage.mapVectors(letterboxPaddingVectors);
// 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) - letterboxPaddingVectors[0];
+ float screenCenterY = (screenVectors[1] / 2.0f) - letterboxPaddingVectors[1];
+ RectF imageBounds = getImageBounds();
+ imageBounds.inset(screenCenterX, screenCenterY);
+ return imageBounds;
+ }
+
+ /**
+ * Provides the amount of padding needed to center the image content on the screen.
+ */
+ private PointF getLetterboxPadding() {
+ 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(((float) mRenderData.screenWidth - imageVectors[0]) / 2.0f, 0.0f);
+ float heightAdjust =
+ Math.max(((float) mRenderData.screenHeight - imageVectors[1]) / 2.0f, 0.0f);
+
+ return new PointF(widthAdjust, heightAdjust);
+ }
+
+ /**
+ * Returns the amount of System UI along each edge of the screen which could overlap the remote
+ * desktop image below it. This is the maximum amount that could overlap, not the actual value.
+ */
+ private RectF getSystemUiOverlap() {
+ // letterBox padding represents the space added to the image to center it on the screen.
+ // Since it does not contain any interactable UI, we ignore it when calculating the overlap
+ // between the System UI and the remote desktop image.
+ // Note: Ignore negative padding (clamp to 0) since that means no overlap exists.
+ PointF letterboxPadding = getLetterboxPadding();
+ return new RectF(Math.max(mSystemUiScreenSize.left - letterboxPadding.x, 0.0f),
+ Math.max(mSystemUiScreenSize.top - letterboxPadding.y, 0.0f),
+ Math.max(mSystemUiScreenSize.right - letterboxPadding.x, 0.0f),
+ Math.max(mSystemUiScreenSize.bottom - letterboxPadding.y, 0.0f));
+ }
+
+ /**
+ * Calculates the amount of padding visible on each edge of the desktop image.
+ */
+ private void updateVisibleImagePadding() {
+ PointF letterboxPadding = getLetterboxPadding();
+ float[] imagePoints = {0.0f, 0.0f, mRenderData.imageWidth, mRenderData.imageHeight};
+ mRenderData.transform.mapPoints(imagePoints);
+
+ mVisibleImagePadding.set(Math.max(imagePoints[0] - letterboxPadding.x, 0.0f),
+ Math.max(imagePoints[1] - letterboxPadding.y, 0.0f),
+ Math.max(mRenderData.screenWidth - imagePoints[2] - letterboxPadding.x, 0.0f),
+ Math.max(mRenderData.screenHeight - imagePoints[3] - letterboxPadding.y, 0.0f));
}
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698