Commit 5030a025 authored by Sahel Sharify's avatar Sahel Sharify Committed by Commit Bot

clean up tap suppression logic.

With browser side fling the fling_controller can tell if the GFC cancels
the fling or not. Thus the tap suprression controller doesn't need to
wait for the ack of the GFC. Stashing a tap(mouse) down event and
dropping or forwarding it later on is not necessary either since on the
arrival of these events the tap suppression controller already knows
whether the GFC has cancelled an active fling or not.

TBR=kinuko@chromium.org

Bug: 249063
Change-Id: I89beff953a0c660bd6151864debe507be8c775ed
Reviewed-on: https://chromium-review.googlesource.com/1033537
Commit-Queue: Sahel Sharifymoghaddam <sahel@chromium.org>
Reviewed-by: default avatarDave Tapuska <dtapuska@chromium.org>
Cr-Commit-Position: refs/heads/master@{#554770}
parent b834c714
...@@ -1286,7 +1286,6 @@ jumbo_source_set("browser") { ...@@ -1286,7 +1286,6 @@ jumbo_source_set("browser") {
"renderer_host/input/synthetic_touchscreen_pinch_gesture.h", "renderer_host/input/synthetic_touchscreen_pinch_gesture.h",
"renderer_host/input/tap_suppression_controller.cc", "renderer_host/input/tap_suppression_controller.cc",
"renderer_host/input/tap_suppression_controller.h", "renderer_host/input/tap_suppression_controller.h",
"renderer_host/input/tap_suppression_controller_client.h",
"renderer_host/input/timeout_monitor.cc", "renderer_host/input/timeout_monitor.cc",
"renderer_host/input/timeout_monitor.h", "renderer_host/input/timeout_monitor.h",
"renderer_host/input/touch_action_filter.cc", "renderer_host/input/touch_action_filter.cc",
......
...@@ -28,16 +28,13 @@ FlingController::Config::Config() {} ...@@ -28,16 +28,13 @@ FlingController::Config::Config() {}
FlingController::FlingController( FlingController::FlingController(
GestureEventQueue* gesture_event_queue, GestureEventQueue* gesture_event_queue,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client, FlingControllerClient* fling_client,
const Config& config) const Config& config)
: gesture_event_queue_(gesture_event_queue), : gesture_event_queue_(gesture_event_queue),
client_(fling_client), client_(fling_client),
touchpad_tap_suppression_controller_( touchpad_tap_suppression_controller_(
touchpad_client,
config.touchpad_tap_suppression_config), config.touchpad_tap_suppression_config),
touchscreen_tap_suppression_controller_( touchscreen_tap_suppression_controller_(
gesture_event_queue,
config.touchscreen_tap_suppression_config), config.touchscreen_tap_suppression_config),
fling_in_progress_(false), fling_in_progress_(false),
send_wheel_events_nonblocking_( send_wheel_events_nonblocking_(
...@@ -45,7 +42,6 @@ FlingController::FlingController( ...@@ -45,7 +42,6 @@ FlingController::FlingController(
features::kTouchpadAndWheelScrollLatching) && features::kTouchpadAndWheelScrollLatching) &&
base::FeatureList::IsEnabled(features::kAsyncWheelEvents)) { base::FeatureList::IsEnabled(features::kAsyncWheelEvents)) {
DCHECK(gesture_event_queue); DCHECK(gesture_event_queue);
DCHECK(touchpad_client);
DCHECK(fling_client); DCHECK(fling_client);
} }
...@@ -59,8 +55,7 @@ bool FlingController::ShouldForwardForGFCFiltering( ...@@ -59,8 +55,7 @@ bool FlingController::ShouldForwardForGFCFiltering(
if (fling_in_progress_) if (fling_in_progress_)
return !fling_booster_->fling_cancellation_is_deferred(); return !fling_booster_->fling_cancellation_is_deferred();
// Auto-scroll flings are still handled by renderer. return false;
return !gesture_event_queue_->ShouldDiscardFlingCancelEvent(gesture_event);
} }
bool FlingController::ShouldForwardForTapSuppression( bool FlingController::ShouldForwardForTapSuppression(
...@@ -69,10 +64,11 @@ bool FlingController::ShouldForwardForTapSuppression( ...@@ -69,10 +64,11 @@ bool FlingController::ShouldForwardForTapSuppression(
case WebInputEvent::kGestureFlingCancel: case WebInputEvent::kGestureFlingCancel:
if (gesture_event.event.SourceDevice() == if (gesture_event.event.SourceDevice() ==
blink::kWebGestureDeviceTouchscreen) { blink::kWebGestureDeviceTouchscreen) {
touchscreen_tap_suppression_controller_.GestureFlingCancel(); touchscreen_tap_suppression_controller_
.GestureFlingCancelStoppedFling();
} else if (gesture_event.event.SourceDevice() == } else if (gesture_event.event.SourceDevice() ==
blink::kWebGestureDeviceTouchpad) { blink::kWebGestureDeviceTouchpad) {
touchpad_tap_suppression_controller_.GestureFlingCancel(); touchpad_tap_suppression_controller_.GestureFlingCancelStoppedFling();
} }
return true; return true;
case WebInputEvent::kGestureTapDown: case WebInputEvent::kGestureTapDown:
...@@ -172,18 +168,9 @@ void FlingController::ScheduleFlingProgress() { ...@@ -172,18 +168,9 @@ void FlingController::ScheduleFlingProgress() {
void FlingController::ProcessGestureFlingCancel( void FlingController::ProcessGestureFlingCancel(
const GestureEventWithLatencyInfo& gesture_event) { const GestureEventWithLatencyInfo& gesture_event) {
fling_in_progress_ = false; fling_in_progress_ = false;
bool processed = false;
if (fling_curve_) { if (fling_curve_)
CancelCurrentFling(); CancelCurrentFling();
processed = true;
}
// FlingCancelEvent handled without being sent to the renderer.
blink::WebGestureDevice source_device = gesture_event.event.SourceDevice();
if (source_device == blink::kWebGestureDeviceTouchscreen) {
touchscreen_tap_suppression_controller_.GestureFlingCancelAck(processed);
} else if (source_device == blink::kWebGestureDeviceTouchpad) {
touchpad_tap_suppression_controller_.GestureFlingCancelAck(processed);
}
} }
gfx::Vector2dF FlingController::ProgressFling(base::TimeTicks current_time) { gfx::Vector2dF FlingController::ProgressFling(base::TimeTicks current_time) {
......
...@@ -62,7 +62,6 @@ class CONTENT_EXPORT FlingController { ...@@ -62,7 +62,6 @@ class CONTENT_EXPORT FlingController {
}; };
FlingController(GestureEventQueue* gesture_event_queue, FlingController(GestureEventQueue* gesture_event_queue,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client, FlingControllerClient* fling_client,
const Config& config); const Config& config);
......
...@@ -22,11 +22,9 @@ namespace content { ...@@ -22,11 +22,9 @@ namespace content {
class FakeFlingController : public FlingController { class FakeFlingController : public FlingController {
public: public:
FakeFlingController(GestureEventQueue* gesture_event_queue, FakeFlingController(GestureEventQueue* gesture_event_queue,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client, FlingControllerClient* fling_client,
const Config& config) const Config& config)
: FlingController(gesture_event_queue, : FlingController(gesture_event_queue,
touchpad_client,
fling_client, fling_client,
config) {} config) {}
...@@ -34,7 +32,6 @@ class FakeFlingController : public FlingController { ...@@ -34,7 +32,6 @@ class FakeFlingController : public FlingController {
}; };
class FlingControllerTest : public testing::Test, class FlingControllerTest : public testing::Test,
public TouchpadTapSuppressionControllerClient,
public GestureEventQueueClient, public GestureEventQueueClient,
public FlingControllerClient { public FlingControllerClient {
public: public:
...@@ -46,18 +43,14 @@ class FlingControllerTest : public testing::Test, ...@@ -46,18 +43,14 @@ class FlingControllerTest : public testing::Test,
~FlingControllerTest() override {} ~FlingControllerTest() override {}
void SetUp() override { void SetUp() override {
queue_ = std::make_unique<GestureEventQueue>(this, this, this, queue_ = std::make_unique<GestureEventQueue>(this, this,
GestureEventQueue::Config()); GestureEventQueue::Config());
fling_controller_ = std::make_unique<FakeFlingController>( fling_controller_ = std::make_unique<FakeFlingController>(
queue_.get(), this, this, FlingController::Config()); queue_.get(), this, FlingController::Config());
feature_list_.InitFromCommandLine( feature_list_.InitFromCommandLine(
features::kTouchpadAndWheelScrollLatching.name, ""); features::kTouchpadAndWheelScrollLatching.name, "");
} }
// TouchpadTapSuppressionControllerClient
void SendMouseEventImmediately(
const MouseEventWithLatencyInfo& event) override {}
// GestureEventQueueClient // GestureEventQueueClient
void SendGestureEventImmediately( void SendGestureEventImmediately(
const GestureEventWithLatencyInfo& event) override {} const GestureEventWithLatencyInfo& event) override {}
......
...@@ -26,7 +26,6 @@ GestureEventQueue::Config::Config() { ...@@ -26,7 +26,6 @@ GestureEventQueue::Config::Config() {
GestureEventQueue::GestureEventQueue( GestureEventQueue::GestureEventQueue(
GestureEventQueueClient* client, GestureEventQueueClient* client,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client, FlingControllerClient* fling_client,
const Config& config) const Config& config)
: client_(client), : client_(client),
...@@ -37,11 +36,9 @@ GestureEventQueue::GestureEventQueue( ...@@ -37,11 +36,9 @@ GestureEventQueue::GestureEventQueue(
base::FeatureList::IsEnabled(features::kVsyncAlignedInputEvents)), base::FeatureList::IsEnabled(features::kVsyncAlignedInputEvents)),
debounce_interval_(config.debounce_interval), debounce_interval_(config.debounce_interval),
fling_controller_(this, fling_controller_(this,
touchpad_client,
fling_client, fling_client,
config.fling_config) { config.fling_config) {
DCHECK(client); DCHECK(client);
DCHECK(touchpad_client);
DCHECK(fling_client); DCHECK(fling_client);
} }
......
...@@ -72,7 +72,6 @@ class CONTENT_EXPORT GestureEventQueue { ...@@ -72,7 +72,6 @@ class CONTENT_EXPORT GestureEventQueue {
// Both |client| and |touchpad_client| must outlive the GestureEventQueue. // Both |client| and |touchpad_client| must outlive the GestureEventQueue.
GestureEventQueue(GestureEventQueueClient* client, GestureEventQueue(GestureEventQueueClient* client,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client, FlingControllerClient* fling_client,
const Config& config); const Config& config);
~GestureEventQueue(); ~GestureEventQueue();
......
...@@ -36,7 +36,6 @@ namespace content { ...@@ -36,7 +36,6 @@ namespace content {
class GestureEventQueueTest : public testing::Test, class GestureEventQueueTest : public testing::Test,
public GestureEventQueueClient, public GestureEventQueueClient,
public TouchpadTapSuppressionControllerClient,
public FlingControllerClient { public FlingControllerClient {
public: public:
GestureEventQueueTest() : GestureEventQueueTest(false) {} GestureEventQueueTest() : GestureEventQueueTest(false) {}
...@@ -56,7 +55,7 @@ class GestureEventQueueTest : public testing::Test, ...@@ -56,7 +55,7 @@ class GestureEventQueueTest : public testing::Test,
// testing::Test // testing::Test
void SetUp() override { void SetUp() override {
queue_.reset(new GestureEventQueue(this, this, this, DefaultConfig())); queue_.reset(new GestureEventQueue(this, this, DefaultConfig()));
} }
void TearDown() override { void TearDown() override {
...@@ -65,18 +64,14 @@ class GestureEventQueueTest : public testing::Test, ...@@ -65,18 +64,14 @@ class GestureEventQueueTest : public testing::Test,
queue_.reset(); queue_.reset();
} }
void SetUpForTapSuppression(int max_cancel_to_down_time_ms, void SetUpForTapSuppression(int max_cancel_to_down_time_ms) {
int max_tap_gap_time_ms) {
GestureEventQueue::Config gesture_config; GestureEventQueue::Config gesture_config;
gesture_config.fling_config.touchscreen_tap_suppression_config.enabled = gesture_config.fling_config.touchscreen_tap_suppression_config.enabled =
true; true;
gesture_config.fling_config.touchscreen_tap_suppression_config gesture_config.fling_config.touchscreen_tap_suppression_config
.max_cancel_to_down_time = .max_cancel_to_down_time =
base::TimeDelta::FromMilliseconds(max_cancel_to_down_time_ms); base::TimeDelta::FromMilliseconds(max_cancel_to_down_time_ms);
gesture_config.fling_config.touchscreen_tap_suppression_config queue_.reset(new GestureEventQueue(this, this, gesture_config));
.max_tap_gap_time =
base::TimeDelta::FromMilliseconds(max_tap_gap_time_ms);
queue_.reset(new GestureEventQueue(this, this, this, gesture_config));
} }
// GestureEventQueueClient // GestureEventQueueClient
...@@ -101,10 +96,6 @@ class GestureEventQueueTest : public testing::Test, ...@@ -101,10 +96,6 @@ class GestureEventQueueTest : public testing::Test,
} }
} }
// TouchpadTapSuppressionControllerClient
void SendMouseEventImmediately(
const MouseEventWithLatencyInfo& event) override {}
// FlingControllerClient // FlingControllerClient
void SendGeneratedWheelEvent( void SendGeneratedWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) override {} const MouseWheelEventWithLatencyInfo& wheel_event) override {}
...@@ -1159,7 +1150,7 @@ TEST_F(GestureEventQueueTest, DebounceDropsDeferredEvents) { ...@@ -1159,7 +1150,7 @@ TEST_F(GestureEventQueueTest, DebounceDropsDeferredEvents) {
// Test that the fling cancelling tap down event and its following tap get // Test that the fling cancelling tap down event and its following tap get
// suppressed when tap suppression is enabled. // suppressed when tap suppression is enabled.
TEST_F(GestureEventQueueTest, TapGetsSuppressedAfterTapDownCancellsFling) { TEST_F(GestureEventQueueTest, TapGetsSuppressedAfterTapDownCancellsFling) {
SetUpForTapSuppression(400, 200); SetUpForTapSuppression(400);
SimulateGestureFlingStartEvent(0, -10, blink::kWebGestureDeviceTouchscreen); SimulateGestureFlingStartEvent(0, -10, blink::kWebGestureDeviceTouchscreen);
EXPECT_TRUE(FlingInProgress()); EXPECT_TRUE(FlingInProgress());
// The fling start event is not sent to the renderer. // The fling start event is not sent to the renderer.
......
...@@ -50,24 +50,11 @@ GestureEventQueue::Config GetGestureEventQueueConfig() { ...@@ -50,24 +50,11 @@ GestureEventQueue::Config GetGestureEventQueueConfig() {
.max_cancel_to_down_time = base::TimeDelta::FromMilliseconds( .max_cancel_to_down_time = base::TimeDelta::FromMilliseconds(
gesture_config->fling_max_cancel_to_down_time_in_ms()); gesture_config->fling_max_cancel_to_down_time_in_ms());
// Tap suppression controller forwards the stashed tapDown and drops the rest
// of the stashed events when the tapDownTimer expires. If a fling cancel ack
// with |processed = false| arrives before the timer expiration, all stashed
// events will be forwarded. The timer is used to avoid waiting for an
// arbitrarily late fling cancel ack. Its delay should be large enough for
// a long press to get stashed and forwarded if needed.
config.fling_config.touchscreen_tap_suppression_config.max_tap_gap_time =
base::TimeDelta::FromMilliseconds(
gesture_config->long_press_time_in_ms() + 50);
config.fling_config.touchpad_tap_suppression_config.enabled = config.fling_config.touchpad_tap_suppression_config.enabled =
gesture_config->fling_touchpad_tap_suppression_enabled(); gesture_config->fling_touchpad_tap_suppression_enabled();
config.fling_config.touchpad_tap_suppression_config.max_cancel_to_down_time = config.fling_config.touchpad_tap_suppression_config.max_cancel_to_down_time =
base::TimeDelta::FromMilliseconds( base::TimeDelta::FromMilliseconds(
gesture_config->fling_max_cancel_to_down_time_in_ms()); gesture_config->fling_max_cancel_to_down_time_in_ms());
config.fling_config.touchpad_tap_suppression_config.max_tap_gap_time =
base::TimeDelta::FromMilliseconds(
gesture_config->fling_max_tap_gap_time_in_ms());
return config; return config;
} }
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "content/browser/renderer_host/input/gesture_event_queue.h" #include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "content/browser/renderer_host/input/input_disposition_handler.h" #include "content/browser/renderer_host/input/input_disposition_handler.h"
#include "content/browser/renderer_host/input/input_router_client.h" #include "content/browser/renderer_host/input/input_router_client.h"
#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
#include "content/common/content_constants_internal.h" #include "content/common/content_constants_internal.h"
#include "content/common/edit_command.h" #include "content/common/edit_command.h"
#include "content/common/input/input_handler.mojom.h" #include "content/common/input/input_handler.mojom.h"
...@@ -81,7 +80,7 @@ InputRouterImpl::InputRouterImpl(InputRouterImplClient* client, ...@@ -81,7 +80,7 @@ InputRouterImpl::InputRouterImpl(InputRouterImplClient* client,
features::kTouchpadAndWheelScrollLatching)), features::kTouchpadAndWheelScrollLatching)),
wheel_event_queue_(this, wheel_scroll_latching_enabled_), wheel_event_queue_(this, wheel_scroll_latching_enabled_),
touch_event_queue_(this, config.touch_config), touch_event_queue_(this, config.touch_config),
gesture_event_queue_(this, this, this, config.gesture_config), gesture_event_queue_(this, this, config.gesture_config),
device_scale_factor_(1.f), device_scale_factor_(1.f),
host_binding_(this), host_binding_(this),
frame_host_binding_(this), frame_host_binding_(this),
...@@ -99,7 +98,7 @@ void InputRouterImpl::SendMouseEvent( ...@@ -99,7 +98,7 @@ void InputRouterImpl::SendMouseEvent(
const MouseEventWithLatencyInfo& mouse_event) { const MouseEventWithLatencyInfo& mouse_event) {
if (mouse_event.event.GetType() == WebInputEvent::kMouseDown && if (mouse_event.event.GetType() == WebInputEvent::kMouseDown &&
gesture_event_queue_.GetTouchpadTapSuppressionController() gesture_event_queue_.GetTouchpadTapSuppressionController()
->ShouldDeferMouseDown(mouse_event)) ->ShouldSuppressMouseDown(mouse_event))
return; return;
if (mouse_event.event.GetType() == WebInputEvent::kMouseUp && if (mouse_event.event.GetType() == WebInputEvent::kMouseUp &&
gesture_event_queue_.GetTouchpadTapSuppressionController() gesture_event_queue_.GetTouchpadTapSuppressionController()
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h" #include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
#include "content/browser/renderer_host/input/passthrough_touch_event_queue.h" #include "content/browser/renderer_host/input/passthrough_touch_event_queue.h"
#include "content/browser/renderer_host/input/touch_action_filter.h" #include "content/browser/renderer_host/input/touch_action_filter.h"
#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
#include "content/common/input/input_event_stream_validator.h" #include "content/common/input/input_event_stream_validator.h"
#include "content/common/input/input_handler.mojom.h" #include "content/common/input/input_handler.mojom.h"
#include "content/common/widget.mojom.h" #include "content/common/widget.mojom.h"
...@@ -56,7 +55,6 @@ class CONTENT_EXPORT InputRouterImpl ...@@ -56,7 +55,6 @@ class CONTENT_EXPORT InputRouterImpl
public FlingControllerClient, public FlingControllerClient,
public MouseWheelEventQueueClient, public MouseWheelEventQueueClient,
public PassthroughTouchEventQueueClient, public PassthroughTouchEventQueueClient,
public TouchpadTapSuppressionControllerClient,
public mojom::WidgetInputHandlerHost { public mojom::WidgetInputHandlerHost {
public: public:
InputRouterImpl(InputRouterImplClient* client, InputRouterImpl(InputRouterImplClient* client,
...@@ -109,9 +107,7 @@ class CONTENT_EXPORT InputRouterImpl ...@@ -109,9 +107,7 @@ class CONTENT_EXPORT InputRouterImpl
// Keeps track of last position of touch points and sets MovementXY for them. // Keeps track of last position of touch points and sets MovementXY for them.
void SetMovementXYForTouchPoints(blink::WebTouchEvent* event); void SetMovementXYForTouchPoints(blink::WebTouchEvent* event);
// TouchpadTapSuppressionControllerClient void SendMouseEventImmediately(const MouseEventWithLatencyInfo& mouse_event);
void SendMouseEventImmediately(
const MouseEventWithLatencyInfo& mouse_event) override;
// PassthroughTouchEventQueueClient // PassthroughTouchEventQueueClient
void SendTouchEventImmediately( void SendTouchEventImmediately(
......
...@@ -6,102 +6,45 @@ ...@@ -6,102 +6,45 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "ui/events/gesture_detection/gesture_configuration.h" #include "ui/events/gesture_detection/gesture_configuration.h"
namespace content { namespace content {
// The tapDownTimer is used to avoid waiting for an arbitrarily late fling
// cancel ack. While the timer is running, if a fling cancel ack with
// |Processed = false| arrives, all stashed gesture events get forwarded. If
// the timer expires, the controller forwards stashed GestureTapDown only, and
// drops the rest of the stashed events. The timer delay should be large enough
// for a GestureLongPress to get stashed and forwarded if needed. It's still
// possible for a GestureLongPress to arrive after the timer expiration. In
// this case, it will be suppressed if the controller is in SUPPRESSING_TAPS
// state.
TapSuppressionController::Config::Config() TapSuppressionController::Config::Config()
: enabled(false), : enabled(false),
max_cancel_to_down_time(base::TimeDelta::FromMilliseconds(180)) { max_cancel_to_down_time(base::TimeDelta::FromMilliseconds(180)) {
ui::GestureConfiguration* gesture_config =
ui::GestureConfiguration::GetInstance();
max_tap_gap_time = base::TimeDelta::FromMilliseconds(
gesture_config->long_press_time_in_ms() + 50);
} }
TapSuppressionController::TapSuppressionController( TapSuppressionController::TapSuppressionController(const Config& config)
TapSuppressionControllerClient* client, : state_(config.enabled ? NOTHING : DISABLED),
const Config& config) max_cancel_to_down_time_(config.max_cancel_to_down_time) {}
: client_(client),
state_(config.enabled ? NOTHING : DISABLED),
max_cancel_to_down_time_(config.max_cancel_to_down_time),
max_tap_gap_time_(config.max_tap_gap_time) {
}
TapSuppressionController::~TapSuppressionController() {} TapSuppressionController::~TapSuppressionController() {}
void TapSuppressionController::GestureFlingCancel() { void TapSuppressionController::GestureFlingCancelStoppedFling() {
switch (state_) {
case DISABLED:
break;
case NOTHING:
case GFC_IN_PROGRESS:
case LAST_CANCEL_STOPPED_FLING:
case SUPPRESSING_TAPS:
state_ = GFC_IN_PROGRESS;
break;
case TAP_DOWN_STASHED:
break;
}
}
void TapSuppressionController::GestureFlingCancelAck(bool processed) {
base::TimeTicks event_time = Now(); base::TimeTicks event_time = Now();
switch (state_) { switch (state_) {
case DISABLED: case DISABLED:
case NOTHING:
case SUPPRESSING_TAPS: case SUPPRESSING_TAPS:
break; break;
case GFC_IN_PROGRESS: case NOTHING:
if (processed)
fling_cancel_time_ = event_time; fling_cancel_time_ = event_time;
state_ = LAST_CANCEL_STOPPED_FLING; state_ = LAST_CANCEL_STOPPED_FLING;
break; break;
case TAP_DOWN_STASHED:
if (!processed) {
TRACE_EVENT0("browser",
"TapSuppressionController::GestureFlingCancelAck");
StopTapDownTimer();
// If the fling cancel is not processed, forward all stashed
// gesture events.
client_->ForwardStashedGestureEvents();
state_ = NOTHING;
} // Else waiting for the timer to release the stashed tap down.
break;
case LAST_CANCEL_STOPPED_FLING: case LAST_CANCEL_STOPPED_FLING:
break; break;
} }
} }
bool TapSuppressionController::ShouldDeferTapDown() { bool TapSuppressionController::ShouldSuppressTapDown() {
base::TimeTicks event_time = Now(); base::TimeTicks event_time = Now();
switch (state_) { switch (state_) {
case DISABLED: case DISABLED:
case NOTHING: case NOTHING:
return false; return false;
case GFC_IN_PROGRESS:
state_ = TAP_DOWN_STASHED;
StartTapDownTimer(max_tap_gap_time_);
return true;
case TAP_DOWN_STASHED:
NOTREACHED() << "TapDown on TAP_DOWN_STASHED state";
state_ = NOTHING;
return false;
case LAST_CANCEL_STOPPED_FLING: case LAST_CANCEL_STOPPED_FLING:
if ((event_time - fling_cancel_time_) < max_cancel_to_down_time_) { if ((event_time - fling_cancel_time_) < max_cancel_to_down_time_) {
state_ = TAP_DOWN_STASHED; state_ = SUPPRESSING_TAPS;
StartTapDownTimer(max_tap_gap_time_);
return true; return true;
} else { } else {
state_ = NOTHING; state_ = NOTHING;
...@@ -120,16 +63,7 @@ bool TapSuppressionController::ShouldSuppressTapEnd() { ...@@ -120,16 +63,7 @@ bool TapSuppressionController::ShouldSuppressTapEnd() {
switch (state_) { switch (state_) {
case DISABLED: case DISABLED:
case NOTHING: case NOTHING:
case GFC_IN_PROGRESS:
return false; return false;
case TAP_DOWN_STASHED:
// A tap cancel happens before long tap and two finger tap events. To
// drop the latter events as well as the tap cancel, change the state
// to "SUPPRESSING_TAPS" when the stashed tap down is dropped.
state_ = SUPPRESSING_TAPS;
StopTapDownTimer();
client_->DropStashedTapDown();
return true;
case LAST_CANCEL_STOPPED_FLING: case LAST_CANCEL_STOPPED_FLING:
NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state"; NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state";
return true; return true;
...@@ -143,36 +77,4 @@ base::TimeTicks TapSuppressionController::Now() { ...@@ -143,36 +77,4 @@ base::TimeTicks TapSuppressionController::Now() {
return base::TimeTicks::Now(); return base::TimeTicks::Now();
} }
void TapSuppressionController::StartTapDownTimer(const base::TimeDelta& delay) {
tap_down_timer_.Start(FROM_HERE, delay, this,
&TapSuppressionController::TapDownTimerExpired);
}
void TapSuppressionController::StopTapDownTimer() {
tap_down_timer_.Stop();
}
void TapSuppressionController::TapDownTimerExpired() {
switch (state_) {
case DISABLED:
case NOTHING:
case SUPPRESSING_TAPS:
NOTREACHED() << "Timer fired on invalid state.";
break;
case GFC_IN_PROGRESS:
case LAST_CANCEL_STOPPED_FLING:
NOTREACHED() << "Timer fired on invalid state.";
state_ = NOTHING;
break;
case TAP_DOWN_STASHED:
TRACE_EVENT0("browser",
"TapSuppressionController::TapDownTimerExpired");
// When the timer expires, only forward the stashed tap down event, and
// drop other stashed gesture events (show press or long press).
client_->ForwardStashedTapDown();
state_ = SUPPRESSING_TAPS;
break;
}
}
} // namespace content } // namespace content
...@@ -12,8 +12,6 @@ ...@@ -12,8 +12,6 @@
namespace content { namespace content {
class TapSuppressionControllerClient;
// The core controller for suppression of taps (touchpad or touchscreen) // The core controller for suppression of taps (touchpad or touchscreen)
// immediately following a GestureFlingCancel event (caused by the same tap). // immediately following a GestureFlingCancel event (caused by the same tap).
// Only taps of sufficient speed and within a specified time window after a // Only taps of sufficient speed and within a specified time window after a
...@@ -29,27 +27,19 @@ class CONTENT_EXPORT TapSuppressionController { ...@@ -29,27 +27,19 @@ class CONTENT_EXPORT TapSuppressionController {
// The maximum time allowed between a GestureFlingCancel and its // The maximum time allowed between a GestureFlingCancel and its
// corresponding tap down. // corresponding tap down.
base::TimeDelta max_cancel_to_down_time; base::TimeDelta max_cancel_to_down_time;
// The maximum time allowed between a single tap's down and up events.
base::TimeDelta max_tap_gap_time;
}; };
TapSuppressionController(TapSuppressionControllerClient* client, TapSuppressionController(const Config& config);
const Config& config);
virtual ~TapSuppressionController(); virtual ~TapSuppressionController();
// Should be called whenever a GestureFlingCancel event is received. // Should be called whenever a GestureFlingCancel actually stopped a fling and
void GestureFlingCancel(); // therefore the controller should suppress the forwarding of the following
// tap.
// Should be called whenever an ACK for a GestureFlingCancel event is void GestureFlingCancelStoppedFling();
// received. |processed| is true when the GestureFlingCancel actually stopped
// a fling and therefore should suppress the forwarding of the following tap.
void GestureFlingCancelAck(bool processed);
// Should be called whenever a tap down (touchpad or touchscreen) is received. // Should be called whenever a tap down (touchpad or touchscreen) is received.
// Returns true if the tap down should be deferred. The caller is responsible // Returns true if the tap down should be suppressed.
// for keeping the event for later release, if needed. bool ShouldSuppressTapDown();
bool ShouldDeferTapDown();
// Should be called whenever a tap ending event is received. Returns true if // Should be called whenever a tap ending event is received. Returns true if
// the tap event should be suppressed. // the tap event should be suppressed.
...@@ -57,33 +47,23 @@ class CONTENT_EXPORT TapSuppressionController { ...@@ -57,33 +47,23 @@ class CONTENT_EXPORT TapSuppressionController {
protected: protected:
virtual base::TimeTicks Now(); virtual base::TimeTicks Now();
virtual void StartTapDownTimer(const base::TimeDelta& delay);
virtual void StopTapDownTimer();
void TapDownTimerExpired();
private: private:
friend class MockTapSuppressionController; friend class MockTapSuppressionController;
enum State { enum State {
DISABLED, DISABLED,
NOTHING, NOTHING,
GFC_IN_PROGRESS,
TAP_DOWN_STASHED,
LAST_CANCEL_STOPPED_FLING, LAST_CANCEL_STOPPED_FLING,
// When the stashed TapDown event is dropped or forwarded due to tap down // When the stashed TapDown event is dropped, the controller enters the
// timer expiration, the controller enters the SUPPRESSING_TAPS state. // SUPPRESSING_TAPS state. This state shows that the controller will
// This state shows that the controller will suppress LongTap, // suppress LongTap, TwoFingerTap, and TapCancel gesture events until the
// TwoFingerTap, and TapCancel gesture events until the next tapDown event // next tapDown event arrives.
// arrives.
SUPPRESSING_TAPS, SUPPRESSING_TAPS,
}; };
TapSuppressionControllerClient* client_;
base::OneShotTimer tap_down_timer_;
State state_; State state_;
base::TimeDelta max_cancel_to_down_time_; base::TimeDelta max_cancel_to_down_time_;
base::TimeDelta max_tap_gap_time_;
// TODO(rjkroege): During debugging, the event times did not prove reliable. // TODO(rjkroege): During debugging, the event times did not prove reliable.
// Replace the use of base::TimeTicks with an accurate event time when they // Replace the use of base::TimeTicks with an accurate event time when they
......
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TAP_SUPPRESSION_CONTROLLER_CLIENT_H_
#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TAP_SUPPRESSION_CONTROLLER_CLIENT_H_
#include "base/macros.h"
namespace content {
// This class provides an interface for callbacks made by
// TapSuppressionController.
class TapSuppressionControllerClient {
public:
virtual ~TapSuppressionControllerClient() {}
// Called whenever the deferred tap down (if saved) should be dropped totally.
virtual void DropStashedTapDown() = 0;
// Called whenever the deferred tap down and other gesture events (if saved)
// should be forwarded to the renderer. The tap down (and possibly other
// gesture events) should go back to normal path they were on before being
// deferred.
virtual void ForwardStashedGestureEvents() = 0;
// Called whenever only the deferred tap down (if saved) should be forwarded
// to the renderer. Other saved gesture events will be dropped.
virtual void ForwardStashedTapDown() = 0;
protected:
TapSuppressionControllerClient() {}
private:
DISALLOW_COPY_AND_ASSIGN(TapSuppressionControllerClient);
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TAP_SUPPRESSION_CONTROLLER_CLIENT_H_
...@@ -7,57 +7,41 @@ ...@@ -7,57 +7,41 @@
#include <memory> #include <memory>
#include "base/macros.h" #include "base/macros.h"
#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using base::TimeDelta; using base::TimeDelta;
namespace content { namespace content {
class MockTapSuppressionController : public TapSuppressionController, class MockTapSuppressionController : public TapSuppressionController {
public TapSuppressionControllerClient {
public: public:
using TapSuppressionController::DISABLED; using TapSuppressionController::DISABLED;
using TapSuppressionController::NOTHING; using TapSuppressionController::NOTHING;
using TapSuppressionController::GFC_IN_PROGRESS;
using TapSuppressionController::TAP_DOWN_STASHED;
using TapSuppressionController::LAST_CANCEL_STOPPED_FLING; using TapSuppressionController::LAST_CANCEL_STOPPED_FLING;
using TapSuppressionController::SUPPRESSING_TAPS; using TapSuppressionController::SUPPRESSING_TAPS;
enum Action { enum Action {
NONE = 0, NONE = 0,
TAP_DOWN_DEFERRED = 1 << 0, TAP_DOWN_FORWARDED = 1 << 0,
TAP_DOWN_FORWARDED = 1 << 1, TAP_DOWN_SUPPRESSED = 1 << 1,
TAP_DOWN_DROPPED = 1 << 2, TAP_UP_SUPPRESSED = 1 << 2,
TAP_UP_SUPPRESSED = 1 << 3, TAP_UP_FORWARDED = 1 << 3,
TAP_UP_FORWARDED = 1 << 4,
TAP_CANCEL_SUPPRESSED = 1 << 5,
TAP_CANCEL_FORWARDED = 1 << 6,
STASHED_TAP_DOWN_FORWARDED = 1 << 7,
}; };
MockTapSuppressionController(const TapSuppressionController::Config& config) MockTapSuppressionController(const TapSuppressionController::Config& config)
: TapSuppressionController(this, config), : TapSuppressionController(config), last_actions_(NONE), time_() {}
last_actions_(NONE),
time_(),
timer_started_(false) {}
~MockTapSuppressionController() override {} ~MockTapSuppressionController() override {}
void SendGestureFlingCancel() { void NotifyGestureFlingCancelStoppedFling() {
last_actions_ = NONE; last_actions_ = NONE;
GestureFlingCancel(); GestureFlingCancelStoppedFling();
}
void SendGestureFlingCancelAck(bool processed) {
last_actions_ = NONE;
GestureFlingCancelAck(processed);
} }
void SendTapDown() { void SendTapDown() {
last_actions_ = NONE; last_actions_ = NONE;
if (ShouldDeferTapDown()) if (ShouldSuppressTapDown())
last_actions_ |= TAP_DOWN_DEFERRED; last_actions_ |= TAP_DOWN_SUPPRESSED;
else else
last_actions_ |= TAP_DOWN_FORWARDED; last_actions_ |= TAP_DOWN_FORWARDED;
} }
...@@ -70,23 +54,9 @@ class MockTapSuppressionController : public TapSuppressionController, ...@@ -70,23 +54,9 @@ class MockTapSuppressionController : public TapSuppressionController,
last_actions_ |= TAP_UP_FORWARDED; last_actions_ |= TAP_UP_FORWARDED;
} }
void SendTapCancel() {
bool stashed_tap_down_forwarded =
last_actions_ & STASHED_TAP_DOWN_FORWARDED;
last_actions_ = NONE;
if (!stashed_tap_down_forwarded && ShouldSuppressTapEnd())
last_actions_ |= TAP_CANCEL_SUPPRESSED;
else
last_actions_ |= TAP_CANCEL_FORWARDED;
}
void AdvanceTime(const base::TimeDelta& delta) { void AdvanceTime(const base::TimeDelta& delta) {
last_actions_ = NONE; last_actions_ = NONE;
time_ += delta; time_ += delta;
if (timer_started_ && time_ >= timer_expiry_time_) {
timer_started_ = false;
TapDownTimerExpired();
}
} }
State state() { return state_; } State state() { return state_; }
...@@ -96,36 +66,17 @@ class MockTapSuppressionController : public TapSuppressionController, ...@@ -96,36 +66,17 @@ class MockTapSuppressionController : public TapSuppressionController,
protected: protected:
base::TimeTicks Now() override { return time_; } base::TimeTicks Now() override { return time_; }
void StartTapDownTimer(const base::TimeDelta& delay) override {
timer_expiry_time_ = time_ + delay;
timer_started_ = true;
}
void StopTapDownTimer() override { timer_started_ = false; }
private: private:
// TapSuppressionControllerClient implementation
void DropStashedTapDown() override { last_actions_ |= TAP_DOWN_DROPPED; }
void ForwardStashedGestureEvents() override {
last_actions_ |= STASHED_TAP_DOWN_FORWARDED;
}
void ForwardStashedTapDown() override {
last_actions_ |= STASHED_TAP_DOWN_FORWARDED;
}
// Hiding some derived public methods // Hiding some derived public methods
using TapSuppressionController::GestureFlingCancel; using TapSuppressionController::GestureFlingCancelStoppedFling;
using TapSuppressionController::GestureFlingCancelAck; using TapSuppressionController::ShouldSuppressTapDown;
using TapSuppressionController::ShouldDeferTapDown;
using TapSuppressionController::ShouldSuppressTapEnd; using TapSuppressionController::ShouldSuppressTapEnd;
int last_actions_; int last_actions_;
base::TimeTicks time_; base::TimeTicks time_;
bool timer_started_;
base::TimeTicks timer_expiry_time_;
DISALLOW_COPY_AND_ASSIGN(MockTapSuppressionController); DISALLOW_COPY_AND_ASSIGN(MockTapSuppressionController);
}; };
...@@ -149,25 +100,17 @@ class TapSuppressionControllerTest : public testing::Test { ...@@ -149,25 +100,17 @@ class TapSuppressionControllerTest : public testing::Test {
TapSuppressionController::Config config; TapSuppressionController::Config config;
config.enabled = true; config.enabled = true;
config.max_cancel_to_down_time = base::TimeDelta::FromMilliseconds(10); config.max_cancel_to_down_time = base::TimeDelta::FromMilliseconds(10);
config.max_tap_gap_time = base::TimeDelta::FromMilliseconds(10);
return config; return config;
} }
std::unique_ptr<MockTapSuppressionController> tap_suppression_controller_; std::unique_ptr<MockTapSuppressionController> tap_suppression_controller_;
}; };
// Test TapSuppressionController for when GestureFlingCancel Ack comes before // Test TapSuppressionController for when GestureFlingCancel actually stops
// TapDown and everything happens without any delays. // fling and the tap down event arrives without any delay.
TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapFast) { TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapFast) {
// Send GestureFlingCancel. // Notify the controller that the GFC has stooped an active fling.
tap_suppression_controller_->SendGestureFlingCancel(); tap_suppression_controller_->NotifyGestureFlingCancelStoppedFling();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true);
EXPECT_EQ(MockTapSuppressionController::NONE, EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions()); tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING, EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
...@@ -175,158 +118,24 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapFast) { ...@@ -175,158 +118,24 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapFast) {
// Send TapDown. This TapDown should be suppressed. // Send TapDown. This TapDown should be suppressed.
tap_suppression_controller_->SendTapDown(); tap_suppression_controller_->SendTapDown();
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED, EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_SUPPRESSED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Send TapUp. This TapUp should be suppressed.
tap_suppression_controller_->SendTapUp();
EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
MockTapSuppressionController::TAP_DOWN_DROPPED,
tap_suppression_controller_->last_actions()); tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS, EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state()); tap_suppression_controller_->state());
}
// Test TapSuppressionController for when GestureFlingCancel Ack comes before
// TapDown, but there is a small delay between TapDown and TapUp.
TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapInsufficientlyLateTapUp) {
// Send GestureFlingCancel.
tap_suppression_controller_->SendGestureFlingCancel();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true);
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
tap_suppression_controller_->state());
// Send TapDown. This TapDown should be suppressed.
tap_suppression_controller_->SendTapDown();
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Wait less than allowed delay between TapDown and TapUp, so they are still
// considered a tap.
tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(7));
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Send TapUp. This TapUp should be suppressed. // Send TapUp. This TapUp should be suppressed.
tap_suppression_controller_->SendTapUp(); tap_suppression_controller_->SendTapUp();
EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
MockTapSuppressionController::TAP_DOWN_DROPPED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
}
// Test TapSuppressionController for when GestureFlingCancel Ack comes before
// TapDown, but there is a long delay between TapDown and TapUp.
TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapUp) {
// Send GestureFlingCancel.
tap_suppression_controller_->SendGestureFlingCancel();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send processed GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true);
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
tap_suppression_controller_->state());
// Send TapDown. This TapDown should be suppressed, for now.
tap_suppression_controller_->SendTapDown();
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Wait more than allowed delay between TapDown and TapUp, so they are not
// considered a tap. This should release the previously suppressed TapDown.
tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
// Send TapUp. This TapUp should be still suppressed.
// LongTap should be suppressed when the previously suppressed TapDown is
// forwarded because of the timer expiration.
tap_suppression_controller_->SendTapUp();
EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED, EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED,
tap_suppression_controller_->last_actions()); tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS, EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state()); tap_suppression_controller_->state());
} }
// Test TapSuppressionController for when stashed TapDown gets forwarded. // Test TapSuppressionController for when GestureFlingCancel actually stops
// The next TapCancel should be forwarded as well to maintain a valid input // fling but there is a small delay between the Ack and TapDown.
// stream.
TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapCancel) {
// Send GestureFlingCancel.
tap_suppression_controller_->SendGestureFlingCancel();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send processed GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true);
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
tap_suppression_controller_->state());
// Send TapDown. This TapDown should be suppressed, for now.
tap_suppression_controller_->SendTapDown();
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Wait more than the delay for TapDown timer. This should release the
// previously stashed TapDown.
tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
// Send TapCancel. This TapCancel should be forwarded.
// When a TapDown is forwarded because of the timer expiration, the next
// TapCancel should get forwarded as well to maintain a valid input stream.
tap_suppression_controller_->SendTapCancel();
EXPECT_EQ(MockTapSuppressionController::TAP_CANCEL_FORWARDED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
}
// Test TapSuppressionController for when GestureFlingCancel Ack comes before
// TapDown, but there is a small delay between the Ack and TapDown.
TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapInsufficientlyLateTapDown) { TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapInsufficientlyLateTapDown) {
// Send GestureFlingCancel. // Notify the controller that the GFC has stooped an active fling.
tap_suppression_controller_->SendGestureFlingCancel(); tap_suppression_controller_->NotifyGestureFlingCancelStoppedFling();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true);
EXPECT_EQ(MockTapSuppressionController::NONE, EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions()); tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING, EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
...@@ -342,32 +151,24 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapInsufficientlyLateTapDown) { ...@@ -342,32 +151,24 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapInsufficientlyLateTapDown) {
// Send TapDown. This TapDown should be suppressed. // Send TapDown. This TapDown should be suppressed.
tap_suppression_controller_->SendTapDown(); tap_suppression_controller_->SendTapDown();
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED, EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_SUPPRESSED,
tap_suppression_controller_->last_actions()); tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED, EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state()); tap_suppression_controller_->state());
// Send TapUp. This TapUp should be suppressed. // Send TapUp. This TapUp should be suppressed.
tap_suppression_controller_->SendTapUp(); tap_suppression_controller_->SendTapUp();
EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED | EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED,
MockTapSuppressionController::TAP_DOWN_DROPPED,
tap_suppression_controller_->last_actions()); tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS, EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state()); tap_suppression_controller_->state());
} }
// Test TapSuppressionController for when GestureFlingCancel Ack comes before // Test TapSuppressionController for when GestureFlingCancel actually stops
// TapDown, but there is a long delay between the Ack and TapDown. // fling but there is a long delay between the Ack and TapDown.
TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapDown) { TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapDown) {
// Send GestureFlingCancel. // Notify the controller that the GFC has stooped an active fling.
tap_suppression_controller_->SendGestureFlingCancel(); tap_suppression_controller_->NotifyGestureFlingCancelStoppedFling();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true);
EXPECT_EQ(MockTapSuppressionController::NONE, EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions()); tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING, EXPECT_EQ(MockTapSuppressionController::LAST_CANCEL_STOPPED_FLING,
...@@ -396,155 +197,6 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapDown) { ...@@ -396,155 +197,6 @@ TEST_F(TapSuppressionControllerTest, GFCAckBeforeTapSufficientlyLateTapDown) {
tap_suppression_controller_->state()); tap_suppression_controller_->state());
} }
// Test TapSuppressionController for when unprocessed GestureFlingCancel Ack
// comes after TapDown and everything happens without any delay.
TEST_F(TapSuppressionControllerTest, GFCAckUnprocessedAfterTapFast) {
// Send GestureFlingCancel.
tap_suppression_controller_->SendGestureFlingCancel();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send TapDown. This TapDown should be suppressed, for now.
tap_suppression_controller_->SendTapDown();
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Send unprocessed GestureFlingCancel Ack. This should release the
// previously suppressed TapDown.
tap_suppression_controller_->SendGestureFlingCancelAck(false);
EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::NOTHING,
tap_suppression_controller_->state());
// Send TapUp. This TapUp should not be suppressed.
tap_suppression_controller_->SendTapUp();
EXPECT_EQ(MockTapSuppressionController::TAP_UP_FORWARDED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::NOTHING,
tap_suppression_controller_->state());
}
// Test TapSuppressionController for when processed GestureFlingCancel Ack comes
// after TapDown and everything happens without any delay.
TEST_F(TapSuppressionControllerTest, GFCAckProcessedAfterTapFast) {
// Send GestureFlingCancel.
tap_suppression_controller_->SendGestureFlingCancel();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send TapDown. This TapDown should be suppressed.
tap_suppression_controller_->SendTapDown();
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Send processed GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true);
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Send TapUp. This TapUp should be suppressed.
tap_suppression_controller_->SendTapUp();
EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
MockTapSuppressionController::TAP_DOWN_DROPPED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
}
// Test TapSuppressionController for when GestureFlingCancel Ack comes after
// TapDown and there is a small delay between the Ack and TapUp.
TEST_F(TapSuppressionControllerTest, GFCAckAfterTapInsufficientlyLateTapUp) {
// Send GestureFlingCancel.
tap_suppression_controller_->SendGestureFlingCancel();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send TapDown. This TapDown should be suppressed.
tap_suppression_controller_->SendTapDown();
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Send GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true);
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Wait less than allowed delay between TapDown and TapUp, so they are still
// considered as a tap.
tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(7));
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Send TapUp. This TapUp should be suppressed.
tap_suppression_controller_->SendTapUp();
EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED |
MockTapSuppressionController::TAP_DOWN_DROPPED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
}
// Test TapSuppressionController for when GestureFlingCancel Ack comes after
// TapDown and there is a long delay between the Ack and TapUp.
TEST_F(TapSuppressionControllerTest, GFCAckAfterTapSufficientlyLateTapUp) {
// Send GestureFlingCancel.
tap_suppression_controller_->SendGestureFlingCancel();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::GFC_IN_PROGRESS,
tap_suppression_controller_->state());
// Send TapDown. This TapDown should be suppressed, for now.
tap_suppression_controller_->SendTapDown();
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_DEFERRED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Send GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true);
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::TAP_DOWN_STASHED,
tap_suppression_controller_->state());
// Wait more than allowed delay between TapDown and TapUp, so they are not
// considered as a tap. This should release the previously suppressed TapDown.
tap_suppression_controller_->AdvanceTime(TimeDelta::FromMilliseconds(13));
EXPECT_EQ(MockTapSuppressionController::STASHED_TAP_DOWN_FORWARDED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
// Send TapUp. This TapUp should be still suppressed.
// LongTap should be suppressed when the previously suppressed TapDown is
// forwarded because of timer expiration.
tap_suppression_controller_->SendTapUp();
EXPECT_EQ(MockTapSuppressionController::TAP_UP_SUPPRESSED,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::SUPPRESSING_TAPS,
tap_suppression_controller_->state());
}
// Test that no suppression occurs if the TapSuppressionController is disabled. // Test that no suppression occurs if the TapSuppressionController is disabled.
TEST_F(TapSuppressionControllerTest, NoSuppressionIfDisabled) { TEST_F(TapSuppressionControllerTest, NoSuppressionIfDisabled) {
TapSuppressionController::Config disabled_config; TapSuppressionController::Config disabled_config;
...@@ -552,15 +204,8 @@ TEST_F(TapSuppressionControllerTest, NoSuppressionIfDisabled) { ...@@ -552,15 +204,8 @@ TEST_F(TapSuppressionControllerTest, NoSuppressionIfDisabled) {
tap_suppression_controller_.reset( tap_suppression_controller_.reset(
new MockTapSuppressionController(disabled_config)); new MockTapSuppressionController(disabled_config));
// Send GestureFlingCancel.
tap_suppression_controller_->SendGestureFlingCancel();
EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::DISABLED,
tap_suppression_controller_->state());
// Send GestureFlingCancel Ack. // Send GestureFlingCancel Ack.
tap_suppression_controller_->SendGestureFlingCancelAck(true); tap_suppression_controller_->NotifyGestureFlingCancelStoppedFling();
EXPECT_EQ(MockTapSuppressionController::NONE, EXPECT_EQ(MockTapSuppressionController::NONE,
tap_suppression_controller_->last_actions()); tap_suppression_controller_->last_actions());
EXPECT_EQ(MockTapSuppressionController::DISABLED, EXPECT_EQ(MockTapSuppressionController::DISABLED,
......
...@@ -7,46 +7,18 @@ ...@@ -7,46 +7,18 @@
namespace content { namespace content {
TouchpadTapSuppressionController::TouchpadTapSuppressionController( TouchpadTapSuppressionController::TouchpadTapSuppressionController(
TouchpadTapSuppressionControllerClient* client,
const TapSuppressionController::Config& config) const TapSuppressionController::Config& config)
: client_(client), controller_(this, config) { : TapSuppressionController(config) {}
}
TouchpadTapSuppressionController::~TouchpadTapSuppressionController() {} TouchpadTapSuppressionController::~TouchpadTapSuppressionController() {}
void TouchpadTapSuppressionController::GestureFlingCancel() { bool TouchpadTapSuppressionController::ShouldSuppressMouseDown(
controller_.GestureFlingCancel();
}
void TouchpadTapSuppressionController::GestureFlingCancelAck(bool processed) {
controller_.GestureFlingCancelAck(processed);
}
bool TouchpadTapSuppressionController::ShouldDeferMouseDown(
const MouseEventWithLatencyInfo& event) { const MouseEventWithLatencyInfo& event) {
bool should_defer = controller_.ShouldDeferTapDown(); return ShouldSuppressTapDown();
if (should_defer)
stashed_mouse_down_ = event;
return should_defer;
} }
bool TouchpadTapSuppressionController::ShouldSuppressMouseUp() { bool TouchpadTapSuppressionController::ShouldSuppressMouseUp() {
return controller_.ShouldSuppressTapEnd(); return ShouldSuppressTapEnd();
}
void TouchpadTapSuppressionController::DropStashedTapDown() {
}
void TouchpadTapSuppressionController::ForwardStashedGestureEvents() {
// Mouse downs are not handled by gesture event filter; so, they are
// immediately forwarded to the renderer.
client_->SendMouseEventImmediately(stashed_mouse_down_);
}
void TouchpadTapSuppressionController::ForwardStashedTapDown() {
// Mouse downs are not handled by gesture event filter; so, they are
// immediately forwarded to the renderer.
client_->SendMouseEventImmediately(stashed_mouse_down_);
} }
} // namespace content } // namespace content
...@@ -8,42 +8,23 @@ ...@@ -8,42 +8,23 @@
#include "base/macros.h" #include "base/macros.h"
#include "content/browser/renderer_host/event_with_latency_info.h" #include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/browser/renderer_host/input/tap_suppression_controller.h" #include "content/browser/renderer_host/input/tap_suppression_controller.h"
#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "third_party/blink/public/platform/web_input_event.h" #include "third_party/blink/public/platform/web_input_event.h"
namespace content { namespace content {
class TapSuppressionController;
class CONTENT_EXPORT TouchpadTapSuppressionControllerClient {
public:
virtual ~TouchpadTapSuppressionControllerClient() {}
virtual void SendMouseEventImmediately(
const MouseEventWithLatencyInfo& event) = 0;
};
// Controls the suppression of touchpad taps immediately following the dispatch // Controls the suppression of touchpad taps immediately following the dispatch
// of a GestureFlingCancel event. // of a GestureFlingCancel event.
class TouchpadTapSuppressionController : public TapSuppressionControllerClient { class TouchpadTapSuppressionController : public TapSuppressionController {
public: public:
// The |client| must outlive the TouchpadTapSupressionController. // The |client| must outlive the TouchpadTapSupressionController.
TouchpadTapSuppressionController( TouchpadTapSuppressionController(
TouchpadTapSuppressionControllerClient* client,
const TapSuppressionController::Config& config); const TapSuppressionController::Config& config);
~TouchpadTapSuppressionController() override; ~TouchpadTapSuppressionController() override;
// Should be called on arrival of GestureFlingCancel events.
void GestureFlingCancel();
// Should be called on arrival of ACK for a GestureFlingCancel event.
// |processed| is true if the GestureFlingCancel successfully stopped a fling.
void GestureFlingCancelAck(bool processed);
// Should be called on arrival of MouseDown events. Returns true if the caller // Should be called on arrival of MouseDown events. Returns true if the caller
// should stop normal handling of the MouseDown. In this case, the caller is // should stop normal handling of the MouseDown.
// responsible for saving the event for later use, if needed. bool ShouldSuppressMouseDown(const MouseEventWithLatencyInfo& event);
bool ShouldDeferMouseDown(const MouseEventWithLatencyInfo& event);
// Should be called on arrival of MouseUp events. Returns true if the caller // Should be called on arrival of MouseUp events. Returns true if the caller
// should stop normal handling of the MouseUp. // should stop normal handling of the MouseUp.
...@@ -52,17 +33,6 @@ class TouchpadTapSuppressionController : public TapSuppressionControllerClient { ...@@ -52,17 +33,6 @@ class TouchpadTapSuppressionController : public TapSuppressionControllerClient {
private: private:
friend class MockRenderWidgetHost; friend class MockRenderWidgetHost;
// TapSuppressionControllerClient implementation.
void DropStashedTapDown() override;
void ForwardStashedGestureEvents() override;
void ForwardStashedTapDown() override;
TouchpadTapSuppressionControllerClient* client_;
MouseEventWithLatencyInfo stashed_mouse_down_;
// The core controller of tap suppression.
TapSuppressionController controller_;
DISALLOW_COPY_AND_ASSIGN(TouchpadTapSuppressionController); DISALLOW_COPY_AND_ASSIGN(TouchpadTapSuppressionController);
}; };
......
...@@ -13,60 +13,26 @@ using blink::WebInputEvent; ...@@ -13,60 +13,26 @@ using blink::WebInputEvent;
namespace content { namespace content {
TouchscreenTapSuppressionController::TouchscreenTapSuppressionController( TouchscreenTapSuppressionController::TouchscreenTapSuppressionController(
GestureEventQueue* geq,
const TapSuppressionController::Config& config) const TapSuppressionController::Config& config)
: gesture_event_queue_(geq), : TapSuppressionController(config) {}
forward_next_tap_cancel_(false),
controller_(this, config) {}
TouchscreenTapSuppressionController::~TouchscreenTapSuppressionController() {} TouchscreenTapSuppressionController::~TouchscreenTapSuppressionController() {}
void TouchscreenTapSuppressionController::GestureFlingCancel() {
controller_.GestureFlingCancel();
}
void TouchscreenTapSuppressionController::GestureFlingCancelAck(
bool processed) {
controller_.GestureFlingCancelAck(processed);
}
bool TouchscreenTapSuppressionController::FilterTapEvent( bool TouchscreenTapSuppressionController::FilterTapEvent(
const GestureEventWithLatencyInfo& event) { const GestureEventWithLatencyInfo& event) {
switch (event.event.GetType()) { switch (event.event.GetType()) {
case WebInputEvent::kGestureTapDown: case WebInputEvent::kGestureTapDown:
forward_next_tap_cancel_ = false; return ShouldSuppressTapDown();
if (!controller_.ShouldDeferTapDown())
return false;
stashed_tap_down_.reset(new GestureEventWithLatencyInfo(event));
return true;
case WebInputEvent::kGestureShowPress: case WebInputEvent::kGestureShowPress:
if (!stashed_tap_down_)
return false;
stashed_show_press_.reset(new GestureEventWithLatencyInfo(event));
return true;
case WebInputEvent::kGestureLongPress: case WebInputEvent::kGestureLongPress:
// It is possible that a GestureLongPress arrives after tapDownTimer
// expiration, in this case it should still get filtered if the
// controller suppresses the tap end events.
if (!stashed_tap_down_)
return controller_.ShouldSuppressTapEnd();
stashed_long_press_.reset(new GestureEventWithLatencyInfo(event));
return true;
case WebInputEvent::kGestureTapUnconfirmed: case WebInputEvent::kGestureTapUnconfirmed:
return !!stashed_tap_down_;
case WebInputEvent::kGestureTapCancel: case WebInputEvent::kGestureTapCancel:
return !forward_next_tap_cancel_ && controller_.ShouldSuppressTapEnd();
case WebInputEvent::kGestureTap: case WebInputEvent::kGestureTap:
case WebInputEvent::kGestureDoubleTap: case WebInputEvent::kGestureDoubleTap:
case WebInputEvent::kGestureLongTap: case WebInputEvent::kGestureLongTap:
case WebInputEvent::kGestureTwoFingerTap: case WebInputEvent::kGestureTwoFingerTap:
return controller_.ShouldSuppressTapEnd(); return ShouldSuppressTapEnd();
default: default:
break; break;
...@@ -74,31 +40,4 @@ bool TouchscreenTapSuppressionController::FilterTapEvent( ...@@ -74,31 +40,4 @@ bool TouchscreenTapSuppressionController::FilterTapEvent(
return false; return false;
} }
void TouchscreenTapSuppressionController::DropStashedTapDown() {
stashed_tap_down_.reset();
stashed_show_press_.reset();
stashed_long_press_.reset();
}
void TouchscreenTapSuppressionController::ForwardStashedGestureEvents() {
DCHECK(stashed_tap_down_);
ScopedGestureEvent tap_down = std::move(stashed_tap_down_);
ScopedGestureEvent show_press = std::move(stashed_show_press_);
ScopedGestureEvent long_press = std::move(stashed_long_press_);
gesture_event_queue_->ForwardGestureEvent(*tap_down);
if (show_press)
gesture_event_queue_->ForwardGestureEvent(*show_press);
if (long_press)
gesture_event_queue_->ForwardGestureEvent(*long_press);
}
void TouchscreenTapSuppressionController::ForwardStashedTapDown() {
DCHECK(stashed_tap_down_);
ScopedGestureEvent tap_down = std::move(stashed_tap_down_);
gesture_event_queue_->ForwardGestureEvent(*tap_down);
stashed_show_press_.reset();
stashed_long_press_.reset();
forward_next_tap_cancel_ = true;
}
} // namespace content } // namespace content
...@@ -10,53 +10,22 @@ ...@@ -10,53 +10,22 @@
#include "base/macros.h" #include "base/macros.h"
#include "content/browser/renderer_host/event_with_latency_info.h" #include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/browser/renderer_host/input/tap_suppression_controller.h" #include "content/browser/renderer_host/input/tap_suppression_controller.h"
#include "content/browser/renderer_host/input/tap_suppression_controller_client.h"
namespace content { namespace content {
class GestureEventQueue;
// Controls the suppression of touchscreen taps immediately following the // Controls the suppression of touchscreen taps immediately following the
// dispatch of a GestureFlingCancel event. // dispatch of a GestureFlingCancel event.
class TouchscreenTapSuppressionController class TouchscreenTapSuppressionController : public TapSuppressionController {
: public TapSuppressionControllerClient {
public: public:
TouchscreenTapSuppressionController( TouchscreenTapSuppressionController(
GestureEventQueue* geq,
const TapSuppressionController::Config& config); const TapSuppressionController::Config& config);
~TouchscreenTapSuppressionController() override; ~TouchscreenTapSuppressionController() override;
// Should be called on arrival of GestureFlingCancel events.
void GestureFlingCancel();
// Should be called on arrival of ACK for a GestureFlingCancel event.
// |processed| is true if the GestureFlingCancel successfully stopped a fling.
void GestureFlingCancelAck(bool processed);
// Should be called on arrival of any tap-related events. Returns true if the // Should be called on arrival of any tap-related events. Returns true if the
// caller should stop normal handling of the gesture. // caller should stop normal handling of the gesture.
bool FilterTapEvent(const GestureEventWithLatencyInfo& event); bool FilterTapEvent(const GestureEventWithLatencyInfo& event);
private: private:
// TapSuppressionControllerClient implementation.
void DropStashedTapDown() override;
void ForwardStashedGestureEvents() override;
void ForwardStashedTapDown() override;
GestureEventQueue* gesture_event_queue_;
typedef std::unique_ptr<GestureEventWithLatencyInfo> ScopedGestureEvent;
ScopedGestureEvent stashed_tap_down_;
ScopedGestureEvent stashed_show_press_;
ScopedGestureEvent stashed_long_press_;
// This is true when the stashed GestureTapDown event gets forwarded. The
// controller should forward the next GestureTapCancel as well to maintain a
// valid input stream.
bool forward_next_tap_cancel_;
// The core controller of tap suppression.
TapSuppressionController controller_;
DISALLOW_COPY_AND_ASSIGN(TouchscreenTapSuppressionController); DISALLOW_COPY_AND_ASSIGN(TouchscreenTapSuppressionController);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment