Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "GestureEventListener.h"
8
#include <math.h> // for fabsf
9
#include <stddef.h> // for size_t
10
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
11
#include "InputBlockState.h" // for TouchBlockState
12
#include "base/task.h" // for CancelableTask, etc
13
#include "InputBlockState.h" // for TouchBlockState
14
#include "mozilla/StaticPrefs_apz.h"
15
#include "mozilla/StaticPrefs_ui.h"
16
#include "nsDebug.h" // for NS_WARNING
17
#include "nsMathUtils.h" // for NS_hypot
18
19
static mozilla::LazyLogModule sApzGelLog("apz.gesture");
20
#define GEL_LOG(...) MOZ_LOG(sApzGelLog, LogLevel::Debug, (__VA_ARGS__))
21
22
namespace mozilla {
23
namespace layers {
24
25
/**
26
* Amount of span or focus change needed to take us from the
27
* GESTURE_WAITING_PINCH state to the GESTURE_PINCH state. This is measured as
28
* either a change in distance between the fingers used to compute the span
29
* ratio, or the a change in position of the focus point between the two
30
* fingers.
31
*/
32
static const float PINCH_START_THRESHOLD = 35.0f;
33
34
/**
35
* Determines how fast a one touch pinch zooms in and out. The greater the
36
* value, the faster it zooms.
37
*/
38
static const float ONE_TOUCH_PINCH_SPEED = 0.005f;
39
40
static bool sLongTapEnabled = true;
41
42
static ScreenPoint GetCurrentFocus(const MultiTouchInput& aEvent) {
43
const ScreenPoint& firstTouch = aEvent.mTouches[0].mScreenPoint;
44
const ScreenPoint& secondTouch = aEvent.mTouches[1].mScreenPoint;
45
return (firstTouch + secondTouch) / 2;
46
}
47
48
static ScreenCoord GetCurrentSpan(const MultiTouchInput& aEvent) {
49
const ScreenPoint& firstTouch = aEvent.mTouches[0].mScreenPoint;
50
const ScreenPoint& secondTouch = aEvent.mTouches[1].mScreenPoint;
51
ScreenPoint delta = secondTouch - firstTouch;
52
return delta.Length();
53
}
54
55
ScreenCoord GestureEventListener::GetYSpanFromGestureStartPoint() {
56
// use the position that began the one-touch-pinch gesture rather
57
// mTouchStartPosition
58
const ScreenPoint start = mOneTouchPinchStartPosition;
59
const ScreenPoint& current = mTouches[0].mScreenPoint;
60
return current.y - start.y;
61
}
62
63
static TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch,
64
TapGestureInput::TapGestureType aType) {
65
return TapGestureInput(aType, aTouch.mTime, aTouch.mTimeStamp,
66
aTouch.mTouches[0].mScreenPoint, aTouch.modifiers);
67
}
68
69
GestureEventListener::GestureEventListener(
70
AsyncPanZoomController* aAsyncPanZoomController)
71
: mAsyncPanZoomController(aAsyncPanZoomController),
72
mState(GESTURE_NONE),
73
mSpanChange(0.0f),
74
mPreviousSpan(0.0f),
75
mFocusChange(0.0f),
76
mLastTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0),
77
mLastTapInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0),
78
mLongTapTimeoutTask(nullptr),
79
mMaxTapTimeoutTask(nullptr) {}
80
81
GestureEventListener::~GestureEventListener() = default;
82
83
nsEventStatus GestureEventListener::HandleInputEvent(
84
const MultiTouchInput& aEvent) {
85
GEL_LOG("Receiving event type %d with %zu touches in state %d\n",
86
aEvent.mType, aEvent.mTouches.Length(), mState);
87
88
nsEventStatus rv = nsEventStatus_eIgnore;
89
90
// Cache the current event since it may become the single or long tap that we
91
// send.
92
mLastTouchInput = aEvent;
93
94
switch (aEvent.mType) {
95
case MultiTouchInput::MULTITOUCH_START:
96
mTouches.Clear();
97
// Cache every touch.
98
for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
99
mTouches.AppendElement(aEvent.mTouches[i]);
100
}
101
102
if (aEvent.mTouches.Length() == 1) {
103
rv = HandleInputTouchSingleStart();
104
} else {
105
rv = HandleInputTouchMultiStart();
106
}
107
break;
108
case MultiTouchInput::MULTITOUCH_MOVE:
109
// Update the screen points of the cached touches.
110
for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
111
for (size_t j = 0; j < mTouches.Length(); j++) {
112
if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) {
113
mTouches[j].mScreenPoint = aEvent.mTouches[i].mScreenPoint;
114
mTouches[j].mLocalScreenPoint =
115
aEvent.mTouches[i].mLocalScreenPoint;
116
}
117
}
118
}
119
rv = HandleInputTouchMove();
120
break;
121
case MultiTouchInput::MULTITOUCH_END:
122
// Remove the cache of the touch that ended.
123
for (size_t i = 0; i < aEvent.mTouches.Length(); i++) {
124
for (size_t j = 0; j < mTouches.Length(); j++) {
125
if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) {
126
mTouches.RemoveElementAt(j);
127
break;
128
}
129
}
130
}
131
132
rv = HandleInputTouchEnd();
133
break;
134
case MultiTouchInput::MULTITOUCH_CANCEL:
135
mTouches.Clear();
136
rv = HandleInputTouchCancel();
137
break;
138
}
139
140
return rv;
141
}
142
143
int32_t GestureEventListener::GetLastTouchIdentifier() const {
144
if (mTouches.Length() != 1) {
145
NS_WARNING(
146
"GetLastTouchIdentifier() called when last touch event "
147
"did not have one touch");
148
}
149
return mTouches.IsEmpty() ? -1 : mTouches[0].mIdentifier;
150
}
151
152
/* static */
153
void GestureEventListener::SetLongTapEnabled(bool aLongTapEnabled) {
154
sLongTapEnabled = aLongTapEnabled;
155
}
156
157
void GestureEventListener::EnterFirstSingleTouchDown() {
158
SetState(GESTURE_FIRST_SINGLE_TOUCH_DOWN);
159
mTouchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
160
mTouchStartOffset = mLastTouchInput.mScreenOffset;
161
162
if (sLongTapEnabled) {
163
CreateLongTapTimeoutTask();
164
}
165
CreateMaxTapTimeoutTask();
166
}
167
168
nsEventStatus GestureEventListener::HandleInputTouchSingleStart() {
169
switch (mState) {
170
case GESTURE_NONE:
171
EnterFirstSingleTouchDown();
172
break;
173
case GESTURE_FIRST_SINGLE_TOUCH_UP:
174
if (SecondTapIsFar()) {
175
// If the second tap goes down far away from the first, then bail out
176
// of any gesture that includes the first tap.
177
CancelLongTapTimeoutTask();
178
CancelMaxTapTimeoutTask();
179
mSingleTapSent = Nothing();
180
181
// But still allow the second tap to participate in a gesture
182
// (e.g. lead to a single tap, or a double tap if an additional
183
// tap occurs near the same location).
184
EnterFirstSingleTouchDown();
185
} else {
186
// Otherwise, reset the touch start position so that, if this turns into
187
// a one-touch-pinch gesture, it uses the second tap's down position as
188
// the focus, rather than the first tap's.
189
mTouchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
190
mTouchStartOffset = mLastTouchInput.mScreenOffset;
191
SetState(GESTURE_SECOND_SINGLE_TOUCH_DOWN);
192
}
193
break;
194
default:
195
NS_WARNING("Unhandled state upon single touch start");
196
SetState(GESTURE_NONE);
197
break;
198
}
199
200
return nsEventStatus_eIgnore;
201
}
202
203
nsEventStatus GestureEventListener::HandleInputTouchMultiStart() {
204
nsEventStatus rv = nsEventStatus_eIgnore;
205
206
switch (mState) {
207
case GESTURE_NONE:
208
SetState(GESTURE_MULTI_TOUCH_DOWN);
209
break;
210
case GESTURE_FIRST_SINGLE_TOUCH_DOWN:
211
CancelLongTapTimeoutTask();
212
CancelMaxTapTimeoutTask();
213
SetState(GESTURE_MULTI_TOUCH_DOWN);
214
// Prevent APZC::OnTouchStart() from handling MULTITOUCH_START event
215
rv = nsEventStatus_eConsumeNoDefault;
216
break;
217
case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN:
218
CancelLongTapTimeoutTask();
219
SetState(GESTURE_MULTI_TOUCH_DOWN);
220
// Prevent APZC::OnTouchStart() from handling MULTITOUCH_START event
221
rv = nsEventStatus_eConsumeNoDefault;
222
break;
223
case GESTURE_FIRST_SINGLE_TOUCH_UP:
224
case GESTURE_SECOND_SINGLE_TOUCH_DOWN:
225
// Cancel wait for double tap
226
CancelMaxTapTimeoutTask();
227
MOZ_ASSERT(mSingleTapSent.isSome());
228
if (!mSingleTapSent.value()) {
229
TriggerSingleTapConfirmedEvent();
230
}
231
mSingleTapSent = Nothing();
232
SetState(GESTURE_MULTI_TOUCH_DOWN);
233
// Prevent APZC::OnTouchStart() from handling MULTITOUCH_START event
234
rv = nsEventStatus_eConsumeNoDefault;
235
break;
236
case GESTURE_LONG_TOUCH_DOWN:
237
SetState(GESTURE_MULTI_TOUCH_DOWN);
238
break;
239
case GESTURE_MULTI_TOUCH_DOWN:
240
case GESTURE_PINCH:
241
// Prevent APZC::OnTouchStart() from handling MULTITOUCH_START event
242
rv = nsEventStatus_eConsumeNoDefault;
243
break;
244
default:
245
NS_WARNING("Unhandled state upon multitouch start");
246
SetState(GESTURE_NONE);
247
break;
248
}
249
250
return rv;
251
}
252
253
bool GestureEventListener::MoveDistanceExceeds(ScreenCoord aThreshold) const {
254
ExternalPoint start = AsyncPanZoomController::ToExternalPoint(
255
mTouchStartOffset, mTouchStartPosition);
256
ExternalPoint end = AsyncPanZoomController::ToExternalPoint(
257
mLastTouchInput.mScreenOffset, mLastTouchInput.mTouches[0].mScreenPoint);
258
return (start - end).Length() > aThreshold;
259
}
260
261
bool GestureEventListener::MoveDistanceIsLarge() const {
262
return MoveDistanceExceeds(mAsyncPanZoomController->GetTouchStartTolerance());
263
}
264
265
bool GestureEventListener::SecondTapIsFar() const {
266
// Allow a little more room here, because the is actually lifting their finger
267
// off the screen before replacing it, and that tends to have more error than
268
// wiggling the finger while on the screen.
269
return MoveDistanceExceeds(mAsyncPanZoomController->GetSecondTapTolerance());
270
}
271
272
nsEventStatus GestureEventListener::HandleInputTouchMove() {
273
nsEventStatus rv = nsEventStatus_eIgnore;
274
275
switch (mState) {
276
case GESTURE_NONE:
277
// Ignore this input signal as the corresponding events get handled by
278
// APZC
279
break;
280
281
case GESTURE_LONG_TOUCH_DOWN:
282
if (MoveDistanceIsLarge()) {
283
// So that we don't fire a long-tap-up if the user moves around after a
284
// long-tap
285
SetState(GESTURE_NONE);
286
}
287
break;
288
289
case GESTURE_FIRST_SINGLE_TOUCH_DOWN:
290
case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: {
291
// If we move too much, bail out of the tap.
292
if (MoveDistanceIsLarge()) {
293
CancelLongTapTimeoutTask();
294
CancelMaxTapTimeoutTask();
295
mSingleTapSent = Nothing();
296
SetState(GESTURE_NONE);
297
}
298
break;
299
}
300
301
// The user has performed a double tap, but not lifted her finger.
302
case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
303
// If touch has moved noticeably (within StaticPrefs::apz_max_tap_time()),
304
// change state.
305
if (MoveDistanceIsLarge()) {
306
CancelLongTapTimeoutTask();
307
CancelMaxTapTimeoutTask();
308
mSingleTapSent = Nothing();
309
if (!StaticPrefs::apz_one_touch_pinch_enabled()) {
310
// If the one-touch-pinch feature is disabled, bail out of the double-
311
// tap gesture instead.
312
SetState(GESTURE_NONE);
313
break;
314
}
315
316
SetState(GESTURE_ONE_TOUCH_PINCH);
317
318
ScreenCoord currentSpan = 1.0f;
319
ScreenPoint currentFocus = mTouchStartPosition;
320
321
// save the position that the one-touch-pinch gesture actually begins
322
mOneTouchPinchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
323
324
PinchGestureInput pinchEvent(
325
PinchGestureInput::PINCHGESTURE_START, mLastTouchInput.mTime,
326
mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset,
327
currentFocus, currentSpan, currentSpan, mLastTouchInput.modifiers);
328
329
rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
330
331
mPreviousSpan = currentSpan;
332
mPreviousFocus = currentFocus;
333
}
334
break;
335
}
336
337
case GESTURE_MULTI_TOUCH_DOWN: {
338
if (mLastTouchInput.mTouches.Length() < 2) {
339
NS_WARNING(
340
"Wrong input: less than 2 moving points in "
341
"GESTURE_MULTI_TOUCH_DOWN state");
342
break;
343
}
344
345
ScreenCoord currentSpan = GetCurrentSpan(mLastTouchInput);
346
ScreenPoint currentFocus = GetCurrentFocus(mLastTouchInput);
347
348
mSpanChange += fabsf(currentSpan - mPreviousSpan);
349
mFocusChange += (currentFocus - mPreviousFocus).Length();
350
if (mSpanChange > PINCH_START_THRESHOLD ||
351
mFocusChange > PINCH_START_THRESHOLD) {
352
SetState(GESTURE_PINCH);
353
PinchGestureInput pinchEvent(
354
PinchGestureInput::PINCHGESTURE_START, mLastTouchInput.mTime,
355
mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset,
356
currentFocus, currentSpan, currentSpan, mLastTouchInput.modifiers);
357
358
rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
359
} else {
360
// Prevent APZC::OnTouchMove from processing a move event when two
361
// touches are active
362
rv = nsEventStatus_eConsumeNoDefault;
363
}
364
365
mPreviousSpan = currentSpan;
366
mPreviousFocus = currentFocus;
367
break;
368
}
369
370
case GESTURE_PINCH: {
371
if (mLastTouchInput.mTouches.Length() < 2) {
372
NS_WARNING(
373
"Wrong input: less than 2 moving points in GESTURE_PINCH state");
374
// Prevent APZC::OnTouchMove() from handling this wrong input
375
rv = nsEventStatus_eConsumeNoDefault;
376
break;
377
}
378
379
ScreenCoord currentSpan = GetCurrentSpan(mLastTouchInput);
380
381
PinchGestureInput pinchEvent(
382
PinchGestureInput::PINCHGESTURE_SCALE, mLastTouchInput.mTime,
383
mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset,
384
GetCurrentFocus(mLastTouchInput), currentSpan, mPreviousSpan,
385
mLastTouchInput.modifiers);
386
387
rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
388
mPreviousSpan = currentSpan;
389
390
break;
391
}
392
393
case GESTURE_ONE_TOUCH_PINCH: {
394
ScreenCoord currentSpan = GetYSpanFromGestureStartPoint();
395
float effectiveSpan =
396
1.0f + (fabsf(currentSpan.value) * ONE_TOUCH_PINCH_SPEED);
397
ScreenPoint currentFocus = mTouchStartPosition;
398
399
// Invert zoom.
400
if (currentSpan.value < 0) {
401
effectiveSpan = 1.0f / effectiveSpan;
402
}
403
404
PinchGestureInput pinchEvent(
405
PinchGestureInput::PINCHGESTURE_SCALE, mLastTouchInput.mTime,
406
mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset,
407
currentFocus, effectiveSpan, mPreviousSpan,
408
mLastTouchInput.modifiers);
409
410
rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
411
mPreviousSpan = effectiveSpan;
412
413
break;
414
}
415
416
default:
417
NS_WARNING("Unhandled state upon touch move");
418
SetState(GESTURE_NONE);
419
break;
420
}
421
422
return rv;
423
}
424
425
nsEventStatus GestureEventListener::HandleInputTouchEnd() {
426
// We intentionally do not pass apzc return statuses up since
427
// it may cause apzc stay in the touching state even after
428
// gestures are completed (please see Bug 1013378 for reference).
429
430
nsEventStatus rv = nsEventStatus_eIgnore;
431
432
switch (mState) {
433
case GESTURE_NONE:
434
// GEL doesn't have a dedicated state for PANNING handled in APZC thus
435
// ignore.
436
break;
437
438
case GESTURE_FIRST_SINGLE_TOUCH_DOWN: {
439
CancelLongTapTimeoutTask();
440
CancelMaxTapTimeoutTask();
441
nsEventStatus tapupStatus = mAsyncPanZoomController->HandleGestureEvent(
442
CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_UP));
443
mSingleTapSent = Some(tapupStatus != nsEventStatus_eIgnore);
444
SetState(GESTURE_FIRST_SINGLE_TOUCH_UP);
445
CreateMaxTapTimeoutTask();
446
break;
447
}
448
449
case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
450
CancelMaxTapTimeoutTask();
451
MOZ_ASSERT(mSingleTapSent.isSome());
452
mAsyncPanZoomController->HandleGestureEvent(CreateTapEvent(
453
mLastTouchInput, mSingleTapSent.value()
454
? TapGestureInput::TAPGESTURE_SECOND
455
: TapGestureInput::TAPGESTURE_DOUBLE));
456
mSingleTapSent = Nothing();
457
SetState(GESTURE_NONE);
458
break;
459
}
460
461
case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN:
462
CancelLongTapTimeoutTask();
463
SetState(GESTURE_NONE);
464
TriggerSingleTapConfirmedEvent();
465
break;
466
467
case GESTURE_LONG_TOUCH_DOWN: {
468
SetState(GESTURE_NONE);
469
mAsyncPanZoomController->HandleGestureEvent(
470
CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG_UP));
471
break;
472
}
473
474
case GESTURE_MULTI_TOUCH_DOWN:
475
if (mTouches.Length() < 2) {
476
SetState(GESTURE_NONE);
477
}
478
break;
479
480
case GESTURE_PINCH:
481
if (mTouches.Length() < 2) {
482
SetState(GESTURE_NONE);
483
ScreenPoint point = PinchGestureInput::BothFingersLifted<ScreenPixel>();
484
if (mTouches.Length() == 1) {
485
// As user still keeps one finger down the event's focus point should
486
// contain meaningful data.
487
point = mTouches[0].mScreenPoint;
488
}
489
PinchGestureInput pinchEvent(
490
PinchGestureInput::PINCHGESTURE_END, mLastTouchInput.mTime,
491
mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset, point,
492
1.0f, 1.0f, mLastTouchInput.modifiers);
493
mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
494
}
495
496
rv = nsEventStatus_eConsumeNoDefault;
497
498
break;
499
500
case GESTURE_ONE_TOUCH_PINCH: {
501
SetState(GESTURE_NONE);
502
ScreenPoint point = PinchGestureInput::BothFingersLifted<ScreenPixel>();
503
PinchGestureInput pinchEvent(
504
PinchGestureInput::PINCHGESTURE_END, mLastTouchInput.mTime,
505
mLastTouchInput.mTimeStamp, mLastTouchInput.mScreenOffset, point,
506
1.0f, 1.0f, mLastTouchInput.modifiers);
507
mAsyncPanZoomController->HandleGestureEvent(pinchEvent);
508
509
rv = nsEventStatus_eConsumeNoDefault;
510
511
break;
512
}
513
514
default:
515
NS_WARNING("Unhandled state upon touch end");
516
SetState(GESTURE_NONE);
517
break;
518
}
519
520
return rv;
521
}
522
523
nsEventStatus GestureEventListener::HandleInputTouchCancel() {
524
mSingleTapSent = Nothing();
525
SetState(GESTURE_NONE);
526
CancelMaxTapTimeoutTask();
527
CancelLongTapTimeoutTask();
528
return nsEventStatus_eIgnore;
529
}
530
531
void GestureEventListener::HandleInputTimeoutLongTap() {
532
GEL_LOG("Running long-tap timeout task in state %d\n", mState);
533
534
mLongTapTimeoutTask = nullptr;
535
536
switch (mState) {
537
case GESTURE_FIRST_SINGLE_TOUCH_DOWN:
538
// just in case MaxTapTime > ContextMenuDelay cancel MaxTap timer
539
// and fall through
540
CancelMaxTapTimeoutTask();
541
[[fallthrough]];
542
case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: {
543
SetState(GESTURE_LONG_TOUCH_DOWN);
544
mAsyncPanZoomController->HandleGestureEvent(
545
CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG));
546
break;
547
}
548
default:
549
NS_WARNING("Unhandled state upon long tap timeout");
550
SetState(GESTURE_NONE);
551
break;
552
}
553
}
554
555
void GestureEventListener::HandleInputTimeoutMaxTap(bool aDuringFastFling) {
556
GEL_LOG("Running max-tap timeout task in state %d\n", mState);
557
558
mMaxTapTimeoutTask = nullptr;
559
560
if (mState == GESTURE_FIRST_SINGLE_TOUCH_DOWN) {
561
SetState(GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN);
562
} else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP ||
563
mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
564
MOZ_ASSERT(mSingleTapSent.isSome());
565
if (!aDuringFastFling && !mSingleTapSent.value()) {
566
TriggerSingleTapConfirmedEvent();
567
}
568
mSingleTapSent = Nothing();
569
SetState(GESTURE_NONE);
570
} else {
571
NS_WARNING("Unhandled state upon MAX_TAP timeout");
572
SetState(GESTURE_NONE);
573
}
574
}
575
576
void GestureEventListener::TriggerSingleTapConfirmedEvent() {
577
mAsyncPanZoomController->HandleGestureEvent(
578
CreateTapEvent(mLastTapInput, TapGestureInput::TAPGESTURE_CONFIRMED));
579
}
580
581
void GestureEventListener::SetState(GestureState aState) {
582
mState = aState;
583
584
if (mState == GESTURE_NONE) {
585
mSpanChange = 0.0f;
586
mPreviousSpan = 0.0f;
587
mFocusChange = 0.0f;
588
} else if (mState == GESTURE_MULTI_TOUCH_DOWN) {
589
mPreviousSpan = GetCurrentSpan(mLastTouchInput);
590
mPreviousFocus = GetCurrentFocus(mLastTouchInput);
591
}
592
}
593
594
void GestureEventListener::CancelLongTapTimeoutTask() {
595
if (mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
596
// being in this state means the task has been canceled already
597
return;
598
}
599
600
if (mLongTapTimeoutTask) {
601
mLongTapTimeoutTask->Cancel();
602
mLongTapTimeoutTask = nullptr;
603
}
604
}
605
606
void GestureEventListener::CreateLongTapTimeoutTask() {
607
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod(
608
"layers::GestureEventListener::HandleInputTimeoutLongTap", this,
609
&GestureEventListener::HandleInputTimeoutLongTap);
610
611
mLongTapTimeoutTask = task;
612
mAsyncPanZoomController->PostDelayedTask(
613
task.forget(), StaticPrefs::ui_click_hold_context_menus_delay());
614
}
615
616
void GestureEventListener::CancelMaxTapTimeoutTask() {
617
if (mState == GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN) {
618
// being in this state means the timer has just been triggered
619
return;
620
}
621
622
if (mMaxTapTimeoutTask) {
623
mMaxTapTimeoutTask->Cancel();
624
mMaxTapTimeoutTask = nullptr;
625
}
626
}
627
628
void GestureEventListener::CreateMaxTapTimeoutTask() {
629
mLastTapInput = mLastTouchInput;
630
631
TouchBlockState* block =
632
mAsyncPanZoomController->GetInputQueue()->GetCurrentTouchBlock();
633
MOZ_ASSERT(block);
634
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod<bool>(
635
"layers::GestureEventListener::HandleInputTimeoutMaxTap", this,
636
&GestureEventListener::HandleInputTimeoutMaxTap,
637
block->IsDuringFastFling());
638
639
mMaxTapTimeoutTask = task;
640
mAsyncPanZoomController->PostDelayedTask(task.forget(),
641
StaticPrefs::apz_max_tap_time());
642
}
643
644
} // namespace layers
645
} // namespace mozilla