Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
mouse-input-test.cc
Go to the documentation of this file.
1// Copyright 2022 The Fuchsia 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 <fuchsia/accessibility/semantics/cpp/fidl.h>
6#include <fuchsia/buildinfo/cpp/fidl.h>
7#include <fuchsia/component/cpp/fidl.h>
8#include <fuchsia/fonts/cpp/fidl.h>
9#include <fuchsia/kernel/cpp/fidl.h>
10#include <fuchsia/logger/cpp/fidl.h>
11#include <fuchsia/memorypressure/cpp/fidl.h>
12#include <fuchsia/metrics/cpp/fidl.h>
13#include <fuchsia/net/interfaces/cpp/fidl.h>
14#include <fuchsia/tracing/provider/cpp/fidl.h>
15#include <fuchsia/ui/app/cpp/fidl.h>
16#include <fuchsia/ui/display/singleton/cpp/fidl.h>
17#include <fuchsia/ui/input/cpp/fidl.h>
18#include <fuchsia/ui/test/input/cpp/fidl.h>
19#include <fuchsia/web/cpp/fidl.h>
20#include <lib/async/cpp/task.h>
21#include <lib/fidl/cpp/binding_set.h>
22#include <lib/fidl/cpp/interface_ptr.h>
23#include <lib/sys/component/cpp/testing/realm_builder.h>
24#include <lib/sys/component/cpp/testing/realm_builder_types.h>
25#include <zircon/status.h>
26#include <zircon/types.h>
27#include <zircon/utc.h>
28
29#include <cstddef>
30#include <cstdint>
31#include <iostream>
32#include <memory>
33#include <optional>
34#include <queue>
35#include <string>
36#include <type_traits>
37#include <utility>
38#include <vector>
39
40#include <gtest/gtest.h>
41
42#include "flutter/fml/logging.h"
44
46namespace {
47// Types imported for the realm_builder library.
48using component_testing::ChildRef;
49using component_testing::ConfigValue;
50using component_testing::LocalComponentImpl;
51using component_testing::ParentRef;
52using component_testing::Protocol;
53using component_testing::Realm;
54using component_testing::Route;
55
57using RealmBuilder = component_testing::RealmBuilder;
58
59// Alias for Component child name as provided to Realm Builder.
60using ChildName = std::string;
61
62// Alias for Component Legacy URL as provided to Realm Builder.
63using LegacyUrl = std::string;
64
65// Maximum pointer movement during a clickpad press for the gesture to
66// be guaranteed to be interpreted as a click. For movement greater than
67// this value, upper layers may, e.g., interpret the gesture as a drag.
68//
69// This value corresponds to the one used to instantiate the ClickDragHandler
70// registered by Input Pipeline in Scene Manager.
71constexpr int64_t kClickToDragThreshold = 16.0;
72
73constexpr auto kMouseInputListener = "mouse_input_listener";
74constexpr auto kMouseInputListenerRef = ChildRef{kMouseInputListener};
75constexpr auto kMouseInputView = "mouse-input-view";
76constexpr auto kMouseInputViewRef = ChildRef{kMouseInputView};
77constexpr auto kMouseInputViewUrl = "mouse-input-view#meta/mouse-input-view.cm";
78
79struct Position {
80 double x = 0.0;
81 double y = 0.0;
82};
83
84// Combines all vectors in `vecs` into one.
85template <typename T>
86std::vector<T> merge(std::initializer_list<std::vector<T>> vecs) {
87 std::vector<T> result;
88 for (auto v : vecs) {
89 result.insert(result.end(), v.begin(), v.end());
90 }
91 return result;
92}
93
94int ButtonsToInt(
95 const std::vector<fuchsia::ui::test::input::MouseButton>& buttons) {
96 int result = 0;
97 for (const auto& button : buttons) {
98 result |= (0x1 >> button);
99 }
100
101 return result;
102}
103
104// `MouseInputListener` is a local test protocol that our test apps use to let
105// us know what position and button press state the mouse cursor has.
106class MouseInputListenerServer
107 : public fuchsia::ui::test::input::MouseInputListener,
108 public LocalComponentImpl {
109 public:
110 explicit MouseInputListenerServer(async_dispatcher_t* dispatcher)
111 : dispatcher_(dispatcher) {}
112
113 void ReportMouseInput(
114 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest
115 request) override {
116 FML_LOG(INFO) << "Received MouseInput event";
117 events_.push(std::move(request));
118 }
119
120 // |MockComponent::OnStart|
121 // When the component framework requests for this component to start, this
122 // method will be invoked by the realm_builder library.
123 void OnStart() override {
124 FML_LOG(INFO) << "Starting MouseInputServer";
125 ASSERT_EQ(ZX_OK, outgoing()->AddPublicService(
126 fidl::InterfaceRequestHandler<
127 fuchsia::ui::test::input::MouseInputListener>(
128 [this](auto request) {
129 bindings_.AddBinding(this, std::move(request),
130 dispatcher_);
131 })));
132 }
133
134 size_t SizeOfEvents() const { return events_.size(); }
135
136 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest
137 PopEvent() {
138 auto e = std::move(events_.front());
139 events_.pop();
140 return e;
141 }
142
143 const fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest&
144 LastEvent() const {
145 return events_.back();
146 }
147
148 void ClearEvents() { events_ = {}; }
149
150 private:
151 // Not owned.
152 async_dispatcher_t* dispatcher_ = nullptr;
153 fidl::BindingSet<fuchsia::ui::test::input::MouseInputListener> bindings_;
154 std::queue<
155 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest>
156 events_;
157};
158
159class MouseInputTest : public PortableUITest,
160 public ::testing::Test,
161 public ::testing::WithParamInterface<std::string> {
162 protected:
163 void SetUp() override {
164 PortableUITest::SetUp();
165
166 // Register fake mouse device.
167 RegisterMouse();
168
169 // Get the display dimensions.
170 FML_LOG(INFO)
171 << "Waiting for display info from fuchsia.ui.display.singleton.Info";
172 fuchsia::ui::display::singleton::InfoPtr display_info =
173 realm_root()
174 ->component()
175 .Connect<fuchsia::ui::display::singleton::Info>();
176 display_info->GetMetrics(
177 [this](fuchsia::ui::display::singleton::Metrics metrics) {
178 display_width_ = metrics.extent_in_px().width;
179 display_height_ = metrics.extent_in_px().height;
180 FML_LOG(INFO) << "Got display_width = " << display_width_
181 << " and display_height = " << display_height_;
182 });
183 RunLoopUntil(
184 [this] { return display_width_ != 0 && display_height_ != 0; });
185 }
186
187 void TearDown() override {
188 // at the end of test, ensure event queue is empty.
189 ASSERT_EQ(mouse_input_listener_->SizeOfEvents(), 0u);
190 }
191
192 MouseInputListenerServer* mouse_input_listener() {
193 return mouse_input_listener_;
194 }
195
196 // Helper method for checking the test.mouse.MouseInputListener response from
197 // the client app.
198 void VerifyEvent(
199 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest&
200 pointer_data,
201 double expected_x,
202 double expected_y,
203 std::vector<fuchsia::ui::test::input::MouseButton> expected_buttons,
204 const fuchsia::ui::test::input::MouseEventPhase expected_phase,
205 const std::string& component_name) {
206 FML_LOG(INFO) << "Client received mouse change at ("
207 << pointer_data.local_x() << ", " << pointer_data.local_y()
208 << ") with buttons " << ButtonsToInt(pointer_data.buttons())
209 << ".";
210 FML_LOG(INFO) << "Expected mouse change is at approximately (" << expected_x
211 << ", " << expected_y << ") with buttons "
212 << ButtonsToInt(expected_buttons) << ".";
213
214 // Allow for minor rounding differences in coordinates.
215 // Note: These approximations don't account for
216 // `PointerMotionDisplayScaleHandler` or `PointerMotionSensorScaleHandler`.
217 // We will need to do so in order to validate larger motion or different
218 // sized displays.
219 EXPECT_NEAR(pointer_data.local_x(), expected_x, 1);
220 EXPECT_NEAR(pointer_data.local_y(), expected_y, 1);
221 EXPECT_EQ(pointer_data.buttons(), expected_buttons);
222 EXPECT_EQ(pointer_data.phase(), expected_phase);
223 EXPECT_EQ(pointer_data.component_name(), component_name);
224 }
225
226 void VerifyEventLocationOnTheRightOfExpectation(
227 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest&
228 pointer_data,
229 double expected_x_min,
230 double expected_y,
231 std::vector<fuchsia::ui::test::input::MouseButton> expected_buttons,
232 const fuchsia::ui::test::input::MouseEventPhase expected_phase,
233 const std::string& component_name) {
234 FML_LOG(INFO) << "Client received mouse change at ("
235 << pointer_data.local_x() << ", " << pointer_data.local_y()
236 << ") with buttons " << ButtonsToInt(pointer_data.buttons())
237 << ".";
238 FML_LOG(INFO) << "Expected mouse change is at approximately (>"
239 << expected_x_min << ", " << expected_y << ") with buttons "
240 << ButtonsToInt(expected_buttons) << ".";
241
242 EXPECT_GT(pointer_data.local_x(), expected_x_min);
243 EXPECT_NEAR(pointer_data.local_y(), expected_y, 1);
244 EXPECT_EQ(pointer_data.buttons(), expected_buttons);
245 EXPECT_EQ(pointer_data.phase(), expected_phase);
246 EXPECT_EQ(pointer_data.component_name(), component_name);
247 }
248
249 // Guaranteed to be initialized after SetUp().
250 uint32_t display_width() const { return display_width_; }
251 uint32_t display_height() const { return display_height_; }
252
253 private:
254 void ExtendRealm() override {
255 FML_LOG(INFO) << "Extending realm";
256
257 // Key part of service setup: have this test component vend the
258 // |MouseInputListener| service in the constructed realm.
259 auto mouse_input_listener =
260 std::make_unique<MouseInputListenerServer>(dispatcher());
261 mouse_input_listener_ = mouse_input_listener.get();
262 realm_builder()->AddLocalChild(
263 kMouseInputListener,
264 [mouse_input_listener = std::move(mouse_input_listener)]() mutable {
265 return std::move(mouse_input_listener);
266 });
267
268 realm_builder()->AddChild(kMouseInputView, kMouseInputViewUrl,
269 component_testing::ChildOptions{
270 .environment = kFlutterRunnerEnvironment,
271 });
272
273 realm_builder()->AddRoute(
274 Route{.capabilities = {Protocol{
275 fuchsia::ui::test::input::MouseInputListener::Name_}},
276 .source = kMouseInputListenerRef,
277 .targets = {kFlutterJitRunnerRef, kMouseInputViewRef}});
278
279 realm_builder()->AddRoute(
280 Route{.capabilities = {Protocol{fuchsia::ui::app::ViewProvider::Name_}},
281 .source = kMouseInputViewRef,
282 .targets = {ParentRef()}});
283 }
284
285 ParamType GetTestUIStackUrl() override { return GetParam(); };
286
287 MouseInputListenerServer* mouse_input_listener_;
288
289 uint32_t display_width_ = 0;
290 uint32_t display_height_ = 0;
291};
292
293// Makes use of gtest's parameterized testing, allowing us
294// to test different combinations of test-ui-stack + runners. Currently, there
295// is just one combination. Documentation:
296// http://go/gunitadvanced#value-parameterized-tests
298 MouseInputTestParameterized,
299 MouseInputTest,
300 ::testing::Values(
301 "fuchsia-pkg://fuchsia.com/flatland-scene-manager-test-ui-stack#meta/"
302 "test-ui-stack.cm"));
303
304TEST_P(MouseInputTest, DISABLED_FlutterMouseMove) {
305 LaunchClient();
306
307 SimulateMouseEvent(/* pressed_buttons = */ {}, /* movement_x = */ 1,
308 /* movement_y = */ 2);
309 RunLoopUntil(
310 [this] { return this->mouse_input_listener()->SizeOfEvents() == 1; });
311
312 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
313
314 auto e = mouse_input_listener()->PopEvent();
315
316 // If the first mouse event is cursor movement, Flutter first sends an ADD
317 // event with updated location.
318 VerifyEvent(e,
319 /*expected_x=*/static_cast<double>(display_width()) / 2.f + 1,
320 /*expected_y=*/static_cast<double>(display_height()) / 2.f + 2,
321 /*expected_buttons=*/{},
322 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::ADD,
323 /*component_name=*/"mouse-input-view");
324}
325
326TEST_P(MouseInputTest, DISABLED_FlutterMouseDown) {
327 LaunchClient();
328
329 SimulateMouseEvent(
330 /* pressed_buttons = */ {fuchsia::ui::test::input::MouseButton::FIRST},
331 /* movement_x = */ 0, /* movement_y = */ 0);
332 RunLoopUntil(
333 [this] { return this->mouse_input_listener()->SizeOfEvents() == 3; });
334
335 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 3u);
336
337 auto event_add = mouse_input_listener()->PopEvent();
338 auto event_down = mouse_input_listener()->PopEvent();
339 auto event_noop_move = mouse_input_listener()->PopEvent();
340
341 // If the first mouse event is a button press, Flutter first sends an ADD
342 // event with no buttons.
343 VerifyEvent(event_add,
344 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
345 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
346 /*expected_buttons=*/{},
347 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::ADD,
348 /*component_name=*/"mouse-input-view");
349
350 // Then Flutter sends a DOWN pointer event with the buttons we care about.
351 VerifyEvent(
352 event_down,
353 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
354 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
355 /*expected_buttons=*/{fuchsia::ui::test::input::MouseButton::FIRST},
356 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::DOWN,
357 /*component_name=*/"mouse-input-view");
358
359 // Then Flutter sends a MOVE pointer event with no new information.
360 VerifyEvent(
361 event_noop_move,
362 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
363 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
364 /*expected_buttons=*/{fuchsia::ui::test::input::MouseButton::FIRST},
365 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::MOVE,
366 /*component_name=*/"mouse-input-view");
367}
368
369TEST_P(MouseInputTest, DISABLED_FlutterMouseDownUp) {
370 LaunchClient();
371
372 SimulateMouseEvent(
373 /* pressed_buttons = */ {fuchsia::ui::test::input::MouseButton::FIRST},
374 /* movement_x = */ 0, /* movement_y = */ 0);
375 RunLoopUntil(
376 [this] { return this->mouse_input_listener()->SizeOfEvents() == 3; });
377
378 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 3u);
379
380 auto event_add = mouse_input_listener()->PopEvent();
381 auto event_down = mouse_input_listener()->PopEvent();
382 auto event_noop_move = mouse_input_listener()->PopEvent();
383
384 // If the first mouse event is a button press, Flutter first sends an ADD
385 // event with no buttons.
386 VerifyEvent(event_add,
387 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
388 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
389 /*expected_buttons=*/{},
390 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::ADD,
391 /*component_name=*/"mouse-input-view");
392
393 // Then Flutter sends a DOWN pointer event with the buttons we care about.
394 VerifyEvent(
395 event_down,
396 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
397 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
398 /*expected_buttons=*/{fuchsia::ui::test::input::MouseButton::FIRST},
399 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::DOWN,
400 /*component_name=*/"mouse-input-view");
401
402 // Then Flutter sends a MOVE pointer event with no new information.
403 VerifyEvent(
404 event_noop_move,
405 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
406 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
407 /*expected_buttons=*/{fuchsia::ui::test::input::MouseButton::FIRST},
408 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::MOVE,
409 /*component_name=*/"mouse-input-view");
410
411 SimulateMouseEvent(/* pressed_buttons = */ {}, /* movement_x = */ 0,
412 /* movement_y = */ 0);
413 RunLoopUntil(
414 [this] { return this->mouse_input_listener()->SizeOfEvents() == 1; });
415
416 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
417
418 auto event_up = mouse_input_listener()->PopEvent();
419 VerifyEvent(event_up,
420 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
421 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
422 /*expected_buttons=*/{},
423 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::UP,
424 /*component_name=*/"mouse-input-view");
425}
426
427TEST_P(MouseInputTest, DISABLED_FlutterMouseDownMoveUp) {
428 LaunchClient();
429
430 SimulateMouseEvent(
431 /* pressed_buttons = */ {fuchsia::ui::test::input::MouseButton::FIRST},
432 /* movement_x = */ 0, /* movement_y = */ 0);
433 RunLoopUntil(
434 [this] { return this->mouse_input_listener()->SizeOfEvents() == 3; });
435
436 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 3u);
437
438 auto event_add = mouse_input_listener()->PopEvent();
439 auto event_down = mouse_input_listener()->PopEvent();
440 auto event_noop_move = mouse_input_listener()->PopEvent();
441
442 // If the first mouse event is a button press, Flutter first sends an ADD
443 // event with no buttons.
444 VerifyEvent(event_add,
445 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
446 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
447 /*expected_buttons=*/{},
448 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::ADD,
449 /*component_name=*/"mouse-input-view");
450
451 // Then Flutter sends a DOWN pointer event with the buttons we care about.
452 VerifyEvent(
453 event_down,
454 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
455 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
456 /*expected_buttons=*/{fuchsia::ui::test::input::MouseButton::FIRST},
457 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::DOWN,
458 /*component_name=*/"mouse-input-view");
459
460 // Then Flutter sends a MOVE pointer event with no new information.
461 VerifyEvent(
462 event_noop_move,
463 /*expected_x=*/static_cast<double>(display_width()) / 2.f,
464 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
465 /*expected_buttons=*/{fuchsia::ui::test::input::MouseButton::FIRST},
466 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::MOVE,
467 /*component_name=*/"mouse-input-view");
468
469 SimulateMouseEvent(
470 /* pressed_buttons = */ {fuchsia::ui::test::input::MouseButton::FIRST},
471 /* movement_x = */ kClickToDragThreshold, /* movement_y = */ 0);
472 RunLoopUntil(
473 [this] { return this->mouse_input_listener()->SizeOfEvents() == 1; });
474
475 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
476
477 auto event_move = mouse_input_listener()->PopEvent();
478
479 VerifyEventLocationOnTheRightOfExpectation(
480 event_move,
481 /*expected_x_min=*/static_cast<double>(display_width()) / 2.f + 1,
482 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
483 /*expected_buttons=*/{fuchsia::ui::test::input::MouseButton::FIRST},
484 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::MOVE,
485 /*component_name=*/"mouse-input-view");
486
487 SimulateMouseEvent(/* pressed_buttons = */ {}, /* movement_x = */ 0,
488 /* movement_y = */ 0);
489 RunLoopUntil(
490 [this] { return this->mouse_input_listener()->SizeOfEvents() == 1; });
491
492 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
493
494 auto event_up = mouse_input_listener()->PopEvent();
495
496 VerifyEventLocationOnTheRightOfExpectation(
497 event_up,
498 /*expected_x_min=*/static_cast<double>(display_width()) / 2.f + 1,
499 /*expected_y=*/static_cast<double>(display_height()) / 2.f,
500 /*expected_buttons=*/{},
501 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::UP,
502 /*component_name=*/"mouse-input-view");
503}
504
505// TODO(fxbug.dev/103098): This test shows the issue when sending mouse wheel as
506// the first event to Flutter.
507// 1. expect Flutter app receive 2 events: ADD - Scroll, but got 3 events: Move
508// - Scroll - Scroll.
509// 2. the first event flutter app received has random value in buttons field
510// Disabled until flutter rolls, since it changes the behavior of this issue.
511TEST_P(MouseInputTest, DISABLED_FlutterMouseWheelIssue103098) {
512 LaunchClient();
513
514 SimulateMouseScroll(/* pressed_buttons = */ {}, /* scroll_x = */ 1,
515 /* scroll_y = */ 0);
516 // Here we expected 2 events, ADD - Scroll, but got 3, Move - Scroll - Scroll.
517 RunLoopUntil(
518 [this] { return this->mouse_input_listener()->SizeOfEvents() == 3; });
519
520 double initial_x = static_cast<double>(display_width()) / 2.f;
521 double initial_y = static_cast<double>(display_height()) / 2.f;
522
523 auto event_1 = mouse_input_listener()->PopEvent();
524 EXPECT_NEAR(event_1.local_x(), initial_x, 1);
525 EXPECT_NEAR(event_1.local_y(), initial_y, 1);
526 // Flutter will scale the count of ticks to pixel.
527 EXPECT_GT(event_1.wheel_x_physical_pixel(), 0);
528 EXPECT_EQ(event_1.wheel_y_physical_pixel(), 0);
529 EXPECT_EQ(event_1.phase(), fuchsia::ui::test::input::MouseEventPhase::MOVE);
530
531 auto event_2 = mouse_input_listener()->PopEvent();
532 VerifyEvent(
533 event_2,
534 /*expected_x=*/initial_x,
535 /*expected_y=*/initial_y,
536 /*expected_buttons=*/{},
537 /*expected_phase=*/fuchsia::ui::test::input::MouseEventPhase::HOVER,
538 /*component_name=*/"mouse-input-view");
539 // Flutter will scale the count of ticks to pixel.
540 EXPECT_GT(event_2.wheel_x_physical_pixel(), 0);
541 EXPECT_EQ(event_2.wheel_y_physical_pixel(), 0);
542
543 auto event_3 = mouse_input_listener()->PopEvent();
544 VerifyEvent(
545 event_3,
546 /*expected_x=*/initial_x,
547 /*expected_y=*/initial_y,
548 /*expected_buttons=*/{},
549 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::HOVER,
550 /*component_name=*/"mouse-input-view");
551 // Flutter will scale the count of ticks to pixel.
552 EXPECT_GT(event_3.wheel_x_physical_pixel(), 0);
553 EXPECT_EQ(event_3.wheel_y_physical_pixel(), 0);
554}
555
556TEST_P(MouseInputTest, DISABLED_FlutterMouseWheel) {
557 LaunchClient();
558
559 double initial_x = static_cast<double>(display_width()) / 2.f + 1;
560 double initial_y = static_cast<double>(display_height()) / 2.f + 2;
561
562 // TODO(fxbug.dev/103098): Send a mouse move as the first event to workaround.
563 SimulateMouseEvent(/* pressed_buttons = */ {},
564 /* movement_x = */ 1, /* movement_y = */ 2);
565 RunLoopUntil(
566 [this] { return this->mouse_input_listener()->SizeOfEvents() == 1; });
567
568 auto event_add = mouse_input_listener()->PopEvent();
569 VerifyEvent(event_add,
570 /*expected_x=*/initial_x,
571 /*expected_y=*/initial_y,
572 /*expected_buttons=*/{},
573 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::ADD,
574 /*component_name=*/"mouse-input-view");
575
576 SimulateMouseScroll(/* pressed_buttons = */ {}, /* scroll_x = */ 1,
577 /* scroll_y = */ 0);
578 RunLoopUntil(
579 [this] { return this->mouse_input_listener()->SizeOfEvents() == 1; });
580
581 auto event_wheel_h = mouse_input_listener()->PopEvent();
582
583 VerifyEvent(
584 event_wheel_h,
585 /*expected_x=*/initial_x,
586 /*expected_y=*/initial_y,
587 /*expected_buttons=*/{},
588 /*expected_phase=*/fuchsia::ui::test::input::MouseEventPhase::HOVER,
589 /*component_name=*/"mouse-input-view");
590 // Flutter will scale the count of ticks to pixel.
591 EXPECT_GT(event_wheel_h.wheel_x_physical_pixel(), 0);
592 EXPECT_EQ(event_wheel_h.wheel_y_physical_pixel(), 0);
593
594 SimulateMouseScroll(/* pressed_buttons = */ {}, /* scroll_x = */ 0,
595 /* scroll_y = */ 1);
596 RunLoopUntil(
597 [this] { return this->mouse_input_listener()->SizeOfEvents() == 1; });
598
599 auto event_wheel_v = mouse_input_listener()->PopEvent();
600
601 VerifyEvent(
602 event_wheel_v,
603 /*expected_x=*/initial_x,
604 /*expected_y=*/initial_y,
605 /*expected_buttons=*/{},
606 /*expected_type=*/fuchsia::ui::test::input::MouseEventPhase::HOVER,
607 /*component_name=*/"mouse-input-view");
608 // Flutter will scale the count of ticks to pixel.
609 EXPECT_LT(event_wheel_v.wheel_y_physical_pixel(), 0);
610 EXPECT_EQ(event_wheel_v.wheel_x_physical_pixel(), 0);
611}
612
613} // namespace
614} // namespace mouse_input_test::testing
int32_t x
#define FML_LOG(severity)
Definition logging.h:101
double y
INSTANTIATE_TEST_SUITE_P(CompilerSuite, CompilerTest, ::testing::Values(TargetPlatform::kOpenGLES, TargetPlatform::kOpenGLDesktop, TargetPlatform::kMetalDesktop, TargetPlatform::kMetalIOS, TargetPlatform::kVulkan), [](const ::testing::TestParamInfo< CompilerTest::ParamType > &info) { return TargetPlatformToString(info.param);})
TEST_P(CompilerTest, CanCompile)