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;
57using RealmBuilder = component_testing::RealmBuilder;
60using ChildName = std::string;
63using LegacyUrl = std::string;
71constexpr int64_t kClickToDragThreshold = 16.0;
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";
86std::vector<T> merge(std::initializer_list<std::vector<T>> vecs) {
87 std::vector<T> result;
89 result.insert(result.end(), v.begin(), v.end());
95 const std::vector<fuchsia::ui::test::input::MouseButton>& buttons) {
97 for (
const auto& button : buttons) {
98 result |= (0x1 >> button);
106class MouseInputListenerServer
107 :
public fuchsia::ui::test::input::MouseInputListener,
108 public LocalComponentImpl {
110 explicit MouseInputListenerServer(async_dispatcher_t* dispatcher)
111 : dispatcher_(dispatcher) {}
113 void ReportMouseInput(
114 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest
116 FML_LOG(INFO) <<
"Received MouseInput event";
117 events_.push(std::move(request));
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),
134 size_t SizeOfEvents()
const {
return events_.size(); }
136 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest
138 auto e = std::move(events_.front());
143 const fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest&
145 return events_.back();
148 void ClearEvents() { events_ = {}; }
152 async_dispatcher_t* dispatcher_ =
nullptr;
153 fidl::BindingSet<fuchsia::ui::test::input::MouseInputListener> bindings_;
155 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest>
159class MouseInputTest :
public PortableUITest,
160 public ::testing::Test,
161 public ::testing::WithParamInterface<std::string> {
163 void SetUp()
override {
164 PortableUITest::SetUp();
171 <<
"Waiting for display info from fuchsia.ui.display.singleton.Info";
172 fuchsia::ui::display::singleton::InfoPtr display_info =
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_;
184 [
this] {
return display_width_ != 0 && display_height_ != 0; });
187 void TearDown()
override {
189 ASSERT_EQ(mouse_input_listener_->SizeOfEvents(), 0u);
192 MouseInputListenerServer* mouse_input_listener() {
193 return mouse_input_listener_;
199 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest&
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())
210 FML_LOG(INFO) <<
"Expected mouse change is at approximately (" << expected_x
211 <<
", " << expected_y <<
") with buttons "
212 << ButtonsToInt(expected_buttons) <<
".";
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);
226 void VerifyEventLocationOnTheRightOfExpectation(
227 fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest&
229 double expected_x_min,
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())
238 FML_LOG(INFO) <<
"Expected mouse change is at approximately (>"
239 << expected_x_min <<
", " << expected_y <<
") with buttons "
240 << ButtonsToInt(expected_buttons) <<
".";
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);
250 uint32_t display_width()
const {
return display_width_; }
251 uint32_t display_height()
const {
return display_height_; }
254 void ExtendRealm()
override {
255 FML_LOG(INFO) <<
"Extending realm";
259 auto mouse_input_listener =
260 std::make_unique<MouseInputListenerServer>(dispatcher());
261 mouse_input_listener_ = mouse_input_listener.get();
262 realm_builder()->AddLocalChild(
264 [mouse_input_listener = std::move(mouse_input_listener)]()
mutable {
265 return std::move(mouse_input_listener);
268 realm_builder()->AddChild(kMouseInputView, kMouseInputViewUrl,
269 component_testing::ChildOptions{
270 .environment = kFlutterRunnerEnvironment,
273 realm_builder()->AddRoute(
274 Route{.capabilities = {Protocol{
275 fuchsia::ui::test::input::MouseInputListener::Name_}},
276 .source = kMouseInputListenerRef,
277 .targets = {kFlutterJitRunnerRef, kMouseInputViewRef}});
279 realm_builder()->AddRoute(
280 Route{.capabilities = {Protocol{fuchsia::ui::app::ViewProvider::Name_}},
281 .source = kMouseInputViewRef,
282 .targets = {ParentRef()}});
285 ParamType GetTestUIStackUrl()
override {
return GetParam(); };
287 MouseInputListenerServer* mouse_input_listener_;
289 uint32_t display_width_ = 0;
290 uint32_t display_height_ = 0;
298 MouseInputTestParameterized,
301 "fuchsia-pkg://fuchsia.com/flatland-scene-manager-test-ui-stack#meta/"
302 "test-ui-stack.cm"));
304TEST_P(MouseInputTest, DISABLED_FlutterMouseMove) {
307 SimulateMouseEvent( {}, 1,
310 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
312 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
314 auto e = mouse_input_listener()->PopEvent();
319 static_cast<double>(display_width()) / 2.f + 1,
320 static_cast<double>(display_height()) / 2.f + 2,
322 fuchsia::ui::test::input::MouseEventPhase::ADD,
326TEST_P(MouseInputTest, DISABLED_FlutterMouseDown) {
330 {fuchsia::ui::test::input::MouseButton::FIRST},
333 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 3; });
335 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 3u);
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();
343 VerifyEvent(event_add,
344 static_cast<double>(display_width()) / 2.f,
345 static_cast<double>(display_height()) / 2.f,
347 fuchsia::ui::test::input::MouseEventPhase::ADD,
353 static_cast<double>(display_width()) / 2.f,
354 static_cast<double>(display_height()) / 2.f,
355 {fuchsia::ui::test::input::MouseButton::FIRST},
356 fuchsia::ui::test::input::MouseEventPhase::DOWN,
362 static_cast<double>(display_width()) / 2.f,
363 static_cast<double>(display_height()) / 2.f,
364 {fuchsia::ui::test::input::MouseButton::FIRST},
365 fuchsia::ui::test::input::MouseEventPhase::MOVE,
369TEST_P(MouseInputTest, DISABLED_FlutterMouseDownUp) {
373 {fuchsia::ui::test::input::MouseButton::FIRST},
376 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 3; });
378 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 3u);
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();
386 VerifyEvent(event_add,
387 static_cast<double>(display_width()) / 2.f,
388 static_cast<double>(display_height()) / 2.f,
390 fuchsia::ui::test::input::MouseEventPhase::ADD,
396 static_cast<double>(display_width()) / 2.f,
397 static_cast<double>(display_height()) / 2.f,
398 {fuchsia::ui::test::input::MouseButton::FIRST},
399 fuchsia::ui::test::input::MouseEventPhase::DOWN,
405 static_cast<double>(display_width()) / 2.f,
406 static_cast<double>(display_height()) / 2.f,
407 {fuchsia::ui::test::input::MouseButton::FIRST},
408 fuchsia::ui::test::input::MouseEventPhase::MOVE,
411 SimulateMouseEvent( {}, 0,
414 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
416 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
418 auto event_up = mouse_input_listener()->PopEvent();
419 VerifyEvent(event_up,
420 static_cast<double>(display_width()) / 2.f,
421 static_cast<double>(display_height()) / 2.f,
423 fuchsia::ui::test::input::MouseEventPhase::UP,
427TEST_P(MouseInputTest, DISABLED_FlutterMouseDownMoveUp) {
431 {fuchsia::ui::test::input::MouseButton::FIRST},
434 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 3; });
436 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 3u);
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();
444 VerifyEvent(event_add,
445 static_cast<double>(display_width()) / 2.f,
446 static_cast<double>(display_height()) / 2.f,
448 fuchsia::ui::test::input::MouseEventPhase::ADD,
454 static_cast<double>(display_width()) / 2.f,
455 static_cast<double>(display_height()) / 2.f,
456 {fuchsia::ui::test::input::MouseButton::FIRST},
457 fuchsia::ui::test::input::MouseEventPhase::DOWN,
463 static_cast<double>(display_width()) / 2.f,
464 static_cast<double>(display_height()) / 2.f,
465 {fuchsia::ui::test::input::MouseButton::FIRST},
466 fuchsia::ui::test::input::MouseEventPhase::MOVE,
470 {fuchsia::ui::test::input::MouseButton::FIRST},
471 kClickToDragThreshold, 0);
473 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
475 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
477 auto event_move = mouse_input_listener()->PopEvent();
479 VerifyEventLocationOnTheRightOfExpectation(
481 static_cast<double>(display_width()) / 2.f + 1,
482 static_cast<double>(display_height()) / 2.f,
483 {fuchsia::ui::test::input::MouseButton::FIRST},
484 fuchsia::ui::test::input::MouseEventPhase::MOVE,
487 SimulateMouseEvent( {}, 0,
490 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
492 ASSERT_EQ(mouse_input_listener()->SizeOfEvents(), 1u);
494 auto event_up = mouse_input_listener()->PopEvent();
496 VerifyEventLocationOnTheRightOfExpectation(
498 static_cast<double>(display_width()) / 2.f + 1,
499 static_cast<double>(display_height()) / 2.f,
501 fuchsia::ui::test::input::MouseEventPhase::UP,
511TEST_P(MouseInputTest, DISABLED_FlutterMouseWheelIssue103098) {
514 SimulateMouseScroll( {}, 1,
518 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 3; });
520 double initial_x =
static_cast<double>(display_width()) / 2.f;
521 double initial_y =
static_cast<double>(display_height()) / 2.f;
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);
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);
531 auto event_2 = mouse_input_listener()->PopEvent();
537 fuchsia::ui::test::input::MouseEventPhase::HOVER,
540 EXPECT_GT(event_2.wheel_x_physical_pixel(), 0);
541 EXPECT_EQ(event_2.wheel_y_physical_pixel(), 0);
543 auto event_3 = mouse_input_listener()->PopEvent();
549 fuchsia::ui::test::input::MouseEventPhase::HOVER,
552 EXPECT_GT(event_3.wheel_x_physical_pixel(), 0);
553 EXPECT_EQ(event_3.wheel_y_physical_pixel(), 0);
556TEST_P(MouseInputTest, DISABLED_FlutterMouseWheel) {
559 double initial_x =
static_cast<double>(display_width()) / 2.f + 1;
560 double initial_y =
static_cast<double>(display_height()) / 2.f + 2;
563 SimulateMouseEvent( {},
566 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
568 auto event_add = mouse_input_listener()->PopEvent();
569 VerifyEvent(event_add,
573 fuchsia::ui::test::input::MouseEventPhase::ADD,
576 SimulateMouseScroll( {}, 1,
579 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
581 auto event_wheel_h = mouse_input_listener()->PopEvent();
588 fuchsia::ui::test::input::MouseEventPhase::HOVER,
591 EXPECT_GT(event_wheel_h.wheel_x_physical_pixel(), 0);
592 EXPECT_EQ(event_wheel_h.wheel_y_physical_pixel(), 0);
594 SimulateMouseScroll( {}, 0,
597 [
this] {
return this->mouse_input_listener()->SizeOfEvents() == 1; });
599 auto event_wheel_v = mouse_input_listener()->PopEvent();
606 fuchsia::ui::test::input::MouseEventPhase::HOVER,
609 EXPECT_LT(event_wheel_v.wheel_y_physical_pixel(), 0);
610 EXPECT_EQ(event_wheel_v.wheel_x_physical_pixel(), 0);