1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
content / common / input / synthetic_tap_gesture.cc [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_IN_MIGRATION()
<< "State SETUP invalid for synthetic tap gesture.";
break;
case DONE:
NOTREACHED_IN_MIGRATION()
<< "State DONE invalid for synthetic tap gesture.";
break;
}
}
base::TimeDelta SyntheticTapGesture::GetDuration() const {
return base::Milliseconds(params().duration_ms);
}
} // namespace content