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.Matrix; | 8 import android.graphics.Matrix; |
9 import android.graphics.PointF; | 9 import android.graphics.PointF; |
| 10 import android.graphics.Rect; |
| 11 import android.graphics.RectF; |
10 import android.view.GestureDetector; | 12 import android.view.GestureDetector; |
11 import android.view.MotionEvent; | 13 import android.view.MotionEvent; |
12 import android.view.ScaleGestureDetector; | 14 import android.view.ScaleGestureDetector; |
13 import android.widget.Scroller; | 15 import android.widget.Scroller; |
14 | 16 |
15 /** | 17 /** |
16 * This class implements the cursor-tracking behavior and gestures. | 18 * This class implements the cursor-tracking behavior and gestures. |
17 */ | 19 */ |
18 public class TrackingInputHandler implements TouchInputHandler { | 20 public class TrackingInputHandler implements TouchInputHandler { |
19 /** | 21 /** |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 * dragging whilst a button is held down. | 74 * dragging whilst a button is held down. |
73 */ | 75 */ |
74 private boolean mSuppressFling = false; | 76 private boolean mSuppressFling = false; |
75 | 77 |
76 /** | 78 /** |
77 * Set to true when 3-finger swipe gesture is complete, so that further move
ment doesn't | 79 * Set to true when 3-finger swipe gesture is complete, so that further move
ment doesn't |
78 * trigger more swipe actions. | 80 * trigger more swipe actions. |
79 */ | 81 */ |
80 private boolean mSwipeCompleted = false; | 82 private boolean mSwipeCompleted = false; |
81 | 83 |
| 84 /** |
| 85 * Represents the amount of vertical space in pixels used by the soft input
device and |
| 86 * accompanying system UI. |
| 87 */ |
| 88 private int mInputMethodOffsetY = 0; |
| 89 |
| 90 /** |
| 91 * Represents the amount of horizontal space in pixels used by the soft inpu
t device and |
| 92 * accompanying system UI. |
| 93 */ |
| 94 private int mInputMethodOffsetX = 0; |
| 95 |
82 public TrackingInputHandler(DesktopViewInterface viewer, Context context, | 96 public TrackingInputHandler(DesktopViewInterface viewer, Context context, |
83 RenderData renderData) { | 97 RenderData renderData) { |
84 mViewer = viewer; | 98 mViewer = viewer; |
85 mRenderData = renderData; | 99 mRenderData = renderData; |
86 | 100 |
87 GestureListener listener = new GestureListener(); | 101 GestureListener listener = new GestureListener(); |
88 mScroller = new GestureDetector(context, listener, null, false); | 102 mScroller = new GestureDetector(context, listener, null, false); |
89 | 103 |
90 // If long-press is enabled, the gesture-detector will not emit any furt
her onScroll | 104 // If long-press is enabled, the gesture-detector will not emit any furt
her onScroll |
91 // notifications after the onLongPress notification. Since onScroll is b
eing used for | 105 // notifications after the onLongPress notification. Since onScroll is b
eing used for |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 | 137 |
124 mViewer.injectMouseEvent((int) newX, (int) newY, BUTTON_UNDEFINED, false
); | 138 mViewer.injectMouseEvent((int) newX, (int) newY, BUTTON_UNDEFINED, false
); |
125 } | 139 } |
126 | 140 |
127 /** | 141 /** |
128 * Repositions the image by translating it (without affecting the zoom level
) to place the | 142 * Repositions the image by translating it (without affecting the zoom level
) to place the |
129 * cursor close to the center of the screen. | 143 * cursor close to the center of the screen. |
130 */ | 144 */ |
131 private void repositionImage() { | 145 private void repositionImage() { |
132 synchronized (mRenderData) { | 146 synchronized (mRenderData) { |
| 147 float adjustedScreenWidth = mRenderData.screenWidth - mInputMethodOf
fsetX; |
| 148 float adjustedScreenHeight = mRenderData.screenHeight - mInputMethod
OffsetY; |
| 149 |
133 // Get the current cursor position in screen coordinates. | 150 // Get the current cursor position in screen coordinates. |
134 float[] cursorScreen = {mCursorPosition.x, mCursorPosition.y}; | 151 float[] cursorScreen = {mCursorPosition.x, mCursorPosition.y}; |
135 mRenderData.transform.mapPoints(cursorScreen); | 152 mRenderData.transform.mapPoints(cursorScreen); |
136 | 153 |
137 // Translate so the cursor is displayed in the middle of the screen. | 154 // Translate so the cursor is displayed in the middle of the screen. |
138 mRenderData.transform.postTranslate( | 155 mRenderData.transform.postTranslate( |
139 (float) mRenderData.screenWidth / 2 - cursorScreen[0], | 156 (float) adjustedScreenWidth / 2 - cursorScreen[0], |
140 (float) mRenderData.screenHeight / 2 - cursorScreen[1]); | 157 (float) adjustedScreenHeight / 2 - cursorScreen[1]); |
141 | 158 |
142 // Now the cursor is displayed in the middle of the screen, see if t
he image can be | 159 // Now the cursor is displayed in the middle of the screen, see if t
he image can be |
143 // panned so that more of it is visible. The primary goal is to show
as much of the | 160 // panned so that more of it is visible. The primary goal is to show
as much of the |
144 // image as possible. The secondary goal is to keep the cursor in th
e middle. | 161 // image as possible. The secondary goal is to keep the cursor in th
e middle. |
145 | 162 |
146 // Get the coordinates of the desktop rectangle (top-left/bottom-rig
ht corners) in | 163 // Get the coordinates of the desktop rectangle (top-left/bottom-rig
ht corners) in |
147 // screen coordinates. Order is: left, top, right, bottom. | 164 // screen coordinates. Order is: left, top, right, bottom. |
148 float[] rectScreen = {0, 0, mRenderData.imageWidth, mRenderData.imag
eHeight}; | 165 RectF rectScreen = new RectF(0, 0, mRenderData.imageWidth, mRenderDa
ta.imageHeight); |
149 mRenderData.transform.mapPoints(rectScreen); | 166 mRenderData.transform.mapRect(rectScreen); |
150 | 167 |
151 float leftDelta = rectScreen[0]; | 168 float leftDelta = rectScreen.left; |
152 float rightDelta = rectScreen[2] - mRenderData.screenWidth; | 169 float rightDelta = rectScreen.right - mRenderData.screenWidth + mInp
utMethodOffsetX; |
153 float topDelta = rectScreen[1]; | 170 float topDelta = rectScreen.top; |
154 float bottomDelta = rectScreen[3] - mRenderData.screenHeight; | 171 float bottomDelta = rectScreen.bottom - mRenderData.screenHeight + m
InputMethodOffsetY; |
155 float xAdjust = 0; | 172 float xAdjust = 0; |
156 float yAdjust = 0; | 173 float yAdjust = 0; |
157 | 174 |
158 if (rectScreen[2] - rectScreen[0] < mRenderData.screenWidth) { | 175 if (rectScreen.right - rectScreen.left < adjustedScreenWidth) { |
159 // Image is narrower than the screen, so center it. | 176 // Image is narrower than the screen, so center it. |
160 xAdjust = -(rightDelta + leftDelta) / 2; | 177 xAdjust = -(rightDelta + leftDelta) / 2; |
161 } else if (leftDelta > 0 && rightDelta > 0) { | 178 } else if (leftDelta > 0 && rightDelta > 0) { |
162 // Panning the image left will show more of it. | 179 // Panning the image left will show more of it. |
163 xAdjust = -Math.min(leftDelta, rightDelta); | 180 xAdjust = -Math.min(leftDelta, rightDelta); |
164 } else if (leftDelta < 0 && rightDelta < 0) { | 181 } else if (leftDelta < 0 && rightDelta < 0) { |
165 // Pan the image right. | 182 // Pan the image right. |
166 xAdjust = Math.min(-leftDelta, -rightDelta); | 183 xAdjust = Math.min(-leftDelta, -rightDelta); |
167 } | 184 } |
168 | 185 |
169 // Apply similar logic for yAdjust. | 186 // Apply similar logic for yAdjust. |
170 if (rectScreen[3] - rectScreen[1] < mRenderData.screenHeight) { | 187 if (rectScreen.bottom - rectScreen.top < adjustedScreenHeight) { |
171 yAdjust = -(bottomDelta + topDelta) / 2; | 188 yAdjust = -(bottomDelta + topDelta) / 2; |
172 } else if (topDelta > 0 && bottomDelta > 0) { | 189 } else if (topDelta > 0 && bottomDelta > 0) { |
173 yAdjust = -Math.min(topDelta, bottomDelta); | 190 yAdjust = -Math.min(topDelta, bottomDelta); |
174 } else if (topDelta < 0 && bottomDelta < 0) { | 191 } else if (topDelta < 0 && bottomDelta < 0) { |
175 yAdjust = Math.min(-topDelta, -bottomDelta); | 192 yAdjust = Math.min(-topDelta, -bottomDelta); |
176 } | 193 } |
177 | 194 |
178 mRenderData.transform.postTranslate(xAdjust, yAdjust); | 195 mRenderData.transform.postTranslate(xAdjust, yAdjust); |
179 } | 196 } |
180 mViewer.transformationChanged(); | 197 mViewer.transformationChanged(); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 repositionImageWithZoom(); | 299 repositionImageWithZoom(); |
283 } | 300 } |
284 | 301 |
285 @Override | 302 @Override |
286 public void onHostSizeChanged(int width, int height) { | 303 public void onHostSizeChanged(int width, int height) { |
287 moveCursor((float) width / 2, (float) height / 2); | 304 moveCursor((float) width / 2, (float) height / 2); |
288 repositionImageWithZoom(); | 305 repositionImageWithZoom(); |
289 } | 306 } |
290 | 307 |
291 @Override | 308 @Override |
| 309 public void onSoftInputMethodVisibilityChanged(boolean inputMethodVisible, R
ect bounds) { |
| 310 synchronized (mRenderData) { |
| 311 if (inputMethodVisible) { |
| 312 mInputMethodOffsetY = mRenderData.screenHeight - bounds.bottom; |
| 313 mInputMethodOffsetX = mRenderData.screenWidth - bounds.right; |
| 314 } else { |
| 315 mInputMethodOffsetY = 0; |
| 316 mInputMethodOffsetX = 0; |
| 317 } |
| 318 } |
| 319 |
| 320 repositionImageWithZoom(); |
| 321 } |
| 322 |
| 323 @Override |
292 public void processAnimation() { | 324 public void processAnimation() { |
293 int previousX = mFlingScroller.getCurrX(); | 325 int previousX = mFlingScroller.getCurrX(); |
294 int previousY = mFlingScroller.getCurrY(); | 326 int previousY = mFlingScroller.getCurrY(); |
295 if (!mFlingScroller.computeScrollOffset()) { | 327 if (!mFlingScroller.computeScrollOffset()) { |
296 mViewer.setAnimationEnabled(false); | 328 mViewer.setAnimationEnabled(false); |
297 return; | 329 return; |
298 } | 330 } |
299 int deltaX = mFlingScroller.getCurrX() - previousX; | 331 int deltaX = mFlingScroller.getCurrX() - previousX; |
300 int deltaY = mFlingScroller.getCurrY() - previousY; | 332 int deltaY = mFlingScroller.getCurrY() - previousY; |
301 float[] delta = {deltaX, deltaY}; | 333 float[] delta = {deltaX, deltaY}; |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 public void onLongPress(int pointerCount) { | 483 public void onLongPress(int pointerCount) { |
452 mHeldButton = mouseButtonFromPointerCount(pointerCount); | 484 mHeldButton = mouseButtonFromPointerCount(pointerCount); |
453 if (mHeldButton != BUTTON_UNDEFINED) { | 485 if (mHeldButton != BUTTON_UNDEFINED) { |
454 injectButtonEvent(mHeldButton, true); | 486 injectButtonEvent(mHeldButton, true); |
455 mViewer.showLongPressFeedback(); | 487 mViewer.showLongPressFeedback(); |
456 mSuppressFling = true; | 488 mSuppressFling = true; |
457 } | 489 } |
458 } | 490 } |
459 } | 491 } |
460 } | 492 } |
OLD | NEW |