| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <fuchsia/ui/pointer/cpp/fidl.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <lib/fdio/fd.h> |
| #include <lib/fidl/cpp/binding_set.h> |
| |
| #include <array> |
| #include <optional> |
| #include <vector> |
| |
| #include <gtest/gtest.h> |
| |
| #include "src/embedder/mouse_delegate.h" |
| #include "src/embedder/test_util/fakes/mouse_source.h" |
| #include "src/embedder/test_util/mouse_event_builder.h" |
| |
| namespace embedder_testing { |
| |
| using fup_EventPhase = fuchsia::ui::pointer::EventPhase; |
| using fup_ViewParameters = fuchsia::ui::pointer::ViewParameters; |
| using fup_MouseEvent = fuchsia::ui::pointer::MouseEvent; |
| |
| constexpr std::array<std::array<float, 2>, 2> kRect = {{{0, 0}, {20, 20}}}; |
| constexpr std::array<float, 9> kIdentity = {1, 0, 0, 0, 1, 0, 0, 0, 1}; |
| |
| constexpr uint32_t kMouseDeviceId = 123; |
| constexpr std::array<int64_t, 2> kNoScrollInPhysicalPixelDelta = {0, 0}; |
| const bool kNotPrecisionScroll = false; |
| const bool kPrecisionScroll = true; |
| |
| // Fixture to exercise Flutter runner's implementation for |
| // fuchsia.ui.pointer.TouchSource. |
| class MouseDelegateTest : public ::testing::Test { |
| protected: |
| MouseDelegateTest() : loop_(&kAsyncLoopConfigAttachToCurrentThread) { |
| mouse_source_ = std::make_unique<FakeMouseSource>(); |
| mouse_delegate_ = std::make_unique<embedder::MouseDelegate>( |
| mouse_source_bindings_.AddBinding(mouse_source_.get())); |
| } |
| |
| void RunLoopUntilIdle() { loop_.RunUntilIdle(); } |
| |
| std::unique_ptr<FakeMouseSource> mouse_source_; |
| std::unique_ptr<embedder::MouseDelegate> mouse_delegate_; |
| |
| async::Loop loop_; |
| fidl::BindingSet<fuchsia::ui::pointer::MouseSource> mouse_source_bindings_; |
| }; |
| |
| TEST_F(MouseDelegateTest, MouseWheel_TickBased) { |
| std::optional<std::vector<FlutterPointerEvent>> pointers; |
| mouse_delegate_->WatchLoop( |
| [&pointers](std::vector<FlutterPointerEvent> events) { pointers = std::move(events); }); |
| RunLoopUntilIdle(); // Server gets watch call. |
| |
| std::vector<fup_MouseEvent> events = |
| MouseEventBuilder() |
| .AddTime(1111789u) |
| .AddViewParameters(kRect, kRect, kIdentity) |
| .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {0, 1}, kNoScrollInPhysicalPixelDelta, |
| kNotPrecisionScroll) |
| .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2}) |
| .BuildAsVector(); |
| mouse_source_->ScheduleCallback(std::move(events)); |
| RunLoopUntilIdle(); |
| |
| ASSERT_TRUE(pointers.has_value()); |
| ASSERT_EQ(pointers.value().size(), 1u); |
| EXPECT_EQ(pointers.value()[0].phase, FlutterPointerPhase::kHover); |
| EXPECT_EQ(pointers.value()[0].signal_kind, |
| FlutterPointerSignalKind::kFlutterPointerSignalKindScroll); |
| EXPECT_EQ(pointers.value()[0].device_kind, |
| FlutterPointerDeviceKind::kFlutterPointerDeviceKindMouse); |
| EXPECT_EQ(pointers.value()[0].buttons, 0); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_x, 0); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_y, -20); |
| pointers = {}; |
| |
| // receive a horizontal scroll |
| events = MouseEventBuilder() |
| .AddTime(1111789u) |
| .AddViewParameters(kRect, kRect, kIdentity) |
| .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {1, 0}, kNoScrollInPhysicalPixelDelta, |
| kNotPrecisionScroll) |
| .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2}) |
| .BuildAsVector(); |
| mouse_source_->ScheduleCallback(std::move(events)); |
| RunLoopUntilIdle(); |
| |
| ASSERT_TRUE(pointers.has_value()); |
| ASSERT_EQ(pointers.value().size(), 1u); |
| EXPECT_EQ(pointers.value()[0].phase, FlutterPointerPhase::kHover); |
| EXPECT_EQ(pointers.value()[0].signal_kind, |
| FlutterPointerSignalKind::kFlutterPointerSignalKindScroll); |
| EXPECT_EQ(pointers.value()[0].device_kind, |
| FlutterPointerDeviceKind::kFlutterPointerDeviceKindMouse); |
| EXPECT_EQ(pointers.value()[0].buttons, 0); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_x, 20); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_y, 0); |
| pointers = {}; |
| } |
| |
| TEST_F(MouseDelegateTest, MouseWheel_PixelBased) { |
| std::optional<std::vector<FlutterPointerEvent>> pointers; |
| mouse_delegate_->WatchLoop( |
| [&pointers](std::vector<FlutterPointerEvent> events) { pointers = std::move(events); }); |
| RunLoopUntilIdle(); // Server gets watch call. |
| |
| std::vector<fup_MouseEvent> events = |
| MouseEventBuilder() |
| .AddTime(1111789u) |
| .AddViewParameters(kRect, kRect, kIdentity) |
| .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {0, 1}, {0, 120}, kNotPrecisionScroll) |
| .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2}) |
| .BuildAsVector(); |
| mouse_source_->ScheduleCallback(std::move(events)); |
| RunLoopUntilIdle(); |
| |
| ASSERT_TRUE(pointers.has_value()); |
| ASSERT_EQ(pointers.value().size(), 1u); |
| EXPECT_EQ(pointers.value()[0].phase, FlutterPointerPhase::kHover); |
| EXPECT_EQ(pointers.value()[0].signal_kind, |
| FlutterPointerSignalKind::kFlutterPointerSignalKindScroll); |
| EXPECT_EQ(pointers.value()[0].device_kind, |
| FlutterPointerDeviceKind::kFlutterPointerDeviceKindMouse); |
| EXPECT_EQ(pointers.value()[0].buttons, 0); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_x, 0); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_y, -120); |
| pointers = {}; |
| |
| // receive a horizontal scroll |
| events = MouseEventBuilder() |
| .AddTime(1111789u) |
| .AddViewParameters(kRect, kRect, kIdentity) |
| .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {1, 0}, {120, 0}, kNotPrecisionScroll) |
| .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2}) |
| .BuildAsVector(); |
| mouse_source_->ScheduleCallback(std::move(events)); |
| RunLoopUntilIdle(); |
| |
| ASSERT_TRUE(pointers.has_value()); |
| ASSERT_EQ(pointers.value().size(), 1u); |
| EXPECT_EQ(pointers.value()[0].phase, FlutterPointerPhase::kHover); |
| EXPECT_EQ(pointers.value()[0].signal_kind, |
| FlutterPointerSignalKind::kFlutterPointerSignalKindScroll); |
| EXPECT_EQ(pointers.value()[0].device_kind, |
| FlutterPointerDeviceKind::kFlutterPointerDeviceKindMouse); |
| EXPECT_EQ(pointers.value()[0].buttons, 0); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_x, 120); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_y, 0); |
| pointers = {}; |
| } |
| |
| TEST_F(MouseDelegateTest, MouseWheel_TouchpadPixelBased) { |
| std::optional<std::vector<FlutterPointerEvent>> pointers; |
| mouse_delegate_->WatchLoop( |
| [&pointers](std::vector<FlutterPointerEvent> events) { pointers = std::move(events); }); |
| RunLoopUntilIdle(); // Server gets watch call. |
| |
| std::vector<fup_MouseEvent> events = |
| MouseEventBuilder() |
| .AddTime(1111789u) |
| .AddViewParameters(kRect, kRect, kIdentity) |
| .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {0, 1}, {0, 120}, kPrecisionScroll) |
| .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2}) |
| .BuildAsVector(); |
| mouse_source_->ScheduleCallback(std::move(events)); |
| RunLoopUntilIdle(); |
| |
| ASSERT_TRUE(pointers.has_value()); |
| ASSERT_EQ(pointers.value().size(), 1u); |
| EXPECT_EQ(pointers.value()[0].phase, FlutterPointerPhase::kHover); |
| EXPECT_EQ(pointers.value()[0].signal_kind, |
| FlutterPointerSignalKind::kFlutterPointerSignalKindScroll); |
| EXPECT_EQ(pointers.value()[0].device_kind, |
| FlutterPointerDeviceKind::kFlutterPointerDeviceKindMouse); |
| EXPECT_EQ(pointers.value()[0].buttons, 0); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_x, 0); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_y, -120); |
| pointers = {}; |
| |
| // receive a horizontal scroll |
| events = MouseEventBuilder() |
| .AddTime(1111789u) |
| .AddViewParameters(kRect, kRect, kIdentity) |
| .AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {1, 0}, {120, 0}, kPrecisionScroll) |
| .AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2}) |
| .BuildAsVector(); |
| mouse_source_->ScheduleCallback(std::move(events)); |
| RunLoopUntilIdle(); |
| |
| ASSERT_TRUE(pointers.has_value()); |
| ASSERT_EQ(pointers.value().size(), 1u); |
| EXPECT_EQ(pointers.value()[0].phase, FlutterPointerPhase::kHover); |
| EXPECT_EQ(pointers.value()[0].signal_kind, |
| FlutterPointerSignalKind::kFlutterPointerSignalKindScroll); |
| EXPECT_EQ(pointers.value()[0].device_kind, |
| FlutterPointerDeviceKind::kFlutterPointerDeviceKindMouse); |
| EXPECT_EQ(pointers.value()[0].buttons, 0); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_x, 120); |
| EXPECT_EQ(pointers.value()[0].scroll_delta_y, 0); |
| pointers = {}; |
| } |
| |
| } // namespace embedder_testing |