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

Side by Side Diff: content/browser/renderer_host/input/tap_suppression_controller.cc

Issue 2542453003: Suppress LongPress/Tap, and TwoFingerTap when TapDown cancels a fling. (Closed)
Patch Set: clarification comments added. Created 4 years 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 #include "content/browser/renderer_host/input/tap_suppression_controller.h" 5 #include "content/browser/renderer_host/input/tap_suppression_controller.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/trace_event/trace_event.h" 8 #include "base/trace_event/trace_event.h"
9 #include "content/browser/renderer_host/input/tap_suppression_controller_client. h" 9 #include "content/browser/renderer_host/input/tap_suppression_controller_client. h"
10 #include "ui/events/gesture_detection/gesture_configuration.h"
10 11
11 namespace content { 12 namespace content {
12 13
14 // The tapDownTimer is used to avoid waiting for an arbitrarily late fling
15 // cancel ack. While the timer is running, if a fling cancel ack with
16 // |Processed = false| arrives, all stashed gesture events get forwarded. If
17 // the timer expires, the controller forwards stashed GestureTapDown only, and
18 // drops the rest of the stashed events. The timer delay should be large enough
19 // for a GestureLongPress to get stashed and forwarded if needed. It's still
20 // possible for a GestureLongPress to arrive after the timer expiration. In
21 // this case, it will be suppressed if the controller is in SUPPRESSING_TAPS
22 // state.
23
13 TapSuppressionController::Config::Config() 24 TapSuppressionController::Config::Config()
14 : enabled(false), 25 : enabled(false),
15 max_cancel_to_down_time(base::TimeDelta::FromMilliseconds(180)), 26 max_cancel_to_down_time(base::TimeDelta::FromMilliseconds(180)) {
16 max_tap_gap_time(base::TimeDelta::FromMilliseconds(500)) { 27 ui::GestureConfiguration* gesture_config =
28 ui::GestureConfiguration::GetInstance();
29 max_tap_gap_time = base::TimeDelta::FromMilliseconds(
30 gesture_config->long_press_time_in_ms() + 50);
17 } 31 }
18 32
19 TapSuppressionController::TapSuppressionController( 33 TapSuppressionController::TapSuppressionController(
20 TapSuppressionControllerClient* client, 34 TapSuppressionControllerClient* client,
21 const Config& config) 35 const Config& config)
22 : client_(client), 36 : client_(client),
23 state_(config.enabled ? NOTHING : DISABLED), 37 state_(config.enabled ? NOTHING : DISABLED),
24 max_cancel_to_down_time_(config.max_cancel_to_down_time), 38 max_cancel_to_down_time_(config.max_cancel_to_down_time),
25 max_tap_gap_time_(config.max_tap_gap_time) { 39 max_tap_gap_time_(config.max_tap_gap_time) {
26 } 40 }
27 41
28 TapSuppressionController::~TapSuppressionController() {} 42 TapSuppressionController::~TapSuppressionController() {}
29 43
30 void TapSuppressionController::GestureFlingCancel() { 44 void TapSuppressionController::GestureFlingCancel() {
31 switch (state_) { 45 switch (state_) {
32 case DISABLED: 46 case DISABLED:
33 break; 47 break;
34 case NOTHING: 48 case NOTHING:
35 case GFC_IN_PROGRESS: 49 case GFC_IN_PROGRESS:
36 case LAST_CANCEL_STOPPED_FLING: 50 case LAST_CANCEL_STOPPED_FLING:
51 case SUPPRESSING_TAPS:
37 state_ = GFC_IN_PROGRESS; 52 state_ = GFC_IN_PROGRESS;
38 break; 53 break;
39 case TAP_DOWN_STASHED: 54 case TAP_DOWN_STASHED:
40 break; 55 break;
41 } 56 }
42 } 57 }
43 58
44 void TapSuppressionController::GestureFlingCancelAck(bool processed) { 59 void TapSuppressionController::GestureFlingCancelAck(bool processed) {
45 base::TimeTicks event_time = Now(); 60 base::TimeTicks event_time = Now();
46 switch (state_) { 61 switch (state_) {
47 case DISABLED: 62 case DISABLED:
48 case NOTHING: 63 case NOTHING:
64 case SUPPRESSING_TAPS:
49 break; 65 break;
50 case GFC_IN_PROGRESS: 66 case GFC_IN_PROGRESS:
51 if (processed) 67 if (processed)
52 fling_cancel_time_ = event_time; 68 fling_cancel_time_ = event_time;
53 state_ = LAST_CANCEL_STOPPED_FLING; 69 state_ = LAST_CANCEL_STOPPED_FLING;
54 break; 70 break;
55 case TAP_DOWN_STASHED: 71 case TAP_DOWN_STASHED:
56 if (!processed) { 72 if (!processed) {
57 TRACE_EVENT0("browser", 73 TRACE_EVENT0("browser",
58 "TapSuppressionController::GestureFlingCancelAck"); 74 "TapSuppressionController::GestureFlingCancelAck");
59 StopTapDownTimer(); 75 StopTapDownTimer();
60 client_->ForwardStashedTapDown(); 76 // If the fling cancel is not processed, forward all stashed
77 // gesture events.
78 client_->ForwardStashedGestureEvents();
61 state_ = NOTHING; 79 state_ = NOTHING;
62 } // Else waiting for the timer to release the stashed tap down. 80 } // Else waiting for the timer to release the stashed tap down.
63 break; 81 break;
64 case LAST_CANCEL_STOPPED_FLING: 82 case LAST_CANCEL_STOPPED_FLING:
65 break; 83 break;
66 } 84 }
67 } 85 }
68 86
69 bool TapSuppressionController::ShouldDeferTapDown() { 87 bool TapSuppressionController::ShouldDeferTapDown() {
70 base::TimeTicks event_time = Now(); 88 base::TimeTicks event_time = Now();
(...skipping 11 matching lines...) Expand all
82 return false; 100 return false;
83 case LAST_CANCEL_STOPPED_FLING: 101 case LAST_CANCEL_STOPPED_FLING:
84 if ((event_time - fling_cancel_time_) < max_cancel_to_down_time_) { 102 if ((event_time - fling_cancel_time_) < max_cancel_to_down_time_) {
85 state_ = TAP_DOWN_STASHED; 103 state_ = TAP_DOWN_STASHED;
86 StartTapDownTimer(max_tap_gap_time_); 104 StartTapDownTimer(max_tap_gap_time_);
87 return true; 105 return true;
88 } else { 106 } else {
89 state_ = NOTHING; 107 state_ = NOTHING;
90 return false; 108 return false;
91 } 109 }
110 // Stop suppressing tap end events.
111 case SUPPRESSING_TAPS:
112 state_ = NOTHING;
113 return false;
92 } 114 }
93 NOTREACHED() << "Invalid state"; 115 NOTREACHED() << "Invalid state";
94 return false; 116 return false;
95 } 117 }
96 118
97 bool TapSuppressionController::ShouldSuppressTapEnd() { 119 bool TapSuppressionController::ShouldSuppressTapEnd() {
98 switch (state_) { 120 switch (state_) {
99 case DISABLED: 121 case DISABLED:
100 case NOTHING: 122 case NOTHING:
101 case GFC_IN_PROGRESS: 123 case GFC_IN_PROGRESS:
102 return false; 124 return false;
103 case TAP_DOWN_STASHED: 125 case TAP_DOWN_STASHED:
104 state_ = NOTHING; 126 // A tap cancel happens before long tap and two finger tap events. To
127 // drop the latter events as well as the tap cancel, change the state
128 // to "SUPPRESSING_TAPS" when the stashed tap down is dropped.
129 state_ = SUPPRESSING_TAPS;
105 StopTapDownTimer(); 130 StopTapDownTimer();
106 client_->DropStashedTapDown(); 131 client_->DropStashedTapDown();
107 return true; 132 return true;
108 case LAST_CANCEL_STOPPED_FLING: 133 case LAST_CANCEL_STOPPED_FLING:
109 NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state"; 134 NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state";
135 case SUPPRESSING_TAPS:
136 return true;
110 } 137 }
111 return false; 138 return false;
112 } 139 }
113 140
114 base::TimeTicks TapSuppressionController::Now() { 141 base::TimeTicks TapSuppressionController::Now() {
115 return base::TimeTicks::Now(); 142 return base::TimeTicks::Now();
116 } 143 }
117 144
118 void TapSuppressionController::StartTapDownTimer(const base::TimeDelta& delay) { 145 void TapSuppressionController::StartTapDownTimer(const base::TimeDelta& delay) {
119 tap_down_timer_.Start(FROM_HERE, delay, this, 146 tap_down_timer_.Start(FROM_HERE, delay, this,
120 &TapSuppressionController::TapDownTimerExpired); 147 &TapSuppressionController::TapDownTimerExpired);
121 } 148 }
122 149
123 void TapSuppressionController::StopTapDownTimer() { 150 void TapSuppressionController::StopTapDownTimer() {
124 tap_down_timer_.Stop(); 151 tap_down_timer_.Stop();
125 } 152 }
126 153
127 void TapSuppressionController::TapDownTimerExpired() { 154 void TapSuppressionController::TapDownTimerExpired() {
128 switch (state_) { 155 switch (state_) {
129 case DISABLED: 156 case DISABLED:
130 case NOTHING: 157 case NOTHING:
158 case SUPPRESSING_TAPS:
131 NOTREACHED() << "Timer fired on invalid state."; 159 NOTREACHED() << "Timer fired on invalid state.";
132 break; 160 break;
133 case GFC_IN_PROGRESS: 161 case GFC_IN_PROGRESS:
134 case LAST_CANCEL_STOPPED_FLING: 162 case LAST_CANCEL_STOPPED_FLING:
135 NOTREACHED() << "Timer fired on invalid state."; 163 NOTREACHED() << "Timer fired on invalid state.";
136 state_ = NOTHING; 164 state_ = NOTHING;
137 break; 165 break;
138 case TAP_DOWN_STASHED: 166 case TAP_DOWN_STASHED:
139 TRACE_EVENT0("browser", 167 TRACE_EVENT0("browser",
140 "TapSuppressionController::TapDownTimerExpired"); 168 "TapSuppressionController::TapDownTimerExpired");
169 // When the timer expires, only forward the stashed tap down event, and
170 // drop other stashed gesture events (show press or long press).
141 client_->ForwardStashedTapDown(); 171 client_->ForwardStashedTapDown();
142 state_ = NOTHING; 172 state_ = SUPPRESSING_TAPS;
143 break; 173 break;
144 } 174 }
145 } 175 }
146 176
147 } // namespace content 177 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698