blob: be2daaa031777af7a37e218f86c86eb59ecd755b [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/input/synthetic_tap_gesture.h"
#include "base/check_op.h"
#include "base/notreached.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "ui/latency/latency_info.h"
namespace content {
SyntheticTapGesture::SyntheticTapGesture(
const SyntheticTapGestureParams& gesture_params)
: SyntheticGestureBase(gesture_params),
gesture_source_type_(content::mojom::GestureSourceType::kDefaultInput),
state_(SETUP) {
CHECK_EQ(SyntheticGestureParams::TAP_GESTURE,
gesture_params.GetGestureType());
DCHECK_GE(params().duration_ms, 0);
if (params().gesture_source_type ==
content::mojom::GestureSourceType::kDefaultInput) {
params().gesture_source_type =
content::mojom::GestureSourceType::kTouchInput;
}
}
SyntheticTapGesture::~SyntheticTapGesture() {}
SyntheticGesture::Result SyntheticTapGesture::ForwardInputEvents(
const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
CHECK(dispatching_controller_);
// Keep this on the stack so we can check if the forwarded event caused the
// deletion of the controller (which owns `this`).
base::WeakPtr<SyntheticGestureController> weak_controller =
dispatching_controller_;
if (state_ == SETUP) {
gesture_source_type_ = params().gesture_source_type;
if (gesture_source_type_ ==
content::mojom::GestureSourceType::kDefaultInput)
gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
state_ = PRESS;
}
DCHECK_NE(gesture_source_type_,
content::mojom::GestureSourceType::kDefaultInput);
if (!synthetic_pointer_driver_)
synthetic_pointer_driver_ = SyntheticPointerDriver::Create(
gesture_source_type_, params().from_devtools_debugger);
if (gesture_source_type_ == content::mojom::GestureSourceType::kTouchInput ||
gesture_source_type_ == content::mojom::GestureSourceType::kMouseInput) {
ForwardTouchOrMouseInputEvents(timestamp, target);
if (!weak_controller) {
// ForwardTouchOrMouseInputEvents may cause the controller (and therefore
// `this`) to be synchronously deleted (e.g. tapping tab-close). Return
// immediately in this case.
return SyntheticGesture::GESTURE_ABORT;
}
} else {
return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
}
return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
: SyntheticGesture::GESTURE_RUNNING;
}
void SyntheticTapGesture::WaitForTargetAck(
base::OnceClosure callback,
SyntheticGestureTarget* target) const {
target->WaitForTargetAck(params().GetGestureType(), gesture_source_type_,
std::move(callback));
}
bool SyntheticTapGesture::AllowHighFrequencyDispatch() const {
return false;
}
// CAUTION: Dispatching press/release events can cause `this` to be deleted.
void SyntheticTapGesture::ForwardTouchOrMouseInputEvents(
const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
// Keep this on the stack so we can check if the forwarded event caused the
// deletion of the controller (which owns `this`).
base::WeakPtr<SyntheticGestureController> weak_controller =
dispatching_controller_;
switch (state_) {
case PRESS:
synthetic_pointer_driver_->Press(params().position.x(),
params().position.y());
synthetic_pointer_driver_->DispatchEvent(target, timestamp);
if (!weak_controller) {
return;
}
// Release immediately if duration is 0.
if (params().duration_ms == 0) {
synthetic_pointer_driver_->Release();
synthetic_pointer_driver_->DispatchEvent(target, timestamp);
if (!weak_controller) {
return;
}
state_ = DONE;
} else {
start_time_ = timestamp;
state_ = WAITING_TO_RELEASE;
}
break;
case WAITING_TO_RELEASE:
if (timestamp - start_time_ >= GetDuration()) {
synthetic_pointer_driver_->Release();
synthetic_pointer_driver_->DispatchEvent(target,
start_time_ + GetDuration());
if (!weak_controller) {
return;
}
state_ = DONE;
}
break;
case SETUP:
NOTREACHED() << "State SETUP invalid for synthetic tap gesture.";
case DONE:
NOTREACHED() << "State DONE invalid for synthetic tap gesture.";
}
}
base::TimeDelta SyntheticTapGesture::GetDuration() const {
return base::Milliseconds(params().duration_ms);
}
} // namespace content