1558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/browser/renderer_host/input/tap_suppression_controller.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/trace_event.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 9558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/browser/renderer_host/input/tap_suppression_controller_client.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TapSuppressionController::Config::Config() 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : enabled(false), 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) max_cancel_to_down_time(base::TimeDelta::FromMilliseconds(180)), 16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) max_tap_gap_time(base::TimeDelta::FromMilliseconds(500)) { 17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TapSuppressionController::TapSuppressionController( 20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) TapSuppressionControllerClient* client, 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Config& config) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : client_(client), 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) state_(config.enabled ? NOTHING : DISABLED), 24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) max_cancel_to_down_time_(config.max_cancel_to_down_time), 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) max_tap_gap_time_(config.max_tap_gap_time) { 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TapSuppressionController::~TapSuppressionController() {} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TapSuppressionController::GestureFlingCancel() { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (state_) { 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) case DISABLED: 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) break; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTHING: 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GFC_IN_PROGRESS: 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case LAST_CANCEL_STOPPED_FLING: 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = GFC_IN_PROGRESS; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case TAP_DOWN_STASHED: 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TapSuppressionController::GestureFlingCancelAck(bool processed) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks event_time = Now(); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (state_) { 47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) case DISABLED: 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTHING: 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GFC_IN_PROGRESS: 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (processed) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fling_cancel_time_ = event_time; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = LAST_CANCEL_STOPPED_FLING; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case TAP_DOWN_STASHED: 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!processed) { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TRACE_EVENT0("browser", 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "TapSuppressionController::GestureFlingCancelAck"); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopTapDownTimer(); 601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) client_->ForwardStashedTapDown(); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = NOTHING; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } // Else waiting for the timer to release the stashed tap down. 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case LAST_CANCEL_STOPPED_FLING: 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TapSuppressionController::ShouldDeferTapDown() { 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks event_time = Now(); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (state_) { 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) case DISABLED: 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTHING: 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GFC_IN_PROGRESS: 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = TAP_DOWN_STASHED; 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) StartTapDownTimer(max_tap_gap_time_); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case TAP_DOWN_STASHED: 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "TapDown on TAP_DOWN_STASHED state"; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = NOTHING; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case LAST_CANCEL_STOPPED_FLING: 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if ((event_time - fling_cancel_time_) < max_cancel_to_down_time_) { 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = TAP_DOWN_STASHED; 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) StartTapDownTimer(max_tap_gap_time_); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = NOTHING; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Invalid state"; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool TapSuppressionController::ShouldSuppressTapEnd() { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (state_) { 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) case DISABLED: 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTHING: 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GFC_IN_PROGRESS: 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case TAP_DOWN_STASHED: 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = NOTHING; 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopTapDownTimer(); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client_->DropStashedTapDown(); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case LAST_CANCEL_STOPPED_FLING: 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state"; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::TimeTicks TapSuppressionController::Now() { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::TimeTicks::Now(); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TapSuppressionController::StartTapDownTimer(const base::TimeDelta& delay) { 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tap_down_timer_.Start(FROM_HERE, delay, this, 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &TapSuppressionController::TapDownTimerExpired); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TapSuppressionController::StopTapDownTimer() { 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tap_down_timer_.Stop(); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TapSuppressionController::TapDownTimerExpired() { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (state_) { 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) case DISABLED: 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case NOTHING: 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NOTREACHED() << "Timer fired on invalid state."; 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) break; 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case GFC_IN_PROGRESS: 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case LAST_CANCEL_STOPPED_FLING: 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Timer fired on invalid state."; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = NOTHING; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case TAP_DOWN_STASHED: 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TRACE_EVENT0("browser", 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "TapSuppressionController::TapDownTimerExpired"); 1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) client_->ForwardStashedTapDown(); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state_ = NOTHING; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 148