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

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, mScrollAnimationJob;
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 }
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>() {
Yuwei 2016/09/08 23:09:15 So annoying that the N SDK still hasn't been inclu
Hzj_jie 2016/09/10 02:06:32 Yes, unfortunately. () -> {} looks extremely bette
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 for (Pair<Object, Event<?>> pair : mAttachedEvents) {
283 pair.second.remove(pair.first);
284 }
285 mAttachedEvents.clear();
286 }
287
288 /**
226 * Steps forward the animation. 289 * Steps forward the animation.
227 * @return true if the animation is not finished yet. 290 * @return true if the animation is not finished yet.
228 */ 291 */
229 private boolean processAnimation() { 292 private boolean processAnimation() {
230 return mCursorAnimationJob.processAnimation() || mScrollAnimationJob.pro cessAnimation(); 293 return mCursorAnimationJob.processAnimation() || mScrollAnimationJob.pro cessAnimation();
231 } 294 }
232 295
233 /** 296 /**
234 * Start stepping animation when onCanvasRendered is triggered. 297 * Start stepping animation when onCanvasRendered is triggered.
235 */ 298 */
236 private void startAnimation() { 299 private void startAnimation() {
237 mViewer.onCanvasRendered().addSelfRemovable(mProcessAnimationCallback); 300 mRenderStub.onCanvasRendered().addSelfRemovable(mProcessAnimationCallbac k);
238 } 301 }
239 302
240 /** 303 /**
241 * Abort all animations. 304 * Abort all animations.
242 */ 305 */
243 private void abortAnimation() { 306 private void abortAnimation() {
244 mCursorAnimationJob.abortAnimation(); 307 mCursorAnimationJob.abortAnimation();
245 mScrollAnimationJob.abortAnimation(); 308 mScrollAnimationJob.abortAnimation();
246 } 309 }
247 310
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( 311 private void handleInputModeChanged(
289 InputModeChangedEventParameter parameter, InputEventSender injector) { 312 InputModeChangedEventParameter parameter, InputEventSender injector) {
290 final Desktop.InputMode inputMode = parameter.inputMode; 313 final Desktop.InputMode inputMode = parameter.inputMode;
291 final CapabilityManager.HostCapability hostTouchCapability = 314 final CapabilityManager.HostCapability hostTouchCapability =
292 parameter.hostCapability; 315 parameter.hostCapability;
293 // We need both input mode and host input capabilities to select the inp ut 316 // We need both input mode and host input capabilities to select the inp ut
294 // strategy. 317 // strategy.
295 if (!inputMode.isSet() || !hostTouchCapability.isSet()) { 318 if (!inputMode.isSet() || !hostTouchCapability.isSet()) {
296 return; 319 return;
297 } 320 }
(...skipping 11 matching lines...) Expand all
309 new SimulatedTouchInputStrategy(mRenderData, injecto r, mContext)); 332 new SimulatedTouchInputStrategy(mRenderData, injecto r, mContext));
310 } 333 }
311 break; 334 break;
312 335
313 default: 336 default:
314 // Unreachable, but required by Google Java style and findbugs. 337 // Unreachable, but required by Google Java style and findbugs.
315 assert false : "Unreached"; 338 assert false : "Unreached";
316 } 339 }
317 340
318 // Ensure the cursor state is updated appropriately. 341 // Ensure the cursor state is updated appropriately.
319 mViewer.cursorVisibilityChanged(mRenderData.drawCursor); 342 mRenderStub.setCursorVisibility(mRenderData.drawCursor);
320 } 343 }
321 344
322 private void handleSystemUiVisibilityChanged( 345 private void handleSystemUiVisibilityChanged(
323 SystemUiVisibilityChangedEventParameter parameter) { 346 SystemUiVisibilityChangedEventParameter parameter) {
324 if (parameter.softInputMethodVisible) { 347 if (parameter.softInputMethodVisible) {
325 mDesktopCanvas.setSystemUiOffsetValues(parameter.left, parameter.top , 348 mDesktopCanvas.setSystemUiOffsetValues(parameter.left, parameter.top ,
326 mRenderData.screenWidth - parameter.right, 349 mRenderData.screenWidth - parameter.right,
327 mRenderData.screenHeight - parameter.bottom); 350 mRenderData.screenHeight - parameter.bottom);
328 } else { 351 } else {
329 mDesktopCanvas.setSystemUiOffsetValues(0, 0, 0, 0); 352 mDesktopCanvas.setSystemUiOffsetValues(0, 0, 0, 0);
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 moveCursor(imagePoint[0], imagePoint[1]); 453 moveCursor(imagePoint[0], imagePoint[1]);
431 } 454 }
432 455
433 /** Moves the cursor to the specified position on the remote host. */ 456 /** Moves the cursor to the specified position on the remote host. */
434 private void moveCursor(float newX, float newY) { 457 private void moveCursor(float newX, float newY) {
435 boolean cursorMoved = mRenderData.setCursorPosition(newX, newY); 458 boolean cursorMoved = mRenderData.setCursorPosition(newX, newY);
436 if (cursorMoved) { 459 if (cursorMoved) {
437 mInputStrategy.injectCursorMoveEvent((int) newX, (int) newY); 460 mInputStrategy.injectCursorMoveEvent((int) newX, (int) newY);
438 } 461 }
439 462
440 mViewer.cursorMoved(mRenderData.getCursorPosition()); 463 mRenderStub.moveCursor(mRenderData.getCursorPosition());
441 } 464 }
442 465
443 /** Processes a (multi-finger) swipe gesture. */ 466 /** Processes a (multi-finger) swipe gesture. */
444 private boolean onSwipe() { 467 private boolean onSwipe() {
445 if (mTotalMotionY > mSwipeThreshold) { 468 if (mTotalMotionY > mSwipeThreshold) {
446 // Swipe down occurred. 469 // Swipe down occurred.
447 mViewer.showActionBar(); 470 mViewer.showActionBar();
448 } else if (mTotalMotionY < -mSwipeThreshold) { 471 } else if (mTotalMotionY < -mSwipeThreshold) {
449 // Swipe up occurred. 472 // Swipe up occurred.
450 mViewer.showKeyboard(); 473 mViewer.showKeyboard();
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 if (!mInputStrategy.isIndirectInputMode()) { 632 if (!mInputStrategy.isIndirectInputMode()) {
610 if (screenPointLiesOutsideImageBoundary(x, y)) { 633 if (screenPointLiesOutsideImageBoundary(x, y)) {
611 return false; 634 return false;
612 } 635 }
613 moveCursorToScreenPoint(x, y); 636 moveCursorToScreenPoint(x, y);
614 } 637 }
615 638
616 if (mInputStrategy.onTap(button)) { 639 if (mInputStrategy.onTap(button)) {
617 PointF pos = mRenderData.getCursorPosition(); 640 PointF pos = mRenderData.getCursorPosition();
618 641
619 mViewer.showInputFeedback(mInputStrategy.getShortPressFeedbackTy pe(), pos); 642 mRenderStub.showInputFeedback(mInputStrategy.getShortPressFeedba ckType(), pos);
620 } 643 }
621 return true; 644 return true;
622 } 645 }
623 646
624 /** Called when a long-press is triggered for one or more fingers. */ 647 /** Called when a long-press is triggered for one or more fingers. */
625 @Override 648 @Override
626 public void onLongPress(int pointerCount, float x, float y) { 649 public void onLongPress(int pointerCount, float x, float y) {
627 int button = mouseButtonFromPointerCount(pointerCount); 650 int button = mouseButtonFromPointerCount(pointerCount);
628 if (button == InputStub.BUTTON_UNDEFINED) { 651 if (button == InputStub.BUTTON_UNDEFINED) {
629 return; 652 return;
630 } 653 }
631 654
632 if (!mInputStrategy.isIndirectInputMode()) { 655 if (!mInputStrategy.isIndirectInputMode()) {
633 if (screenPointLiesOutsideImageBoundary(x, y)) { 656 if (screenPointLiesOutsideImageBoundary(x, y)) {
634 return; 657 return;
635 } 658 }
636 moveCursorToScreenPoint(x, y); 659 moveCursorToScreenPoint(x, y);
637 } 660 }
638 661
639 if (mInputStrategy.onPressAndHold(button)) { 662 if (mInputStrategy.onPressAndHold(button)) {
640 PointF pos = mRenderData.getCursorPosition(); 663 PointF pos = mRenderData.getCursorPosition();
641 664
642 mViewer.showInputFeedback(mInputStrategy.getLongPressFeedbackTyp e(), pos); 665 mRenderStub.showInputFeedback(mInputStrategy.getLongPressFeedbac kType(), pos);
643 mSuppressFling = true; 666 mSuppressFling = true;
644 mIsDragging = true; 667 mIsDragging = true;
645 } 668 }
646 } 669 }
647 670
648 /** Maps the number of fingers in a tap or long-press gesture to a mouse -button. */ 671 /** Maps the number of fingers in a tap or long-press gesture to a mouse -button. */
649 private int mouseButtonFromPointerCount(int pointerCount) { 672 private int mouseButtonFromPointerCount(int pointerCount) {
650 switch (pointerCount) { 673 switch (pointerCount) {
651 case 1: 674 case 1:
652 return InputStub.BUTTON_LEFT; 675 return InputStub.BUTTON_LEFT;
(...skipping 11 matching lines...) Expand all
664 float[] mappedPoints = mapScreenPointToImagePoint(screenX, screenY); 687 float[] mappedPoints = mapScreenPointToImagePoint(screenX, screenY);
665 688
666 float imageWidth = (float) mRenderData.imageWidth + EPSILON; 689 float imageWidth = (float) mRenderData.imageWidth + EPSILON;
667 float imageHeight = (float) mRenderData.imageHeight + EPSILON; 690 float imageHeight = (float) mRenderData.imageHeight + EPSILON;
668 691
669 return mappedPoints[0] < -EPSILON || mappedPoints[0] > imageWidth 692 return mappedPoints[0] < -EPSILON || mappedPoints[0] > imageWidth
670 || mappedPoints[1] < -EPSILON || mappedPoints[1] > imageHeig ht; 693 || mappedPoints[1] < -EPSILON || mappedPoints[1] > imageHeig ht;
671 } 694 }
672 } 695 }
673 } 696 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698