[go: nahoru, domu]

blob: f28da04e910f12e92292b537e36ac448c3aa68b1 [file] [log] [blame]
shepshapard648840f2019-07-17 14:28:50 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.ui.core.gesture
18
19import androidx.ui.core.Direction
20import androidx.ui.core.Duration
21import androidx.ui.core.PointerEventPass
22import androidx.ui.core.consumeDownChange
23import androidx.ui.core.ipx
24import androidx.ui.core.milliseconds
shepshapard648840f2019-07-17 14:28:50 -070025import androidx.ui.core.px
26import androidx.ui.testutils.consume
27import androidx.ui.testutils.down
28import androidx.ui.testutils.invokeOverAllPasses
29import androidx.ui.testutils.invokeOverPasses
30import androidx.ui.testutils.moveBy
31import androidx.ui.testutils.moveTo
32import androidx.ui.testutils.up
33import com.google.common.truth.Truth.assertThat
34import org.junit.Before
35import org.junit.Test
36import org.junit.runner.RunWith
37import org.junit.runners.JUnit4
38
39// TODO(shepshapard): Write the following tests.
40// Verify correct shape of slop area (should it be a square or circle)?
41// Test for cases with more than one pointer
42// Test for cases where things are reset when last pointer goes up
43// Verify all methods called during onPostUp
44// Verify default behavior when no callback provided for recognizer or canDrag
45
46// Changing this value will break tests that expect the value to be 10.
47private const val TestTouchSlop = 10
48
49@RunWith(JUnit4::class)
50class TouchSlopExceededGestureDetectorTest {
51
52 private val onTouchSlopExceeded: () -> Unit = { onTouchSlopExceededCallCount++ }
53 private val canDrag: (Direction) -> Boolean = { direction ->
54 canDragDirections.add(direction)
55 canDragReturn
56 }
57 private var onTouchSlopExceededCallCount: Int = 0
58 private var canDragReturn = false
59 private var canDragDirections: MutableList<Direction> = mutableListOf()
60 private lateinit var mRecognizer: TouchSlopExceededGestureRecognizer
61
62 @Before
63 fun setup() {
64 onTouchSlopExceededCallCount = 0
65 canDragReturn = true
66 canDragDirections.clear()
67 mRecognizer =
68 TouchSlopExceededGestureRecognizer(TestTouchSlop.ipx)
69 mRecognizer.canDrag = canDrag
70 mRecognizer.onTouchSlopExceeded = onTouchSlopExceeded
71 }
72
73 // Verify the circumstances under which canDrag should not be called.
74
75 @Test
76 fun onPointerInputChanges_down_canDragNotCalled() {
shepshapard63512902019-10-02 14:44:51 -070077 mRecognizer.pointerInputHandler.invokeOverAllPasses(down())
shepshapard648840f2019-07-17 14:28:50 -070078 assertThat(canDragDirections).isEmpty()
79 }
80
81 @Test
82 fun onPointerInputChanges_downUp_canDragNotCalled() {
Shep Shaparde261df92019-11-15 11:24:31 -080083 val down = down(duration = 0.milliseconds)
shepshapard63512902019-10-02 14:44:51 -070084 mRecognizer.pointerInputHandler.invokeOverAllPasses(down())
Shep Shaparde261df92019-11-15 11:24:31 -080085 val up = down.up(10.milliseconds)
shepshapard63512902019-10-02 14:44:51 -070086 mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
shepshapard648840f2019-07-17 14:28:50 -070087
88 assertThat(canDragDirections).isEmpty()
89 }
90
91 @Test
92 fun onPointerInputChanges_downMoveFullyConsumed_canDragNotCalled() {
93 val down = down()
shepshapard63512902019-10-02 14:44:51 -070094 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -070095 val move = down.moveBy(Duration(milliseconds = 10), 3f, 5f).consume(3f, 5f)
shepshapard63512902019-10-02 14:44:51 -070096 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -070097
98 assertThat(canDragDirections).isEmpty()
99 }
100
101 // Verify the circumstances under which canDrag should be called.
102
103 @Test
104 fun onPointerInputChanges_downMove1Dimension_canDragCalledOnce() {
105 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700106 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700107 val move = down.moveBy(Duration(milliseconds = 10), 3f, 0f)
shepshapard63512902019-10-02 14:44:51 -0700108 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700109
110 // Twice because while under touch slop, TouchSlopExceededGestureDetector checks during PostUp and PostDown
111 assertThat(canDragDirections).hasSize(2)
112 }
113
114 @Test
115 fun onPointerInputChanges_downMove2Dimensions_canDragCalledTwice() {
116 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700117 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700118 val move = down.moveBy(Duration(milliseconds = 10), 3f, 5f)
shepshapard63512902019-10-02 14:44:51 -0700119 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700120
121 // 4 times because while under touch slop, TouchSlopExceededGestureDetector checks during PostUp and
122 // PostDown
123 assertThat(canDragDirections).hasSize(4)
124 }
125
126 @Test
127 fun onPointerInputChanges_downMoveOneDimensionPartiallyConsumed_canDragCalledOnce() {
128 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700129 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700130 val move = down.moveBy(Duration(milliseconds = 10), 0f, 5f).consume(0f, 4f)
shepshapard63512902019-10-02 14:44:51 -0700131 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700132
133 // Twice because while under touch slop, DragGestureDetector checks during PostUp and
134 // PostDown
135 assertThat(canDragDirections).hasSize(2)
136 }
137
138 @Test
139 fun onPointerInputChanges_downMoveTwoDimensionPartiallyConsumed_canDragCalledTwice() {
140 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700141 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700142 val move = down.moveBy(Duration(milliseconds = 10), 3f, 5f).consume(2f, 4f)
shepshapard63512902019-10-02 14:44:51 -0700143 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700144
145 // 4 times because while under touch slop, DragGestureDetector checks during PostUp and
146 // PostDown
147 assertThat(canDragDirections).hasSize(4)
148 }
149
150 @Test
151 fun onPointerInputChanges_dragPastTouchSlopOneDimensionAndDrag3MoreTimes_canDragCalledOnce() {
152 val justBeyondSlop = (TestTouchSlop + 1).toFloat()
153
154 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700155 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
Shep Shaparde261df92019-11-15 11:24:31 -0800156 var move = down.moveTo(10.milliseconds, 0f, justBeyondSlop)
shepshapard63512902019-10-02 14:44:51 -0700157 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700158 repeat(3) {
159 move = move.moveBy(Duration(milliseconds = 10), 0f, 1f)
shepshapard63512902019-10-02 14:44:51 -0700160 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700161 }
162
163 // Once because although DragGestureDetector checks during PostUp and PostDown, slop is
164 // surpassed during PostUp, and thus isn't checked again.
165 assertThat(canDragDirections).hasSize(1)
166 }
167
168 @Test
169 fun onPointerInputChanges_downMoveUnderSlop3Times_canDragCalled3Times() {
170 val thirdSlop = TestTouchSlop.toFloat() / 3
171
172 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700173 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700174 var move = down
175 repeat(3) {
176 move = move.moveBy(Duration(milliseconds = 10), 0f, thirdSlop)
shepshapard63512902019-10-02 14:44:51 -0700177 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700178 }
179
180 // 6 times because while under touch slop, DragGestureDetector checks during PostUp and
181 // PostDown
182 assertThat(canDragDirections).hasSize(6)
183 }
184
185 @Test
186 fun onPointerInputChanges_moveBeyondSlopThenIntoTouchSlopAreaAndOutAgain_canDragCalledOnce() {
187 val beyondTouchSlop = (TestTouchSlop + 1).toFloat()
188
189 var event = down()
shepshapard63512902019-10-02 14:44:51 -0700190 mRecognizer.pointerInputHandler.invokeOverAllPasses(event)
shepshapard648840f2019-07-17 14:28:50 -0700191 // Out of touch slop region
192 event = event.moveBy(Duration(milliseconds = 10), 0f, beyondTouchSlop)
shepshapard63512902019-10-02 14:44:51 -0700193 mRecognizer.pointerInputHandler.invokeOverAllPasses(event)
shepshapard648840f2019-07-17 14:28:50 -0700194 // Back into touch slop region
195 event = event.moveBy(Duration(milliseconds = 10), 0f, -beyondTouchSlop)
shepshapard63512902019-10-02 14:44:51 -0700196 mRecognizer.pointerInputHandler.invokeOverAllPasses(event)
shepshapard648840f2019-07-17 14:28:50 -0700197 // Out of touch slop region again
198 event = event.moveBy(Duration(milliseconds = 10), 0f, beyondTouchSlop)
shepshapard63512902019-10-02 14:44:51 -0700199 mRecognizer.pointerInputHandler.invokeOverAllPasses(event)
shepshapard648840f2019-07-17 14:28:50 -0700200
201 // Once because although DragGestureDetector checks during PostUp and PostDown, slop is
202 // surpassed during PostUp, and thus isn't checked again.
203 assertThat(canDragDirections).hasSize(1)
204 }
205
206 // Verification of correctness of values passed to canDrag.
207
208 @Test
209 fun onPointerInputChanges_canDragCalledWithCorrectDirection() {
210 onPointerInputChanges_canDragCalledWithCorrectDirection(
211 -1f, 0f, arrayOf(Direction.LEFT)
212 )
213 onPointerInputChanges_canDragCalledWithCorrectDirection(
214 0f, -1f, arrayOf(Direction.UP)
215 )
216 onPointerInputChanges_canDragCalledWithCorrectDirection(
217 1f, 0f, arrayOf(Direction.RIGHT)
218 )
219 onPointerInputChanges_canDragCalledWithCorrectDirection(
220 0f, 1f, arrayOf(Direction.DOWN)
221 )
222 onPointerInputChanges_canDragCalledWithCorrectDirection(
223 -1f, -1f, arrayOf(Direction.LEFT, Direction.UP)
224 )
225 onPointerInputChanges_canDragCalledWithCorrectDirection(
226 -1f, 1f, arrayOf(Direction.LEFT, Direction.DOWN)
227 )
228 onPointerInputChanges_canDragCalledWithCorrectDirection(
229 1f, -1f, arrayOf(Direction.RIGHT, Direction.UP)
230 )
231 onPointerInputChanges_canDragCalledWithCorrectDirection(
232 1f, 1f, arrayOf(Direction.RIGHT, Direction.DOWN)
233 )
234 }
235
236 private fun onPointerInputChanges_canDragCalledWithCorrectDirection(
237 dx: Float,
238 dy: Float,
239 expectedDirections: Array<Direction>
240 ) {
241 canDragDirections.clear()
242 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700243 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700244 val move = down.moveBy(Duration(milliseconds = 10), dx, dy)
shepshapard63512902019-10-02 14:44:51 -0700245 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700246
247 // Everything here is twice because DragGestureDetector checks during PostUp and PostDown.
248 assertThat(canDragDirections).hasSize(expectedDirections.size * 2)
249 expectedDirections.forEach { direction ->
250 assertThat(canDragDirections.count { it == direction })
251 .isEqualTo(2)
252 }
253 }
254
255 // Verify the circumstances under which onTouchSlopExceeded should not be called.
256
257 // TODO(b/129701831): This test assumes that if a pointer moves by slop in both x and y, we are
258 // still under slop even though sqrt(slop^2 + slop^2) > slop. This may be inaccurate and this
259 // test may therefore need to be updated.
260 @Test
261 fun onPointerInputChanges_downMoveWithinSlop_onTouchSlopExceededNotCalled() {
262 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700263 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700264 val move = down.moveBy(
265 Duration(milliseconds = 10),
266 TestTouchSlop.toFloat(),
267 TestTouchSlop.toFloat()
268 )
shepshapard63512902019-10-02 14:44:51 -0700269 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700270
271 assertThat(onTouchSlopExceededCallCount).isEqualTo(0)
272 }
273
274 @Test
275 fun onPointerInputChanges_moveBeyondSlopInUnsupportedDirection_onTouchSlopExceededNotCalled() {
276 val beyondSlop = (TestTouchSlop + 1).toFloat()
277 canDragReturn = false
278
279 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700280 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700281 val move = down.moveBy(
282 Duration(milliseconds = 10),
283 beyondSlop,
284 beyondSlop
285 )
shepshapard63512902019-10-02 14:44:51 -0700286 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700287
288 assertThat(onTouchSlopExceededCallCount).isEqualTo(0)
289 }
290
291 @Test
292 fun onPointerInputChanges_moveBeyondSlopButConsumeUnder_onTouchSlopExceededNotCalled() {
293
294 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700295 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700296
297 val move = down().moveBy(10.milliseconds, TestTouchSlop + 1f, 0f).consume(dx = 1f)
shepshapard63512902019-10-02 14:44:51 -0700298 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700299
300 // Assert
301
302 assertThat(onTouchSlopExceededCallCount).isEqualTo(0)
303 }
304
305 @Test
306 fun onPointerInputChanges_moveUnderToPostUpThenModOverInOppDir_onTouchSlopExceededNotCalled() {
307
308 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700309 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700310
311 val move = down().moveBy(10.milliseconds, TestTouchSlop.toFloat(), 0f)
shepshapard63512902019-10-02 14:44:51 -0700312 mRecognizer.pointerInputHandler.invokeOverPasses(
shepshapard648840f2019-07-17 14:28:50 -0700313 listOf(move),
314 PointerEventPass.InitialDown,
315 PointerEventPass.PreUp,
316 PointerEventPass.PreDown,
317 PointerEventPass.PostUp
318 )
319 val move2 = move.consume(dx = (TestTouchSlop * 2f + 1))
shepshapard63512902019-10-02 14:44:51 -0700320 mRecognizer.pointerInputHandler.invokeOverPasses(
shepshapard648840f2019-07-17 14:28:50 -0700321 listOf(move2),
322 PointerEventPass.PostDown
323 )
324
325 // Assert
326
327 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
328 }
329
330 // TODO(b/129701831): This test assumes that if a pointer moves by slop in both x and y, we are
331 // still under slop even though sqrt(slop^2 + slop^2) > slop. This may be inaccurate and this
332 // test may therefore need to be updated.
333 @Test
334 fun onPointerInputChanges_moveAroundWithinSlop_onTouchSlopExceededNotCalled() {
335 val slop = TestTouchSlop.toFloat()
336
337 var change = down()
shepshapard63512902019-10-02 14:44:51 -0700338 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700339
340 // Go around the border of the touch slop area
341
342 // To top left
Shep Shaparde261df92019-11-15 11:24:31 -0800343 change = change.moveTo(10.milliseconds, -slop, -slop)
shepshapard63512902019-10-02 14:44:51 -0700344 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700345 // To bottom left
Shep Shaparde261df92019-11-15 11:24:31 -0800346 change = change.moveTo(20.milliseconds, -slop, slop)
shepshapard63512902019-10-02 14:44:51 -0700347 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700348 // To bottom right
Shep Shaparde261df92019-11-15 11:24:31 -0800349 change = change.moveTo(30.milliseconds, slop, slop)
shepshapard63512902019-10-02 14:44:51 -0700350 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700351 // To top right
Shep Shaparde261df92019-11-15 11:24:31 -0800352 change = change.moveTo(40.milliseconds, slop, -slop)
shepshapard63512902019-10-02 14:44:51 -0700353 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700354
355 // Jump from corner to opposite corner and back
356
357 // To bottom left
Shep Shaparde261df92019-11-15 11:24:31 -0800358 change = change.moveTo(50.milliseconds, -slop, slop)
shepshapard63512902019-10-02 14:44:51 -0700359 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700360 // To top right
Shep Shaparde261df92019-11-15 11:24:31 -0800361 change = change.moveTo(60.milliseconds, slop, -slop)
shepshapard63512902019-10-02 14:44:51 -0700362 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700363
364 // Move the other diagonal
365
366 // To top left
Shep Shaparde261df92019-11-15 11:24:31 -0800367 change = change.moveTo(70.milliseconds, -slop, -slop)
shepshapard63512902019-10-02 14:44:51 -0700368 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700369
370 // Jump from corner to opposite corner and back
371
372 // To bottom right
Shep Shaparde261df92019-11-15 11:24:31 -0800373 change = change.moveTo(80.milliseconds, slop, slop)
shepshapard63512902019-10-02 14:44:51 -0700374 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700375 // To top left
Shep Shaparde261df92019-11-15 11:24:31 -0800376 change = change.moveTo(90.milliseconds, -slop, -slop)
shepshapard63512902019-10-02 14:44:51 -0700377 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700378
379 assertThat(onTouchSlopExceededCallCount).isEqualTo(0)
380 }
381
382 // Verify the circumstances under which onTouchSlopExceeded should be called.
383
384 @Test
385 fun onPointerInputChanges_movePassedSlop_onTouchSlopExceededCallOnce() {
386 val beyondTouchSlop = (TestTouchSlop + 1).toFloat()
387
388 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700389 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700390 val move = down.moveBy(
391 Duration(milliseconds = 100),
392 beyondTouchSlop,
393 0f
394 )
shepshapard63512902019-10-02 14:44:51 -0700395 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700396
397 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
398 }
399
400 @Test
401 fun onPointerInputChanges_movePassedSlopIn2Events_onTouchSlopExceededCallOnce() {
402
403 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700404 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700405 val move = down.moveBy(
406 Duration(milliseconds = 100),
407 TestTouchSlop.toFloat(),
408 0f
409 )
shepshapard63512902019-10-02 14:44:51 -0700410 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700411 val move2 = down.moveBy(
412 Duration(milliseconds = 100),
413 1f,
414 0f
415 )
shepshapard63512902019-10-02 14:44:51 -0700416 mRecognizer.pointerInputHandler.invokeOverAllPasses(move2)
shepshapard648840f2019-07-17 14:28:50 -0700417
418 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
419 }
420
421 @Test
422 fun onPointerInputChanges_passSlopThenInSlopAreaThenOut_onTouchSlopExceededCallOnce() {
423 val beyondTouchSlop = (TestTouchSlop + 1).toFloat()
424
425 var event = down()
shepshapard63512902019-10-02 14:44:51 -0700426 mRecognizer.pointerInputHandler.invokeOverAllPasses(event)
shepshapard648840f2019-07-17 14:28:50 -0700427 // Out of touch slop region
428 event = event.moveBy(Duration(milliseconds = 10), 0f, beyondTouchSlop)
shepshapard63512902019-10-02 14:44:51 -0700429 mRecognizer.pointerInputHandler.invokeOverAllPasses(event)
shepshapard648840f2019-07-17 14:28:50 -0700430 // Back into touch slop region
431 event = event.moveBy(Duration(milliseconds = 10), 0f, -beyondTouchSlop)
shepshapard63512902019-10-02 14:44:51 -0700432 mRecognizer.pointerInputHandler.invokeOverAllPasses(event)
shepshapard648840f2019-07-17 14:28:50 -0700433 // Out of touch slop region again
434 event = event.moveBy(Duration(milliseconds = 10), 0f, beyondTouchSlop)
shepshapard63512902019-10-02 14:44:51 -0700435 mRecognizer.pointerInputHandler.invokeOverAllPasses(event)
shepshapard648840f2019-07-17 14:28:50 -0700436
437 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
438 }
439
440 @Test
441 fun onPointerInputChanges_downConsumedMovePassedSlop_onTouchSlopExceededCallOnce() {
442 val beyondTouchSlop = (TestTouchSlop + 1).toFloat()
443
444 val down = down().consumeDownChange()
shepshapard63512902019-10-02 14:44:51 -0700445 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700446 val move = down.moveBy(Duration(milliseconds = 100), beyondTouchSlop, 0f)
shepshapard63512902019-10-02 14:44:51 -0700447 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700448
449 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
450 }
451
452 @Test
453 fun onPointerInputChanges_beyondInUnsupportThenBeyondInSupport_onTouchSlopExceededCallOnce() {
454 val doubleTouchSlop = (TestTouchSlop * 2).toFloat()
455 val beyondTouchSlop = (TestTouchSlop + 1).toFloat()
456
457 var change = down()
shepshapard63512902019-10-02 14:44:51 -0700458 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700459 canDragReturn = false
460 change = change.moveBy(
461 Duration(milliseconds = 10),
462 0f,
463 doubleTouchSlop
464 )
465 // Sanity check that onTouchSlopExceeded has not been called.
466 assertThat(onTouchSlopExceededCallCount).isEqualTo(0)
467
468 canDragReturn = true
shepshapard63512902019-10-02 14:44:51 -0700469 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700470 change = change.moveBy(
471 Duration(milliseconds = 10),
472 0f,
473 -beyondTouchSlop
474 )
shepshapard63512902019-10-02 14:44:51 -0700475 mRecognizer.pointerInputHandler.invokeOverAllPasses(change)
shepshapard648840f2019-07-17 14:28:50 -0700476
477 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
478 }
479
480 @Test
481 fun onPointerInputChanges_2PointsMoveInOpposite_onTouchSlopExceededCallOnce() {
482
483 // Arrange
484
485 val beyondTouchSlop = (TestTouchSlop + 1).toFloat()
486
487 var pointer1 = down(1)
488 var pointer2 = down(2)
shepshapard63512902019-10-02 14:44:51 -0700489 mRecognizer.pointerInputHandler.invokeOverAllPasses(pointer1, pointer2)
shepshapard648840f2019-07-17 14:28:50 -0700490
491 // Act
492
493 pointer1 = pointer1.moveBy(
494 Duration(milliseconds = 100),
495 beyondTouchSlop,
496 0f
497 )
498 pointer2 = pointer2.moveBy(
499 Duration(milliseconds = 100),
500 -beyondTouchSlop,
501 0f
502 )
shepshapard63512902019-10-02 14:44:51 -0700503 mRecognizer.pointerInputHandler.invokeOverAllPasses(pointer1, pointer2)
shepshapard648840f2019-07-17 14:28:50 -0700504
505 // Assert
506
507 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
508 }
509
510 @Test
511 fun onPointerInputChanges_3PointsMoveAverage0_onTouchSlopExceededCallOnce() {
512
513 // Arrange
514
515 val beyondTouchSlop = (TestTouchSlop + 1).toFloat()
516
517 val pointers = arrayListOf(down(0), down(1), down(2))
shepshapard63512902019-10-02 14:44:51 -0700518 mRecognizer.pointerInputHandler.invokeOverAllPasses(pointers)
shepshapard648840f2019-07-17 14:28:50 -0700519
520 // Act
521
522 // These movements average to no movement.
523 pointers[0] =
524 pointers[0].moveBy(
525 Duration(milliseconds = 100),
526 beyondTouchSlop * -1,
527 beyondTouchSlop * -1
528 )
529 pointers[1] =
530 pointers[1].moveBy(
531 Duration(milliseconds = 100),
532 beyondTouchSlop * 1,
533 beyondTouchSlop * -1
534 )
535 pointers[2] =
536 pointers[2].moveBy(
537 Duration(milliseconds = 100),
538 0f,
539 beyondTouchSlop * 2
540 )
shepshapard63512902019-10-02 14:44:51 -0700541 mRecognizer.pointerInputHandler.invokeOverAllPasses(pointers)
shepshapard648840f2019-07-17 14:28:50 -0700542
543 // Assert
544
545 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
546 }
547
548 @Test
549 fun onPointerInputChanges_5Points1MoveBeyondSlop_onTouchSlopExceededCallOnce() {
550
551 // Arrange
552
553 val beyondTouchSlop = (TestTouchSlop + 1).toFloat()
554
555 val pointers = arrayListOf(down(0), down(1), down(2), down(3), down(4))
shepshapard63512902019-10-02 14:44:51 -0700556 mRecognizer.pointerInputHandler.invokeOverAllPasses(pointers)
shepshapard648840f2019-07-17 14:28:50 -0700557
558 // Act
559
560 // These movements average to no movement.
561 for (i in 0..3) {
562 pointers[i] = pointers[i].moveBy(
563 Duration(milliseconds = 100),
564 0f,
565 0f
566 )
567 }
568 pointers[4] =
569 pointers[4].moveBy(
570 Duration(milliseconds = 100),
571 beyondTouchSlop * -1,
572 0f
573 )
shepshapard63512902019-10-02 14:44:51 -0700574 mRecognizer.pointerInputHandler.invokeOverAllPasses(pointers)
shepshapard648840f2019-07-17 14:28:50 -0700575
576 // Assert
577
578 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
579 }
580
581 @Test
582 fun onPointerInputChanges_1PointMovesBeyondSlopAndThenManyTimes_onTouchSlopExceededCallOnce() {
583
584 // Arrange
585
586 val beyondTouchSlop = (TestTouchSlop + 1).toFloat()
587
588 var pointer = down(0)
shepshapard63512902019-10-02 14:44:51 -0700589 mRecognizer.pointerInputHandler.invokeOverAllPasses(pointer)
shepshapard648840f2019-07-17 14:28:50 -0700590
591 // Act
592
593 repeat(5) {
594 pointer = pointer.moveBy(100.milliseconds, beyondTouchSlop, beyondTouchSlop)
shepshapard63512902019-10-02 14:44:51 -0700595 mRecognizer.pointerInputHandler.invokeOverAllPasses(pointer)
shepshapard648840f2019-07-17 14:28:50 -0700596 }
597
598 // Assert
599
600 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
601 }
602
603 @Test
604 fun onPointerInputChanges_1ModifiedToMoveBeyondSlopBeforePostUp_onTouchSlopExceededCallOnce() {
605
606 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700607 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700608
609 val move = down().moveBy(10.milliseconds, 0f, 0f).consume(dx = TestTouchSlop + 1f)
shepshapard63512902019-10-02 14:44:51 -0700610 mRecognizer.pointerInputHandler.invokeOverPasses(
shepshapard648840f2019-07-17 14:28:50 -0700611 listOf(move),
612 PointerEventPass.InitialDown,
613 PointerEventPass.PreUp,
614 PointerEventPass.PreDown,
615 PointerEventPass.PostUp
616 )
617
618 // Assert
619
620 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
621 }
622
623 @Test
624 fun onPointerInputChanges_1ModedToMoveBeyondSlopBeforePostDown_onTouchSlopExceededCallOnce() {
625
626 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700627 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700628
629 val move = down().moveBy(10.milliseconds, 0f, 0f)
shepshapard63512902019-10-02 14:44:51 -0700630 mRecognizer.pointerInputHandler.invokeOverPasses(
shepshapard648840f2019-07-17 14:28:50 -0700631 listOf(move),
632 PointerEventPass.InitialDown,
633 PointerEventPass.PreUp,
634 PointerEventPass.PreDown,
635 PointerEventPass.PostUp
636 )
637
638 val moveConsumed = move.consume(dx = TestTouchSlop + 1f)
shepshapard63512902019-10-02 14:44:51 -0700639 mRecognizer.pointerInputHandler.invokeOverPasses(
shepshapard648840f2019-07-17 14:28:50 -0700640 listOf(moveConsumed),
641 PointerEventPass.PostDown
642 )
643
644 // Assert
645
646 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
647 }
648
649 @Test
650 fun onPointerInputChanges_moveUnderToPostUpThenModOverToPostDown_onTouchSlopExceededCallOnce() {
651
652 val halfSlop = TestTouchSlop / 2
653 val restOfSlopAndBeyond = TestTouchSlop - halfSlop + 1
654
655 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700656 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700657
658 val move = down().moveBy(10.milliseconds, halfSlop.toFloat(), 0f)
shepshapard63512902019-10-02 14:44:51 -0700659 mRecognizer.pointerInputHandler.invokeOverPasses(
shepshapard648840f2019-07-17 14:28:50 -0700660 listOf(move),
661 PointerEventPass.InitialDown,
662 PointerEventPass.PreUp,
663 PointerEventPass.PreDown,
664 PointerEventPass.PostUp
665 )
666
667 val moveConsumed = move.consume(dx = -restOfSlopAndBeyond.toFloat())
shepshapard63512902019-10-02 14:44:51 -0700668 mRecognizer.pointerInputHandler.invokeOverPasses(
shepshapard648840f2019-07-17 14:28:50 -0700669 listOf(moveConsumed),
670 PointerEventPass.PostDown
671 )
672
673 // Assert
674
675 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
676 }
677
678 @Test
679 fun onPointerInputChanges_moveBeyondSlopAllPassesUpToPostUp_onTouchSlopExceededCallOnce() {
680
681 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700682 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700683
684 val move = down().moveBy(10.milliseconds, TestTouchSlop + 1f, 0f)
shepshapard63512902019-10-02 14:44:51 -0700685 mRecognizer.pointerInputHandler.invokeOverPasses(
shepshapard648840f2019-07-17 14:28:50 -0700686 listOf(move),
687 PointerEventPass.InitialDown,
688 PointerEventPass.PreUp,
689 PointerEventPass.PreDown,
690 PointerEventPass.PostUp
691 )
692
693 // Assert
694
695 assertThat(onTouchSlopExceededCallCount).isEqualTo(1)
696 }
697
698 // Verification that TouchSlopExceededGestureDetector does not consume any changes.
699
700 @Test
701 fun onPointerInputChanges_1Down_nothingConsumed() {
702
shepshapard63512902019-10-02 14:44:51 -0700703 val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(down())
shepshapard648840f2019-07-17 14:28:50 -0700704
705 // Assert
706
707 assertThat(result[0].consumed.downChange).isFalse()
708 assertThat(result[0].consumed.positionChange.x).isEqualTo(0.px)
709 assertThat(result[0].consumed.positionChange.y).isEqualTo(0.px)
710 }
711
712 @Test
713 fun onPointerInputChanges_1MoveUnderSlop_nothingConsumed() {
714
715 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700716 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700717
718 val move = down().moveBy(10.milliseconds, TestTouchSlop.toFloat(), TestTouchSlop.toFloat())
shepshapard63512902019-10-02 14:44:51 -0700719 val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700720
721 // Assert
722
723 assertThat(result[0].consumed.downChange).isFalse()
724 assertThat(result[0].consumed.positionChange.x).isEqualTo(0.px)
725 assertThat(result[0].consumed.positionChange.y).isEqualTo(0.px)
726 }
727
728 @Test
729 fun onPointerInputChanges_1MoveUnderSlopThenUp_nothingConsumed() {
730
731 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700732 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700733
734 val move = down().moveBy(10.milliseconds, TestTouchSlop.toFloat(), TestTouchSlop.toFloat())
shepshapard63512902019-10-02 14:44:51 -0700735 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700736
Shep Shaparde261df92019-11-15 11:24:31 -0800737 val up = move.up(20.milliseconds)
shepshapard63512902019-10-02 14:44:51 -0700738 val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
shepshapard648840f2019-07-17 14:28:50 -0700739
740 // Assert
741
742 assertThat(result[0].consumed.downChange).isFalse()
743 assertThat(result[0].consumed.positionChange.x).isEqualTo(0.px)
744 assertThat(result[0].consumed.positionChange.y).isEqualTo(0.px)
745 }
746
747 @Test
748 fun onPointerInputChanges_1MoveOverSlop_nothingConsumed() {
749
750 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700751 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700752
753 val move = down().moveBy(10.milliseconds, TestTouchSlop + 1f, TestTouchSlop + 1f)
shepshapard63512902019-10-02 14:44:51 -0700754 val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700755
756 // Assert
757
758 assertThat(result[0].consumed.downChange).isFalse()
759 assertThat(result[0].consumed.positionChange.x).isEqualTo(0.px)
760 assertThat(result[0].consumed.positionChange.y).isEqualTo(0.px)
761 }
762
763 @Test
764 fun onPointerInputChanges_1MoveOverSlopThenUp_nothingConsumed() {
765
766 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700767 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700768
769 val move = down().moveBy(10.milliseconds, TestTouchSlop + 1f, TestTouchSlop + 1f)
shepshapard63512902019-10-02 14:44:51 -0700770 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700771
Shep Shaparde261df92019-11-15 11:24:31 -0800772 val up = move.up(20.milliseconds)
shepshapard63512902019-10-02 14:44:51 -0700773 val result = mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
shepshapard648840f2019-07-17 14:28:50 -0700774
775 // Assert
776
777 assertThat(result[0].consumed.downChange).isFalse()
778 assertThat(result[0].consumed.positionChange.x).isEqualTo(0.px)
779 assertThat(result[0].consumed.positionChange.y).isEqualTo(0.px)
780 }
781
782 // Verification that TouchSlopExceededGestureDetector resets after up correctly.
783
784 @Test
785 fun onPointerInputChanges_MoveBeyondUpDownMoveBeyond_onTouchSlopExceededCalledTwice() {
786
787 repeat(2) {
788 val down = down()
shepshapard63512902019-10-02 14:44:51 -0700789 mRecognizer.pointerInputHandler.invokeOverAllPasses(down)
shepshapard648840f2019-07-17 14:28:50 -0700790
791 val move = down().moveBy(10.milliseconds, TestTouchSlop + 1f, 0f)
shepshapard63512902019-10-02 14:44:51 -0700792 mRecognizer.pointerInputHandler.invokeOverAllPasses(move)
shepshapard648840f2019-07-17 14:28:50 -0700793
Shep Shaparde261df92019-11-15 11:24:31 -0800794 val up = move.up(20.milliseconds)
shepshapard63512902019-10-02 14:44:51 -0700795 mRecognizer.pointerInputHandler.invokeOverAllPasses(up)
shepshapard648840f2019-07-17 14:28:50 -0700796 }
797
798 assertThat(onTouchSlopExceededCallCount).isEqualTo(2)
799 }
800}