5#include <fuchsia/ui/composition/cpp/fidl.h>
6#include <fuchsia/ui/composition/cpp/fidl_test_base.h>
7#include <fuchsia/ui/input/cpp/fidl.h>
8#include <fuchsia/ui/input3/cpp/fidl.h>
9#include <fuchsia/ui/input3/cpp/fidl_test_base.h>
10#include <fuchsia/ui/views/cpp/fidl.h>
11#include <lib/async-loop/cpp/loop.h>
12#include <lib/async-loop/default.h>
13#include <lib/async/default.h>
14#include <lib/fidl/cpp/binding_set.h>
15#include <lib/zx/eventpair.h>
22#include "flutter/flow/embedded_views.h"
23#include "flutter/lib/ui/window/platform_message.h"
24#include "flutter/lib/ui/window/pointer_data.h"
25#include "flutter/lib/ui/window/viewport_metrics.h"
26#include "flutter/shell/common/context_options.h"
27#include "flutter/shell/platform/fuchsia/flutter/platform_view.h"
28#include "gmock/gmock.h"
29#include "gtest/gtest.h"
35#include "flutter/shell/platform/fuchsia/flutter/surface.h"
36#include "flutter/shell/platform/fuchsia/flutter/task_runner_adapter.h"
47 void CancelFrame()
override {}
50 raster_thread_merger)
override {}
52 void PrepareFlutterView(
SkISize frame_size,
53 double device_pixel_ratio)
override {}
55 void SubmitFlutterView(
56 int64_t flutter_view_id,
58 const std::shared_ptr<impeller::AiksContext>& aiks_context,
59 std::unique_ptr<flutter::SurfaceFrame>
frame)
override {}
61 void PrerollCompositeEmbeddedView(
63 std::unique_ptr<flutter::EmbeddedViewParams>
params)
override {}
75 semantics_features_ = 0;
76 semantics_enabled_ =
false;
77 pointer_packets_.clear();
81 void OnPlatformViewCreated(std::unique_ptr<flutter::Surface>
surface) {
87 void OnPlatformViewDestroyed() {}
89 void OnPlatformViewScheduleFrame() {}
91 void OnPlatformViewAddView(int64_t view_id,
93 AddViewCallback
callback)
override {}
95 void OnPlatformViewRemoveView(int64_t view_id,
96 RemoveViewCallback
callback)
override {}
100 void OnPlatformViewSetViewportMetrics(
110 void OnPlatformViewDispatchPlatformMessage(
111 std::unique_ptr<flutter::PlatformMessage>
message) {
115 void OnPlatformViewDispatchPointerDataPacket(
116 std::unique_ptr<flutter::PointerDataPacket> packet) {
117 pointer_packets_.push_back(std::move(packet));
120 void OnPlatformViewDispatchKeyDataPacket(
121 std::unique_ptr<flutter::KeyDataPacket> packet,
124 void OnPlatformViewDispatchSemanticsAction(int32_t
id,
128 void OnPlatformViewSetSemanticsEnabled(
bool enabled) {
129 semantics_enabled_ = enabled;
132 void OnPlatformViewSetAccessibilityFeatures(int32_t
flags) {
133 semantics_features_ =
flags;
136 void OnPlatformViewRegisterTexture(
137 std::shared_ptr<flutter::Texture>
texture) {}
139 void OnPlatformViewUnregisterTexture(int64_t
texture_id) {}
141 void OnPlatformViewMarkTextureFrameAvailable(int64_t
texture_id) {}
143 std::unique_ptr<std::vector<std::string>> ComputePlatformViewResolvedLocale(
144 const std::vector<std::string>& supported_locale_data) {
149 intptr_t loading_unit_id,
150 std::unique_ptr<const fml::Mapping> snapshot_data,
151 std::unique_ptr<const fml::Mapping> snapshot_instructions) {}
153 void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
154 const std::string error_message,
157 void UpdateAssetResolverByType(
158 std::unique_ptr<flutter::AssetResolver> updated_asset_resolver,
164 int32_t semantics_features()
const {
return semantics_features_; }
165 bool semantics_enabled()
const {
return semantics_enabled_; }
166 const std::vector<std::unique_ptr<flutter::PointerDataPacket>>&
167 pointer_packets()
const {
168 return pointer_packets_;
170 std::vector<std::unique_ptr<flutter::PointerDataPacket>>
171 TakePointerDataPackets() {
172 auto tmp = std::move(pointer_packets_);
173 pointer_packets_.clear();
178 std::unique_ptr<flutter::Surface>
surface_;
179 std::unique_ptr<flutter::PlatformMessage> message_;
181 std::vector<std::unique_ptr<flutter::PointerDataPacket>> pointer_packets_;
182 int32_t semantics_features_ = 0;
183 bool semantics_enabled_ =
false;
189 MOCK_METHOD(
void, Complete, (std::unique_ptr<fml::Mapping>
data), (
override));
190 MOCK_METHOD(
void, CompleteEmpty, (), (
override));
195 TestPlatformMessageResponse() {}
196 void Complete(std::unique_ptr<fml::Mapping>
data)
override {
198 reinterpret_cast<const char*
>(
data->GetMapping()),
data->GetSize());
201 void CompleteEmpty()
override { is_complete_ =
true; }
206class MockKeyboard :
public fuchsia::ui::input3::testing::Keyboard_TestBase {
208 explicit MockKeyboard(
209 fidl::InterfaceRequest<fuchsia::ui::input3::Keyboard> keyboard)
211 ~MockKeyboard() =
default;
213 void AddListener(fuchsia::ui::views::ViewRef view_ref,
214 fuchsia::ui::input3::KeyboardListenerHandle listener,
215 AddListenerCallback
callback)
override {
224 void NotImplemented_(
const std::string&
name)
override {
FAIL(); }
233class MockChildViewWatcher
234 :
public fuchsia::ui::composition::testing::ChildViewWatcher_TestBase {
236 explicit MockChildViewWatcher(
237 fidl::InterfaceRequest<fuchsia::ui::composition::ChildViewWatcher>
240 ~MockChildViewWatcher() =
default;
243 void GetStatus(GetStatusCallback
callback)
override {
248 callback(fuchsia::ui::composition::ChildViewStatus::CONTENT_HAS_PRESENTED);
253 void GetViewRef(GetViewRefCallback
callback)
override {
256 fuchsia::ui::views::ViewRefControl view_ref_control;
257 fuchsia::ui::views::ViewRef view_ref;
259 0u, &view_ref_control.reference, &view_ref.reference);
260 ZX_ASSERT(status == ZX_OK);
261 view_ref_control.reference.replace(
262 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
263 &view_ref_control.reference);
264 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
269 void NotImplemented_(
const std::string&
name)
override {
FAIL(); }
271 fidl::Binding<fuchsia::ui::composition::ChildViewWatcher>
binding_;
278class MockParentViewportWatcher
279 :
public fuchsia::ui::composition::testing::ParentViewportWatcher_TestBase {
281 explicit MockParentViewportWatcher() :
binding_(this,
handle_.NewRequest()) {}
282 ~MockParentViewportWatcher() =
default;
285 void GetStatus(GetStatusCallback
callback)
override {
291 fuchsia::ui::composition::ParentViewportStatus::CONNECTED_TO_DISPLAY);
296 void GetLayout(GetLayoutCallback
callback)
override {
306 void SetLayout(uint32_t logical_size_x,
307 uint32_t logical_size_y,
309 ::fuchsia::math::SizeU logical_size;
310 logical_size.width = logical_size_x;
311 logical_size.height = logical_size_y;
312 layout_.set_logical_size(logical_size);
313 layout_.set_device_pixel_ratio({DPR, DPR});
323 fuchsia::ui::composition::ParentViewportWatcherHandle GetHandle() {
328 void NotImplemented_(
const std::string&
name)
override {
FAIL(); }
330 fuchsia::ui::composition::ParentViewportWatcherHandle
handle_;
331 fidl::Binding<fuchsia::ui::composition::ParentViewportWatcher>
binding_;
348class PlatformViewBuilder {
353 fuchsia::ui::views::ViewRefControl view_ref_control;
354 fuchsia::ui::views::ViewRef view_ref;
356 0u, &view_ref_control.reference, &view_ref.reference);
357 ZX_ASSERT(status == ZX_OK);
358 view_ref_control.reference.replace(
359 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
360 &view_ref_control.reference);
361 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
363 std::make_pair(std::move(view_ref_control), std::move(view_ref));
364 view_ref_pair_ = std::move(view_ref_pair);
367 PlatformViewBuilder& SetExternalViewEmbedder(
368 std::shared_ptr<flutter::ExternalViewEmbedder> embedder) {
369 external_external_view_embedder_ = embedder;
373 PlatformViewBuilder& SetImeService(
374 fuchsia::ui::input::ImeServiceHandle ime_service) {
375 ime_service_ = std::move(ime_service);
379 PlatformViewBuilder& SetKeyboard(
380 fuchsia::ui::input3::KeyboardHandle keyboard) {
385 PlatformViewBuilder& SetTouchSource(
386 fuchsia::ui::pointer::TouchSourceHandle touch_source) {
387 touch_source_ = std::move(touch_source);
391 PlatformViewBuilder& SetMouseSource(
392 fuchsia::ui::pointer::MouseSourceHandle mouse_source) {
393 mouse_source_ = std::move(mouse_source);
397 PlatformViewBuilder& SetFocuser(fuchsia::ui::views::FocuserHandle focuser) {
398 focuser_ = std::move(focuser);
402 PlatformViewBuilder& SetViewRefFocused(
403 fuchsia::ui::views::ViewRefFocusedHandle view_ref_focused) {
404 view_ref_focused_ = std::move(view_ref_focused);
408 PlatformViewBuilder& SetPointerInjectorRegistry(
409 fuchsia::ui::pointerinjector::RegistryHandle pointerinjector_registry) {
410 pointerinjector_registry_ = std::move(pointerinjector_registry);
414 PlatformViewBuilder& SetEnableWireframeCallback(
416 wireframe_enabled_callback_ = std::move(
callback);
420 PlatformViewBuilder& SetParentViewportWatcher(
421 fuchsia::ui::composition::ParentViewportWatcherHandle
422 parent_viewport_watcher) {
423 parent_viewport_watcher_ = std::move(parent_viewport_watcher);
428 on_create_view_callback_ = std::move(
callback);
433 on_destroy_view_callback_ = std::move(
callback);
438 on_update_view_callback_ = std::move(
callback);
442 PlatformViewBuilder& SetCreateSurfaceCallback(
444 on_create_surface_callback_ = std::move(
callback);
448 PlatformViewBuilder& SetShaderWarmupCallback(
450 on_shader_warmup_callback_ = std::move(
callback);
455 PlatformView
Build() {
456 EXPECT_FALSE(std::exchange(built_,
true))
457 <<
"Build() was already called, this builder is good for one use only.";
459 delegate_, task_runners_, std::move(view_ref_pair_.second),
460 external_external_view_embedder_, std::move(ime_service_),
461 std::move(
keyboard_), std::move(touch_source_),
462 std::move(mouse_source_), std::move(focuser_),
463 std::move(view_ref_focused_), std::move(parent_viewport_watcher_),
464 std::move(pointerinjector_registry_),
465 std::move(wireframe_enabled_callback_),
466 std::move(on_create_view_callback_),
467 std::move(on_update_view_callback_),
468 std::move(on_destroy_view_callback_),
469 std::move(on_create_surface_callback_),
470 std::move(on_semantics_node_update_callback_),
471 std::move(on_request_announce_callback_),
472 std::move(on_shader_warmup_callback_), [](
auto...) {}, [](
auto...) {},
477 PlatformViewBuilder() =
delete;
481 std::pair<fuchsia::ui::views::ViewRefControl, fuchsia::ui::views::ViewRef>
484 std::shared_ptr<flutter::ExternalViewEmbedder>
485 external_external_view_embedder_;
486 fuchsia::ui::input::ImeServiceHandle ime_service_;
487 fuchsia::ui::input3::KeyboardHandle
keyboard_;
488 fuchsia::ui::pointer::TouchSourceHandle touch_source_;
489 fuchsia::ui::pointer::MouseSourceHandle mouse_source_;
490 fuchsia::ui::views::ViewRefFocusedHandle view_ref_focused_;
491 fuchsia::ui::views::FocuserHandle focuser_;
492 fuchsia::ui::pointerinjector::RegistryHandle pointerinjector_registry_;
495 fuchsia::ui::composition::ParentViewportWatcherHandle
496 parent_viewport_watcher_;
515 std::unique_ptr<flutter::PointerDataPacket> packet) {
516 for (
size_t i = 0;
i < packet->GetLength();
i++) {
518 output.push_back(pointer_data);
529 async_dispatcher_t*
dispatcher() {
return loop_.dispatcher(); }
532 loop_.RunUntilIdle();
537 loop_.Run(zx::time::infinite(),
true);
543 std::optional<fuchsia::ui::input3::Modifiers> modifiers,
545 fuchsia::ui::input3::KeyEvent
event;
546 event.set_timestamp(++event_timestamp_);
548 if (modifiers.has_value()) {
549 event.set_modifiers(modifiers.value());
556 fuchsia::ui::composition::ChildViewWatcherPtr ptr;
557 auto watcher = std::make_unique<MockChildViewWatcher>(
558 ptr.NewRequest(loop_.dispatcher()));
559 child_view_watchers_.push_back(std::move(watcher));
566 uint64_t event_timestamp_{42};
568 std::vector<std::unique_ptr<MockChildViewWatcher>> child_view_watchers_;
576 MockPlatformViewDelegate delegate;
581 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
582 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
584 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
585 .SetViewRefFocused(std::move(vrf_handle))
595 base_view->HandlePlatformMessage(response1->WithMessage(
596 "flutter/invalid",
"{\"method\":\"Invalid.invalidMethod\"}"));
600 base_view->HandlePlatformMessage(
601 response2->WithMessage(
"flutter/platform_views",
"{Invalid JSON"));
605 base_view->HandlePlatformMessage(response3->WithMessage(
606 "flutter/platform_views",
"{\"method\":\"View.focus.invalidMethod\"}"));
610 base_view->HandlePlatformMessage(response4->WithMessage(
611 "flutter/platform_views",
"{\"method\":\"View.update\"}"));
613 base_view->HandlePlatformMessage(
614 response5->WithMessage(
"flutter/platform_views",
615 "{\"method\":\"View.update\",\"args\":{"
616 "\"irrelevantField\":\"irrelevantValue\"}}"));
620 base_view->HandlePlatformMessage(response6->WithMessage(
621 "flutter/platform_views",
622 "{\"method\":\"View.update\",\"args\":{\"viewId\":false,\"hitTestable\":"
623 "123,\"focusable\":\"yes\"}}"));
627 response1->ExpectCompleted(
"");
628 response2->ExpectCompleted(
"");
629 response3->ExpectCompleted(
"");
630 response4->ExpectCompleted(
"");
631 response5->ExpectCompleted(
"");
632 response6->ExpectCompleted(
"");
638 MockPlatformViewDelegate delegate;
644 async_get_default_dispatcher()),
653 std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
654 std::make_shared<MockExternalViewEmbedder>();
655 auto CreateSurfaceCallback = [&external_view_embedder, gr_context]() {
656 return std::make_unique<flutter_runner::Surface>(
657 "PlatformViewTest", external_view_embedder, gr_context.
get());
660 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
661 .SetCreateSurfaceCallback(CreateSurfaceCallback)
662 .SetExternalViewEmbedder(external_view_embedder)
668 EXPECT_EQ(gr_context.
get(), delegate.surface()->GetContext());
669 EXPECT_EQ(external_view_embedder.get(),
677 constexpr float kDPR = 2;
678 constexpr uint32_t
width = 640;
679 constexpr uint32_t
height = 480;
681 MockPlatformViewDelegate delegate;
684 MockParentViewportWatcher watcher;
687 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
688 .SetParentViewportWatcher(watcher.GetHandle())
695 EXPECT_EQ(delegate.metrics(),
704 MockPlatformViewDelegate delegate;
708 EXPECT_FALSE(delegate.semantics_enabled());
709 EXPECT_EQ(delegate.semantics_features(), 0);
712 PlatformViewBuilder(delegate, std::move(task_runners)).Build();
719 EXPECT_EQ(delegate.semantics_features(),
720 static_cast<int32_t
>(
725 EXPECT_FALSE(delegate.semantics_enabled());
726 EXPECT_EQ(delegate.semantics_features(), 0);
732 MockPlatformViewDelegate delegate;
739 bool wireframe_enabled =
false;
740 auto EnableWireframeCallback = [&wireframe_enabled](
bool should_enable) {
741 wireframe_enabled = should_enable;
744 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
745 .SetEnableWireframeCallback(EnableWireframeCallback)
754 const uint8_t
txt[] =
756 " \"method\":\"View.enableWireframe\","
762 std::unique_ptr<flutter::PlatformMessage>
message =
763 std::make_unique<flutter::PlatformMessage>(
766 base_view->HandlePlatformMessage(std::move(
message));
776 MockPlatformViewDelegate delegate;
777 const uint64_t view_id = 42;
781 async_get_default_dispatcher()),
790 bool create_view_called =
false;
791 auto CreateViewCallback =
792 [&create_view_called,
this](
796 create_view_called =
true;
798 fuchsia::ui::composition::ContentId content_id;
799 on_view_bound(std::move(content_id), MakeChildViewWatcher());
802 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
803 .SetCreateViewCallback(CreateViewCallback)
812 std::ostringstream create_view_message;
813 create_view_message <<
"{" <<
" \"method\":\"View.create\","
814 <<
" \"args\":{" <<
" \"viewId\":" << view_id <<
","
815 <<
" \"hitTestable\":true," <<
" \"focusable\":true"
818 std::string create_view_call = create_view_message.str();
819 std::unique_ptr<flutter::PlatformMessage>
message =
820 std::make_unique<flutter::PlatformMessage>(
821 "flutter/platform_views",
823 create_view_call.size()),
825 base_view->HandlePlatformMessage(std::move(
message));
833 std::ostringstream view_connected_expected_out;
834 view_connected_expected_out <<
"{" <<
"\"method\":\"View.viewConnected\","
835 <<
"\"args\":{" <<
" \"viewId\":" << view_id
838 ASSERT_NE(delegate.message(),
nullptr);
839 EXPECT_EQ(view_connected_expected_out.str(),
840 ToString(delegate.message()->data()));
846 MockPlatformViewDelegate delegate;
850 std::optional<SkRect> occlusion_hint_for_test;
851 std::optional<bool> hit_testable_for_test;
852 std::optional<bool> focusable_for_test;
853 auto UpdateViewCallback = [&occlusion_hint_for_test, &hit_testable_for_test,
854 &focusable_for_test](
855 int64_t view_id,
SkRect occlusion_hint,
856 bool hit_testable,
bool focusable) {
857 occlusion_hint_for_test = occlusion_hint;
858 hit_testable_for_test = hit_testable;
859 focusable_for_test = focusable;
862 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
863 .SetUpdateViewCallback(UpdateViewCallback)
872 const uint8_t json[] =
874 " \"method\":\"View.update\","
877 " \"hitTestable\":true,"
878 " \"focusable\":true"
881 std::unique_ptr<flutter::PlatformMessage>
message =
882 std::make_unique<flutter::PlatformMessage>(
883 "flutter/platform_views",
886 base_view->HandlePlatformMessage(std::move(
message));
889 ASSERT_TRUE(occlusion_hint_for_test.has_value());
890 ASSERT_TRUE(hit_testable_for_test.has_value());
891 ASSERT_TRUE(focusable_for_test.has_value());
893 EXPECT_EQ(hit_testable_for_test.value(),
true);
894 EXPECT_EQ(focusable_for_test.value(),
true);
897 occlusion_hint_for_test.reset();
898 hit_testable_for_test.reset();
899 focusable_for_test.reset();
902 const uint8_t json_false[] =
904 " \"method\":\"View.update\","
907 " \"hitTestable\":false,"
908 " \"focusable\":false"
911 std::unique_ptr<flutter::PlatformMessage> message_false =
912 std::make_unique<flutter::PlatformMessage>(
913 "flutter/platform_views",
916 base_view->HandlePlatformMessage(std::move(message_false));
918 ASSERT_TRUE(occlusion_hint_for_test.has_value());
919 ASSERT_TRUE(hit_testable_for_test.has_value());
920 ASSERT_TRUE(focusable_for_test.has_value());
922 EXPECT_EQ(hit_testable_for_test.value(),
false);
923 EXPECT_EQ(focusable_for_test.value(),
false);
926 occlusion_hint_for_test.reset();
927 hit_testable_for_test.reset();
928 focusable_for_test.reset();
931 const uint8_t json_occlusion_hint[] =
933 " \"method\":\"View.update\","
936 " \"hitTestable\":true,"
937 " \"focusable\":true,"
938 " \"viewOcclusionHintLTRB\":[0.1,0.2,0.3,0.4]"
941 std::unique_ptr<flutter::PlatformMessage> message_occlusion_hint =
942 std::make_unique<flutter::PlatformMessage>(
943 "flutter/platform_views",
945 sizeof(json_occlusion_hint)),
947 base_view->HandlePlatformMessage(std::move(message_occlusion_hint));
949 ASSERT_TRUE(occlusion_hint_for_test.has_value());
950 ASSERT_TRUE(hit_testable_for_test.has_value());
951 ASSERT_TRUE(focusable_for_test.has_value());
952 EXPECT_EQ(occlusion_hint_for_test.value(),
954 EXPECT_EQ(hit_testable_for_test.value(),
true);
955 EXPECT_EQ(focusable_for_test.value(),
true);
961 MockPlatformViewDelegate delegate;
962 const uint64_t view_id = 42;
967 async_get_default_dispatcher()),
973 bool destroy_view_called =
false;
975 auto on_destroy_view = [&destroy_view_called](
978 destroy_view_called =
true;
979 fuchsia::ui::composition::ContentId content_id;
980 on_view_unbound(std::move(content_id));
983 bool create_view_called =
false;
984 auto on_create_view = [&create_view_called,
this](
988 bool hit_testable,
bool focusable) {
989 create_view_called =
true;
991 fuchsia::ui::composition::ContentId content_id;
992 on_view_bound(std::move(content_id), MakeChildViewWatcher());
995 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
996 .SetCreateViewCallback(on_create_view)
997 .SetDestroyViewCallback(on_destroy_view)
1005 std::ostringstream create_message;
1006 create_message <<
"{" <<
" \"method\":\"View.create\","
1007 <<
" \"args\": {" <<
" \"viewId\":" << view_id <<
","
1008 <<
" \"hitTestable\":true,"
1009 <<
" \"focusable\":true" <<
" }" <<
"}";
1012 base_view->HandlePlatformMessage(create_response->WithMessage(
1013 "flutter/platform_views", create_message.str()));
1019 std::ostringstream dispose_message;
1020 dispose_message <<
"{" <<
" \"method\":\"View.dispose\","
1021 <<
" \"args\": {" <<
" \"viewId\":" << view_id
1024 std::string dispose_view_call = dispose_message.str();
1025 std::unique_ptr<flutter::PlatformMessage>
message =
1026 std::make_unique<flutter::PlatformMessage>(
1027 "flutter/platform_views",
1029 dispose_view_call.size()),
1031 base_view->HandlePlatformMessage(std::move(
message));
1039 std::ostringstream view_disconnected_expected_out;
1040 view_disconnected_expected_out
1041 <<
"{" <<
"\"method\":\"View.viewDisconnected\"," <<
"\"args\":{"
1042 <<
" \"viewId\":" << view_id <<
" }" <<
"}";
1044 ASSERT_NE(delegate.message(),
nullptr);
1045 EXPECT_EQ(view_disconnected_expected_out.str(),
1046 ToString(delegate.message()->data()));
1053 MockPlatformViewDelegate delegate;
1058 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
1059 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
1061 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1062 .SetViewRefFocused(std::move(vrf_handle))
1070 std::vector<bool> vrf_states{
false,
true,
true,
false,
1071 true,
false,
true,
true};
1073 for (std::size_t
i = 0;
i < vrf_states.size(); ++
i) {
1076 base_view->HandlePlatformMessage(response1->WithMessage(
1077 "flutter/platform_views",
"{\"method\":\"View.focus.getNext\"}"));
1080 base_view->HandlePlatformMessage(response2->WithMessage(
1081 "flutter/platform_views",
"{\"method\":\"View.focus.getNext\"}"));
1093 base_view->HandlePlatformMessage(response3->WithMessage(
1094 "flutter/platform_views",
"{\"method\":\"View.focus.getCurrent\"}"));
1097 base_view->HandlePlatformMessage(response4->WithMessage(
1098 "flutter/platform_views",
"{\"method\":\"View.focus.getCurrent\"}"));
1102 response1->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1103 response2->ExpectCompleted(
"[null]");
1104 response3->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1105 response4->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1112 MockPlatformViewDelegate delegate;
1116 async_get_default_dispatcher()),
1123 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1124 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1126 bool create_view_called =
false;
1127 auto on_create_view = [&create_view_called,
this](
1131 bool hit_testable,
bool focusable) {
1132 create_view_called =
true;
1134 fuchsia::ui::composition::ContentId content_id;
1135 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1138 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1139 .SetFocuser(std::move(focuser_handle))
1140 .SetCreateViewCallback(on_create_view)
1148 uint64_t view_id = 42;
1150 std::ostringstream create_message;
1151 create_message <<
"{" <<
" \"method\":\"View.create\","
1152 <<
" \"args\": {" <<
" \"viewId\":" << view_id <<
","
1153 <<
" \"hitTestable\":true,"
1154 <<
" \"focusable\":true" <<
" }" <<
"}";
1158 base_view->HandlePlatformMessage(create_response->WithMessage(
1159 "flutter/platform_views", create_message.str()));
1164 std::ostringstream focus_message;
1165 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1166 <<
" \"args\": {" <<
" \"viewId\":" << view_id
1171 base_view->HandlePlatformMessage(focus_response->WithMessage(
1172 "flutter/platform_views", focus_message.str()));
1175 focus_response->ExpectCompleted(
"[0]");
1181 MockPlatformViewDelegate delegate;
1185 async_get_default_dispatcher()),
1192 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1193 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1195 bool create_view_called =
false;
1196 auto on_create_view = [&create_view_called,
this](
1200 bool hit_testable,
bool focusable) {
1201 create_view_called =
true;
1203 fuchsia::ui::composition::ContentId content_id;
1204 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1207 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1208 .SetFocuser(std::move(focuser_handle))
1209 .SetCreateViewCallback(on_create_view)
1215 uint64_t view_id = 42;
1217 std::ostringstream focus_message;
1218 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1219 <<
" \"args\": {" <<
" \"viewId\":" << view_id
1224 base_view->HandlePlatformMessage(focus_response->WithMessage(
1225 "flutter/platform_views", focus_message.str()));
1228 focus_response->ExpectCompleted(
"[1]");
1233 MockPlatformViewDelegate delegate;
1237 async_get_default_dispatcher()),
1244 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1245 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1247 bool create_view_called =
false;
1248 auto on_create_view = [&create_view_called,
this](
1252 bool hit_testable,
bool focusable) {
1253 create_view_called =
true;
1255 fuchsia::ui::composition::ContentId content_id;
1256 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1259 bool destroy_view_called =
false;
1261 auto on_destroy_view = [&destroy_view_called](
1264 destroy_view_called =
true;
1265 fuchsia::ui::composition::ContentId content_id;
1266 on_view_unbound(std::move(content_id));
1269 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1270 .SetFocuser(std::move(focuser_handle))
1271 .SetCreateViewCallback(on_create_view)
1272 .SetDestroyViewCallback(on_destroy_view)
1278 uint64_t view_id = 42;
1281 std::ostringstream create_message;
1282 create_message <<
"{" <<
" \"method\":\"View.create\","
1283 <<
" \"args\": {" <<
" \"viewId\":" << view_id <<
","
1284 <<
" \"hitTestable\":true,"
1285 <<
" \"focusable\":true" <<
" }" <<
"}";
1288 base_view->HandlePlatformMessage(create_response->WithMessage(
1289 "flutter/platform_views", create_message.str()));
1292 EXPECT_FALSE(destroy_view_called);
1294 std::ostringstream dispose_message;
1295 dispose_message <<
"{" <<
" \"method\":\"View.dispose\","
1296 <<
" \"args\": {" <<
" \"viewId\":" << view_id
1300 base_view->HandlePlatformMessage(dispose_response->WithMessage(
1301 "flutter/platform_views", dispose_message.str()));
1306 std::ostringstream focus_message;
1307 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1308 <<
" \"args\": {" <<
" \"viewId\":" << view_id
1312 base_view->HandlePlatformMessage(focus_response->WithMessage(
1313 "flutter/platform_views", focus_message.str()));
1317 focus_response->ExpectCompleted(
"[1]");
1324 fuchsia::ui::input3::KeyEvent
event;
1325 fuchsia::ui::input3::KeyEventStatus expected_key_event_status;
1326 std::string expected_platform_message;
1329 MockPlatformViewDelegate delegate;
1333 fuchsia::ui::input3::KeyboardHandle keyboard_service;
1334 MockKeyboard keyboard(keyboard_service.NewRequest());
1336 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1337 .SetKeyboard(std::move(keyboard_service))
1341 std::vector<EventFlow> events;
1344 events.emplace_back(EventFlow{
1345 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1347 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1348 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1351 events.emplace_back(EventFlow{
1352 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED, std::nullopt,
1354 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1355 R
"({"type":"keyup","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1358 events.emplace_back(EventFlow{
1359 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED,
1360 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1361 fuchsia::input::Key::CAPS_LOCK),
1362 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1363 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1366 events.emplace_back(EventFlow{
1367 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1369 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1370 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1373 events.emplace_back(EventFlow{
1374 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED,
1375 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1376 fuchsia::input::Key::CAPS_LOCK),
1377 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1378 R
"({"type":"keyup","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1382 events.emplace_back(EventFlow{
1383 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1385 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1386 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1389 for (
const auto&
event : events) {
1390 fuchsia::ui::input3::KeyEvent
e;
1391 event.event.Clone(&
e);
1392 fuchsia::ui::input3::KeyEventStatus key_event_status{0u};
1393 keyboard.listener_->OnKeyEvent(
1395 [&key_event_status](fuchsia::ui::input3::KeyEventStatus status) {
1396 key_event_status = status;
1401 EXPECT_EQ(
event.expected_platform_message,
1402 ToString(delegate.message()->data()));
1403 EXPECT_EQ(
event.expected_key_event_status, key_event_status);
1408 MockPlatformViewDelegate delegate;
1412 uint64_t
width = 200;
1414 std::vector<std::string> shaders = {
"foo.skp",
"bar.skp",
"baz.skp"};
1417 [&](
const std::vector<std::string>& shaders_in,
1418 std::function<void(uint32_t)> completion_callback, uint64_t width_in,
1419 uint64_t height_in) {
1420 ASSERT_EQ(shaders.size(), shaders_in.size());
1421 for (
size_t i = 0;
i < shaders_in.size();
i++) {
1422 ASSERT_EQ(shaders[
i], shaders_in[
i]);
1424 ASSERT_EQ(
width, width_in);
1425 ASSERT_EQ(
height, height_in);
1427 completion_callback(shaders_in.size());
1430 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1431 .SetShaderWarmupCallback(on_shader_warmup_callback)
1434 std::ostringstream shaders_array_ostream;
1435 shaders_array_ostream <<
"[ ";
1436 for (
auto it = shaders.begin(); it != shaders.end(); ++it) {
1437 shaders_array_ostream <<
"\"" << *it <<
"\"";
1439 shaders_array_ostream <<
", ";
1442 shaders_array_ostream <<
"]";
1444 std::string shaders_array_string = shaders_array_ostream.str();
1447 std::ostringstream warmup_shaders_ostream;
1448 warmup_shaders_ostream <<
"{" <<
" \"method\":\"WarmupSkps\","
1450 <<
" \"shaders\":" << shaders_array_string <<
","
1451 <<
" \"width\":" <<
width <<
","
1452 <<
" \"height\":" <<
height <<
" }" <<
"}\n";
1453 std::string warmup_shaders_string = warmup_shaders_ostream.str();
1456 new TestPlatformMessageResponse);
1458 ->HandlePlatformMessage(std::make_unique<flutter::PlatformMessage>(
1459 "fuchsia/shader_warmup",
1461 warmup_shaders_string.size()),
1464 ASSERT_TRUE(response->is_complete());
1466 std::ostringstream expected_result_ostream;
1467 expected_result_ostream <<
"[" << shaders.size() <<
"]";
1468 std::string expected_result_string = expected_result_ostream.str();
1469 EXPECT_EQ(expected_result_string, response->result_string);
1473 constexpr uint32_t
width = 640;
1474 constexpr uint32_t
height = 480;
1475 constexpr std::array<std::array<float, 2>, 2>
kRect = {
1477 constexpr std::array<float, 9>
kIdentity = {1, 0, 0, 0, 1, 0, 0, 0, 1};
1478 constexpr fuchsia::ui::pointer::TouchInteractionId
kIxnOne = {
1479 .device_id = 0u, .pointer_id = 1u, .interaction_id = 2u};
1481 MockPlatformViewDelegate delegate;
1485 MockParentViewportWatcher viewport_watcher;
1487 fidl::BindingSet<fuchsia::ui::pointer::TouchSource> touch_bindings;
1488 auto touch_handle = touch_bindings.AddBinding(&touch_server);
1490 PlatformViewBuilder(delegate, std::move(task_runners))
1491 .SetParentViewportWatcher(viewport_watcher.GetHandle())
1492 .SetTouchSource(std::move(touch_handle))
1495 EXPECT_EQ(delegate.pointer_packets().size(), 0u);
1499 EXPECT_EQ(delegate.metrics(),
1503 std::vector<fuchsia::ui::pointer::TouchEvent> events =
1511 .status = fuchsia::ui::pointer::TouchInteractionStatus::GRANTED})
1517 std::vector<std::unique_ptr<flutter::PointerDataPacket>> packets =
1518 delegate.TakePointerDataPackets();
1519 ASSERT_EQ(packets.size(), 1u);
1520 std::vector<flutter::PointerData> flutter_events;
1524 ASSERT_EQ(flutter_events.size(), 2u);
1529 EXPECT_EQ(flutter_events[0].physical_x,
width / 2);
1530 EXPECT_EQ(flutter_events[0].physical_y,
height / 2);
1531 EXPECT_EQ(flutter_events[1].physical_x,
width / 2);
1532 EXPECT_EQ(flutter_events[1].physical_y,
height / 2);
static void round(SkPoint *p)
static float next(float f)
ax::mojom::Event event_type
#define ASSERT_NOTNULL(ptr)
static sk_sp< GrDirectContext > MakeMock(const GrMockOptions *, const GrContextOptions &)
AssetResolverType
Identifies the type of AssetResolver an instance is.
Developer-facing API for rendering anything within the engine.
Abstract Base Class that represents where we will be rendering content.
bool request_focus_called() const
void ScheduleCallback(std::vector< fuchsia::ui::pointer::TouchEvent > events)
void ScheduleCallback(bool focused)
std::size_t times_watched
TouchEventBuilder & AddViewParameters(std::array< std::array< float, 2 >, 2 > view, std::array< std::array< float, 2 >, 2 > viewport, std::array< float, 9 > transform)
TouchEventBuilder & AddSample(fuchsia::ui::pointer::TouchInteractionId id, fuchsia::ui::pointer::EventPhase phase, std::array< float, 2 > position)
static TouchEventBuilder New()
TouchEventBuilder & AddTime(zx_time_t time)
A Mapping like NonOwnedMapping, but uses Free as its release proc.
static MallocMapping Copy(const T *begin, const T *end)
virtual const uint8_t * GetMapping() const =0
virtual size_t GetSize() const =0
const EmbeddedViewParams * params
TaskRunners task_runners_
#define FAIL(name, result)
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
#define FML_CHECK(condition)
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Dart_NativeFunction function
def Build(configs, env, options)
void UnpackPointerPacket(std::vector< PointerData > &output, std::unique_ptr< PointerDataPacket > packet)
constexpr std::array< std::array< float, 2 >, 2 > kRect
constexpr std::array< float, 9 > kIdentity
TEST_F(FocusDelegateTest, WatchCallbackSeries)
constexpr fup_TouchIxnId kIxnOne
std::function< void(const std::vector< std::string > &, std::function< void(uint32_t)>, uint64_t, uint64_t)> OnShaderWarmupCallback
fit::function< void(int64_t, ViewCallback, ViewCreatedCallback, bool, bool)> OnCreateViewCallback
fit::function< void(int64_t, ViewIdCallback)> OnDestroyViewCallback
fit::function< void(int64_t, SkRect, bool, bool)> OnUpdateViewCallback
fit::function< std::unique_ptr< flutter::Surface >()> OnCreateSurfaceCallback
std::function< void()> ViewCallback
fit::function< void(flutter::SemanticsNodeUpdates, float)> OnSemanticsNodeUpdateCallback
std::function< void(fuchsia::ui::composition::ContentId)> ViewIdCallback
fml::RefPtr< fml::TaskRunner > CreateFMLTaskRunner(async_dispatcher_t *dispatcher)
fit::function< void(std::string)> OnRequestAnnounceCallback
std::function< void(fuchsia::ui::composition::ContentId, fuchsia::ui::composition::ChildViewWatcherHandle child_view_watcher)> ViewCreatedCallback
fit::function< void(bool)> OnEnableWireframeCallback
GrContextOptions MakeDefaultContextOptions(ContextType type, std::optional< GrBackendApi > api)
Initializes GrContextOptions with values suitable for Flutter. The options can be further tweaked bef...
DEF_SWITCHES_START aot vmservice shared library name
static void LoadDartDeferredLibrary(JNIEnv *env, jobject obj, jlong shell_holder, jint jLoadingUnitId, jobjectArray jSearchPaths)
@ kRender
The context is used to render to a texture or renderbuffer.
static void SetViewportMetrics(JNIEnv *env, jobject jcaller, jlong shell_holder, jfloat devicePixelRatio, jint physicalWidth, jint physicalHeight, jint physicalPaddingTop, jint physicalPaddingRight, jint physicalPaddingBottom, jint physicalPaddingLeft, jint physicalViewInsetTop, jint physicalViewInsetRight, jint physicalViewInsetBottom, jint physicalViewInsetLeft, jint systemGestureInsetTop, jint systemGestureInsetRight, jint systemGestureInsetBottom, jint systemGestureInsetLeft, jint physicalTouchSlop, jintArray javaDisplayFeaturesBounds, jintArray javaDisplayFeaturesType, jintArray javaDisplayFeaturesState)
std::function< void()> closure
static std::string ToString(CompilerBackend::Type type)
static constexpr SkRect MakeEmpty()
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
std::shared_ptr< const fml::Mapping > data
#define EXPECT_TRUE(handle)