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