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,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