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") {
"renderer_host/input/synthetic_touchscreen_pinch_gesture.h",
"renderer_host/input/tap_suppression_controller.cc",
"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.h",
"renderer_host/input/touch_action_filter.cc",
......
......@@ -28,16 +28,13 @@ FlingController::Config::Config() {}
FlingController::FlingController(
GestureEventQueue* gesture_event_queue,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client,
const Config& config)
: gesture_event_queue_(gesture_event_queue),
client_(fling_client),
touchpad_tap_suppression_controller_(
touchpad_client,
config.touchpad_tap_suppression_config),
touchscreen_tap_suppression_controller_(
gesture_event_queue,
config.touchscreen_tap_suppression_config),
fling_in_progress_(false),
send_wheel_events_nonblocking_(
......@@ -45,7 +42,6 @@ FlingController::FlingController(
features::kTouchpadAndWheelScrollLatching) &&
base::FeatureList::IsEnabled(features::kAsyncWheelEvents)) {
DCHECK(gesture_event_queue);
DCHECK(touchpad_client);
DCHECK(fling_client);
}
......@@ -59,8 +55,7 @@ bool FlingController::ShouldForwardForGFCFiltering(
if (fling_in_progress_)
return !fling_booster_->fling_cancellation_is_deferred();
// Auto-scroll flings are still handled by renderer.
return !gesture_event_queue_->ShouldDiscardFlingCancelEvent(gesture_event);
return false;
}
bool FlingController::ShouldForwardForTapSuppression(
......@@ -69,10 +64,11 @@ bool FlingController::ShouldForwardForTapSuppression(
case WebInputEvent::kGestureFlingCancel:
if (gesture_event.event.SourceDevice() ==
blink::kWebGestureDeviceTouchscreen) {
touchscreen_tap_suppression_controller_.GestureFlingCancel();
touchscreen_tap_suppression_controller_
.GestureFlingCancelStoppedFling();
} else if (gesture_event.event.SourceDevice() ==
blink::kWebGestureDeviceTouchpad) {
touchpad_tap_suppression_controller_.GestureFlingCancel();
touchpad_tap_suppression_controller_.GestureFlingCancelStoppedFling();
}
return true;
case WebInputEvent::kGestureTapDown:
......@@ -172,18 +168,9 @@ void FlingController::ScheduleFlingProgress() {
void FlingController::ProcessGestureFlingCancel(
const GestureEventWithLatencyInfo& gesture_event) {
fling_in_progress_ = false;
bool processed = false;
if (fling_curve_) {
if (fling_curve_)
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) {
......
......@@ -62,7 +62,6 @@ class CONTENT_EXPORT FlingController {
};
FlingController(GestureEventQueue* gesture_event_queue,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client,
const Config& config);
......
......@@ -22,11 +22,9 @@ namespace content {
class FakeFlingController : public FlingController {
public:
FakeFlingController(GestureEventQueue* gesture_event_queue,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client,
const Config& config)
: FlingController(gesture_event_queue,
touchpad_client,
fling_client,
config) {}
......@@ -34,7 +32,6 @@ class FakeFlingController : public FlingController {
};
class FlingControllerTest : public testing::Test,
public TouchpadTapSuppressionControllerClient,
public GestureEventQueueClient,
public FlingControllerClient {
public:
......@@ -46,18 +43,14 @@ class FlingControllerTest : public testing::Test,
~FlingControllerTest() override {}
void SetUp() override {
queue_ = std::make_unique<GestureEventQueue>(this, this, this,
queue_ = std::make_unique<GestureEventQueue>(this, this,
GestureEventQueue::Config());
fling_controller_ = std::make_unique<FakeFlingController>(
queue_.get(), this, this, FlingController::Config());
queue_.get(), this, FlingController::Config());
feature_list_.InitFromCommandLine(
features::kTouchpadAndWheelScrollLatching.name, "");
}
// TouchpadTapSuppressionControllerClient
void SendMouseEventImmediately(
const MouseEventWithLatencyInfo& event) override {}
// GestureEventQueueClient
void SendGestureEventImmediately(
const GestureEventWithLatencyInfo& event) override {}
......
......@@ -26,7 +26,6 @@ GestureEventQueue::Config::Config() {
GestureEventQueue::GestureEventQueue(
GestureEventQueueClient* client,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client,
const Config& config)
: client_(client),
......@@ -37,11 +36,9 @@ GestureEventQueue::GestureEventQueue(
base::FeatureList::IsEnabled(features::kVsyncAlignedInputEvents)),
debounce_interval_(config.debounce_interval),
fling_controller_(this,
touchpad_client,
fling_client,
config.fling_config) {
DCHECK(client);
DCHECK(touchpad_client);
DCHECK(fling_client);
}
......
......@@ -72,7 +72,6 @@ class CONTENT_EXPORT GestureEventQueue {
// Both |client| and |touchpad_client| must outlive the GestureEventQueue.
GestureEventQueue(GestureEventQueueClient* client,
TouchpadTapSuppressionControllerClient* touchpad_client,
FlingControllerClient* fling_client,
const Config& config);
~GestureEventQueue();
......
......@@ -36,7 +36,6 @@ namespace content {
class GestureEventQueueTest : public testing::Test,
public GestureEventQueueClient,
public TouchpadTapSuppressionControllerClient,
public FlingControllerClient {
public:
GestureEventQueueTest() : GestureEventQueueTest(false) {}
......@@ -56,7 +55,7 @@ class GestureEventQueueTest : public testing::Test,
// testing::Test
void SetUp() override {
queue_.reset(new GestureEventQueue(this, this, this, DefaultConfig()));
queue_.reset(new GestureEventQueue(this, this, DefaultConfig()));
}
void TearDown() override {
......@@ -65,18 +64,14 @@ class GestureEventQueueTest : public testing::Test,
queue_.reset();
}
void SetUpForTapSuppression(int max_cancel_to_down_time_ms,
int max_tap_gap_time_ms) {
void SetUpForTapSuppression(int max_cancel_to_down_time_ms) {
GestureEventQueue::Config gesture_config;
gesture_config.fling_config.touchscreen_tap_suppression_config.enabled =
true;
gesture_config.fling_config.touchscreen_tap_suppression_config
.max_cancel_to_down_time =
base::TimeDelta::FromMilliseconds(max_cancel_to_down_time_ms);
gesture_config.fling_config.touchscreen_tap_suppression_config
.max_tap_gap_time =
base::TimeDelta::FromMilliseconds(max_tap_gap_time_ms);
queue_.reset(new GestureEventQueue(this, this, this, gesture_config));
queue_.reset(new GestureEventQueue(this, this, gesture_config));
}
// GestureEventQueueClient
......@@ -101,10 +96,6 @@ class GestureEventQueueTest : public testing::Test,
}
}
// TouchpadTapSuppressionControllerClient
void SendMouseEventImmediately(
const MouseEventWithLatencyInfo& event) override {}
// FlingControllerClient
void SendGeneratedWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) override {}
......@@ -1159,7 +1150,7 @@ TEST_F(GestureEventQueueTest, DebounceDropsDeferredEvents) {
// Test that the fling cancelling tap down event and its following tap get
// suppressed when tap suppression is enabled.
TEST_F(GestureEventQueueTest, TapGetsSuppressedAfterTapDownCancellsFling) {
SetUpForTapSuppression(400, 200);
SetUpForTapSuppression(400);
SimulateGestureFlingStartEvent(0, -10, blink::kWebGestureDeviceTouchscreen);
EXPECT_TRUE(FlingInProgress());
// The fling start event is not sent to the renderer.
......
......@@ -50,24 +50,11 @@ GestureEventQueue::Config GetGestureEventQueueConfig() {
.max_cancel_to_down_time = base::TimeDelta::FromMilliseconds(
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 =
gesture_config->fling_touchpad_tap_suppression_enabled();
config.fling_config.touchpad_tap_suppression_config.max_cancel_to_down_time =
base::TimeDelta::FromMilliseconds(
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;
}
......
......@@ -15,7 +15,6 @@
#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_router_client.h"
#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
#include "content/common/content_constants_internal.h"
#include "content/common/edit_command.h"
#include "content/common/input/input_handler.mojom.h"
......@@ -81,7 +80,7 @@ InputRouterImpl::InputRouterImpl(InputRouterImplClient* client,
features::kTouchpadAndWheelScrollLatching)),
wheel_event_queue_(this, wheel_scroll_latching_enabled_),
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),
host_binding_(this),
frame_host_binding_(this),
......@@ -99,7 +98,7 @@ void InputRouterImpl::SendMouseEvent(
const MouseEventWithLatencyInfo& mouse_event) {
if (mouse_event.event.GetType() == WebInputEvent::kMouseDown &&
gesture_event_queue_.GetTouchpadTapSuppressionController()
->ShouldDeferMouseDown(mouse_event))
->ShouldSuppressMouseDown(mouse_event))
return;
if (mouse_event.event.GetType() == WebInputEvent::kMouseUp &&
gesture_event_queue_.GetTouchpadTapSuppressionController()
......
......@@ -21,7 +21,6 @@
#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/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_handler.mojom.h"
#include "content/common/widget.mojom.h"
......@@ -56,7 +55,6 @@ class CONTENT_EXPORT InputRouterImpl
public FlingControllerClient,
public MouseWheelEventQueueClient,
public PassthroughTouchEventQueueClient,
public TouchpadTapSuppressionControllerClient,
public mojom::WidgetInputHandlerHost {
public:
InputRouterImpl(InputRouterImplClient* client,
......@@ -109,9 +107,7 @@ class CONTENT_EXPORT InputRouterImpl
// Keeps track of last position of touch points and sets MovementXY for them.
void SetMovementXYForTouchPoints(blink::WebTouchEvent* event);
// TouchpadTapSuppressionControllerClient
void SendMouseEventImmediately(
const MouseEventWithLatencyInfo& mouse_event) override;
void SendMouseEventImmediately(const MouseEventWithLatencyInfo& mouse_event);
// PassthroughTouchEventQueueClient
void SendTouchEventImmediately(
......
......@@ -6,102 +6,45 @@
#include "base/logging.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"
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()
: enabled(false),
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(
TapSuppressionControllerClient* client,
const Config& config)
: 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(const Config& config)
: state_(config.enabled ? NOTHING : DISABLED),
max_cancel_to_down_time_(config.max_cancel_to_down_time) {}
TapSuppressionController::~TapSuppressionController() {}
void TapSuppressionController::GestureFlingCancel() {
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) {
void TapSuppressionController::GestureFlingCancelStoppedFling() {
base::TimeTicks event_time = Now();
switch (state_) {
case DISABLED:
case NOTHING:
case SUPPRESSING_TAPS:
break;
case GFC_IN_PROGRESS:
if (processed)
case NOTHING:
fling_cancel_time_ = event_time;
state_ = LAST_CANCEL_STOPPED_FLING;
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:
break;
}
}
bool TapSuppressionController::ShouldDeferTapDown() {
bool TapSuppressionController::ShouldSuppressTapDown() {
base::TimeTicks event_time = Now();
switch (state_) {
case DISABLED:
case NOTHING:
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:
if ((event_time - fling_cancel_time_) < max_cancel_to_down_time_) {
state_ = TAP_DOWN_STASHED;
StartTapDownTimer(max_tap_gap_time_);
state_ = SUPPRESSING_TAPS;
return true;
} else {
state_ = NOTHING;
......@@ -120,16 +63,7 @@ bool TapSuppressionController::ShouldSuppressTapEnd() {
switch (state_) {
case DISABLED:
case NOTHING:
case GFC_IN_PROGRESS:
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:
NOTREACHED() << "Invalid tap end on LAST_CANCEL_STOPPED_FLING state";
return true;
......@@ -143,36 +77,4 @@ base::TimeTicks TapSuppressionController::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
......@@ -12,8 +12,6 @@
namespace content {
class TapSuppressionControllerClient;
// The core controller for suppression of taps (touchpad or touchscreen)
// immediately following a GestureFlingCancel event (caused by the same tap).
// Only taps of sufficient speed and within a specified time window after a
......@@ -29,27 +27,19 @@ class CONTENT_EXPORT TapSuppressionController {
// The maximum time allowed between a GestureFlingCancel and its
// corresponding tap down.
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,
const Config& config);
TapSuppressionController(const Config& config);
virtual ~TapSuppressionController();
// Should be called whenever a GestureFlingCancel event is received.
void GestureFlingCancel();
// Should be called whenever an ACK for a GestureFlingCancel event is
// 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 GestureFlingCancel actually stopped a fling and
// therefore the controller should suppress the forwarding of the following
// tap.
void GestureFlingCancelStoppedFling();
// 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
// for keeping the event for later release, if needed.
bool ShouldDeferTapDown();
// Returns true if the tap down should be suppressed.
bool ShouldSuppressTapDown();
// Should be called whenever a tap ending event is received. Returns true if
// the tap event should be suppressed.
......@@ -57,33 +47,23 @@ class CONTENT_EXPORT TapSuppressionController {
protected:
virtual base::TimeTicks Now();
virtual void StartTapDownTimer(const base::TimeDelta& delay);
virtual void StopTapDownTimer();
void TapDownTimerExpired();
private:
friend class MockTapSuppressionController;
enum State {
DISABLED,
NOTHING,
GFC_IN_PROGRESS,
TAP_DOWN_STASHED,
LAST_CANCEL_STOPPED_FLING,
// When the stashed TapDown event is dropped or forwarded due to tap down
// timer expiration, the controller enters the SUPPRESSING_TAPS state.
// This state shows that the controller will suppress LongTap,
// TwoFingerTap, and TapCancel gesture events until the next tapDown event
// arrives.
// When the stashed TapDown event is dropped, the controller enters the
// SUPPRESSING_TAPS state. This state shows that the controller will
// suppress LongTap, TwoFingerTap, and TapCancel gesture events until the
// next tapDown event arrives.
SUPPRESSING_TAPS,
};
TapSuppressionControllerClient* client_;
base::OneShotTimer tap_down_timer_;
State state_;
base::TimeDelta max_cancel_to_down_time_;
base::TimeDelta max_tap_gap_time_;
// TODO(rjkroege): During debugging, the event times did not prove reliable.
// 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 @@
namespace content {
TouchpadTapSuppressionController::TouchpadTapSuppressionController(
TouchpadTapSuppressionControllerClient* client,
const TapSuppressionController::Config& config)
: client_(client), controller_(this, config) {
}
: TapSuppressionController(config) {}
TouchpadTapSuppressionController::~TouchpadTapSuppressionController() {}
void TouchpadTapSuppressionController::GestureFlingCancel() {
controller_.GestureFlingCancel();
}
void TouchpadTapSuppressionController::GestureFlingCancelAck(bool processed) {
controller_.GestureFlingCancelAck(processed);
}
bool TouchpadTapSuppressionController::ShouldDeferMouseDown(
bool TouchpadTapSuppressionController::ShouldSuppressMouseDown(
const MouseEventWithLatencyInfo& event) {
bool should_defer = controller_.ShouldDeferTapDown();
if (should_defer)
stashed_mouse_down_ = event;
return should_defer;
return ShouldSuppressTapDown();
}
bool TouchpadTapSuppressionController::ShouldSuppressMouseUp() {
return controller_.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_);
return ShouldSuppressTapEnd();
}
} // namespace content
......@@ -8,42 +8,23 @@
#include "base/macros.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_client.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/platform/web_input_event.h"
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
// of a GestureFlingCancel event.
class TouchpadTapSuppressionController : public TapSuppressionControllerClient {
class TouchpadTapSuppressionController : public TapSuppressionController {
public:
// The |client| must outlive the TouchpadTapSupressionController.
TouchpadTapSuppressionController(
TouchpadTapSuppressionControllerClient* client,
const TapSuppressionController::Config& config);
~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 stop normal handling of the MouseDown. In this case, the caller is
// responsible for saving the event for later use, if needed.
bool ShouldDeferMouseDown(const MouseEventWithLatencyInfo& event);
// should stop normal handling of the MouseDown.
bool ShouldSuppressMouseDown(const MouseEventWithLatencyInfo& event);
// Should be called on arrival of MouseUp events. Returns true if the caller
// should stop normal handling of the MouseUp.
......@@ -52,17 +33,6 @@ class TouchpadTapSuppressionController : public TapSuppressionControllerClient {
private:
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);
};
......
......@@ -13,60 +13,26 @@ using blink::WebInputEvent;
namespace content {
TouchscreenTapSuppressionController::TouchscreenTapSuppressionController(
GestureEventQueue* geq,
const TapSuppressionController::Config& config)
: gesture_event_queue_(geq),
forward_next_tap_cancel_(false),
controller_(this, config) {}
: TapSuppressionController(config) {}
TouchscreenTapSuppressionController::~TouchscreenTapSuppressionController() {}
void TouchscreenTapSuppressionController::GestureFlingCancel() {
controller_.GestureFlingCancel();
}
void TouchscreenTapSuppressionController::GestureFlingCancelAck(
bool processed) {
controller_.GestureFlingCancelAck(processed);
}
bool TouchscreenTapSuppressionController::FilterTapEvent(
const GestureEventWithLatencyInfo& event) {
switch (event.event.GetType()) {
case WebInputEvent::kGestureTapDown:
forward_next_tap_cancel_ = false;
if (!controller_.ShouldDeferTapDown())
return false;
stashed_tap_down_.reset(new GestureEventWithLatencyInfo(event));
return true;
return ShouldSuppressTapDown();
case WebInputEvent::kGestureShowPress:
if (!stashed_tap_down_)
return false;
stashed_show_press_.reset(new GestureEventWithLatencyInfo(event));
return true;
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:
return !!stashed_tap_down_;
case WebInputEvent::kGestureTapCancel:
return !forward_next_tap_cancel_ && controller_.ShouldSuppressTapEnd();
case WebInputEvent::kGestureTap:
case WebInputEvent::kGestureDoubleTap:
case WebInputEvent::kGestureLongTap:
case WebInputEvent::kGestureTwoFingerTap:
return controller_.ShouldSuppressTapEnd();
return ShouldSuppressTapEnd();
default:
break;
......@@ -74,31 +40,4 @@ bool TouchscreenTapSuppressionController::FilterTapEvent(
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
......@@ -10,53 +10,22 @@
#include "base/macros.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_client.h"
namespace content {
class GestureEventQueue;
// Controls the suppression of touchscreen taps immediately following the
// dispatch of a GestureFlingCancel event.
class TouchscreenTapSuppressionController
: public TapSuppressionControllerClient {
class TouchscreenTapSuppressionController : public TapSuppressionController {
public:
TouchscreenTapSuppressionController(
GestureEventQueue* geq,
const TapSuppressionController::Config& config);
~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
// caller should stop normal handling of the gesture.
bool FilterTapEvent(const GestureEventWithLatencyInfo& event);
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);
};
......
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