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

Side by Side Diff: remoting/android/java/src/org/chromium/chromoting/DesktopView.java

Issue 19482019: Change Android client desktop panning and zooming behavior (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rescale/recenter after device rotation, clarify comments Created 7 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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.content.Context; 7 import android.content.Context;
8 import android.graphics.Bitmap; 8 import android.graphics.Bitmap;
9 import android.graphics.Canvas; 9 import android.graphics.Canvas;
10 import android.graphics.Color; 10 import android.graphics.Color;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 50
51 /** Stores pan and zoom configuration and converts image coordinates to scre en coordinates. */ 51 /** Stores pan and zoom configuration and converts image coordinates to scre en coordinates. */
52 private Matrix mTransform; 52 private Matrix mTransform;
53 53
54 private int mScreenWidth; 54 private int mScreenWidth;
55 private int mScreenHeight; 55 private int mScreenHeight;
56 56
57 /** Specifies the dimension by which the zoom level is being lower-bounded. */ 57 /** Specifies the dimension by which the zoom level is being lower-bounded. */
58 private Constraint mConstraint; 58 private Constraint mConstraint;
59 59
60 /** Whether the right edge of the image was visible on-screen during the las t render. */
61 private boolean mRightUsedToBeOut;
62
63 /** Whether the bottom edge of the image was visible on-screen during the la st render. */
64 private boolean mBottomUsedToBeOut;
65
60 /** Whether the device has just been rotated, necessitating a canvas redraw. */ 66 /** Whether the device has just been rotated, necessitating a canvas redraw. */
61 private boolean mJustRotated; 67 private boolean mJustRotated;
62 68
63 public DesktopView(Context context) { 69 public DesktopView(Context context) {
64 super(context); 70 super(context);
65 getHolder().addCallback(this); 71 getHolder().addCallback(this);
66 DesktopListener listener = new DesktopListener(); 72 DesktopListener listener = new DesktopListener();
67 mScroller = new GestureDetector(context, listener); 73 mScroller = new GestureDetector(context, listener);
68 mZoomer = new ScaleGestureDetector(context, listener); 74 mZoomer = new ScaleGestureDetector(context, listener);
69 75
70 mTransform = new Matrix(); 76 mTransform = new Matrix();
71 mScreenWidth = 0; 77 mScreenWidth = 0;
72 mScreenHeight = 0; 78 mScreenHeight = 0;
73 mConstraint = Constraint.UNDEFINED; 79 mConstraint = Constraint.UNDEFINED;
80
81 mRightUsedToBeOut = false;
82 mBottomUsedToBeOut = false;
83
84 mJustRotated = false;
74 } 85 }
75 86
76 /** 87 /**
77 * Redraws the canvas. This should be done on a non-UI thread or it could 88 * Redraws the canvas. This should be done on a non-UI thread or it could
78 * cause the UI to lag. Specifically, it is currently invoked on the native 89 * cause the UI to lag. Specifically, it is currently invoked on the native
79 * graphics thread using a JNI. 90 * graphics thread using a JNI.
80 */ 91 */
81 @Override 92 @Override
82 public void run() { 93 public void run() {
83 if (Looper.myLooper()==Looper.getMainLooper()) { 94 if (Looper.myLooper() == Looper.getMainLooper()) {
84 Log.w("deskview", "Canvas being redrawn on UI thread"); 95 Log.w("deskview", "Canvas being redrawn on UI thread");
85 } 96 }
86 97
98 Bitmap image = JniInterface.retrieveVideoFrame();
87 Canvas canvas = getHolder().lockCanvas(); 99 Canvas canvas = getHolder().lockCanvas();
88 Bitmap image = JniInterface.retrieveVideoFrame();
89 synchronized (mTransform) { 100 synchronized (mTransform) {
90 canvas.setMatrix(mTransform); 101 canvas.setMatrix(mTransform);
91 102
103 // Internal parameters of the transformation matrix.
92 float[] values = new float[9]; 104 float[] values = new float[9];
93 mTransform.getValues(values); 105 mTransform.getValues(values);
106
107 // Screen coordinates of two defining points of the image.
94 float[] topleft = {0, 0}; 108 float[] topleft = {0, 0};
95 mTransform.mapPoints(topleft); 109 mTransform.mapPoints(topleft);
96 float[] bottomright = {image.getWidth(), image.getHeight()}; 110 float[] bottomright = {image.getWidth(), image.getHeight()};
97 mTransform.mapPoints(bottomright); 111 mTransform.mapPoints(bottomright);
98 112
99 if (mConstraint==Constraint.UNDEFINED) { 113 // Whether to rescale and recenter the view.
114 boolean recenter = false;
115
116 if (mConstraint == Constraint.UNDEFINED) {
100 mConstraint = image.getWidth()/image.getHeight() > mScreenWidth/ mScreenHeight ? 117 mConstraint = image.getWidth()/image.getHeight() > mScreenWidth/ mScreenHeight ?
101 Constraint.HEIGHT : Constraint.WIDTH; 118 Constraint.WIDTH : Constraint.HEIGHT;
119 recenter = true; // We always rescale and recenter after a rota tion.
102 } 120 }
103 121
104 if (mConstraint==Constraint.WIDTH && bottomright[0] - topleft[0] < m ScreenWidth) { 122 if (mConstraint == Constraint.WIDTH &&
105 mTransform.setPolyToPoly(new float[] {0, 0, image.getWidth(), 0} , 0, 123 ((int)(bottomright[0] - topleft[0] + 0.5) < mScreenWidth || recenter)) {
106 new float[] {0, 0, mScreenWidth, 0}, 0, 2); 124 // The vertical edges of the image are flush against the device' s screen edges
107 } else if (mConstraint==Constraint.HEIGHT && 125 // when the entire host screen is visible, and the user has zoom ed out too far.
108 bottomright[1] - topleft[1] < mScreenHeight) { 126 float imageMiddle = (float)image.getHeight() / 2;
109 mTransform.setPolyToPoly(new float[] {0, 0, 0, image.getHeight() }, 0, 127 float screenMiddle = (float)mScreenHeight / 2;
110 new float[] {0, 0, 0, mScreenHeight}, 0, 2); 128 mTransform.setPolyToPoly(
129 new float[] {0, imageMiddle, image.getWidth(), imageMidd le}, 0,
130 new float[] {0, screenMiddle, mScreenWidth, screenMiddle }, 0, 2);
131 } else if (mConstraint == Constraint.HEIGHT &&
132 ((int)(bottomright[1] - topleft[1] + 0.5) < mScreenHeight || recenter)) {
133 // The horizontal image edges are flush against the device's scr een edges when
134 // the entire host screen is visible, and the user has zoomed ou t too far.
135 float imageCenter = (float)image.getWidth() / 2;
136 float screenCenter = (float)mScreenWidth / 2;
137 mTransform.setPolyToPoly(
138 new float[] {imageCenter, 0, imageCenter, image.getHeigh t()}, 0,
139 new float[] {screenCenter, 0, screenCenter, mScreenHeigh t}, 0, 2);
111 } else { 140 } else {
112 if (values[Matrix.MTRANS_X] > 0) { 141 // It's fine for both members of a pair of image edges to be wit hin the screen
113 values[Matrix.MTRANS_X] = 0; 142 // edges (or "out of bounds"); that simply means that the image is zoomed out as
143 // far as permissible. And both members of a pair can obviously be outside the
144 // screen's edges, which indicates that the image is zoomed in t o far to see the
145 // whole host screen. However, if only one of a pair of edges ha s entered the
146 // screen, the user is attempting to scroll into a blank area of the canvas.
147
148 // A value of true means the corresponding edge has entered the screen's borders.
149 boolean leftEdgeOutOfBounds = values[Matrix.MTRANS_X] > 0;
150 boolean topEdgeOutOfBounds = values[Matrix.MTRANS_Y] > 0;
151 boolean rightEdgeOutOfBounds = bottomright[0] < mScreenWidth;
152 boolean bottomEdgeOutOfBounds = bottomright[1] < mScreenHeight;
153
154 if (leftEdgeOutOfBounds != rightEdgeOutOfBounds) {
155 if (leftEdgeOutOfBounds != mRightUsedToBeOut) {
156 values[Matrix.MTRANS_X] = 0;
157 }
158 else {
159 values[Matrix.MTRANS_X] += mScreenWidth - bottomright[0] ;
160 }
114 } 161 }
115 if (values[Matrix.MTRANS_Y] > 0) { 162 else { // The view would oscillate if this were updated while s crolling off-screen.
116 values[Matrix.MTRANS_Y] = 0; 163 mRightUsedToBeOut = rightEdgeOutOfBounds;
117 } 164 }
118 if (bottomright[0] < mScreenWidth) { 165
119 values[Matrix.MTRANS_X] += mScreenWidth - bottomright[0]; 166 if (topEdgeOutOfBounds != bottomEdgeOutOfBounds) {
167 if (topEdgeOutOfBounds != mBottomUsedToBeOut) {
168 values[Matrix.MTRANS_Y] = 0;
169 }
170 else {
171 values[Matrix.MTRANS_Y] += mScreenHeight - bottomright[1 ];
172 }
120 } 173 }
121 if (bottomright[1] < mScreenHeight) { 174 else { // The view would oscillate if this were updated while s crolling off-screen.
122 values[Matrix.MTRANS_Y] += mScreenHeight - bottomright[1]; 175 mBottomUsedToBeOut = bottomEdgeOutOfBounds;
123 } 176 }
124 177
125 mTransform.setValues(values); 178 mTransform.setValues(values);
126 } 179 }
127 180
128 canvas.setMatrix(mTransform); 181 canvas.setMatrix(mTransform);
129 } 182 }
130 183
131 canvas.drawColor(Color.BLACK); 184 canvas.drawColor(Color.BLACK);
132 canvas.drawBitmap(image, 0, 0, new Paint()); 185 canvas.drawBitmap(image, 0, 0, new Paint());
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 283
231 /** 284 /**
232 * Called when the user is done zooming. Defers to onScale()'s judgement . 285 * Called when the user is done zooming. Defers to onScale()'s judgement .
233 */ 286 */
234 @Override 287 @Override
235 public void onScaleEnd(ScaleGestureDetector detector) { 288 public void onScaleEnd(ScaleGestureDetector detector) {
236 onScale(detector); 289 onScale(detector);
237 } 290 }
238 } 291 }
239 } 292 }
OLDNEW
« no previous file with comments | « no previous file | remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698