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;
58using RealmBuilder = component_testing::RealmBuilder;
61using ChildName = std::string;
64using LegacyUrl = std::string;
72constexpr int64_t kClickToDragThreshold = 16.0;
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 =
"mouse-input-view#meta/mouse-input-view.cm";
87std::vector<T> merge(std::initializer_list<std::vector<T>> vecs) {
88 std::vector<T> result;
90 result.insert(result.end(), v.begin(), v.end());
96 const std::vector<fuchsia::ui::test::input::MouseButton>& buttons) {
98 for (
const auto& button : buttons) {
99 result |= (0x1 >> button);
107class MouseInputListenerServer
108 :
public fuchsia::ui::test::input::MouseInputListener,
109 public LocalComponentImpl {
111 explicit MouseInputListenerServer(async_dispatcher_t* dispatcher)
112 : dispatcher_(dispatcher) {}
114 void ReportMouseInput(
115 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest
117 FML_LOG(INFO) <<
"Received MouseInput event";
118 events_.push(std::move(request));
124 void OnStart()
override {
125 FML_LOG(INFO) <<
"Starting MouseInputServer";
126 ASSERT_EQ(ZX_OK, outgoing()->AddPublicService(
127 fidl::InterfaceRequestHandler<
128 fuchsia::ui::test::input::MouseInputListener>(
129 [
this](
auto request) {
130 bindings_.AddBinding(
this, std::move(request),
135 size_t SizeOfEvents()
const {
return events_.size(); }
137 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest
139 auto e = std::move(events_.front());
144 const fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest&
146 return events_.back();
149 void ClearEvents() { events_ = {}; }
153 async_dispatcher_t* dispatcher_ =
nullptr;
154 fidl::BindingSet<fuchsia::ui::test::input::MouseInputListener> bindings_;
156 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest>
160class MouseInputTest :
public PortableUITest,
161 public ::testing::Test,
162 public ::testing::WithParamInterface<std::string> {
164 void SetUp()
override {
165 PortableUITest::SetUp();
172 <<
"Waiting for display info from fuchsia.ui.display.singleton.Info";
173 fuchsia::ui::display::singleton::InfoPtr display_info =
176 .Connect<fuchsia::ui::display::singleton::Info>();
177 display_info->GetMetrics(
178 [
this](fuchsia::ui::display::singleton::Metrics metrics) {
179 display_width_ = metrics.extent_in_px().width;
180 display_height_ = metrics.extent_in_px().height;
181 FML_LOG(INFO) <<
"Got display_width = " << display_width_
182 <<
" and display_height = " << display_height_;
185 [
this] {
return display_width_ != 0 && display_height_ != 0; });
188 void TearDown()
override {
190 ASSERT_EQ(mouse_input_listener_->SizeOfEvents(), 0u);
193 MouseInputListenerServer* mouse_input_listener() {
194 return mouse_input_listener_;
200 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest&
204 std::vector<fuchsia::ui::test::input::MouseButton> expected_buttons,
205 const fuchsia::ui::test::input::MouseEventPhase expected_phase,
206 const std::string& component_name) {
207 FML_LOG(INFO) <<
"Client received mouse change at ("
208 << pointer_data.local_x() <<
", " << pointer_data.local_y()
209 <<
") with buttons " << ButtonsToInt(pointer_data.buttons())
211 FML_LOG(INFO) <<
"Expected mouse change is at approximately (" << expected_x
212 <<
", " << expected_y <<
") with buttons "
213 << ButtonsToInt(expected_buttons) <<
".";
220 EXPECT_NEAR(pointer_data.local_x(), expected_x, 1);
221 EXPECT_NEAR(pointer_data.local_y(), expected_y, 1);
222 EXPECT_EQ(pointer_data.buttons(), expected_buttons);
223 EXPECT_EQ(pointer_data.phase(), expected_phase);
224 EXPECT_EQ(pointer_data.component_name(), component_name);
227 void VerifyEventLocationOnTheRightOfExpectation(
228 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest&
230 double expected_x_min,
232 std::vector<fuchsia::ui::test::input::MouseButton> expected_buttons,
233 const fuchsia::ui::test::input::MouseEventPhase expected_phase,
234 const std::string& component_name) {
235 FML_LOG(INFO) <<
"Client received mouse change at ("
236 << pointer_data.local_x() <<
", " << pointer_data.local_y()
237 <<
") with buttons " << ButtonsToInt(pointer_data.buttons())
239 FML_LOG(INFO) <<
"Expected mouse change is at approximately (>"
240 << expected_x_min <<
", " << expected_y <<
") with buttons "
241 << ButtonsToInt(expected_buttons) <<
".";
243 EXPECT_GT(pointer_data.local_x(), expected_x_min);
244 EXPECT_NEAR(pointer_data.local_y(), expected_y, 1);
245 EXPECT_EQ(pointer_data.buttons(), expected_buttons);
246 EXPECT_EQ(pointer_data.phase(), expected_phase);
247 EXPECT_EQ(pointer_data.component_name(), component_name);
251 uint32_t display_width()
const {
return display_width_; }
252 uint32_t display_height()
const {
return display_height_; }
255 void ExtendRealm()
override {
256 FML_LOG(INFO) <<
"Extending realm";
260 auto mouse_input_listener =
261 std::make_unique<MouseInputListenerServer>(dispatcher());
262 mouse_input_listener_ = mouse_input_listener.get();
263 realm_builder()->AddLocalChild(
265 [mouse_input_listener = std::move(mouse_input_listener)]()
mutable {
266 return std::move(mouse_input_listener);
269 realm_builder()->AddChild(kMouseInputView, kMouseInputViewUrl,
270 component_testing::ChildOptions{
271 .environment = kFlutterRunnerEnvironment,
274 realm_builder()->AddRoute(
275 Route{.capabilities = {Protocol{
276 fuchsia::ui::test::input::MouseInputListener::Name_}},
277 .source = kMouseInputListenerRef,
278 .targets = {kFlutterJitRunnerRef, kMouseInputViewRef}});
280 realm_builder()->AddRoute(
281 Route{.capabilities = {Protocol{fuchsia::ui::app::ViewProvider::Name_}},
282 .source = kMouseInputViewRef,
283 .targets = {ParentRef()}});
286 ParamType GetTestUIStackUrl()
override {
return GetParam(); };
288 MouseInputListenerServer* mouse_input_listener_;
290 uint32_t display_width_ = 0;
291 uint32_t display_height_ = 0;
299 MouseInputTestParameterized,
302 "fuchsia-pkg://fuchsia.com/flatland-scene-manager-test-ui-stack#meta/"
303 "test-ui-stack.cm"));
305TEST_P(MouseInputTest, DISABLED_FlutterMouseMove) {
308 SimulateMouseEvent( {}, 1,
311 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
313 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
315 auto e = mouse_input_listener()->PopEvent();
320 static_cast<double>(display_width()) / 2.f + 1,
321 static_cast<double>(display_height()) / 2.f + 2,
323 fuchsia::ui::test::input::MouseEventPhase::ADD,
327TEST_P(MouseInputTest, DISABLED_FlutterMouseDown) {
331 {fuchsia::ui::test::input::MouseButton::FIRST},
334 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 3; });
336 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 3u);
338 auto event_add = mouse_input_listener()->PopEvent();
339 auto event_down = mouse_input_listener()->PopEvent();
340 auto event_noop_move = mouse_input_listener()->PopEvent();
344 VerifyEvent(event_add,
345 static_cast<double>(display_width()) / 2.f,
346 static_cast<double>(display_height()) / 2.f,
348 fuchsia::ui::test::input::MouseEventPhase::ADD,
354 static_cast<double>(display_width()) / 2.f,
355 static_cast<double>(display_height()) / 2.f,
356 {fuchsia::ui::test::input::MouseButton::FIRST},
357 fuchsia::ui::test::input::MouseEventPhase::DOWN,
363 static_cast<double>(display_width()) / 2.f,
364 static_cast<double>(display_height()) / 2.f,
365 {fuchsia::ui::test::input::MouseButton::FIRST},
366 fuchsia::ui::test::input::MouseEventPhase::MOVE,
370TEST_P(MouseInputTest, DISABLED_FlutterMouseDownUp) {
374 {fuchsia::ui::test::input::MouseButton::FIRST},
377 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 3; });
379 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 3u);
381 auto event_add = mouse_input_listener()->PopEvent();
382 auto event_down = mouse_input_listener()->PopEvent();
383 auto event_noop_move = mouse_input_listener()->PopEvent();
387 VerifyEvent(event_add,
388 static_cast<double>(display_width()) / 2.f,
389 static_cast<double>(display_height()) / 2.f,
391 fuchsia::ui::test::input::MouseEventPhase::ADD,
397 static_cast<double>(display_width()) / 2.f,
398 static_cast<double>(display_height()) / 2.f,
399 {fuchsia::ui::test::input::MouseButton::FIRST},
400 fuchsia::ui::test::input::MouseEventPhase::DOWN,
406 static_cast<double>(display_width()) / 2.f,
407 static_cast<double>(display_height()) / 2.f,
408 {fuchsia::ui::test::input::MouseButton::FIRST},
409 fuchsia::ui::test::input::MouseEventPhase::MOVE,
412 SimulateMouseEvent( {}, 0,
415 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
417 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
419 auto event_up = mouse_input_listener()->PopEvent();
420 VerifyEvent(event_up,
421 static_cast<double>(display_width()) / 2.f,
422 static_cast<double>(display_height()) / 2.f,
424 fuchsia::ui::test::input::MouseEventPhase::UP,
428TEST_P(MouseInputTest, DISABLED_FlutterMouseDownMoveUp) {
432 {fuchsia::ui::test::input::MouseButton::FIRST},
435 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 3; });
437 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 3u);
439 auto event_add = mouse_input_listener()->PopEvent();
440 auto event_down = mouse_input_listener()->PopEvent();
441 auto event_noop_move = mouse_input_listener()->PopEvent();
445 VerifyEvent(event_add,
446 static_cast<double>(display_width()) / 2.f,
447 static_cast<double>(display_height()) / 2.f,
449 fuchsia::ui::test::input::MouseEventPhase::ADD,
455 static_cast<double>(display_width()) / 2.f,
456 static_cast<double>(display_height()) / 2.f,
457 {fuchsia::ui::test::input::MouseButton::FIRST},
458 fuchsia::ui::test::input::MouseEventPhase::DOWN,
464 static_cast<double>(display_width()) / 2.f,
465 static_cast<double>(display_height()) / 2.f,
466 {fuchsia::ui::test::input::MouseButton::FIRST},
467 fuchsia::ui::test::input::MouseEventPhase::MOVE,
471 {fuchsia::ui::test::input::MouseButton::FIRST},
472 kClickToDragThreshold, 0);
474 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
476 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
478 auto event_move = mouse_input_listener()->PopEvent();
480 VerifyEventLocationOnTheRightOfExpectation(
482 static_cast<double>(display_width()) / 2.f + 1,
483 static_cast<double>(display_height()) / 2.f,
484 {fuchsia::ui::test::input::MouseButton::FIRST},
485 fuchsia::ui::test::input::MouseEventPhase::MOVE,
488 SimulateMouseEvent( {}, 0,
491 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
493 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
495 auto event_up = mouse_input_listener()->PopEvent();
497 VerifyEventLocationOnTheRightOfExpectation(
499 static_cast<double>(display_width()) / 2.f + 1,
500 static_cast<double>(display_height()) / 2.f,
502 fuchsia::ui::test::input::MouseEventPhase::UP,
512TEST_P(MouseInputTest, DISABLED_FlutterMouseWheelIssue103098) {
515 SimulateMouseScroll( {}, 1,
519 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 3; });
521 double initial_x =
static_cast<double>(display_width()) / 2.f;
522 double initial_y =
static_cast<double>(display_height()) / 2.f;
524 auto event_1 = mouse_input_listener()->PopEvent();
525 EXPECT_NEAR(event_1.local_x(), initial_x, 1);
526 EXPECT_NEAR(event_1.local_y(), initial_y, 1);
528 EXPECT_GT(event_1.wheel_x_physical_pixel(), 0);
529 EXPECT_EQ(event_1.wheel_y_physical_pixel(), 0);
530 EXPECT_EQ(event_1.phase(), fuchsia::ui::test::input::MouseEventPhase::MOVE);
532 auto event_2 = mouse_input_listener()->PopEvent();
538 fuchsia::ui::test::input::MouseEventPhase::HOVER,
541 EXPECT_GT(event_2.wheel_x_physical_pixel(), 0);
542 EXPECT_EQ(event_2.wheel_y_physical_pixel(), 0);
544 auto event_3 = mouse_input_listener()->PopEvent();
550 fuchsia::ui::test::input::MouseEventPhase::HOVER,
553 EXPECT_GT(event_3.wheel_x_physical_pixel(), 0);
554 EXPECT_EQ(event_3.wheel_y_physical_pixel(), 0);
557TEST_P(MouseInputTest, DISABLED_FlutterMouseWheel) {
560 double initial_x =
static_cast<double>(display_width()) / 2.f + 1;
561 double initial_y =
static_cast<double>(display_height()) / 2.f + 2;
564 SimulateMouseEvent( {},
567 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
569 auto event_add = mouse_input_listener()->PopEvent();
570 VerifyEvent(event_add,
574 fuchsia::ui::test::input::MouseEventPhase::ADD,
577 SimulateMouseScroll( {}, 1,
580 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
582 auto event_wheel_h = mouse_input_listener()->PopEvent();
589 fuchsia::ui::test::input::MouseEventPhase::HOVER,
592 EXPECT_GT(event_wheel_h.wheel_x_physical_pixel(), 0);
593 EXPECT_EQ(event_wheel_h.wheel_y_physical_pixel(), 0);
595 SimulateMouseScroll( {}, 0,
598 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
600 auto event_wheel_v = mouse_input_listener()->PopEvent();
607 fuchsia::ui::test::input::MouseEventPhase::HOVER,
610 EXPECT_LT(event_wheel_v.wheel_y_physical_pixel(), 0);
611 EXPECT_EQ(event_wheel_v.wheel_x_physical_pixel(), 0);