1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <utility>
11
12 #include "base/location.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/test/metrics/histogram_tester.h"
16 #include "base/test/task_environment.h"
17 #include "base/threading/thread_task_runner_handle.h"
18 #include "build/build_config.h"
19 #include "build/chromeos_buildflags.h"
20 #include "content/browser/renderer_host/input/timeout_monitor.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
23 #include "third_party/blink/public/common/input/web_input_event.h"
24 #include "ui/events/base_event_utils.h"
25
26 using blink::WebGestureEvent;
27 using blink::WebInputEvent;
28 using blink::WebMouseWheelEvent;
29
30 namespace content {
31 namespace {
32
33 const float kWheelScrollX = 10;
34 const float kWheelScrollY = 12;
35 const float kWheelScrollGlobalX = 50;
36 const float kWheelScrollGlobalY = 72;
37
38 #define EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event) \
39 EXPECT_EQ(WebInputEvent::Type::kGestureScrollBegin, event->GetType()); \
40 EXPECT_EQ(kWheelScrollX, event->PositionInWidget().x()); \
41 EXPECT_EQ(kWheelScrollY, event->PositionInWidget().y()); \
42 EXPECT_EQ(kWheelScrollGlobalX, event->PositionInScreen().x()); \
43 EXPECT_EQ(kWheelScrollGlobalY, event->PositionInScreen().y()); \
44 EXPECT_EQ(scroll_units, event->data.scroll_begin.delta_hint_units);
45
46 #define EXPECT_GESTURE_SCROLL_BEGIN(event) \
47 EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
48 EXPECT_FALSE(event->data.scroll_begin.synthetic); \
49 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kUnknownMomentum, \
50 event->data.scroll_begin.inertial_phase);
51
52 #define EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(event) \
53 EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
54 EXPECT_FALSE(event->data.scroll_begin.synthetic); \
55 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
56 event->data.scroll_begin.inertial_phase);
57
58 #define EXPECT_SYNTHETIC_GESTURE_SCROLL_BEGIN(event) \
59 EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
60 EXPECT_TRUE(event->data.scroll_begin.synthetic); \
61 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
62 event->data.scroll_begin.inertial_phase);
63
64 #define EXPECT_INERTIAL_GESTURE_SCROLL_BEGIN(event) \
65 EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
66 EXPECT_FALSE(event->data.scroll_begin.synthetic); \
67 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
68 event->data.scroll_begin.inertial_phase);
69
70 #define EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_BEGIN(event) \
71 EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
72 EXPECT_TRUE(event->data.scroll_begin.synthetic); \
73 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
74 event->data.scroll_begin.inertial_phase);
75
76 #define EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event) \
77 EXPECT_EQ(WebInputEvent::Type::kGestureScrollUpdate, event->GetType()); \
78 EXPECT_EQ(scroll_units, event->data.scroll_update.delta_units); \
79 EXPECT_EQ(kWheelScrollX, event->PositionInWidget().x()); \
80 EXPECT_EQ(kWheelScrollY, event->PositionInWidget().y()); \
81 EXPECT_EQ(kWheelScrollGlobalX, event->PositionInScreen().x()); \
82 EXPECT_EQ(kWheelScrollGlobalY, event->PositionInScreen().y());
83
84 #define EXPECT_GESTURE_SCROLL_UPDATE(event) \
85 EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
86 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kUnknownMomentum, \
87 event->data.scroll_update.inertial_phase);
88
89 #define EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(event) \
90 EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
91 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
92 event->data.scroll_update.inertial_phase);
93
94 #define EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(event) \
95 EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
96 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
97 event->data.scroll_update.inertial_phase);
98
99 #define EXPECT_GESTURE_SCROLL_END_IMPL(event) \
100 EXPECT_EQ(WebInputEvent::Type::kGestureScrollEnd, event->GetType()); \
101 EXPECT_EQ(scroll_units, event->data.scroll_end.delta_units); \
102 EXPECT_EQ(kWheelScrollX, event->PositionInWidget().x()); \
103 EXPECT_EQ(kWheelScrollY, event->PositionInWidget().y()); \
104 EXPECT_EQ(kWheelScrollGlobalX, event->PositionInScreen().x()); \
105 EXPECT_EQ(kWheelScrollGlobalY, event->PositionInScreen().y());
106
107 #define EXPECT_GESTURE_SCROLL_END(event) \
108 EXPECT_GESTURE_SCROLL_END_IMPL(event); \
109 EXPECT_FALSE(event->data.scroll_end.synthetic); \
110 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kUnknownMomentum, \
111 event->data.scroll_end.inertial_phase);
112
113 #define EXPECT_GESTURE_SCROLL_END_WITH_PHASE(event) \
114 EXPECT_GESTURE_SCROLL_END_IMPL(event); \
115 EXPECT_FALSE(event->data.scroll_end.synthetic); \
116 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
117 event->data.scroll_end.inertial_phase);
118
119 #define EXPECT_SYNTHETIC_GESTURE_SCROLL_END(event) \
120 EXPECT_GESTURE_SCROLL_END_IMPL(event); \
121 EXPECT_TRUE(event->data.scroll_end.synthetic); \
122 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kNonMomentum, \
123 event->data.scroll_end.inertial_phase);
124
125 #define EXPECT_INERTIAL_GESTURE_SCROLL_END(event) \
126 EXPECT_GESTURE_SCROLL_END_IMPL(event); \
127 EXPECT_FALSE(event->data.scroll_end.synthetic); \
128 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
129 event->data.scroll_end.inertial_phase);
130
131 #if BUILDFLAG(IS_CHROMEOS_ASH)
132 #define EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_END(event) \
133 EXPECT_GESTURE_SCROLL_END_IMPL(event); \
134 EXPECT_TRUE(event->data.scroll_end.synthetic); \
135 EXPECT_EQ(WebGestureEvent::InertialPhaseState::kMomentum, \
136 event->data.scroll_end.inertial_phase); \
137 EXPECT_TRUE(event->data.scroll_end.generated_by_fling_controller);
138 #endif
139
140 #define EXPECT_MOUSE_WHEEL(event) \
141 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, event->GetType());
142
143 } // namespace
144
145 class MouseWheelEventQueueTest : public testing::Test,
146 public MouseWheelEventQueueClient {
147 public:
MouseWheelEventQueueTest()148 MouseWheelEventQueueTest()
149 : task_environment_(
150 base::test::SingleThreadTaskEnvironment::MainThreadType::UI),
151 acked_event_count_(0),
152 last_acked_event_state_(blink::mojom::InputEventResultState::kUnknown) {
153 queue_.reset(new MouseWheelEventQueue(this));
154 }
155
~MouseWheelEventQueueTest()156 ~MouseWheelEventQueueTest() override {}
157
158 // MouseWheelEventQueueClient
SendMouseWheelEventImmediately(const MouseWheelEventWithLatencyInfo & event,MouseWheelEventHandledCallback callback)159 void SendMouseWheelEventImmediately(
160 const MouseWheelEventWithLatencyInfo& event,
161 MouseWheelEventHandledCallback callback) override {
162 WebMouseWheelEvent* cloned_event = new WebMouseWheelEvent();
163 std::unique_ptr<WebInputEvent> cloned_event_holder(cloned_event);
164 *cloned_event = event.event;
165 sent_events_.push_back(std::move(cloned_event_holder));
166 callbacks_.emplace_back(base::BindOnce(
167 [](MouseWheelEventHandledCallback callback,
168 const MouseWheelEventWithLatencyInfo& event,
169 blink::mojom::InputEventResultSource ack_source,
170 blink::mojom::InputEventResultState ack_result) {
171 std::move(callback).Run(event, ack_source, ack_result);
172 },
173 std::move(callback), event));
174 }
175
ForwardGestureEventWithLatencyInfo(const blink::WebGestureEvent & event,const ui::LatencyInfo & latency_info)176 void ForwardGestureEventWithLatencyInfo(
177 const blink::WebGestureEvent& event,
178 const ui::LatencyInfo& latency_info) override {
179 WebGestureEvent* cloned_event = new WebGestureEvent();
180 std::unique_ptr<WebInputEvent> cloned_event_holder(cloned_event);
181 *cloned_event = event;
182 if (event.GetType() == WebInputEvent::Type::kGestureScrollBegin) {
183 is_wheel_scroll_in_progress_ = true;
184 } else if (event.GetType() == WebInputEvent::Type::kGestureScrollEnd) {
185 is_wheel_scroll_in_progress_ = false;
186 }
187 sent_events_.push_back(std::move(cloned_event_holder));
188 }
189
OnMouseWheelEventAck(const MouseWheelEventWithLatencyInfo & event,blink::mojom::InputEventResultSource ack_source,blink::mojom::InputEventResultState ack_result)190 void OnMouseWheelEventAck(
191 const MouseWheelEventWithLatencyInfo& event,
192 blink::mojom::InputEventResultSource ack_source,
193 blink::mojom::InputEventResultState ack_result) override {
194 ++acked_event_count_;
195 last_acked_event_ = event.event;
196 last_acked_event_state_ = ack_result;
197 }
198
IsWheelScrollInProgress()199 bool IsWheelScrollInProgress() override {
200 return is_wheel_scroll_in_progress_;
201 }
202
IsAutoscrollInProgress()203 bool IsAutoscrollInProgress() override { return false; }
204
205 protected:
206 using HandleEventCallback =
207 base::OnceCallback<void(blink::mojom::InputEventResultSource ack_source,
208 blink::mojom::InputEventResultState ack_result)>;
209
queued_event_count() const210 size_t queued_event_count() const { return queue_->queued_size(); }
211
event_in_flight() const212 bool event_in_flight() const { return queue_->event_in_flight(); }
213
all_sent_events()214 std::vector<std::unique_ptr<WebInputEvent>>& all_sent_events() {
215 return sent_events_;
216 }
217
sent_input_event(size_t index)218 const std::unique_ptr<WebInputEvent>& sent_input_event(size_t index) {
219 return sent_events_[index];
220 }
sent_gesture_event(size_t index)221 const WebGestureEvent* sent_gesture_event(size_t index) {
222 return static_cast<WebGestureEvent*>(sent_events_[index].get());
223 }
224
acked_event() const225 const WebMouseWheelEvent& acked_event() const { return last_acked_event_; }
226
GetAndResetSentEventCount()227 size_t GetAndResetSentEventCount() {
228 size_t count = sent_events_.size();
229 sent_events_.clear();
230 return count;
231 }
232
GetAndResetAckedEventCount()233 size_t GetAndResetAckedEventCount() {
234 size_t count = acked_event_count_;
235 acked_event_count_ = 0;
236 return count;
237 }
238
SendMouseWheelEventAck(blink::mojom::InputEventResultState ack_result)239 void SendMouseWheelEventAck(blink::mojom::InputEventResultState ack_result) {
240 std::move(callbacks_.front())
241 .Run(blink::mojom::InputEventResultSource::kCompositorThread,
242 ack_result);
243 callbacks_.pop_front();
244 }
245
SendMouseWheel(float x,float y,float global_x,float global_y,float dX,float dY,int modifiers,bool high_precision,blink::WebMouseWheelEvent::Phase phase,blink::WebMouseWheelEvent::Phase momentum_phase,WebInputEvent::RailsMode rails_mode,bool has_synthetic_phase=false)246 void SendMouseWheel(float x,
247 float y,
248 float global_x,
249 float global_y,
250 float dX,
251 float dY,
252 int modifiers,
253 bool high_precision,
254 blink::WebMouseWheelEvent::Phase phase,
255 blink::WebMouseWheelEvent::Phase momentum_phase,
256 WebInputEvent::RailsMode rails_mode,
257 bool has_synthetic_phase = false) {
258 WebMouseWheelEvent event = blink::SyntheticWebMouseWheelEventBuilder::Build(
259 x, y, global_x, global_y, dX, dY, modifiers,
260 high_precision ? ui::ScrollGranularity::kScrollByPrecisePixel
261 : ui::ScrollGranularity::kScrollByPixel);
262 event.phase = phase;
263 event.momentum_phase = momentum_phase;
264 event.rails_mode = rails_mode;
265 event.has_synthetic_phase = has_synthetic_phase;
266 queue_->QueueEvent(MouseWheelEventWithLatencyInfo(event));
267 }
SendMouseWheel(float x,float y,float global_x,float global_y,float dX,float dY,int modifiers,bool high_precision,blink::WebMouseWheelEvent::Phase phase,blink::WebMouseWheelEvent::Phase momentum_phase,bool has_synthetic_phase=false)268 void SendMouseWheel(float x,
269 float y,
270 float global_x,
271 float global_y,
272 float dX,
273 float dY,
274 int modifiers,
275 bool high_precision,
276 blink::WebMouseWheelEvent::Phase phase,
277 blink::WebMouseWheelEvent::Phase momentum_phase,
278 bool has_synthetic_phase = false) {
279 SendMouseWheel(x, y, global_x, global_y, dX, dY, modifiers, high_precision,
280 phase, momentum_phase, WebInputEvent::kRailsModeFree,
281 has_synthetic_phase);
282 }
283
SendGestureEvent(WebInputEvent::Type type)284 void SendGestureEvent(WebInputEvent::Type type) {
285 WebGestureEvent event(type, WebInputEvent::kNoModifiers,
286 ui::EventTimeForNow(),
287 blink::WebGestureDevice::kTouchscreen);
288 queue_->OnGestureScrollEvent(
289 GestureEventWithLatencyInfo(event, ui::LatencyInfo()));
290 }
291
RunTasksAndWait(base::TimeDelta delay)292 static void RunTasksAndWait(base::TimeDelta delay) {
293 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
294 FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
295 delay);
296 base::RunLoop().Run();
297 }
298
GestureSendingTest(bool high_precision)299 void GestureSendingTest(bool high_precision) {
300 const ui::ScrollGranularity scroll_units =
301 high_precision ? ui::ScrollGranularity::kScrollByPrecisePixel
302 : ui::ScrollGranularity::kScrollByPixel;
303 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
304 kWheelScrollGlobalY, 1, 1, 0, high_precision,
305 WebMouseWheelEvent::kPhaseBegan,
306 WebMouseWheelEvent::kPhaseNone);
307 EXPECT_EQ(0U, queued_event_count());
308 EXPECT_TRUE(event_in_flight());
309 EXPECT_EQ(1U, GetAndResetSentEventCount());
310
311 // The second mouse wheel should not be sent since one is already in
312 // queue.
313 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
314 kWheelScrollGlobalY, 5, 5, 0, high_precision,
315 WebMouseWheelEvent::kPhaseChanged,
316 WebMouseWheelEvent::kPhaseNone);
317 EXPECT_EQ(1U, queued_event_count());
318 EXPECT_TRUE(event_in_flight());
319 EXPECT_EQ(0U, GetAndResetSentEventCount());
320
321 // Receive an ACK for the mouse wheel event and release the next
322 // mouse wheel event.
323 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
324 EXPECT_EQ(0U, queued_event_count());
325 EXPECT_TRUE(event_in_flight());
326 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
327 EXPECT_EQ(1U, GetAndResetAckedEventCount());
328 EXPECT_EQ(3U, all_sent_events().size());
329 EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
330 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
331 EXPECT_MOUSE_WHEEL(sent_input_event(2));
332 EXPECT_EQ(3U, GetAndResetSentEventCount());
333 }
334
PhaseGestureSendingTest(bool high_precision)335 void PhaseGestureSendingTest(bool high_precision) {
336 const ui::ScrollGranularity scroll_units =
337 high_precision ? ui::ScrollGranularity::kScrollByPrecisePixel
338 : ui::ScrollGranularity::kScrollByPixel;
339
340 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
341 kWheelScrollGlobalY, 1, 1, 0, high_precision,
342 WebMouseWheelEvent::kPhaseBegan,
343 WebMouseWheelEvent::kPhaseNone);
344 EXPECT_EQ(1U, GetAndResetSentEventCount());
345 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
346 EXPECT_EQ(2U, all_sent_events().size());
347 EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
348 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
349 EXPECT_EQ(2U, GetAndResetSentEventCount());
350
351 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
352 kWheelScrollGlobalY, 5, 5, 0, high_precision,
353 WebMouseWheelEvent::kPhaseChanged,
354 WebMouseWheelEvent::kPhaseNone);
355 EXPECT_EQ(1U, GetAndResetSentEventCount());
356 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
357 EXPECT_EQ(1U, all_sent_events().size());
358 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(0));
359 EXPECT_EQ(1U, GetAndResetSentEventCount());
360
361 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
362 kWheelScrollGlobalY, 5, 5, 0, high_precision,
363 WebMouseWheelEvent::kPhaseNone,
364 WebMouseWheelEvent::kPhaseBegan);
365 EXPECT_EQ(1U, GetAndResetSentEventCount());
366 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
367 // A fling has started, no ScrollEnd/ScrollBegin is sent.
368 EXPECT_EQ(1U, all_sent_events().size());
369 EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(sent_gesture_event(0));
370 EXPECT_EQ(1U, GetAndResetSentEventCount());
371
372 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
373 kWheelScrollGlobalY, 5, 5, 0, high_precision,
374 WebMouseWheelEvent::kPhaseNone,
375 WebMouseWheelEvent::kPhaseChanged);
376 EXPECT_EQ(1U, GetAndResetSentEventCount());
377 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
378 EXPECT_EQ(1U, all_sent_events().size());
379 EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(sent_gesture_event(0));
380 EXPECT_EQ(1U, GetAndResetSentEventCount());
381
382 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
383 kWheelScrollGlobalY, 0, 0, 0, high_precision,
384 WebMouseWheelEvent::kPhaseNone,
385 WebMouseWheelEvent::kPhaseEnded);
386 EXPECT_EQ(1U, GetAndResetSentEventCount());
387 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
388 // MomentumPhase is ended, the scroll is done, and GSE is sent
389 // immediately.
390 EXPECT_EQ(1U, all_sent_events().size());
391 EXPECT_INERTIAL_GESTURE_SCROLL_END(sent_gesture_event(0));
392 EXPECT_EQ(1U, GetAndResetSentEventCount());
393 }
394
395 base::test::SingleThreadTaskEnvironment task_environment_;
396 std::unique_ptr<MouseWheelEventQueue> queue_;
397 std::vector<std::unique_ptr<WebInputEvent>> sent_events_;
398 base::circular_deque<HandleEventCallback> callbacks_;
399 size_t acked_event_count_;
400 blink::mojom::InputEventResultState last_acked_event_state_;
401 WebMouseWheelEvent last_acked_event_;
402
403 private:
404 bool is_wheel_scroll_in_progress_ = false;
405 };
406
407 // Tests that mouse wheel events are queued properly.
TEST_F(MouseWheelEventQueueTest,Basic)408 TEST_F(MouseWheelEventQueueTest, Basic) {
409 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
410 kWheelScrollGlobalY, 1, 1, 0, false,
411 WebMouseWheelEvent::kPhaseBegan,
412 WebMouseWheelEvent::kPhaseNone);
413 EXPECT_EQ(0U, queued_event_count());
414 EXPECT_TRUE(event_in_flight());
415 EXPECT_EQ(1U, GetAndResetSentEventCount());
416
417 // The second mouse wheel should not be sent since one is already in queue.
418 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
419 kWheelScrollGlobalY, 5, 5, 0, false,
420 WebMouseWheelEvent::kPhaseChanged,
421 WebMouseWheelEvent::kPhaseNone);
422 EXPECT_EQ(1U, queued_event_count());
423 EXPECT_TRUE(event_in_flight());
424 EXPECT_EQ(0U, GetAndResetSentEventCount());
425
426 // Receive an ACK for the first mouse wheel event.
427 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kConsumed);
428 EXPECT_EQ(0U, queued_event_count());
429 EXPECT_TRUE(event_in_flight());
430 EXPECT_EQ(1U, GetAndResetSentEventCount());
431 EXPECT_EQ(1U, GetAndResetAckedEventCount());
432 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
433
434 // Receive an ACK for the second mouse wheel event.
435 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kConsumed);
436 EXPECT_EQ(0U, queued_event_count());
437 EXPECT_FALSE(event_in_flight());
438 EXPECT_EQ(0U, GetAndResetSentEventCount());
439 EXPECT_EQ(1U, GetAndResetAckedEventCount());
440 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
441 }
442
TEST_F(MouseWheelEventQueueTest,GestureSending)443 TEST_F(MouseWheelEventQueueTest, GestureSending) {
444 GestureSendingTest(false);
445 }
446
TEST_F(MouseWheelEventQueueTest,GestureSendingPrecisePixels)447 TEST_F(MouseWheelEventQueueTest, GestureSendingPrecisePixels) {
448 GestureSendingTest(true);
449 }
450
TEST_F(MouseWheelEventQueueTest,GestureSendingWithPhaseInformation)451 TEST_F(MouseWheelEventQueueTest, GestureSendingWithPhaseInformation) {
452 PhaseGestureSendingTest(false);
453 }
454
TEST_F(MouseWheelEventQueueTest,GestureSendingWithPhaseInformationPrecisePixels)455 TEST_F(MouseWheelEventQueueTest,
456 GestureSendingWithPhaseInformationPrecisePixels) {
457 PhaseGestureSendingTest(true);
458 }
459
460 // Tests that a Wheel event with synthetic momentumn_phase == PhaseEnded that is
461 // generated by the fling controller properly populates
462 // scroll_end.data.scroll_end.generated_by_fling_controller.
463 #if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(MouseWheelEventQueueTest,WheelEndWithMomentumPhaseEndedInformation)464 TEST_F(MouseWheelEventQueueTest, WheelEndWithMomentumPhaseEndedInformation) {
465 const ui::ScrollGranularity scroll_units =
466 ui::ScrollGranularity::kScrollByPrecisePixel;
467 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
468 kWheelScrollGlobalY, 1, 1, 0, true /* high_precision */,
469 WebMouseWheelEvent::kPhaseBegan,
470 WebMouseWheelEvent::kPhaseNone);
471 EXPECT_EQ(0U, queued_event_count());
472 EXPECT_TRUE(event_in_flight());
473 EXPECT_EQ(1U, GetAndResetSentEventCount());
474 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
475 EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
476 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
477 EXPECT_EQ(2U, GetAndResetSentEventCount());
478
479 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
480 kWheelScrollGlobalY, 0, 0, 0, true /* high_precision */,
481 WebMouseWheelEvent::kPhaseNone,
482 WebMouseWheelEvent::kPhaseEnded, true /*has_synthetic_phase*/);
483 EXPECT_EQ(0U, queued_event_count());
484 EXPECT_TRUE(event_in_flight());
485 EXPECT_EQ(1U, GetAndResetSentEventCount());
486 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
487
488 EXPECT_EQ(1U, all_sent_events().size());
489 EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_END(sent_gesture_event(0));
490 EXPECT_EQ(1U, GetAndResetSentEventCount());
491 }
492 #endif // BUILDFLAG(IS_CHROMEOS_ASH)
493
TEST_F(MouseWheelEventQueueTest,GestureSendingInterrupted)494 TEST_F(MouseWheelEventQueueTest, GestureSendingInterrupted) {
495 const ui::ScrollGranularity scroll_units =
496 ui::ScrollGranularity::kScrollByPixel;
497 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
498 kWheelScrollGlobalY, 1, 1, 0, false,
499 WebMouseWheelEvent::kPhaseBegan,
500 WebMouseWheelEvent::kPhaseNone);
501 EXPECT_EQ(0U, queued_event_count());
502 EXPECT_TRUE(event_in_flight());
503 EXPECT_EQ(1U, GetAndResetSentEventCount());
504
505 // Receive an ACK for the mouse wheel event.
506 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
507 EXPECT_EQ(0U, queued_event_count());
508 EXPECT_FALSE(event_in_flight());
509 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
510 EXPECT_EQ(1U, GetAndResetAckedEventCount());
511 EXPECT_EQ(2U, all_sent_events().size());
512 EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
513 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
514 EXPECT_EQ(2U, GetAndResetSentEventCount());
515
516 // When a touch based GSB arrives in the
517 // middle of wheel scrolling sequence, a synthetic wheel event with zero
518 // deltas and phase = |kPhaseEnded| will be sent.
519 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
520 kWheelScrollGlobalY, 0, 0, 0, false,
521 WebMouseWheelEvent::kPhaseEnded,
522 WebMouseWheelEvent::kPhaseNone);
523 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
524 EXPECT_EQ(1U, GetAndResetAckedEventCount());
525
526 // Ensure that a gesture scroll begin terminates the current scroll event.
527 SendGestureEvent(WebInputEvent::Type::kGestureScrollBegin);
528
529 EXPECT_EQ(2U, all_sent_events().size());
530 EXPECT_GESTURE_SCROLL_END_WITH_PHASE(sent_gesture_event(1));
531 EXPECT_EQ(2U, GetAndResetSentEventCount());
532
533 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
534 kWheelScrollGlobalY, 1, 1, 0, false,
535 WebMouseWheelEvent::kPhaseBegan,
536 WebMouseWheelEvent::kPhaseNone);
537
538 EXPECT_EQ(0U, queued_event_count());
539 EXPECT_TRUE(event_in_flight());
540 EXPECT_EQ(1U, GetAndResetSentEventCount());
541
542 // New mouse wheel events won't cause gestures because a scroll
543 // is already in progress by another device.
544 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
545 EXPECT_EQ(0U, queued_event_count());
546 EXPECT_FALSE(event_in_flight());
547 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
548 EXPECT_EQ(1U, GetAndResetAckedEventCount());
549 EXPECT_EQ(0U, all_sent_events().size());
550
551 SendGestureEvent(WebInputEvent::Type::kGestureScrollEnd);
552 EXPECT_EQ(0U, all_sent_events().size());
553
554 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
555 kWheelScrollGlobalY, 1, 1, 0, false,
556 WebMouseWheelEvent::kPhaseBegan,
557 WebMouseWheelEvent::kPhaseNone);
558
559 EXPECT_EQ(0U, queued_event_count());
560 EXPECT_TRUE(event_in_flight());
561 EXPECT_EQ(1U, GetAndResetSentEventCount());
562
563 // Receive an ACK for the mouse wheel event.
564 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
565 EXPECT_EQ(0U, queued_event_count());
566 EXPECT_FALSE(event_in_flight());
567 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
568 EXPECT_EQ(1U, GetAndResetAckedEventCount());
569 EXPECT_EQ(2U, all_sent_events().size());
570 EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
571 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
572 EXPECT_EQ(2U, GetAndResetSentEventCount());
573 }
574
TEST_F(MouseWheelEventQueueTest,GestureRailScrolling)575 TEST_F(MouseWheelEventQueueTest, GestureRailScrolling) {
576 const ui::ScrollGranularity scroll_units =
577 ui::ScrollGranularity::kScrollByPixel;
578 SendMouseWheel(
579 kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
580 1, 0, false, WebMouseWheelEvent::kPhaseBegan,
581 WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeHorizontal);
582 EXPECT_EQ(0U, queued_event_count());
583 EXPECT_TRUE(event_in_flight());
584 EXPECT_EQ(1U, GetAndResetSentEventCount());
585
586 // Receive an ACK for the mouse wheel event.
587 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
588 EXPECT_EQ(0U, queued_event_count());
589 EXPECT_FALSE(event_in_flight());
590 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
591 EXPECT_EQ(1U, GetAndResetAckedEventCount());
592 EXPECT_EQ(2U, all_sent_events().size());
593 EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
594 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
595 EXPECT_EQ(1U, sent_gesture_event(1)->data.scroll_update.delta_x);
596 EXPECT_EQ(0U, sent_gesture_event(1)->data.scroll_update.delta_y);
597 EXPECT_EQ(2U, GetAndResetSentEventCount());
598
599 SendMouseWheel(
600 kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
601 1, 0, false, WebMouseWheelEvent::kPhaseChanged,
602 WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeVertical);
603
604 EXPECT_EQ(0U, queued_event_count());
605 EXPECT_TRUE(event_in_flight());
606 EXPECT_EQ(1U, GetAndResetSentEventCount());
607
608 // Receive an ACK for the mouse wheel event.
609 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
610 EXPECT_EQ(0U, queued_event_count());
611 EXPECT_FALSE(event_in_flight());
612 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
613 EXPECT_EQ(1U, GetAndResetAckedEventCount());
614 size_t scroll_update_index = 0;
615 EXPECT_EQ(1U, all_sent_events().size());
616 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(0));
617
618 EXPECT_EQ(
619 0U, sent_gesture_event(scroll_update_index)->data.scroll_update.delta_x);
620 EXPECT_EQ(
621 1U, sent_gesture_event(scroll_update_index)->data.scroll_update.delta_y);
622 EXPECT_EQ(1U, GetAndResetSentEventCount());
623 }
624
TEST_F(MouseWheelEventQueueTest,WheelScrollLatching)625 TEST_F(MouseWheelEventQueueTest, WheelScrollLatching) {
626 const ui::ScrollGranularity scroll_units =
627 ui::ScrollGranularity::kScrollByPixel;
628 SendMouseWheel(
629 kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
630 1, 0, false, WebMouseWheelEvent::kPhaseBegan,
631 WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeVertical);
632 EXPECT_EQ(0U, queued_event_count());
633 EXPECT_TRUE(event_in_flight());
634 EXPECT_EQ(1U, GetAndResetSentEventCount());
635
636 // Receive an ACK for the mouse wheel event.
637 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
638 EXPECT_EQ(0U, queued_event_count());
639 EXPECT_FALSE(event_in_flight());
640 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
641 EXPECT_EQ(1U, GetAndResetAckedEventCount());
642 EXPECT_EQ(2U, all_sent_events().size());
643 EXPECT_GESTURE_SCROLL_BEGIN_WITH_PHASE(sent_gesture_event(0));
644 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(1));
645 EXPECT_EQ(0U, sent_gesture_event(1)->data.scroll_update.delta_x);
646 EXPECT_EQ(1U, sent_gesture_event(1)->data.scroll_update.delta_y);
647 EXPECT_EQ(2U, GetAndResetSentEventCount());
648
649 SendMouseWheel(
650 kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX, kWheelScrollGlobalY, 1,
651 1, 0, false, WebMouseWheelEvent::kPhaseChanged,
652 WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeVertical);
653 EXPECT_EQ(0U, queued_event_count());
654 EXPECT_TRUE(event_in_flight());
655 EXPECT_EQ(1U, GetAndResetSentEventCount());
656
657 // Receive an ACK for the mouse wheel event.
658 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
659 EXPECT_EQ(0U, queued_event_count());
660 EXPECT_FALSE(event_in_flight());
661 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
662 EXPECT_EQ(1U, GetAndResetAckedEventCount());
663
664 // Scroll latching: no new scroll begin expected.
665 EXPECT_EQ(1U, all_sent_events().size());
666 EXPECT_GESTURE_SCROLL_UPDATE_WITH_PHASE(sent_gesture_event(0));
667 EXPECT_EQ(0U, sent_gesture_event(0)->data.scroll_update.delta_x);
668 EXPECT_EQ(1U, sent_gesture_event(0)->data.scroll_update.delta_y);
669 EXPECT_EQ(1U, GetAndResetSentEventCount());
670 }
671
TEST_F(MouseWheelEventQueueTest,WheelScrollingWasLatchedHistogramCheck)672 TEST_F(MouseWheelEventQueueTest, WheelScrollingWasLatchedHistogramCheck) {
673 base::HistogramTester histogram_tester;
674 const char latching_histogram_name[] = "WheelScrolling.WasLatched";
675
676 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
677 kWheelScrollGlobalY, 1, 1, 0, false,
678 WebMouseWheelEvent::kPhaseBegan,
679 WebMouseWheelEvent::kPhaseNone);
680 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
681 histogram_tester.ExpectBucketCount(latching_histogram_name, 0, 1);
682
683 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
684 kWheelScrollGlobalY, 1, 1, 0, false,
685 WebMouseWheelEvent::kPhaseChanged,
686 WebMouseWheelEvent::kPhaseNone);
687 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
688 histogram_tester.ExpectBucketCount(latching_histogram_name, 0, 1);
689 histogram_tester.ExpectBucketCount(latching_histogram_name, 1, 1);
690 }
691
692 #if defined(OS_MAC)
TEST_F(MouseWheelEventQueueTest,DoNotSwapXYForShiftScroll)693 TEST_F(MouseWheelEventQueueTest, DoNotSwapXYForShiftScroll) {
694 // Send an event with shift modifier, zero value for delta X, and no direction
695 // for |rails_mode|. Do not swap the scroll direction.
696 SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
697 kWheelScrollGlobalY, 0.0, 1.0, WebInputEvent::kShiftKey, false,
698 WebMouseWheelEvent::kPhaseBegan,
699 WebMouseWheelEvent::kPhaseNone, WebInputEvent::kRailsModeFree);
700 EXPECT_EQ(0U, queued_event_count());
701 EXPECT_TRUE(event_in_flight());
702 EXPECT_EQ(1U, GetAndResetSentEventCount());
703
704 // Receive an ACK for the mouse wheel event.
705 SendMouseWheelEventAck(blink::mojom::InputEventResultState::kNotConsumed);
706 EXPECT_EQ(0U, queued_event_count());
707 EXPECT_FALSE(event_in_flight());
708 EXPECT_EQ(WebInputEvent::Type::kMouseWheel, acked_event().GetType());
709 EXPECT_EQ(1U, GetAndResetAckedEventCount());
710
711 EXPECT_EQ(2U, all_sent_events().size());
712 EXPECT_EQ(0U, sent_gesture_event(1)->data.scroll_update.delta_x);
713 EXPECT_EQ(1U, sent_gesture_event(1)->data.scroll_update.delta_y);
714 EXPECT_EQ(2U, GetAndResetSentEventCount());
715 }
716 #endif
717 } // namespace content
718