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