OLD | NEW |
---|---|
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 Loading... | |
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 if (mConstraint == Constraint.UNDEFINED) { |
100 mConstraint = image.getWidth()/image.getHeight() > mScreenWidth/ mScreenHeight ? | 114 mConstraint = image.getWidth()/image.getHeight() > mScreenWidth/ mScreenHeight ? |
101 Constraint.HEIGHT : Constraint.WIDTH; | 115 Constraint.WIDTH : Constraint.HEIGHT; |
102 } | 116 } |
103 | 117 |
104 if (mConstraint==Constraint.WIDTH && bottomright[0] - topleft[0] < m ScreenWidth) { | 118 if (mConstraint == Constraint.WIDTH && |
105 mTransform.setPolyToPoly(new float[] {0, 0, image.getWidth(), 0} , 0, | 119 (int)(bottomright[0] - topleft[0] + 0.5) < mScreenWidth) { |
106 new float[] {0, 0, mScreenWidth, 0}, 0, 2); | 120 // The vertical edges of the image are flush against the dev ice's screen edges |
107 } else if (mConstraint==Constraint.HEIGHT && | 121 // when the entire host screen is visible, and the user has zoomed out too far. |
108 bottomright[1] - topleft[1] < mScreenHeight) { | 122 float imageMiddle = (float)image.getHeight() / 2; |
109 mTransform.setPolyToPoly(new float[] {0, 0, 0, image.getHeight() }, 0, | 123 float screenMiddle = (float)mScreenHeight / 2; |
110 new float[] {0, 0, 0, mScreenHeight}, 0, 2); | 124 mTransform.setPolyToPoly( |
125 new float[] {0, imageMiddle, image.getWidth(), imageMidd le}, 0, | |
126 new float[] {0, screenMiddle, mScreenWidth, screenMiddle }, 0, 2); | |
127 } else if (mConstraint == Constraint.HEIGHT && | |
128 (int)(bottomright[1] - topleft[1] + 0.5) < mScreenHeight) { | |
129 // The horizontal image edges are flush against the device's screen edges when | |
130 // the entire host screen is visible, and the user has zoome d out too far. | |
131 float imageCenter = (float)image.getWidth() / 2; | |
132 float screenCenter = (float)mScreenWidth / 2; | |
133 mTransform.setPolyToPoly( | |
134 new float[] {imageCenter, 0, imageCenter, image.getHeigh t()}, 0, | |
135 new float[] {screenCenter, 0, screenCenter, mScreenHeigh t}, 0, 2); | |
111 } else { | 136 } else { |
112 if (values[Matrix.MTRANS_X] > 0) { | 137 // It's fine for both members of a pair of image edges to be within the screen |
113 values[Matrix.MTRANS_X] = 0; | 138 // edges (or "out of bounds"); that simply means that the im age is zoomed out as |
139 // far as permissible. And both members of a pair can obviou sly be outside the | |
140 // screen's edges, which indicates that the image is zoomed in to far to see the | |
141 // whole host screen. However, if only one of a pair of edge s has entered the | |
142 // screen, the user is attempting to scroll into a blank are a of the canvas. | |
garykac
2013/07/20 21:10:44
These comments (here and above) seem indented stra
solb
2013/07/21 08:18:07
Okay; I'll bump them out one level.
| |
143 // A value of true means the corresponding edge has entered the screen's borders. | |
144 boolean leftEdgeOutOfBounds = values[Matrix.MTRANS_X] > 0; | |
145 boolean topEdgeOutOfBounds = values[Matrix.MTRANS_Y] > 0; | |
146 boolean rightEdgeOutOfBounds = bottomright[0] < mScreenWidth; | |
147 boolean bottomEdgeOutOfBounds = bottomright[1] < mScreenHeight; | |
148 | |
149 if (leftEdgeOutOfBounds != rightEdgeOutOfBounds) { | |
150 if (leftEdgeOutOfBounds != mRightUsedToBeOut) { | |
151 values[Matrix.MTRANS_X] = 0; | |
152 } | |
153 else { | |
154 values[Matrix.MTRANS_X] += mScreenWidth - bottomright[0] ; | |
155 } | |
114 } | 156 } |
115 if (values[Matrix.MTRANS_Y] > 0) { | 157 else { // Updating this value during an attempt to scroll away causes oscillation. |
garykac
2013/07/20 21:10:44
If these comments apply to the line below, then th
solb
2013/07/21 08:18:07
Actually, this comment was intended to explain the
| |
116 values[Matrix.MTRANS_Y] = 0; | 158 mRightUsedToBeOut = rightEdgeOutOfBounds; |
117 } | 159 } |
118 if (bottomright[0] < mScreenWidth) { | 160 |
119 values[Matrix.MTRANS_X] += mScreenWidth - bottomright[0]; | 161 if (topEdgeOutOfBounds != bottomEdgeOutOfBounds) { |
162 if (topEdgeOutOfBounds != mBottomUsedToBeOut) { | |
163 values[Matrix.MTRANS_Y] = 0; | |
164 } | |
165 else { | |
166 values[Matrix.MTRANS_Y] += mScreenHeight - bottomright[1 ]; | |
167 } | |
120 } | 168 } |
121 if (bottomright[1] < mScreenHeight) { | 169 else { // Updating this value during an attempt to scroll away causes oscillation. |
122 values[Matrix.MTRANS_Y] += mScreenHeight - bottomright[1]; | 170 mBottomUsedToBeOut = bottomEdgeOutOfBounds; |
123 } | 171 } |
124 | 172 |
125 mTransform.setValues(values); | 173 mTransform.setValues(values); |
126 } | 174 } |
127 | 175 |
128 canvas.setMatrix(mTransform); | 176 canvas.setMatrix(mTransform); |
129 } | 177 } |
130 | 178 |
131 canvas.drawColor(Color.BLACK); | 179 canvas.drawColor(Color.BLACK); |
132 canvas.drawBitmap(image, 0, 0, new Paint()); | 180 canvas.drawBitmap(image, 0, 0, new Paint()); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 | 278 |
231 /** | 279 /** |
232 * Called when the user is done zooming. Defers to onScale()'s judgement . | 280 * Called when the user is done zooming. Defers to onScale()'s judgement . |
233 */ | 281 */ |
234 @Override | 282 @Override |
235 public void onScaleEnd(ScaleGestureDetector detector) { | 283 public void onScaleEnd(ScaleGestureDetector detector) { |
236 onScale(detector); | 284 onScale(detector); |
237 } | 285 } |
238 } | 286 } |
239 } | 287 } |
OLD | NEW |