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>
28#include "gmock/gmock.h"
29#include "gtest/gtest.h"
38#include "platform/assert.h"
47 void CancelFrame()
override {}
48 void BeginFrame(GrDirectContext*
context,
50 raster_thread_merger)
override {}
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 {}
98 void OnPlatformViewSetNextFrameCallback(
const fml::closure& closure) {}
100 void OnPlatformViewSetViewportMetrics(
110 std::shared_ptr<fml::BasicTaskRunner>
111 OnPlatformViewGetShutdownSafeIOTaskRunner()
const {
115 void OnPlatformViewDispatchPlatformMessage(
116 std::unique_ptr<flutter::PlatformMessage>
message) {
120 void OnPlatformViewDispatchPointerDataPacket(
121 std::unique_ptr<flutter::PointerDataPacket> packet) {
122 pointer_packets_.push_back(std::move(packet));
131 void OnPlatformViewDispatchKeyDataPacket(
132 std::unique_ptr<flutter::KeyDataPacket> packet,
133 std::function<
void(
bool)>
callback) {}
135 void OnPlatformViewDispatchSemanticsAction(int64_t
view_id,
140 void OnPlatformViewSetSemanticsEnabled(
bool enabled) {
141 semantics_enabled_ = enabled;
144 void OnPlatformViewSetAccessibilityFeatures(int32_t flags) {
145 semantics_features_ = flags;
148 void OnPlatformViewRegisterTexture(
149 std::shared_ptr<flutter::Texture>
texture) {}
151 void OnPlatformViewUnregisterTexture(int64_t
texture_id) {}
153 void OnPlatformViewMarkTextureFrameAvailable(int64_t
texture_id) {}
155 std::unique_ptr<std::vector<std::string>> ComputePlatformViewResolvedLocale(
156 const std::vector<std::string>& supported_locale_data) {
160 void LoadDartDeferredLibrary(
161 intptr_t loading_unit_id,
162 std::unique_ptr<const fml::Mapping> snapshot_data,
163 std::unique_ptr<const fml::Mapping> snapshot_instructions) {}
165 void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
166 const std::string error_message,
169 void UpdateAssetResolverByType(
170 std::unique_ptr<flutter::AssetResolver> updated_asset_resolver,
179 int32_t semantics_features()
const {
return semantics_features_; }
180 bool semantics_enabled()
const {
return semantics_enabled_; }
181 const std::vector<std::unique_ptr<flutter::PointerDataPacket>>&
182 pointer_packets()
const {
183 return pointer_packets_;
185 std::vector<std::unique_ptr<flutter::PointerDataPacket>>
186 TakePointerDataPackets() {
187 auto tmp = std::move(pointer_packets_);
188 pointer_packets_.clear();
193 std::unique_ptr<flutter::Surface>
surface_;
194 std::unique_ptr<flutter::PlatformMessage> message_;
196 std::vector<std::unique_ptr<flutter::PointerDataPacket>> pointer_packets_;
197 int32_t semantics_features_ = 0;
198 bool semantics_enabled_ =
false;
204 MOCK_METHOD(
void, Complete, (std::unique_ptr<fml::Mapping> data), (
override));
205 MOCK_METHOD(
void, CompleteEmpty, (), (
override));
210 TestPlatformMessageResponse() {}
211 void Complete(std::unique_ptr<fml::Mapping> data)
override {
213 reinterpret_cast<const char*
>(
data->GetMapping()),
data->GetSize());
216 void CompleteEmpty()
override { is_complete_ =
true; }
221class MockKeyboard :
public fuchsia::ui::input3::testing::Keyboard_TestBase {
223 explicit MockKeyboard(
224 fidl::InterfaceRequest<fuchsia::ui::input3::Keyboard> keyboard)
226 ~MockKeyboard() =
default;
228 void AddListener(fuchsia::ui::views::ViewRef view_ref,
229 fuchsia::ui::input3::KeyboardListenerHandle listener,
230 AddListenerCallback
callback)
override {
234 view_ref_ = std::move(view_ref);
239 void NotImplemented_(
const std::string&
name)
override { FAIL(); }
243 fuchsia::ui::views::ViewRef view_ref_{};
248class MockChildViewWatcher
249 :
public fuchsia::ui::composition::testing::ChildViewWatcher_TestBase {
251 explicit MockChildViewWatcher(
252 fidl::InterfaceRequest<fuchsia::ui::composition::ChildViewWatcher>
255 ~MockChildViewWatcher() =
default;
258 void GetStatus(GetStatusCallback
callback)
override {
260 if (get_status_returned_) {
263 callback(fuchsia::ui::composition::ChildViewStatus::CONTENT_HAS_PRESENTED);
268 void GetViewRef(GetViewRefCallback
callback)
override {
271 fuchsia::ui::views::ViewRefControl view_ref_control;
272 fuchsia::ui::views::ViewRef view_ref;
273 auto status = zx::eventpair::create(
274 0u, &view_ref_control.reference, &view_ref.reference);
275 ZX_ASSERT(status == ZX_OK);
276 view_ref_control.reference.replace(
277 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
278 &view_ref_control.reference);
279 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
284 void NotImplemented_(
const std::string&
name)
override { FAIL(); }
286 fidl::Binding<fuchsia::ui::composition::ChildViewWatcher>
binding_;
293class MockParentViewportWatcher
294 :
public fuchsia::ui::composition::testing::ParentViewportWatcher_TestBase {
296 explicit MockParentViewportWatcher() :
binding_(this,
handle_.NewRequest()) {}
297 ~MockParentViewportWatcher() =
default;
300 void GetStatus(GetStatusCallback
callback)
override {
302 if (get_status_returned_) {
306 fuchsia::ui::composition::ParentViewportStatus::CONNECTED_TO_DISPLAY);
311 void GetLayout(GetLayoutCallback
callback)
override {
312 if (layout_changed_) {
321 void SetLayout(uint32_t logical_size_x,
322 uint32_t logical_size_y,
324 ::fuchsia::math::SizeU logical_size;
325 logical_size.width = logical_size_x;
326 logical_size.height = logical_size_y;
327 layout_.set_logical_size(logical_size);
328 layout_.set_device_pixel_ratio({DPR, DPR});
330 if (pending_callback_valid_) {
338 fuchsia::ui::composition::ParentViewportWatcherHandle GetHandle() {
340 return std::move(handle_);
343 void NotImplemented_(
const std::string&
name)
override { FAIL(); }
345 fuchsia::ui::composition::ParentViewportWatcherHandle
handle_;
346 fidl::Binding<fuchsia::ui::composition::ParentViewportWatcher>
binding_;
363class PlatformViewBuilder {
368 fuchsia::ui::views::ViewRefControl view_ref_control;
369 fuchsia::ui::views::ViewRef view_ref;
370 auto status = zx::eventpair::create(
371 0u, &view_ref_control.reference, &view_ref.reference);
372 ZX_ASSERT(status == ZX_OK);
373 view_ref_control.reference.replace(
374 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
375 &view_ref_control.reference);
376 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
378 std::make_pair(std::move(view_ref_control), std::move(view_ref));
379 view_ref_pair_ = std::move(view_ref_pair);
382 PlatformViewBuilder& SetExternalViewEmbedder(
383 std::shared_ptr<flutter::ExternalViewEmbedder> embedder) {
384 external_external_view_embedder_ = embedder;
388 PlatformViewBuilder& SetImeService(
389 fuchsia::ui::input::ImeServiceHandle ime_service) {
390 ime_service_ = std::move(ime_service);
394 PlatformViewBuilder& SetKeyboard(
395 fuchsia::ui::input3::KeyboardHandle keyboard) {
400 PlatformViewBuilder& SetTouchSource(
401 fuchsia::ui::pointer::TouchSourceHandle touch_source) {
402 touch_source_ = std::move(touch_source);
406 PlatformViewBuilder& SetMouseSource(
407 fuchsia::ui::pointer::MouseSourceHandle mouse_source) {
408 mouse_source_ = std::move(mouse_source);
412 PlatformViewBuilder& SetFocuser(fuchsia::ui::views::FocuserHandle focuser) {
413 focuser_ = std::move(focuser);
417 PlatformViewBuilder& SetViewRefFocused(
418 fuchsia::ui::views::ViewRefFocusedHandle view_ref_focused) {
419 view_ref_focused_ = std::move(view_ref_focused);
423 PlatformViewBuilder& SetPointerInjectorRegistry(
424 fuchsia::ui::pointerinjector::RegistryHandle pointerinjector_registry) {
425 pointerinjector_registry_ = std::move(pointerinjector_registry);
429 PlatformViewBuilder& SetEnableWireframeCallback(
431 wireframe_enabled_callback_ = std::move(
callback);
435 PlatformViewBuilder& SetParentViewportWatcher(
436 fuchsia::ui::composition::ParentViewportWatcherHandle
437 parent_viewport_watcher) {
438 parent_viewport_watcher_ = std::move(parent_viewport_watcher);
443 on_create_view_callback_ = std::move(
callback);
448 on_destroy_view_callback_ = std::move(
callback);
453 on_update_view_callback_ = std::move(
callback);
457 PlatformViewBuilder& SetCreateSurfaceCallback(
459 on_create_surface_callback_ = std::move(
callback);
463 PlatformViewBuilder& SetShaderWarmupCallback(
465 on_shader_warmup_callback_ = std::move(
callback);
470 PlatformView Build() {
471 EXPECT_FALSE(std::exchange(built_,
true))
472 <<
"Build() was already called, this builder is good for one use only.";
474 delegate_, task_runners_, std::move(view_ref_pair_.second),
475 external_external_view_embedder_, std::move(ime_service_),
476 std::move(keyboard_), std::move(touch_source_),
477 std::move(mouse_source_), std::move(focuser_),
478 std::move(view_ref_focused_), std::move(parent_viewport_watcher_),
479 std::move(pointerinjector_registry_),
480 std::move(wireframe_enabled_callback_),
481 std::move(on_create_view_callback_),
482 std::move(on_update_view_callback_),
483 std::move(on_destroy_view_callback_),
484 std::move(on_create_surface_callback_),
485 std::move(on_semantics_node_update_callback_),
486 std::move(on_request_announce_callback_),
487 std::move(on_shader_warmup_callback_), [](
auto...) {}, [](
auto...) {},
492 PlatformViewBuilder() =
delete;
496 std::pair<fuchsia::ui::views::ViewRefControl, fuchsia::ui::views::ViewRef>
499 std::shared_ptr<flutter::ExternalViewEmbedder>
500 external_external_view_embedder_;
501 fuchsia::ui::input::ImeServiceHandle ime_service_;
502 fuchsia::ui::input3::KeyboardHandle
keyboard_;
503 fuchsia::ui::pointer::TouchSourceHandle touch_source_;
504 fuchsia::ui::pointer::MouseSourceHandle mouse_source_;
505 fuchsia::ui::views::ViewRefFocusedHandle view_ref_focused_;
506 fuchsia::ui::views::FocuserHandle focuser_;
507 fuchsia::ui::pointerinjector::RegistryHandle pointerinjector_registry_;
508 fit::closure on_session_listener_error_callback_;
510 fuchsia::ui::composition::ParentViewportWatcherHandle
511 parent_viewport_watcher_;
530 std::unique_ptr<flutter::PointerDataPacket> packet) {
531 for (
size_t i = 0;
i < packet->GetLength();
i++) {
533 output.push_back(pointer_data);
544 async_dispatcher_t*
dispatcher() {
return loop_.dispatcher(); }
547 loop_.RunUntilIdle();
552 loop_.Run(zx::time::infinite(),
true);
558 std::optional<fuchsia::ui::input3::Modifiers> modifiers,
559 fuchsia::input::Key
key) {
560 fuchsia::ui::input3::KeyEvent event;
561 event.set_timestamp(++event_timestamp_);
563 if (modifiers.has_value()) {
564 event.set_modifiers(modifiers.value());
571 fuchsia::ui::composition::ChildViewWatcherPtr ptr;
572 auto watcher = std::make_unique<MockChildViewWatcher>(
573 ptr.NewRequest(loop_.dispatcher()));
574 child_view_watchers_.push_back(std::move(watcher));
581 uint64_t event_timestamp_{42};
583 std::vector<std::unique_ptr<MockChildViewWatcher>> child_view_watchers_;
591 MockPlatformViewDelegate delegate;
596 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
597 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
599 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
600 .SetViewRefFocused(std::move(vrf_handle))
606 EXPECT_TRUE(base_view);
610 base_view->HandlePlatformMessage(response1->WithMessage(
611 "flutter/invalid",
"{\"method\":\"Invalid.invalidMethod\"}"));
615 base_view->HandlePlatformMessage(
616 response2->WithMessage(
"flutter/platform_views",
"{Invalid JSON"));
620 base_view->HandlePlatformMessage(response3->WithMessage(
621 "flutter/platform_views",
"{\"method\":\"View.focus.invalidMethod\"}"));
625 base_view->HandlePlatformMessage(response4->WithMessage(
626 "flutter/platform_views",
"{\"method\":\"View.update\"}"));
628 base_view->HandlePlatformMessage(
629 response5->WithMessage(
"flutter/platform_views",
630 "{\"method\":\"View.update\",\"args\":{"
631 "\"irrelevantField\":\"irrelevantValue\"}}"));
635 base_view->HandlePlatformMessage(response6->WithMessage(
636 "flutter/platform_views",
637 "{\"method\":\"View.update\",\"args\":{\"viewId\":false,\"hitTestable\":"
638 "123,\"focusable\":\"yes\"}}"));
642 response1->ExpectCompleted(
"");
643 response2->ExpectCompleted(
"");
644 response3->ExpectCompleted(
"");
645 response4->ExpectCompleted(
"");
646 response5->ExpectCompleted(
"");
647 response6->ExpectCompleted(
"");
653 MockPlatformViewDelegate delegate;
659 async_get_default_dispatcher()),
665 sk_sp<GrDirectContext> gr_context = GrDirectContext::MakeMock(
668 std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
669 std::make_shared<MockExternalViewEmbedder>();
670 auto CreateSurfaceCallback = [&external_view_embedder, gr_context]() {
671 return std::make_unique<flutter_runner::Surface>(
672 "PlatformViewTest", external_view_embedder, gr_context.get());
675 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
676 .SetCreateSurfaceCallback(CreateSurfaceCallback)
677 .SetExternalViewEmbedder(external_view_embedder)
683 EXPECT_EQ(gr_context.get(), delegate.surface()->GetContext());
684 EXPECT_EQ(external_view_embedder.get(),
692 constexpr float kDPR = 2;
693 constexpr uint32_t
width = 640;
694 constexpr uint32_t
height = 480;
696 MockPlatformViewDelegate delegate;
699 MockParentViewportWatcher watcher;
702 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
703 .SetParentViewportWatcher(watcher.GetHandle())
710 EXPECT_EQ(delegate.metrics(),
712 std::round(
height * kDPR), -1.0, 0));
719 MockPlatformViewDelegate delegate;
723 EXPECT_FALSE(delegate.semantics_enabled());
724 EXPECT_EQ(delegate.semantics_features(), 0);
727 PlatformViewBuilder(delegate, std::move(task_runners)).Build();
733 EXPECT_TRUE(delegate.semantics_enabled());
734 EXPECT_EQ(delegate.semantics_features(),
735 static_cast<int32_t
>(
740 EXPECT_FALSE(delegate.semantics_enabled());
741 EXPECT_EQ(delegate.semantics_features(), 0);
747 MockPlatformViewDelegate delegate;
754 bool wireframe_enabled =
false;
755 auto EnableWireframeCallback = [&wireframe_enabled](
bool should_enable) {
756 wireframe_enabled = should_enable;
759 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
760 .SetEnableWireframeCallback(EnableWireframeCallback)
766 EXPECT_TRUE(base_view);
769 const uint8_t
txt[] =
771 " \"method\":\"View.enableWireframe\","
777 std::unique_ptr<flutter::PlatformMessage>
message =
778 std::make_unique<flutter::PlatformMessage>(
781 base_view->HandlePlatformMessage(std::move(
message));
785 EXPECT_TRUE(wireframe_enabled);
791 MockPlatformViewDelegate delegate;
796 async_get_default_dispatcher()),
805 bool create_view_called =
false;
806 auto CreateViewCallback =
807 [&create_view_called,
this](
811 create_view_called =
true;
813 fuchsia::ui::composition::ContentId content_id;
814 on_view_bound(std::move(content_id), MakeChildViewWatcher());
817 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
818 .SetCreateViewCallback(CreateViewCallback)
824 EXPECT_TRUE(base_view);
827 std::ostringstream create_view_message;
828 create_view_message <<
"{" <<
" \"method\":\"View.create\","
829 <<
" \"args\":{" <<
" \"viewId\":" <<
view_id <<
","
830 <<
" \"hitTestable\":true," <<
" \"focusable\":true"
833 std::string create_view_call = create_view_message.str();
834 std::unique_ptr<flutter::PlatformMessage>
message =
835 std::make_unique<flutter::PlatformMessage>(
836 "flutter/platform_views",
838 create_view_call.size()),
840 base_view->HandlePlatformMessage(std::move(
message));
844 EXPECT_TRUE(create_view_called);
848 std::ostringstream view_connected_expected_out;
849 view_connected_expected_out <<
"{" <<
"\"method\":\"View.viewConnected\","
850 <<
"\"args\":{" <<
" \"viewId\":" <<
view_id
853 ASSERT_NE(delegate.message(),
nullptr);
854 EXPECT_EQ(view_connected_expected_out.str(),
855 ToString(delegate.message()->data()));
861 MockPlatformViewDelegate delegate;
865 std::optional<SkRect> occlusion_hint_for_test;
866 std::optional<bool> hit_testable_for_test;
867 std::optional<bool> focusable_for_test;
868 auto UpdateViewCallback = [&occlusion_hint_for_test, &hit_testable_for_test,
869 &focusable_for_test](
870 int64_t
view_id, SkRect occlusion_hint,
871 bool hit_testable,
bool focusable) {
872 occlusion_hint_for_test = occlusion_hint;
873 hit_testable_for_test = hit_testable;
874 focusable_for_test = focusable;
877 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
878 .SetUpdateViewCallback(UpdateViewCallback)
884 EXPECT_TRUE(base_view);
887 const uint8_t json[] =
889 " \"method\":\"View.update\","
892 " \"hitTestable\":true,"
893 " \"focusable\":true"
896 std::unique_ptr<flutter::PlatformMessage>
message =
897 std::make_unique<flutter::PlatformMessage>(
898 "flutter/platform_views",
901 base_view->HandlePlatformMessage(std::move(
message));
904 ASSERT_TRUE(occlusion_hint_for_test.has_value());
905 ASSERT_TRUE(hit_testable_for_test.has_value());
906 ASSERT_TRUE(focusable_for_test.has_value());
907 EXPECT_EQ(occlusion_hint_for_test.value(), SkRect::MakeEmpty());
908 EXPECT_EQ(hit_testable_for_test.value(),
true);
909 EXPECT_EQ(focusable_for_test.value(),
true);
912 occlusion_hint_for_test.reset();
913 hit_testable_for_test.reset();
914 focusable_for_test.reset();
917 const uint8_t json_false[] =
919 " \"method\":\"View.update\","
922 " \"hitTestable\":false,"
923 " \"focusable\":false"
926 std::unique_ptr<flutter::PlatformMessage> message_false =
927 std::make_unique<flutter::PlatformMessage>(
928 "flutter/platform_views",
931 base_view->HandlePlatformMessage(std::move(message_false));
933 ASSERT_TRUE(occlusion_hint_for_test.has_value());
934 ASSERT_TRUE(hit_testable_for_test.has_value());
935 ASSERT_TRUE(focusable_for_test.has_value());
936 EXPECT_EQ(occlusion_hint_for_test.value(), SkRect::MakeEmpty());
937 EXPECT_EQ(hit_testable_for_test.value(),
false);
938 EXPECT_EQ(focusable_for_test.value(),
false);
941 occlusion_hint_for_test.reset();
942 hit_testable_for_test.reset();
943 focusable_for_test.reset();
946 const uint8_t json_occlusion_hint[] =
948 " \"method\":\"View.update\","
951 " \"hitTestable\":true,"
952 " \"focusable\":true,"
953 " \"viewOcclusionHintLTRB\":[0.1,0.2,0.3,0.4]"
956 std::unique_ptr<flutter::PlatformMessage> message_occlusion_hint =
957 std::make_unique<flutter::PlatformMessage>(
958 "flutter/platform_views",
960 sizeof(json_occlusion_hint)),
962 base_view->HandlePlatformMessage(std::move(message_occlusion_hint));
964 ASSERT_TRUE(occlusion_hint_for_test.has_value());
965 ASSERT_TRUE(hit_testable_for_test.has_value());
966 ASSERT_TRUE(focusable_for_test.has_value());
967 EXPECT_EQ(occlusion_hint_for_test.value(),
968 SkRect::MakeLTRB(0.1, 0.2, 0.3, 0.4));
969 EXPECT_EQ(hit_testable_for_test.value(),
true);
970 EXPECT_EQ(focusable_for_test.value(),
true);
976 MockPlatformViewDelegate delegate;
982 async_get_default_dispatcher()),
988 bool destroy_view_called =
false;
990 auto on_destroy_view = [&destroy_view_called](
993 destroy_view_called =
true;
994 fuchsia::ui::composition::ContentId content_id;
995 on_view_unbound(std::move(content_id));
998 bool create_view_called =
false;
999 auto on_create_view = [&create_view_called,
this](
1003 bool hit_testable,
bool focusable) {
1004 create_view_called =
true;
1006 fuchsia::ui::composition::ContentId content_id;
1007 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1010 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1011 .SetCreateViewCallback(on_create_view)
1012 .SetDestroyViewCallback(on_destroy_view)
1018 EXPECT_TRUE(base_view);
1020 std::ostringstream create_message;
1021 create_message <<
"{" <<
" \"method\":\"View.create\","
1022 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id <<
","
1023 <<
" \"hitTestable\":true,"
1024 <<
" \"focusable\":true" <<
" }" <<
"}";
1027 base_view->HandlePlatformMessage(create_response->WithMessage(
1028 "flutter/platform_views", create_message.str()));
1034 std::ostringstream dispose_message;
1035 dispose_message <<
"{" <<
" \"method\":\"View.dispose\","
1036 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1039 std::string dispose_view_call = dispose_message.str();
1040 std::unique_ptr<flutter::PlatformMessage>
message =
1041 std::make_unique<flutter::PlatformMessage>(
1042 "flutter/platform_views",
1044 dispose_view_call.size()),
1046 base_view->HandlePlatformMessage(std::move(
message));
1050 EXPECT_TRUE(destroy_view_called);
1054 std::ostringstream view_disconnected_expected_out;
1055 view_disconnected_expected_out
1056 <<
"{" <<
"\"method\":\"View.viewDisconnected\"," <<
"\"args\":{"
1057 <<
" \"viewId\":" <<
view_id <<
" }" <<
"}";
1059 ASSERT_NE(delegate.message(),
nullptr);
1060 EXPECT_EQ(view_disconnected_expected_out.str(),
1061 ToString(delegate.message()->data()));
1068 MockPlatformViewDelegate delegate;
1073 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
1074 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
1076 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1077 .SetViewRefFocused(std::move(vrf_handle))
1083 EXPECT_TRUE(base_view);
1085 std::vector<bool> vrf_states{
false,
true,
true,
false,
1086 true,
false,
true,
true};
1088 for (std::size_t
i = 0;
i < vrf_states.size(); ++
i) {
1091 base_view->HandlePlatformMessage(response1->WithMessage(
1092 "flutter/platform_views",
"{\"method\":\"View.focus.getNext\"}"));
1095 base_view->HandlePlatformMessage(response2->WithMessage(
1096 "flutter/platform_views",
"{\"method\":\"View.focus.getNext\"}"));
1108 base_view->HandlePlatformMessage(response3->WithMessage(
1109 "flutter/platform_views",
"{\"method\":\"View.focus.getCurrent\"}"));
1112 base_view->HandlePlatformMessage(response4->WithMessage(
1113 "flutter/platform_views",
"{\"method\":\"View.focus.getCurrent\"}"));
1117 response1->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1118 response2->ExpectCompleted(
"[null]");
1119 response3->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1120 response4->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1127 MockPlatformViewDelegate delegate;
1131 async_get_default_dispatcher()),
1138 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1139 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1141 bool create_view_called =
false;
1142 auto on_create_view = [&create_view_called,
this](
1146 bool hit_testable,
bool focusable) {
1147 create_view_called =
true;
1149 fuchsia::ui::composition::ContentId content_id;
1150 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1153 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1154 .SetFocuser(std::move(focuser_handle))
1155 .SetCreateViewCallback(on_create_view)
1161 EXPECT_TRUE(base_view);
1165 std::ostringstream create_message;
1166 create_message <<
"{" <<
" \"method\":\"View.create\","
1167 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id <<
","
1168 <<
" \"hitTestable\":true,"
1169 <<
" \"focusable\":true" <<
" }" <<
"}";
1173 base_view->HandlePlatformMessage(create_response->WithMessage(
1174 "flutter/platform_views", create_message.str()));
1179 std::ostringstream focus_message;
1180 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1181 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1186 base_view->HandlePlatformMessage(focus_response->WithMessage(
1187 "flutter/platform_views", focus_message.str()));
1190 focus_response->ExpectCompleted(
"[0]");
1196 MockPlatformViewDelegate delegate;
1200 async_get_default_dispatcher()),
1207 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1208 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1210 bool create_view_called =
false;
1211 auto on_create_view = [&create_view_called,
this](
1215 bool hit_testable,
bool focusable) {
1216 create_view_called =
true;
1218 fuchsia::ui::composition::ContentId content_id;
1219 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1222 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1223 .SetFocuser(std::move(focuser_handle))
1224 .SetCreateViewCallback(on_create_view)
1228 EXPECT_TRUE(base_view);
1232 std::ostringstream focus_message;
1233 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1234 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1239 base_view->HandlePlatformMessage(focus_response->WithMessage(
1240 "flutter/platform_views", focus_message.str()));
1243 focus_response->ExpectCompleted(
"[1]");
1248 MockPlatformViewDelegate delegate;
1252 async_get_default_dispatcher()),
1259 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1260 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1262 bool create_view_called =
false;
1263 auto on_create_view = [&create_view_called,
this](
1267 bool hit_testable,
bool focusable) {
1268 create_view_called =
true;
1270 fuchsia::ui::composition::ContentId content_id;
1271 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1274 bool destroy_view_called =
false;
1276 auto on_destroy_view = [&destroy_view_called](
1279 destroy_view_called =
true;
1280 fuchsia::ui::composition::ContentId content_id;
1281 on_view_unbound(std::move(content_id));
1284 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1285 .SetFocuser(std::move(focuser_handle))
1286 .SetCreateViewCallback(on_create_view)
1287 .SetDestroyViewCallback(on_destroy_view)
1291 EXPECT_TRUE(base_view);
1296 std::ostringstream create_message;
1297 create_message <<
"{" <<
" \"method\":\"View.create\","
1298 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id <<
","
1299 <<
" \"hitTestable\":true,"
1300 <<
" \"focusable\":true" <<
" }" <<
"}";
1303 base_view->HandlePlatformMessage(create_response->WithMessage(
1304 "flutter/platform_views", create_message.str()));
1307 EXPECT_FALSE(destroy_view_called);
1309 std::ostringstream dispose_message;
1310 dispose_message <<
"{" <<
" \"method\":\"View.dispose\","
1311 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1315 base_view->HandlePlatformMessage(dispose_response->WithMessage(
1316 "flutter/platform_views", dispose_message.str()));
1318 EXPECT_TRUE(destroy_view_called);
1321 std::ostringstream focus_message;
1322 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1323 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1327 base_view->HandlePlatformMessage(focus_response->WithMessage(
1328 "flutter/platform_views", focus_message.str()));
1332 focus_response->ExpectCompleted(
"[1]");
1339 fuchsia::ui::input3::KeyEvent event;
1340 fuchsia::ui::input3::KeyEventStatus expected_key_event_status;
1341 std::string expected_platform_message;
1344 MockPlatformViewDelegate delegate;
1348 fuchsia::ui::input3::KeyboardHandle keyboard_service;
1349 MockKeyboard keyboard(keyboard_service.NewRequest());
1351 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1352 .SetKeyboard(std::move(keyboard_service))
1356 std::vector<EventFlow> events;
1359 events.emplace_back(EventFlow{
1360 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1361 fuchsia::input::Key::A),
1362 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1363 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1366 events.emplace_back(EventFlow{
1367 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED, std::nullopt,
1368 fuchsia::input::Key::A),
1369 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1370 R
"({"type":"keyup","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1373 events.emplace_back(EventFlow{
1374 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED,
1375 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1376 fuchsia::input::Key::CAPS_LOCK),
1377 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1378 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1381 events.emplace_back(EventFlow{
1382 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1383 fuchsia::input::Key::A),
1384 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1385 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1388 events.emplace_back(EventFlow{
1389 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED,
1390 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1391 fuchsia::input::Key::CAPS_LOCK),
1392 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1393 R
"({"type":"keyup","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1397 events.emplace_back(EventFlow{
1398 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1399 fuchsia::input::Key::A),
1400 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1401 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1404 for (
const auto& event : events) {
1405 fuchsia::ui::input3::KeyEvent e;
1406 event.event.Clone(&e);
1407 fuchsia::ui::input3::KeyEventStatus key_event_status{0u};
1408 keyboard.listener_->OnKeyEvent(
1410 [&key_event_status](fuchsia::ui::input3::KeyEventStatus status) {
1411 key_event_status = status;
1415 ASSERT_NOTNULL(delegate.message());
1416 EXPECT_EQ(event.expected_platform_message,
1417 ToString(delegate.message()->data()));
1418 EXPECT_EQ(event.expected_key_event_status, key_event_status);
1423 MockPlatformViewDelegate delegate;
1427 uint64_t
width = 200;
1429 std::vector<std::string> shaders = {
"foo.skp",
"bar.skp",
"baz.skp"};
1432 [&](
const std::vector<std::string>& shaders_in,
1433 std::function<void(uint32_t)> completion_callback, uint64_t width_in,
1434 uint64_t height_in) {
1435 ASSERT_EQ(shaders.size(), shaders_in.size());
1436 for (
size_t i = 0;
i < shaders_in.size();
i++) {
1437 ASSERT_EQ(shaders[
i], shaders_in[
i]);
1439 ASSERT_EQ(
width, width_in);
1440 ASSERT_EQ(
height, height_in);
1442 completion_callback(shaders_in.size());
1445 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1446 .SetShaderWarmupCallback(on_shader_warmup_callback)
1449 std::ostringstream shaders_array_ostream;
1450 shaders_array_ostream <<
"[ ";
1451 for (
auto it = shaders.begin(); it != shaders.end(); ++it) {
1452 shaders_array_ostream <<
"\"" << *it <<
"\"";
1453 if (std::next(it) != shaders.end()) {
1454 shaders_array_ostream <<
", ";
1457 shaders_array_ostream <<
"]";
1459 std::string shaders_array_string = shaders_array_ostream.str();
1462 std::ostringstream warmup_shaders_ostream;
1463 warmup_shaders_ostream <<
"{" <<
" \"method\":\"WarmupSkps\","
1465 <<
" \"shaders\":" << shaders_array_string <<
","
1466 <<
" \"width\":" <<
width <<
","
1467 <<
" \"height\":" <<
height <<
" }" <<
"}\n";
1468 std::string warmup_shaders_string = warmup_shaders_ostream.str();
1471 new TestPlatformMessageResponse);
1473 ->HandlePlatformMessage(std::make_unique<flutter::PlatformMessage>(
1474 "fuchsia/shader_warmup",
1476 warmup_shaders_string.size()),
1479 ASSERT_TRUE(response->is_complete());
1481 std::ostringstream expected_result_ostream;
1482 expected_result_ostream <<
"[" << shaders.size() <<
"]";
1483 std::string expected_result_string = expected_result_ostream.str();
1484 EXPECT_EQ(expected_result_string, response->result_string);
1488 constexpr uint32_t
width = 640;
1489 constexpr uint32_t
height = 480;
1490 constexpr std::array<std::array<float, 2>, 2>
kRect = {
1492 constexpr std::array<float, 9>
kIdentity = {1, 0, 0, 0, 1, 0, 0, 0, 1};
1493 constexpr fuchsia::ui::pointer::TouchInteractionId
kIxnOne = {
1494 .device_id = 0u, .pointer_id = 1u, .interaction_id = 2u};
1496 MockPlatformViewDelegate delegate;
1500 MockParentViewportWatcher viewport_watcher;
1502 fidl::BindingSet<fuchsia::ui::pointer::TouchSource> touch_bindings;
1503 auto touch_handle = touch_bindings.AddBinding(&touch_server);
1505 PlatformViewBuilder(delegate, std::move(task_runners))
1506 .SetParentViewportWatcher(viewport_watcher.GetHandle())
1507 .SetTouchSource(std::move(touch_handle))
1510 EXPECT_EQ(delegate.pointer_packets().size(), 0u);
1514 EXPECT_EQ(delegate.metrics(),
1518 std::vector<fuchsia::ui::pointer::TouchEvent> events =
1526 .status = fuchsia::ui::pointer::TouchInteractionStatus::GRANTED})
1532 std::vector<std::unique_ptr<flutter::PointerDataPacket>> packets =
1533 delegate.TakePointerDataPackets();
1534 ASSERT_EQ(packets.size(), 1u);
1535 std::vector<flutter::PointerData> flutter_events;
1536 UnpackPointerPacket(flutter_events, std::move(packets[0]));
1539 ASSERT_EQ(flutter_events.size(), 2u);
1544 EXPECT_EQ(flutter_events[0].physical_x,
width / 2);
1545 EXPECT_EQ(flutter_events[0].physical_y,
height / 2);
1546 EXPECT_EQ(flutter_events[1].physical_x,
width / 2);
1547 EXPECT_EQ(flutter_events[1].physical_y,
height / 2);
ax::mojom::Event event_type
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_
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS FlutterViewId view_id
FlutterDesktopBinaryReply callback
#define FML_CHECK(condition)
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
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...
@ kRender
The context is used to render to a texture or renderbuffer.
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
void Reset(SkPathBuilder *path)
std::function< void()> closure
const char * ToString(ax::mojom::Event event)
std::shared_ptr< ContextGLES > context
impeller::ShaderType type