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

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

Issue 2097273002: [Chromoting] Add InputMonitor and InputState (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Resolve review comments Created 4 years, 5 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
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chromoting;
6
7 import android.content.Context;
8 import android.graphics.Rect;
9 import android.view.GestureDetector;
10 import android.view.MotionEvent;
11 import android.view.ScaleGestureDetector;
12 import android.view.ViewConfiguration;
13
14 import org.chromium.chromoting.InputState.DetectedAction;
15 import org.chromium.chromoting.InputState.StartAction;
16
17 /**
18 * A combination of existing Android and chromium motion and touch detectors, an d provide a set of
19 * {@link Event} when each kind of touch behavior has been detected.
20 */
21 public final class InputMonitor
22 implements GestureDetector.OnGestureListener,
23 ScaleGestureDetector.OnScaleGestureListener,
24 TapGestureDetector.OnTapListener {
25 /** Tap with one or more fingers. */
26 private final Event.Raisable<TapEventParameter> mOnTap;
27
28 /** Long press and hold with one or more fingers. */
29 private final Event.Raisable<TapEventParameter> mOnPressAndHold;
30
31 /** Any motion event received. */
32 private final Event.Raisable<MotionEvent> mOnTouchEvent;
33
34 /** Scroll with two fingers. */
35 private final Event.Raisable<TwoPointsEventParameter> mOnScroll;
36
37 /** Fling with two fingers. */
38 private final Event.Raisable<TwoPointsEventParameter> mOnScrollFling;
39
40 /** Fling with one finger. */
41 private final Event.Raisable<TwoPointsEventParameter> mOnFling;
42
43 /** Scale with two fingers. */
44 private final Event.Raisable<ScaleEventParameter> mOnScale;
45
46 /** Swipe with three or more fingers. */
47 private final Event.Raisable<TwoPointsEventParameter> mOnSwipe;
48
49 /** Move with one finger. */
50 private final Event.Raisable<TwoPointsEventParameter> mOnMove;
51
52 private final InputState.Settable mInputState;
53 private final int mEdgeSlopInPx;
54 private final float mSwipeThreshold;
55 private final GestureDetector mScroller;
56 private final ScaleGestureDetector mZoomer;
57 private final TapGestureDetector mTapDetector;
58 private final SwipePinchDetector mSwipePinchDetector;
59
60 private Rect mPanGestureBounds;
61
62 InputMonitor(AbstractDesktopView view, Context context) {
63 mOnTap = new Event.Raisable<>();
64 mOnPressAndHold = new Event.Raisable<>();
65 mOnTouchEvent = new Event.Raisable<>();
66 mOnScroll = new Event.Raisable<>();
67 mOnScrollFling = new Event.Raisable<>();
68 mOnFling = new Event.Raisable<>();
69 mOnScale = new Event.Raisable<>();
70 mOnSwipe = new Event.Raisable<>();
71 mOnMove = new Event.Raisable<>();
72 mInputState = new InputState.Settable();
73 mEdgeSlopInPx = ViewConfiguration.get(context).getScaledEdgeSlop();
74 mSwipeThreshold = 40 * context.getResources().getDisplayMetrics().densit y;
75 mScroller = new GestureDetector(context, this, null, false);
76 mScroller.setIsLongpressEnabled(false);
77 mZoomer = new ScaleGestureDetector(context, this);
78 mTapDetector = new TapGestureDetector(context, this);
79 mSwipePinchDetector = new SwipePinchDetector(context);
80 view.onClientSizeChanged().add(
81 new Event.ParameterRunnable<SizeChangedEventParameter>() {
82 @Override
83 public void run(SizeChangedEventParameter param) {
84 handleClientSizeChanged(param);
85 }
86 });
87 // Currently we support only touch events.
88 view.onTouch().add(
89 new Event.ParameterRunnable<TouchEventParameter>() {
90 @Override
91 public void run(TouchEventParameter param) {
92 handleTouch(param);
93 }
94 });
95 }
96
97 // -------------- Getters -------------------------------------------------- -----------
98 public Event<TapEventParameter> onTap() {
99 return mOnTap;
100 }
101
102 public Event<TapEventParameter> onPressAndHold() {
103 return mOnPressAndHold;
104 }
105
106 public Event<MotionEvent> onTouchEvent() {
107 return mOnTouchEvent;
108 }
109
110 public Event<TwoPointsEventParameter> onScroll() {
111 return mOnScroll;
112 }
113
114 public Event<TwoPointsEventParameter> onScrollFling() {
115 return mOnScrollFling;
116 }
117
118 public Event<TwoPointsEventParameter> onFling() {
119 return mOnFling;
120 }
121
122 public Event<ScaleEventParameter> onScale() {
123 return mOnScale;
124 }
125
126 public Event<TwoPointsEventParameter> onSwipe() {
127 return mOnSwipe;
128 }
129
130 public Event<TwoPointsEventParameter> onMove() {
131 return mOnMove;
132 }
133
134 public InputState inputState() {
135 return mInputState;
136 }
137
138 // -------------- Implementations of GestureDetector.OnGestureListener ----- -----------
139
140 /** Called whenever a gesture starts. Always accepts the gesture so it isn't ignored. */
141 @Override
142 public boolean onDown(MotionEvent e) {
143 return true;
144 }
145
146 /** Called when a fling gesture is recognized. */
147 @Override
148 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, floa t velocityY) {
149 if (mInputState.shouldSuppressFling()) {
150 return false;
151 }
152
153 if (mInputState.isScrollFling()) {
154 mInputState.setDetectedAction(DetectedAction.AFTER_SCROLL_FLING);
155 mOnScrollFling.raise(new TwoPointsEventParameter(e1, e2, velocityX, velocityY));
156 return true;
157 }
158
159 if (mInputState.shouldSuppressCursorMovement()) {
160 return false;
161 }
162
163 mInputState.setDetectedAction(DetectedAction.FLING);
164 mOnFling.raise(new TwoPointsEventParameter(e1, e2, velocityX, velocityY) );
165 return true;
166 }
167
168 /** Called when a long-press is triggered for one or more fingers. */
169 @Override
170 public void onLongPress(MotionEvent e) {}
171
172 /** Called when the user drags one or more fingers across the touchscreen. * /
173 @Override
174 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, flo at distanceY) {
175 if (!isInPanGestureBounds(e1)) {
176 // The gesture of scrolling from edge to the center should be handle d by Android OS.
177 mInputState.setDetectedAction(InputState.DetectedAction.SCROLL_EDGE) ;
178 return false;
179 }
180
181 if (e2.getPointerCount() >= 3 && !mInputState.swipeCompleted()) {
182 if (distanceY > mSwipeThreshold || distanceY < -mSwipeThreshold) {
183 mInputState.setDetectedAction(DetectedAction.SWIPE);
184 mOnSwipe.raise(new TwoPointsEventParameter(e1, e2, distanceX, di stanceY));
185 return true;
186 }
187 return false;
188 }
189
190 if (e2.getPointerCount() == 2 && mSwipePinchDetector.isSwiping()) {
191 mInputState.setDetectedAction(DetectedAction.SCROLL);
192 mOnScroll.raise(new TwoPointsEventParameter(e1, e2, distanceX, dista nceY));
193 return true;
194 }
195
196 if (e2.getPointerCount() != 1 || mInputState.shouldSuppressCursorMovemen t()) {
197 return false;
198 }
199
200 mInputState.setDetectedAction(DetectedAction.MOVE);
201 mOnMove.raise(new TwoPointsEventParameter(e1, e2, distanceX, distanceY)) ;
202 return true;
203 }
204
205 /** Called by {@link GestureDetector}, does nothing. */
206 @Override
207 public void onShowPress(MotionEvent e) {}
208
209 /** Called by {@link GestureDetector}, returns false to continue following g esture detection. */
210 @Override
211 public boolean onSingleTapUp(MotionEvent e) {
212 return false;
213 }
214
215 // --------- Implementations of ScaleGestureDetector.OnScaleGestureListener -----------
216 /** Called when the user is in the process of pinch-zooming. */
217 @Override
218 public boolean onScale(ScaleGestureDetector detector) {
219 if (!mSwipePinchDetector.isPinching()) {
220 return false;
221 }
222
223 mInputState.setDetectedAction(DetectedAction.SCALE);
224 mOnScale.raise(new ScaleEventParameter(detector.getScaleFactor(),
225 detector.getFocusX(),
226 detector.getFocusY()));
227 return true;
228 }
229
230 /**
231 * Called when the user starts to zoom. Always accepts the zoom so that
232 * onScale() can decide whether to respond to it.
233 */
234 @Override
235 public boolean onScaleBegin(ScaleGestureDetector detector) {
236 return true;
237 }
238
239 /** Called when the user is done zooming. Defers to onScale()'s judgement. * /
240 @Override
241 public void onScaleEnd(ScaleGestureDetector detector) {
242 onScale(detector);
243 }
244
245 // -------------- Implementations of TapGestureDetector.OnTapListener ------ ----------
246 /** Called when the user taps the screen with one or more fingers. */
247 @Override
248 public boolean onTap(int pointerCount, float x, float y) {
249 TapEventParameter para = new TapEventParameter(pointerCount, x, y);
250 mOnTap.raise(para);
251 return para.handled;
252 }
253
254 /** Called when a long-press is triggered for one or more fingers. */
255 @Override
256 public void onLongPress(int pointerCount, float x, float y) {
257 TapEventParameter para = new TapEventParameter(pointerCount, x, y);
258 mOnPressAndHold.raise(para);
259 if (para.handled) {
260 mInputState.setStartAction(StartAction.LONG_PRESS);
261 }
262 }
263
264 /**
265 * Returns a boolean value to indicate whether the MotionEvent is in the ran ge of
266 * {@link mPanGestureBounds}
267 */
268 private boolean isInPanGestureBounds(MotionEvent e) {
269 Preconditions.notNull(e);
270 return mPanGestureBounds == null
271 || mPanGestureBounds.contains((int) e.getX(), (int) e.getY());
272 }
273
274 // ---------------------------- Event handlers ----------------------------- ----------
275 private void handleClientSizeChanged(SizeChangedEventParameter parameter) {
276 mPanGestureBounds = new Rect(mEdgeSlopInPx,
277 mEdgeSlopInPx,
278 parameter.width - mEdgeSlopInPx,
279 parameter.height - mEdgeSlopInPx);
280 }
281
282 private void handleTouch(TouchEventParameter parameter) {
283 mOnTouchEvent.raise(parameter.event);
284
285 boolean handled = mScroller.onTouchEvent(parameter.event);
286 handled |= mZoomer.onTouchEvent(parameter.event);
287 handled |= mTapDetector.onTouchEvent(parameter.event);
288 mSwipePinchDetector.onTouchEvent(parameter.event);
289
290 parameter.handled = handled;
291 }
292 }
OLDNEW
« no previous file with comments | « remoting/android/client_java_tmpl.gni ('k') | remoting/android/java/src/org/chromium/chromoting/InputState.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698