blob: bcf2ae45b97e4d2f1eaf80d82a6a9bed110f76b2 [file] [log] [blame] [edit]
// 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