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

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

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

Powered by Google App Engine
This is Rietveld 408576698