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

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

Issue 2322623002: [Remoting Android] Refactor GlDesktopView (Closed)
Patch Set: Fix processAnimation bug. Abort animation when detach Created 4 years, 3 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
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.Matrix; 8 import android.graphics.Matrix;
9 import android.graphics.PointF; 9 import android.graphics.PointF;
10 import android.graphics.Rect; 10 import android.graphics.Rect;
11 import android.util.Pair;
11 import android.view.GestureDetector; 12 import android.view.GestureDetector;
12 import android.view.MotionEvent; 13 import android.view.MotionEvent;
13 import android.view.ScaleGestureDetector; 14 import android.view.ScaleGestureDetector;
14 import android.view.ViewConfiguration; 15 import android.view.ViewConfiguration;
15 16
17 import java.util.ArrayList;
18 import java.util.List;
19
16 /** 20 /**
17 * This class is responsible for handling Touch input from the user. Touch even ts which manipulate 21 * This class is responsible for handling Touch input from the user. Touch even ts which manipulate
18 * the local canvas are handled in this class and any input which should be sent to the remote host 22 * the local canvas are handled in this class and any input which should be sent to the remote host
19 * are passed to the InputStrategyInterface implementation set by the DesktopVie w. 23 * are passed to the InputStrategyInterface implementation set by the DesktopVie w.
20 */ 24 */
21 public class TouchInputHandler { 25 public class TouchInputHandler {
22 private static final float EPSILON = 0.001f; 26 private static final float EPSILON = 0.001f;
23 27
28 private final List<Pair<Object, Event<?>>> mAttachedEvents = new ArrayList<> ();
24 private final DesktopView mViewer; 29 private final DesktopView mViewer;
25 private final Context mContext; 30 private final Context mContext;
26 private final RenderData mRenderData; 31 private final RenderData mRenderData;
27 private final DesktopCanvas mDesktopCanvas; 32 private final DesktopCanvas mDesktopCanvas;
28 private InputStrategyInterface mInputStrategy; 33 private final RenderStub mRenderStub;
29 34 private final GestureDetector mScroller;
30 private GestureDetector mScroller; 35 private final ScaleGestureDetector mZoomer;
31 private ScaleGestureDetector mZoomer; 36 private final TapGestureDetector mTapDetector;
32 private TapGestureDetector mTapDetector;
33 37
34 /** Used to disambiguate a 2-finger gesture as a swipe or a pinch. */ 38 /** Used to disambiguate a 2-finger gesture as a swipe or a pinch. */
35 private SwipePinchDetector mSwipePinchDetector; 39 private final SwipePinchDetector mSwipePinchDetector;
36 40
37 // Used for processing cursor & scroller fling animations. 41 // Used for processing cursor & scroller fling animations.
38 // May consider using a List of AnimationJob if we have more than two animat ion jobs in 42 // May consider using a List of AnimationJob if we have more than two animat ion jobs in
39 // the future. 43 // the future.
40 private FlingAnimationJob mCursorAnimationJob, mScrollAnimationJob; 44 private final FlingAnimationJob mCursorAnimationJob, mScrollAnimationJob;
Hzj_jie 2016/09/10 02:06:32 IMO, placing two variables in a same definition li
Yuwei 2016/09/12 18:56:13 Done.
45
46 private InputStrategyInterface mInputStrategy;
41 47
42 /** 48 /**
43 * Used for tracking swipe gestures. Only the Y-direction is needed for resp onding to swipe-up 49 * Used for tracking swipe gestures. Only the Y-direction is needed for resp onding to swipe-up
44 * or swipe-down. 50 * or swipe-down.
45 */ 51 */
46 private float mTotalMotionY = 0; 52 private float mTotalMotionY = 0;
47 53
48 /** 54 /**
49 * Distance in pixels beyond which a motion gesture is considered to be a sw ipe. This is 55 * Distance in pixels beyond which a motion gesture is considered to be a sw ipe. This is
50 * initialized using the Context passed into the ctor. 56 * initialized using the Context passed into the ctor.
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 public RenderStub.InputFeedbackType getLongPressFeedbackType() { 179 public RenderStub.InputFeedbackType getLongPressFeedbackType() {
174 return RenderStub.InputFeedbackType.NONE; 180 return RenderStub.InputFeedbackType.NONE;
175 } 181 }
176 182
177 @Override 183 @Override
178 public boolean isIndirectInputMode() { 184 public boolean isIndirectInputMode() {
179 return false; 185 return false;
180 } 186 }
181 } 187 }
182 188
183 public TouchInputHandler(DesktopView viewer, Context context) { 189 private <ParamT> void attachEvent(Event<ParamT> event,
190 Event.ParameterRunnable<ParamT> runnable) {
191 mAttachedEvents.add(new Pair<Object, Event<?>>(event.add(runnable), even t));
192 }
Hzj_jie 2016/09/10 02:06:32 Functions should be placed after constructors.
Yuwei 2016/09/12 18:56:13 Done.
193
194 public TouchInputHandler(DesktopView viewer, Desktop desktop, RenderStub ren derStub,
195 final InputEventSender injector) {
196 Preconditions.notNull(injector);
197 Preconditions.notNull(renderStub);
198
184 mViewer = viewer; 199 mViewer = viewer;
185 mContext = context; 200 mContext = desktop;
201 mRenderStub = renderStub;
186 mRenderData = new RenderData(); 202 mRenderData = new RenderData();
187 mDesktopCanvas = new DesktopCanvas(mViewer, mRenderData); 203 mDesktopCanvas = new DesktopCanvas(renderStub, mRenderData);
188 204
189 GestureListener listener = new GestureListener(); 205 GestureListener listener = new GestureListener();
190 mScroller = new GestureDetector(context, listener, null, false); 206 mScroller = new GestureDetector(desktop, listener, null, false);
191 207
192 // If long-press is enabled, the gesture-detector will not emit any furt her onScroll 208 // If long-press is enabled, the gesture-detector will not emit any furt her onScroll
193 // notifications after the onLongPress notification. Since onScroll is b eing used for 209 // notifications after the onLongPress notification. Since onScroll is b eing used for
194 // moving the cursor, it means that the cursor would become stuck if the finger were held 210 // moving the cursor, it means that the cursor would become stuck if the finger were held
195 // down too long. 211 // down too long.
196 mScroller.setIsLongpressEnabled(false); 212 mScroller.setIsLongpressEnabled(false);
197 213
198 mZoomer = new ScaleGestureDetector(context, listener); 214 mZoomer = new ScaleGestureDetector(desktop, listener);
199 mTapDetector = new TapGestureDetector(context, listener); 215 mTapDetector = new TapGestureDetector(desktop, listener);
200 mSwipePinchDetector = new SwipePinchDetector(context); 216 mSwipePinchDetector = new SwipePinchDetector(desktop);
201 217
202 // The threshold needs to be bigger than the ScaledTouchSlop used by the gesture-detectors, 218 // The threshold needs to be bigger than the ScaledTouchSlop used by the gesture-detectors,
203 // so that a gesture cannot be both a tap and a swipe. It also needs to be small enough so 219 // so that a gesture cannot be both a tap and a swipe. It also needs to be small enough so
204 // that intentional swipes are usually detected. 220 // that intentional swipes are usually detected.
205 float density = context.getResources().getDisplayMetrics().density; 221 float density = desktop.getResources().getDisplayMetrics().density;
206 mSwipeThreshold = 40 * density; 222 mSwipeThreshold = 40 * density;
207 223
208 mEdgeSlopInPx = ViewConfiguration.get(context).getScaledEdgeSlop(); 224 mEdgeSlopInPx = ViewConfiguration.get(desktop).getScaledEdgeSlop();
209 225
210 mInputStrategy = new NullInputStrategy(); 226 mInputStrategy = new NullInputStrategy();
211 227
212 mCursorAnimationJob = new CursorAnimationJob(context); 228 mCursorAnimationJob = new CursorAnimationJob(desktop);
213 mScrollAnimationJob = new ScrollAnimationJob(context); 229 mScrollAnimationJob = new ScrollAnimationJob(desktop);
214 230
215 mProcessAnimationCallback = new Event.ParameterCallback<Boolean, Void>() { 231 mProcessAnimationCallback = new Event.ParameterCallback<Boolean, Void>() {
216 @Override 232 @Override
217 public Boolean run(Void p) { 233 public Boolean run(Void p) {
218 return processAnimation(); 234 return processAnimation();
219 } 235 }
220 }; 236 };
221 237
222 attachViewEvents(viewer); 238 attachEvent(mViewer.onTouch(), new Event.ParameterRunnable<TouchEventPar ameter>() {
239 @Override
240 public void run(TouchEventParameter parameter) {
241 parameter.handled = handleTouchEvent(parameter.event);
242 }
243 });
244
245 attachEvent(desktop.onInputModeChanged(),
246 new Event.ParameterRunnable<InputModeChangedEventParameter>() {
247 @Override
248 public void run(InputModeChangedEventParameter parameter) {
249 handleInputModeChanged(parameter, injector);
250 }
251 });
252
253 attachEvent(desktop.onSystemUiVisibilityChanged(),
254 new Event.ParameterRunnable<SystemUiVisibilityChangedEventParame ter>() {
255 @Override
256 public void run(SystemUiVisibilityChangedEventParameter para meter) {
257 handleSystemUiVisibilityChanged(parameter);
258 }
259 });
260
261 attachEvent(renderStub.onClientSizeChanged(),
262 new Event.ParameterRunnable<SizeChangedEventParameter>() {
263 @Override
264 public void run(SizeChangedEventParameter parameter) {
265 handleClientSizeChanged(parameter.width, parameter.heigh t);
266 }
267 });
268
269 attachEvent(renderStub.onHostSizeChanged(),
270 new Event.ParameterRunnable<SizeChangedEventParameter>() {
271 @Override
272 public void run(SizeChangedEventParameter parameter) {
273 handleHostSizeChanged(parameter.width, parameter.height) ;
274 }
275 });
223 } 276 }
224 277
225 /** 278 /**
279 * Detaches all registered event listeners.
280 */
281 public void detach() {
282 abortAnimation();
283 for (Pair<Object, Event<?>> pair : mAttachedEvents) {
284 pair.second.remove(pair.first);
285 }
286 mAttachedEvents.clear();
287 }
288
289 /**
226 * Steps forward the animation. 290 * Steps forward the animation.
227 * @return true if the animation is not finished yet. 291 * @return true if the animation is not finished yet.
228 */ 292 */
229 private boolean processAnimation() { 293 private boolean processAnimation() {
230 return mCursorAnimationJob.processAnimation() || mScrollAnimationJob.pro cessAnimation(); 294 return mCursorAnimationJob.processAnimation() || mScrollAnimationJob.pro cessAnimation();
231 } 295 }
232 296
233 /** 297 /**
234 * Start stepping animation when onCanvasRendered is triggered. 298 * Start stepping animation when onCanvasRendered is triggered.
235 */ 299 */
236 private void startAnimation() { 300 private void startAnimation() {
237 mViewer.onCanvasRendered().addSelfRemovable(mProcessAnimationCallback); 301 mRenderStub.onCanvasRendered().addSelfRemovable(mProcessAnimationCallbac k);
238 } 302 }
239 303
240 /** 304 /**
241 * Abort all animations. 305 * Abort all animations.
242 */ 306 */
243 private void abortAnimation() { 307 private void abortAnimation() {
244 mCursorAnimationJob.abortAnimation(); 308 mCursorAnimationJob.abortAnimation();
245 mScrollAnimationJob.abortAnimation(); 309 mScrollAnimationJob.abortAnimation();
246 } 310 }
247 311
248 public void init(Desktop desktop, final InputEventSender injector) {
249 Preconditions.notNull(injector);
250 desktop.onInputModeChanged().add(
251 new Event.ParameterRunnable<InputModeChangedEventParameter>() {
252 @Override
253 public void run(InputModeChangedEventParameter parameter) {
254 handleInputModeChanged(parameter, injector);
255 }
256 });
257
258 desktop.onSystemUiVisibilityChanged().add(
259 new Event.ParameterRunnable<SystemUiVisibilityChangedEventParame ter>() {
260 @Override
261 public void run(SystemUiVisibilityChangedEventParameter para meter) {
262 handleSystemUiVisibilityChanged(parameter);
263 }
264 });
265 }
266
267 private void attachViewEvents(DesktopView viewer) {
268 viewer.onTouch().add(new Event.ParameterRunnable<TouchEventParameter>() {
269 @Override
270 public void run(TouchEventParameter parameter) {
271 parameter.handled = handleTouchEvent(parameter.event);
272 }
273 });
274 viewer.onClientSizeChanged().add(new Event.ParameterRunnable<SizeChanged EventParameter>() {
275 @Override
276 public void run(SizeChangedEventParameter parameter) {
277 handleClientSizeChanged(parameter.width, parameter.height);
278 }
279 });
280 viewer.onHostSizeChanged().add(new Event.ParameterRunnable<SizeChangedEv entParameter>() {
281 @Override
282 public void run(SizeChangedEventParameter parameter) {
283 handleHostSizeChanged(parameter.width, parameter.height);
284 }
285 });
286 }
287
288 private void handleInputModeChanged( 312 private void handleInputModeChanged(
289 InputModeChangedEventParameter parameter, InputEventSender injector) { 313 InputModeChangedEventParameter parameter, InputEventSender injector) {
290 final Desktop.InputMode inputMode = parameter.inputMode; 314 final Desktop.InputMode inputMode = parameter.inputMode;
291 final CapabilityManager.HostCapability hostTouchCapability = 315 final CapabilityManager.HostCapability hostTouchCapability =
292 parameter.hostCapability; 316 parameter.hostCapability;
293 // We need both input mode and host input capabilities to select the inp ut 317 // We need both input mode and host input capabilities to select the inp ut
294 // strategy. 318 // strategy.
295 if (!inputMode.isSet() || !hostTouchCapability.isSet()) { 319 if (!inputMode.isSet() || !hostTouchCapability.isSet()) {
296 return; 320 return;
297 } 321 }
(...skipping 11 matching lines...) Expand all
309 new SimulatedTouchInputStrategy(mRenderData, injecto r, mContext)); 333 new SimulatedTouchInputStrategy(mRenderData, injecto r, mContext));
310 } 334 }
311 break; 335 break;
312 336
313 default: 337 default:
314 // Unreachable, but required by Google Java style and findbugs. 338 // Unreachable, but required by Google Java style and findbugs.
315 assert false : "Unreached"; 339 assert false : "Unreached";
316 } 340 }
317 341
318 // Ensure the cursor state is updated appropriately. 342 // Ensure the cursor state is updated appropriately.
319 mViewer.cursorVisibilityChanged(mRenderData.drawCursor); 343 mRenderStub.setCursorVisibility(mRenderData.drawCursor);
320 } 344 }
321 345
322 private void handleSystemUiVisibilityChanged( 346 private void handleSystemUiVisibilityChanged(
323 SystemUiVisibilityChangedEventParameter parameter) { 347 SystemUiVisibilityChangedEventParameter parameter) {
324 if (parameter.softInputMethodVisible) { 348 if (parameter.softInputMethodVisible) {
325 mDesktopCanvas.setSystemUiOffsetValues(parameter.left, parameter.top , 349 mDesktopCanvas.setSystemUiOffsetValues(parameter.left, parameter.top ,
326 mRenderData.screenWidth - parameter.right, 350 mRenderData.screenWidth - parameter.right,
327 mRenderData.screenHeight - parameter.bottom); 351 mRenderData.screenHeight - parameter.bottom);
328 } else { 352 } else {
329 mDesktopCanvas.setSystemUiOffsetValues(0, 0, 0, 0); 353 mDesktopCanvas.setSystemUiOffsetValues(0, 0, 0, 0);
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 moveCursor(imagePoint[0], imagePoint[1]); 454 moveCursor(imagePoint[0], imagePoint[1]);
431 } 455 }
432 456
433 /** Moves the cursor to the specified position on the remote host. */ 457 /** Moves the cursor to the specified position on the remote host. */
434 private void moveCursor(float newX, float newY) { 458 private void moveCursor(float newX, float newY) {
435 boolean cursorMoved = mRenderData.setCursorPosition(newX, newY); 459 boolean cursorMoved = mRenderData.setCursorPosition(newX, newY);
436 if (cursorMoved) { 460 if (cursorMoved) {
437 mInputStrategy.injectCursorMoveEvent((int) newX, (int) newY); 461 mInputStrategy.injectCursorMoveEvent((int) newX, (int) newY);
438 } 462 }
439 463
440 mViewer.cursorMoved(mRenderData.getCursorPosition()); 464 mRenderStub.moveCursor(mRenderData.getCursorPosition());
441 } 465 }
442 466
443 /** Processes a (multi-finger) swipe gesture. */ 467 /** Processes a (multi-finger) swipe gesture. */
444 private boolean onSwipe() { 468 private boolean onSwipe() {
445 if (mTotalMotionY > mSwipeThreshold) { 469 if (mTotalMotionY > mSwipeThreshold) {
446 // Swipe down occurred. 470 // Swipe down occurred.
447 mViewer.showActionBar(); 471 mViewer.showActionBar();
448 } else if (mTotalMotionY < -mSwipeThreshold) { 472 } else if (mTotalMotionY < -mSwipeThreshold) {
449 // Swipe up occurred. 473 // Swipe up occurred.
450 mViewer.showKeyboard(); 474 mViewer.showKeyboard();
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 if (!mInputStrategy.isIndirectInputMode()) { 633 if (!mInputStrategy.isIndirectInputMode()) {
610 if (screenPointLiesOutsideImageBoundary(x, y)) { 634 if (screenPointLiesOutsideImageBoundary(x, y)) {
611 return false; 635 return false;
612 } 636 }
613 moveCursorToScreenPoint(x, y); 637 moveCursorToScreenPoint(x, y);
614 } 638 }
615 639
616 if (mInputStrategy.onTap(button)) { 640 if (mInputStrategy.onTap(button)) {
617 PointF pos = mRenderData.getCursorPosition(); 641 PointF pos = mRenderData.getCursorPosition();
618 642
619 mViewer.showInputFeedback(mInputStrategy.getShortPressFeedbackTy pe(), pos); 643 mRenderStub.showInputFeedback(mInputStrategy.getShortPressFeedba ckType(), pos);
620 } 644 }
621 return true; 645 return true;
622 } 646 }
623 647
624 /** Called when a long-press is triggered for one or more fingers. */ 648 /** Called when a long-press is triggered for one or more fingers. */
625 @Override 649 @Override
626 public void onLongPress(int pointerCount, float x, float y) { 650 public void onLongPress(int pointerCount, float x, float y) {
627 int button = mouseButtonFromPointerCount(pointerCount); 651 int button = mouseButtonFromPointerCount(pointerCount);
628 if (button == InputStub.BUTTON_UNDEFINED) { 652 if (button == InputStub.BUTTON_UNDEFINED) {
629 return; 653 return;
630 } 654 }
631 655
632 if (!mInputStrategy.isIndirectInputMode()) { 656 if (!mInputStrategy.isIndirectInputMode()) {
633 if (screenPointLiesOutsideImageBoundary(x, y)) { 657 if (screenPointLiesOutsideImageBoundary(x, y)) {
634 return; 658 return;
635 } 659 }
636 moveCursorToScreenPoint(x, y); 660 moveCursorToScreenPoint(x, y);
637 } 661 }
638 662
639 if (mInputStrategy.onPressAndHold(button)) { 663 if (mInputStrategy.onPressAndHold(button)) {
640 PointF pos = mRenderData.getCursorPosition(); 664 PointF pos = mRenderData.getCursorPosition();
641 665
642 mViewer.showInputFeedback(mInputStrategy.getLongPressFeedbackTyp e(), pos); 666 mRenderStub.showInputFeedback(mInputStrategy.getLongPressFeedbac kType(), pos);
643 mSuppressFling = true; 667 mSuppressFling = true;
644 mIsDragging = true; 668 mIsDragging = true;
645 } 669 }
646 } 670 }
647 671
648 /** Maps the number of fingers in a tap or long-press gesture to a mouse -button. */ 672 /** Maps the number of fingers in a tap or long-press gesture to a mouse -button. */
649 private int mouseButtonFromPointerCount(int pointerCount) { 673 private int mouseButtonFromPointerCount(int pointerCount) {
650 switch (pointerCount) { 674 switch (pointerCount) {
651 case 1: 675 case 1:
652 return InputStub.BUTTON_LEFT; 676 return InputStub.BUTTON_LEFT;
(...skipping 11 matching lines...) Expand all
664 float[] mappedPoints = mapScreenPointToImagePoint(screenX, screenY); 688 float[] mappedPoints = mapScreenPointToImagePoint(screenX, screenY);
665 689
666 float imageWidth = (float) mRenderData.imageWidth + EPSILON; 690 float imageWidth = (float) mRenderData.imageWidth + EPSILON;
667 float imageHeight = (float) mRenderData.imageHeight + EPSILON; 691 float imageHeight = (float) mRenderData.imageHeight + EPSILON;
668 692
669 return mappedPoints[0] < -EPSILON || mappedPoints[0] > imageWidth 693 return mappedPoints[0] < -EPSILON || mappedPoints[0] > imageWidth
670 || mappedPoints[1] < -EPSILON || mappedPoints[1] > imageHeig ht; 694 || mappedPoints[1] < -EPSILON || mappedPoints[1] > imageHeig ht;
671 } 695 }
672 } 696 }
673 } 697 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698