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

Side by Side 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: Cleaning up some of the previous code. 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chromoting; 5 package org.chromium.chromoting;
6 6
7 import android.graphics.Matrix; 7 import android.graphics.Matrix;
8 import android.graphics.PointF; 8 import android.graphics.PointF;
9 import android.graphics.Rect; 9 import android.graphics.Rect;
10 import android.graphics.RectF; 10 import android.graphics.RectF;
11 11
12 /** 12 /**
13 * This class is responsible for transforming the desktop image matrix. 13 * This class is responsible for transforming the desktop image matrix.
14 */ 14 */
15 public class DesktopCanvas { 15 public class DesktopCanvas {
16 /** 16 /**
17 * Maximum allowed zoom level - see {@link #repositionImageWithZoom()}. 17 * Maximum allowed zoom level - see {@link #scaleAndRepositionImage()}.
18 */ 18 */
19 private static final float MAX_ZOOM_FACTOR = 100.0f; 19 private static final float MAX_ZOOM_FACTOR = 100.0f;
20 20
21 /**
22 * Used to smoothly reduce the amount of padding while the user is zooming.
23 */
24 private static final float PADDING_REDUCTION_FACTOR = 0.85f;
25
21 private final RenderStub mRenderStub; 26 private final RenderStub mRenderStub;
22 private final RenderData mRenderData; 27 private final RenderData mRenderData;
23 28
24 /** 29 /**
25 * Represents the actual center of the viewport. This value needs to be a p air of floats so the 30 * Represents the actual center of the viewport in image space. This value needs to be a pair
26 * desktop image can be positioned with sub-pixel accuracy for smoother pann ing animations at 31 * of floats so the desktop image can be positioned with sub-pixel accuracy for smoother panning
27 * high zoom levels. 32 * animations at high zoom levels.
28 */ 33 */
29 private PointF mViewportPosition = new PointF(); 34 private PointF mViewportPosition = new PointF();
Lambros 2016/10/04 22:06:35 Optional, not really part of this CL: Is there any
joedow 2016/10/04 23:32:11 This was more important before I rewrote the posit
30 35
31 /** 36 /**
32 * Represents the desired center of the viewport. This value may not repres ent the actual 37 * Represents the desired center of the viewport in image space. This value may not represent
Lambros 2016/10/04 22:06:35 Clarify that this position may extend beyond the b
joedow 2016/10/04 23:32:11 Done.
33 * center of the viewport as adjustments are made to ensure as much of the d esktop is visible as 38 * the actual center of the viewport as adjustments are made to ensure as mu ch of the desktop is
34 * possible. This value needs to be a pair of floats so the desktop image c an be positioned 39 * visible as possible. This value needs to be a pair of floats so the desk top image can be
35 * with sub-pixel accuracy for smoother panning animations at high zoom leve ls. 40 * positioned with sub-pixel accuracy for smoother panning animations at hig h zoom levels.
36 */ 41 */
37 private PointF mCursorPosition = new PointF(); 42 private PointF mCursorPosition = new PointF();
38 43
39 /** 44 /**
40 * Represents the amount of space, in pixels, used by System UI. 45 * Represents the amount of space, in pixels, used by System UI on each edge of the screen.
41 */ 46 */
42 private Rect mSystemUiOffsetPixels = new Rect(); 47 private Rect mSystemUiScreenSize = new Rect();
Lambros 2016/10/04 22:06:35 Now you've renamed this to remove 'offset', maybe
joedow 2016/10/04 23:32:11 Acknowledged. Added TODO.
48
49 /**
50 * Represents the amount of padding, in screen pixels, added to each edge of the desktop image.
51 * This extra space allows the user to reveal portions of the desktop image which are obscured
52 * by System UI.
53 */
54 private RectF mVisibleImagePadding = new RectF();
Lambros 2016/10/04 22:06:35 optional: Would be nice if you could remove this m
joedow 2016/10/04 23:32:11 Acknowledged.
43 55
44 public DesktopCanvas(RenderStub renderStub, RenderData renderData) { 56 public DesktopCanvas(RenderStub renderStub, RenderData renderData) {
45 mRenderStub = renderStub; 57 mRenderStub = renderStub;
46 mRenderData = renderData; 58 mRenderData = renderData;
47 } 59 }
48 60
49 /** 61 /**
50 * Sets the desired center position of the viewport (a.k.a. the cursor posit ion) and ensures 62 * Sets the desired center position of the viewport (a.k.a. the cursor posit ion) and ensures
51 * the viewport is updated to include the cursor within it. 63 * the viewport is updated to include the cursor within it.
52 * 64 *
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 109
98 /** 110 /**
99 * Sets the offset values used to calculate the space used by System UI. 111 * Sets the offset values used to calculate the space used by System UI.
100 * 112 *
101 * @param left The space used by System UI on the left edge of the screen. 113 * @param left The space used by System UI on the left edge of the screen.
102 * @param top The space used by System UI on the top edge of the screen. 114 * @param top The space used by System UI on the top edge of the screen.
103 * @param right The space used by System UI on the right edge of the screen. 115 * @param right The space used by System UI on the right edge of the screen.
104 * @param bottom The space used by System UI on the bottom edge of the scree n. 116 * @param bottom The space used by System UI on the bottom edge of the scree n.
105 */ 117 */
106 public void setSystemUiOffsetValues(int left, int top, int right, int bottom ) { 118 public void setSystemUiOffsetValues(int left, int top, int right, int bottom ) {
107 mSystemUiOffsetPixels.set(left, top, right, bottom); 119 mSystemUiScreenSize.set(left, top, right, bottom);
108 } 120 }
109 121
110 /** Called to indicate that no System UI is visible. */ 122 /** Called to indicate that no System UI is visible. */
111 public void clearSystemUiOffsets() { 123 public void clearSystemUiOffsets() {
112 mSystemUiOffsetPixels.setEmpty(); 124 mSystemUiScreenSize.setEmpty();
113 } 125 }
114 126
115 /** Resizes the image by zooming it such that the image is displayed without borders. */ 127 /** Resizes the image by zooming it such that the image is displayed without borders. */
116 public void resizeImageToFitScreen() { 128 public void resizeImageToFitScreen() {
117 // Protect against being called before the image has been initialized. 129 // Protect against being called before the image has been initialized.
118 if (mRenderData.imageWidth == 0 || mRenderData.imageHeight == 0) { 130 if (mRenderData.imageWidth == 0 || mRenderData.imageHeight == 0) {
119 return; 131 return;
120 } 132 }
121 133
122 float widthRatio = (float) mRenderData.screenWidth / mRenderData.imageWi dth; 134 float widthRatio = (float) mRenderData.screenWidth / mRenderData.imageWi dth;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 mRenderData.transform.mapVectors(imageSize); 174 mRenderData.transform.mapVectors(imageSize);
163 175
164 if (imageSize[0] < mRenderData.screenWidth && imageSize[1] < mRenderData .screenHeight) { 176 if (imageSize[0] < mRenderData.screenWidth && imageSize[1] < mRenderData .screenHeight) {
165 // Displayed image is too small in both directions, so apply the min imum zoom 177 // Displayed image is too small in both directions, so apply the min imum zoom
166 // level needed to fit either the width or height. 178 // level needed to fit either the width or height.
167 float scale = Math.min((float) mRenderData.screenWidth / mRenderData .imageWidth, 179 float scale = Math.min((float) mRenderData.screenWidth / mRenderData .imageWidth,
168 (float) mRenderData.screenHeight / mRenderDat a.imageHeight); 180 (float) mRenderData.screenHeight / mRenderDat a.imageHeight);
169 mRenderData.transform.setScale(scale, scale); 181 mRenderData.transform.setScale(scale, scale);
170 } 182 }
171 183
184 // Trim the image padding if the user is zooming out. This prevents cas es where the image
185 // pops to the center when it reaches its minimum size. Note that we do not need to do
186 // anything when the user is zooming in as the canvas will expand and ab sorb the padding.
187 if (scaleFactor < 1.0f) {
188 mVisibleImagePadding.set(mVisibleImagePadding.left * PADDING_REDUCTI ON_FACTOR,
189 mVisibleImagePadding.top * PADDING_REDUCTION_FACTOR,
190 mVisibleImagePadding.right * PADDING_REDUCTION_FACTOR,
191 mVisibleImagePadding.bottom * PADDING_REDUCTION_FACTOR);
192 }
193
172 if (centerOnCursor) { 194 if (centerOnCursor) {
173 setCursorPosition(mCursorPosition.x, mCursorPosition.y); 195 setCursorPosition(mCursorPosition.x, mCursorPosition.y);
174 } else { 196 } else {
175 // Find the new screen center (it was probably changed during the zo om operation) and 197 // Find the new screen center (it was probably changed during the zo om operation) and
176 // update the viewport and cursor. 198 // update the viewport and cursor.
177 float[] mappedPoints = { 199 float[] mappedPoints = {
178 ((float) mRenderData.screenWidth / 2), ((float) mRenderData. screenHeight / 2)}; 200 ((float) mRenderData.screenWidth / 2), ((float) mRenderData. screenHeight / 2)};
179 Matrix screenToImage = new Matrix(); 201 Matrix screenToImage = new Matrix();
180 mRenderData.transform.invert(screenToImage); 202 mRenderData.transform.invert(screenToImage);
181 screenToImage.mapPoints(mappedPoints); 203 screenToImage.mapPoints(mappedPoints);
182 // The cursor is mapped to the center of the viewport in this case. 204 // The cursor is mapped to the center of the viewport in this case.
183 setCursorPosition(mappedPoints[0], mappedPoints[1]); 205 setCursorPosition(mappedPoints[0], mappedPoints[1]);
184 } 206 }
185 } 207 }
186 208
187 /** 209 /**
188 * Repositions the image by translating it (without affecting the zoom level ). 210 * Repositions the image by translating it (without affecting the zoom level ).
189 */ 211 */
190 private void repositionImage() { 212 private void repositionImage() {
191 // Map the current viewport position to screen coordinates and adjust th e image position. 213 // Map the current viewport position to screen coordinates and adjust th e image position.
192 float[] viewportPosition = {mViewportPosition.x, mViewportPosition.y}; 214 float[] viewportPosition = {mViewportPosition.x, mViewportPosition.y};
193 mRenderData.transform.mapPoints(viewportPosition); 215 mRenderData.transform.mapPoints(viewportPosition);
194 216
195 float viewportTransX = ((float) mRenderData.screenWidth / 2) - viewportP osition[0]; 217 float viewportTransX = ((float) mRenderData.screenWidth / 2) - viewportP osition[0];
196 float viewportTransY = ((float) mRenderData.screenHeight / 2) - viewport Position[1]; 218 float viewportTransY = ((float) mRenderData.screenHeight / 2) - viewport Position[1];
197 219
198 // Translate the image so the viewport center is displayed in the middle of the screen. 220 // Translate the image so the viewport center is displayed in the middle of the screen.
199 mRenderData.transform.postTranslate(viewportTransX, viewportTransY); 221 mRenderData.transform.postTranslate(viewportTransX, viewportTransY);
200 222
223 updateVisibleImagePadding();
224
201 mRenderStub.setTransformation(mRenderData.transform); 225 mRenderStub.setTransformation(mRenderData.transform);
202 } 226 }
203 227
204 /** 228 /**
205 * Updates the given point such that it refers to a coordinate within the bo unds provided. 229 * Updates the given point such that it refers to a coordinate within the bo unds provided.
206 * 230 *
207 * @param point The point to adjust, the original object is modified. 231 * @param point The point to adjust, the original object is modified.
208 * @param bounds The bounds used to constrain the point. 232 * @param bounds The bounds used to constrain the point.
209 */ 233 */
210 private void constrainPointToBounds(PointF point, RectF bounds) { 234 private void constrainPointToBounds(PointF point, RectF bounds) {
211 if (point.x < bounds.left) { 235 if (point.x < bounds.left) {
212 point.x = bounds.left; 236 point.x = bounds.left;
213 } else if (point.x > bounds.right) { 237 } else if (point.x > bounds.right) {
214 point.x = bounds.right; 238 point.x = bounds.right;
215 } 239 }
216 240
217 if (point.y < bounds.top) { 241 if (point.y < bounds.top) {
218 point.y = bounds.top; 242 point.y = bounds.top;
219 } else if (point.y > bounds.bottom) { 243 } else if (point.y > bounds.bottom) {
220 point.y = bounds.bottom; 244 point.y = bounds.bottom;
221 } 245 }
222 } 246 }
223 247
224 /** Returns a region which defines the set of valid cursor values in image s pace. */ 248 /** Returns a region which defines the set of valid cursor positions in imag e space. */
225 private RectF getImageBounds() { 249 private RectF getImageBounds() {
226 return new RectF(0, 0, mRenderData.imageWidth, mRenderData.imageHeight); 250 // The set of valid cursor positions includes any point on the image as well as the padding.
251 // Padding is additional space added to the image which is the larger va lue of:
252 // - Potential overlap of the System UI and image content
253 // - Actual amount of padding already being used
254 //
255 // By expanding the area, we allow the user to move the cursor 'under' t he System UI which
256 // pulls the content out from under it and allows it to be visible. Onc e the System UI has
257 // been dismissed or changes size, we use the actual padding value inste ad which prevents
258 // the desktop image from 'snapping' back to pre-System UI state.
259 RectF systemUiOverlap = getSystemUiOverlap();
260 float[] padding = {Math.max(mVisibleImagePadding.left, systemUiOverlap.l eft),
261 Math.max(mVisibleImagePadding.top, systemUiOverlap.top),
262 Math.max(mVisibleImagePadding.right, systemUiOverlap.right),
263 Math.max(mVisibleImagePadding.bottom, systemUiOverlap.bottom)};
264 Matrix screenToImage = new Matrix();
265 mRenderData.transform.invert(screenToImage);
266 screenToImage.mapVectors(padding);
267
268 return new RectF(-padding[0], -padding[1], mRenderData.imageWidth + padd ing[2],
269 mRenderData.imageHeight + padding[3]);
227 } 270 }
228 271
229 /** Returns a region which defines the set of valid viewport center values i n image space. */ 272 /** Returns a region which defines the set of valid viewport center values i n image space. */
230 private RectF getViewportBounds() { 273 private RectF getViewportBounds() {
231 float[] screenVectors = {(float) mRenderData.screenWidth, (float) mRende rData.screenHeight}; 274 // The region of allowable viewport values is the imageBound rect, inset by the size of the
275 // viewport itself. This prevent over and under panning of the viewport while still
Lambros 2016/10/04 22:06:35 prevents
joedow 2016/10/04 23:32:11 Done.
276 // allowing the user to see and interact with all pixels one the desktop image.
232 Matrix screenToImage = new Matrix(); 277 Matrix screenToImage = new Matrix();
233 mRenderData.transform.invert(screenToImage); 278 mRenderData.transform.invert(screenToImage);
279
280 float[] screenVectors = {(float) mRenderData.screenWidth, (float) mRende rData.screenHeight};
234 screenToImage.mapVectors(screenVectors); 281 screenToImage.mapVectors(screenVectors);
235 282
236 float xAdjust = 0.0f; 283 PointF letterboxPadding = getLetterboxPadding();
237 if (mRenderData.imageWidth < screenVectors[0]) { 284 float[] letterboxPaddingVectors = {letterboxPadding.x, letterboxPadding. y};
238 // Image is narrower than the screen, so adjust the bounds to center it. 285 screenToImage.mapVectors(letterboxPaddingVectors);
239 xAdjust = (screenVectors[0] - mRenderData.imageWidth) / 2.0f;
240 }
241
242 float yAdjust = 0.0f;
243 if (mRenderData.imageHeight < screenVectors[1]) {
244 // Image is shorter than the screen, so adjust the bounds to center it.
245 yAdjust = (screenVectors[1] - mRenderData.imageHeight) / 2.0f;
246 }
247 286
248 // screenCenter values are 1/2 of a particular screen dimension mapped t o image space. 287 // screenCenter values are 1/2 of a particular screen dimension mapped t o image space.
249 float screenCenterX = screenVectors[0] / 2.0f; 288 float screenCenterX = (screenVectors[0] / 2.0f) - letterboxPaddingVector s[0];
250 float screenCenterY = screenVectors[1] / 2.0f; 289 float screenCenterY = (screenVectors[1] / 2.0f) - letterboxPaddingVector s[1];
251 return new RectF(screenCenterX - xAdjust, screenCenterY - yAdjust, 290 RectF imageBounds = getImageBounds();
252 mRenderData.imageWidth - screenCenterX + xAdjust, 291 imageBounds.inset(screenCenterX, screenCenterY);
253 mRenderData.imageHeight - screenCenterY + yAdjust); 292 return imageBounds;
293 }
294
295 /**
296 * Provides the amount of padding needed to center the image content on the screen.
297 */
298 private PointF getLetterboxPadding() {
299 float[] imageVectors = {mRenderData.imageWidth, mRenderData.imageHeight} ;
300 mRenderData.transform.mapVectors(imageVectors);
301
302 // We want to letterbox when the image is smaller than the screen in a s pecific dimension.
303 // Since we center the image, split the difference so it is equally dist ributed.
304 float widthAdjust =
305 Math.max(((float) mRenderData.screenWidth - imageVectors[0]) / 2 .0f, 0.0f);
306 float heightAdjust =
307 Math.max(((float) mRenderData.screenHeight - imageVectors[1]) / 2.0f, 0.0f);
308
309 return new PointF(widthAdjust, heightAdjust);
310 }
311
312 /**
313 * Returns the amount of System UI along each edge of the screen which could overlap the remote
314 * desktop image below it. This is the maximum amount that could overlap, n ot the actual value.
315 */
316 private RectF getSystemUiOverlap() {
317 // letterBox padding represents the space added to the image to center i t on the screen.
318 // Since it does not contain any interactable UI, we ignore it when calc ulating the overlap
319 // between the System UI and the remote desktop image.
320 // Note: Ignore negative padding (clamp to 0) since that means no overla p exists.
321 PointF letterboxPadding = getLetterboxPadding();
322 return new RectF(Math.max(mSystemUiScreenSize.left - letterboxPadding.x, 0.0f),
323 Math.max(mSystemUiScreenSize.top - letterboxPadding.y, 0.0f),
324 Math.max(mSystemUiScreenSize.right - letterboxPadding.x, 0.0f),
325 Math.max(mSystemUiScreenSize.bottom - letterboxPadding.y, 0.0f)) ;
326 }
327
328 /**
329 * Calculates the amount of padding visible on each edge of the desktop imag e.
330 */
331 private void updateVisibleImagePadding() {
332 PointF letterboxPadding = getLetterboxPadding();
333 float[] imagePoints = {0.0f, 0.0f, mRenderData.imageWidth, mRenderData.i mageHeight};
334 mRenderData.transform.mapPoints(imagePoints);
335
336 mVisibleImagePadding.set(Math.max(imagePoints[0] - letterboxPadding.x, 0 .0f),
337 Math.max(imagePoints[1] - letterboxPadding.y, 0.0f),
338 Math.max(mRenderData.screenWidth - imagePoints[2] - letterboxPad ding.x, 0.0f),
339 Math.max(mRenderData.screenHeight - imagePoints[3] - letterboxPa dding.y, 0.0f));
254 } 340 }
255 } 341 }
OLDNEW
« 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