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
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/input/tap_suppression_controller.h"
6
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
10
11 namespace content {
12
Config()13 TapSuppressionController::Config::Config()
14 : enabled(false),
15 max_cancel_to_down_time(base::TimeDelta::FromMilliseconds(180)),
16 max_tap_gap_time(base::TimeDelta::FromMilliseconds(500)) {
17 }
18
TapSuppressionController(TapSuppressionControllerClient * client,const Config & config)19 TapSuppressionController::TapSuppressionController(
20 TapSuppressionControllerClient* client,
21 const Config& config)
22 : client_(client),
23 state_(config.enabled ? NOTHING : DISABLED),
24 max_cancel_to_down_time_(config.max_cancel_to_down_time),
25 max_tap_gap_time_(config.max_tap_gap_time) {
26 }
27
~TapSuppressionController()28 TapSuppressionController::~TapSuppressionController() {}
29
GestureFlingCancel()30 void TapSuppressionController::GestureFlingCancel() {
31 switch (state_) {
32 case DISABLED:
33 break;
34 case NOTHING:
35 case GFC_IN_PROGRESS:
36 case LAST_CANCEL_STOPPED_FLING:
37 state_ = GFC_IN_PROGRESS;
38 break;
39 case TAP_DOWN_STASHED:
40 break;
41 }
42 }
43
GestureFlingCancelAck(bool processed)44 void TapSuppressionController::GestureFlingCancelAck(bool processed) {
45 base::TimeTicks event_time = Now();
46 switch (state_) {
47 case DISABLED:
48 case NOTHING:
49 break;
50 case GFC_IN_PROGRESS:
51 if (processed)
52 fling_cancel_time_ = event_time;
53 state_ = LAST_CANCEL_STOPPED_FLING;
54 break;
55 case TAP_DOWN_STASHED:
56 if (!processed) {
57 TRACE_EVENT0("browser",
58 "TapSuppressionController::GestureFlingCancelAck");
59 StopTapDownTimer();
60 client_->ForwardStashedTapDown();
61 state_ = NOTHING;
62 } // Else waiting for the timer to release the stashed tap down.
63 break;
64 case LAST_CANCEL_STOPPED_FLING:
65 break;
66 }
67 }
68
ShouldDeferTapDown()69 bool TapSuppressionController::ShouldDeferTapDown() {
70 base::TimeTicks event_time = Now();
71 switch (state_) {
72 case DISABLED:
73 case NOTHING:
74 return false;
75 case GFC_IN_PROGRESS:
76 state_ = TAP_DOWN_STASHED;
77 StartTapDownTimer(max_tap_gap_time_);
78 return true;
79 case TAP_DOWN_STASHED:
80 NOTREACHED() << "TapDown on TAP_DOWN_STASHED state";
81 state_ = NOTHING;
82 return false;
83 case LAST_CANCEL_STOPPED_FLING:
84 if ((event_time - fling_cancel_time_) < max_cancel_to_down_time_) {
85 state_ = TAP_DOWN_STASHED;
86 StartTapDownTimer(max_tap_gap_time_);
87 return true;
88 } else {
89 state_ = NOTHING;
90 return false;
91 }
92 }
93 NOTREACHED() << "Invalid state";
94 return false;
95 }
96
ShouldSuppressTapEnd()97 bool TapSuppressionController::ShouldSuppressTapEnd() {
98 switch (state_) {
99 case DISABLED:
100 case NOTHING:
101 case GFC_IN_PROGRESS:
102 return false;
103 case TAP_DOWN_STASHED:
104 state_ = NOTHING;
105 StopTapDownTimer();
106 client_->DropStashedTapDown();
107 return true;
108 case LAST_CANCEL_STOPPED_FLING:
109 NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state";
110 }
111 return false;
112 }
113
Now()114 base::TimeTicks TapSuppressionController::Now() {
115 return base::TimeTicks::Now();
116 }
117
StartTapDownTimer(const base::TimeDelta & delay)118 void TapSuppressionController::StartTapDownTimer(const base::TimeDelta& delay) {
119 tap_down_timer_.Start(FROM_HERE, delay, this,
120 &TapSuppressionController::TapDownTimerExpired);
121 }
122
StopTapDownTimer()123 void TapSuppressionController::StopTapDownTimer() {
124 tap_down_timer_.Stop();
125 }
126
TapDownTimerExpired()127 void TapSuppressionController::TapDownTimerExpired() {
128 switch (state_) {
129 case DISABLED:
130 case NOTHING:
131 NOTREACHED() << "Timer fired on invalid state.";
132 break;
133 case GFC_IN_PROGRESS:
134 case LAST_CANCEL_STOPPED_FLING:
135 NOTREACHED() << "Timer fired on invalid state.";
136 state_ = NOTHING;
137 break;
138 case TAP_DOWN_STASHED:
139 TRACE_EVENT0("browser",
140 "TapSuppressionController::TapDownTimerExpired");
141 client_->ForwardStashedTapDown();
142 state_ = NOTHING;
143 break;
144 }
145 }
146
147 } // namespace content
148