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,
57 GrDirectContext* context,
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 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));
126 void OnPlatformViewDispatchKeyDataPacket(
127 std::unique_ptr<flutter::KeyDataPacket> packet,
128 std::function<
void(
bool)>
callback) {}
130 void OnPlatformViewDispatchSemanticsAction(int64_t
view_id,
135 void OnPlatformViewSetSemanticsEnabled(
bool enabled) {
136 semantics_enabled_ = enabled;
139 void OnPlatformViewSetAccessibilityFeatures(int32_t flags) {
140 semantics_features_ = flags;
143 void OnPlatformViewRegisterTexture(
144 std::shared_ptr<flutter::Texture>
texture) {}
146 void OnPlatformViewUnregisterTexture(int64_t
texture_id) {}
148 void OnPlatformViewMarkTextureFrameAvailable(int64_t
texture_id) {}
150 std::unique_ptr<std::vector<std::string>> ComputePlatformViewResolvedLocale(
151 const std::vector<std::string>& supported_locale_data) {
155 void LoadDartDeferredLibrary(
156 intptr_t loading_unit_id,
157 std::unique_ptr<const fml::Mapping> snapshot_data,
158 std::unique_ptr<const fml::Mapping> snapshot_instructions) {}
160 void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
161 const std::string error_message,
164 void UpdateAssetResolverByType(
165 std::unique_ptr<flutter::AssetResolver> updated_asset_resolver,
174 int32_t semantics_features()
const {
return semantics_features_; }
175 bool semantics_enabled()
const {
return semantics_enabled_; }
176 const std::vector<std::unique_ptr<flutter::PointerDataPacket>>&
177 pointer_packets()
const {
178 return pointer_packets_;
180 std::vector<std::unique_ptr<flutter::PointerDataPacket>>
181 TakePointerDataPackets() {
182 auto tmp = std::move(pointer_packets_);
183 pointer_packets_.clear();
188 std::unique_ptr<flutter::Surface>
surface_;
189 std::unique_ptr<flutter::PlatformMessage> message_;
191 std::vector<std::unique_ptr<flutter::PointerDataPacket>> pointer_packets_;
192 int32_t semantics_features_ = 0;
193 bool semantics_enabled_ =
false;
199 MOCK_METHOD(
void, Complete, (std::unique_ptr<fml::Mapping> data), (
override));
200 MOCK_METHOD(
void, CompleteEmpty, (), (
override));
205 TestPlatformMessageResponse() {}
206 void Complete(std::unique_ptr<fml::Mapping> data)
override {
208 reinterpret_cast<const char*
>(
data->GetMapping()),
data->GetSize());
211 void CompleteEmpty()
override { is_complete_ =
true; }
216class MockKeyboard :
public fuchsia::ui::input3::testing::Keyboard_TestBase {
218 explicit MockKeyboard(
219 fidl::InterfaceRequest<fuchsia::ui::input3::Keyboard> keyboard)
221 ~MockKeyboard() =
default;
223 void AddListener(fuchsia::ui::views::ViewRef view_ref,
224 fuchsia::ui::input3::KeyboardListenerHandle listener,
225 AddListenerCallback
callback)
override {
229 view_ref_ = std::move(view_ref);
234 void NotImplemented_(
const std::string&
name)
override { FAIL(); }
238 fuchsia::ui::views::ViewRef view_ref_{};
243class MockChildViewWatcher
244 :
public fuchsia::ui::composition::testing::ChildViewWatcher_TestBase {
246 explicit MockChildViewWatcher(
247 fidl::InterfaceRequest<fuchsia::ui::composition::ChildViewWatcher>
250 ~MockChildViewWatcher() =
default;
253 void GetStatus(GetStatusCallback
callback)
override {
255 if (get_status_returned_) {
258 callback(fuchsia::ui::composition::ChildViewStatus::CONTENT_HAS_PRESENTED);
263 void GetViewRef(GetViewRefCallback
callback)
override {
266 fuchsia::ui::views::ViewRefControl view_ref_control;
267 fuchsia::ui::views::ViewRef view_ref;
268 auto status = zx::eventpair::create(
269 0u, &view_ref_control.reference, &view_ref.reference);
270 ZX_ASSERT(status == ZX_OK);
271 view_ref_control.reference.replace(
272 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
273 &view_ref_control.reference);
274 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
279 void NotImplemented_(
const std::string&
name)
override { FAIL(); }
281 fidl::Binding<fuchsia::ui::composition::ChildViewWatcher>
binding_;
288class MockParentViewportWatcher
289 :
public fuchsia::ui::composition::testing::ParentViewportWatcher_TestBase {
291 explicit MockParentViewportWatcher() :
binding_(this,
handle_.NewRequest()) {}
292 ~MockParentViewportWatcher() =
default;
295 void GetStatus(GetStatusCallback
callback)
override {
297 if (get_status_returned_) {
301 fuchsia::ui::composition::ParentViewportStatus::CONNECTED_TO_DISPLAY);
306 void GetLayout(GetLayoutCallback
callback)
override {
307 if (layout_changed_) {
316 void SetLayout(uint32_t logical_size_x,
317 uint32_t logical_size_y,
319 ::fuchsia::math::SizeU logical_size;
320 logical_size.width = logical_size_x;
321 logical_size.height = logical_size_y;
322 layout_.set_logical_size(logical_size);
323 layout_.set_device_pixel_ratio({DPR, DPR});
325 if (pending_callback_valid_) {
333 fuchsia::ui::composition::ParentViewportWatcherHandle GetHandle() {
335 return std::move(handle_);
338 void NotImplemented_(
const std::string&
name)
override { FAIL(); }
340 fuchsia::ui::composition::ParentViewportWatcherHandle
handle_;
341 fidl::Binding<fuchsia::ui::composition::ParentViewportWatcher>
binding_;
358class PlatformViewBuilder {
363 fuchsia::ui::views::ViewRefControl view_ref_control;
364 fuchsia::ui::views::ViewRef view_ref;
365 auto status = zx::eventpair::create(
366 0u, &view_ref_control.reference, &view_ref.reference);
367 ZX_ASSERT(status == ZX_OK);
368 view_ref_control.reference.replace(
369 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
370 &view_ref_control.reference);
371 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
373 std::make_pair(std::move(view_ref_control), std::move(view_ref));
374 view_ref_pair_ = std::move(view_ref_pair);
377 PlatformViewBuilder& SetExternalViewEmbedder(
378 std::shared_ptr<flutter::ExternalViewEmbedder> embedder) {
379 external_external_view_embedder_ = embedder;
383 PlatformViewBuilder& SetImeService(
384 fuchsia::ui::input::ImeServiceHandle ime_service) {
385 ime_service_ = std::move(ime_service);
389 PlatformViewBuilder& SetKeyboard(
390 fuchsia::ui::input3::KeyboardHandle keyboard) {
395 PlatformViewBuilder& SetTouchSource(
396 fuchsia::ui::pointer::TouchSourceHandle touch_source) {
397 touch_source_ = std::move(touch_source);
401 PlatformViewBuilder& SetMouseSource(
402 fuchsia::ui::pointer::MouseSourceHandle mouse_source) {
403 mouse_source_ = std::move(mouse_source);
407 PlatformViewBuilder& SetFocuser(fuchsia::ui::views::FocuserHandle focuser) {
408 focuser_ = std::move(focuser);
412 PlatformViewBuilder& SetViewRefFocused(
413 fuchsia::ui::views::ViewRefFocusedHandle view_ref_focused) {
414 view_ref_focused_ = std::move(view_ref_focused);
418 PlatformViewBuilder& SetPointerInjectorRegistry(
419 fuchsia::ui::pointerinjector::RegistryHandle pointerinjector_registry) {
420 pointerinjector_registry_ = std::move(pointerinjector_registry);
424 PlatformViewBuilder& SetEnableWireframeCallback(
426 wireframe_enabled_callback_ = std::move(
callback);
430 PlatformViewBuilder& SetParentViewportWatcher(
431 fuchsia::ui::composition::ParentViewportWatcherHandle
432 parent_viewport_watcher) {
433 parent_viewport_watcher_ = std::move(parent_viewport_watcher);
438 on_create_view_callback_ = std::move(
callback);
443 on_destroy_view_callback_ = std::move(
callback);
448 on_update_view_callback_ = std::move(
callback);
452 PlatformViewBuilder& SetCreateSurfaceCallback(
454 on_create_surface_callback_ = std::move(
callback);
458 PlatformViewBuilder& SetShaderWarmupCallback(
460 on_shader_warmup_callback_ = std::move(
callback);
465 PlatformView Build() {
466 EXPECT_FALSE(std::exchange(built_,
true))
467 <<
"Build() was already called, this builder is good for one use only.";
469 delegate_, task_runners_, std::move(view_ref_pair_.second),
470 external_external_view_embedder_, std::move(ime_service_),
471 std::move(keyboard_), std::move(touch_source_),
472 std::move(mouse_source_), std::move(focuser_),
473 std::move(view_ref_focused_), std::move(parent_viewport_watcher_),
474 std::move(pointerinjector_registry_),
475 std::move(wireframe_enabled_callback_),
476 std::move(on_create_view_callback_),
477 std::move(on_update_view_callback_),
478 std::move(on_destroy_view_callback_),
479 std::move(on_create_surface_callback_),
480 std::move(on_semantics_node_update_callback_),
481 std::move(on_request_announce_callback_),
482 std::move(on_shader_warmup_callback_), [](
auto...) {}, [](
auto...) {},
487 PlatformViewBuilder() =
delete;
491 std::pair<fuchsia::ui::views::ViewRefControl, fuchsia::ui::views::ViewRef>
494 std::shared_ptr<flutter::ExternalViewEmbedder>
495 external_external_view_embedder_;
496 fuchsia::ui::input::ImeServiceHandle ime_service_;
497 fuchsia::ui::input3::KeyboardHandle
keyboard_;
498 fuchsia::ui::pointer::TouchSourceHandle touch_source_;
499 fuchsia::ui::pointer::MouseSourceHandle mouse_source_;
500 fuchsia::ui::views::ViewRefFocusedHandle view_ref_focused_;
501 fuchsia::ui::views::FocuserHandle focuser_;
502 fuchsia::ui::pointerinjector::RegistryHandle pointerinjector_registry_;
503 fit::closure on_session_listener_error_callback_;
505 fuchsia::ui::composition::ParentViewportWatcherHandle
506 parent_viewport_watcher_;
525 std::unique_ptr<flutter::PointerDataPacket> packet) {
526 for (
size_t i = 0;
i < packet->GetLength();
i++) {
528 output.push_back(pointer_data);
539 async_dispatcher_t*
dispatcher() {
return loop_.dispatcher(); }
542 loop_.RunUntilIdle();
547 loop_.Run(zx::time::infinite(),
true);
553 std::optional<fuchsia::ui::input3::Modifiers> modifiers,
554 fuchsia::input::Key
key) {
555 fuchsia::ui::input3::KeyEvent event;
556 event.set_timestamp(++event_timestamp_);
558 if (modifiers.has_value()) {
559 event.set_modifiers(modifiers.value());
566 fuchsia::ui::composition::ChildViewWatcherPtr ptr;
567 auto watcher = std::make_unique<MockChildViewWatcher>(
568 ptr.NewRequest(loop_.dispatcher()));
569 child_view_watchers_.push_back(std::move(watcher));
576 uint64_t event_timestamp_{42};
578 std::vector<std::unique_ptr<MockChildViewWatcher>> child_view_watchers_;
586 MockPlatformViewDelegate delegate;
591 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
592 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
594 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
595 .SetViewRefFocused(std::move(vrf_handle))
601 EXPECT_TRUE(base_view);
605 base_view->HandlePlatformMessage(response1->WithMessage(
606 "flutter/invalid",
"{\"method\":\"Invalid.invalidMethod\"}"));
610 base_view->HandlePlatformMessage(
611 response2->WithMessage(
"flutter/platform_views",
"{Invalid JSON"));
615 base_view->HandlePlatformMessage(response3->WithMessage(
616 "flutter/platform_views",
"{\"method\":\"View.focus.invalidMethod\"}"));
620 base_view->HandlePlatformMessage(response4->WithMessage(
621 "flutter/platform_views",
"{\"method\":\"View.update\"}"));
623 base_view->HandlePlatformMessage(
624 response5->WithMessage(
"flutter/platform_views",
625 "{\"method\":\"View.update\",\"args\":{"
626 "\"irrelevantField\":\"irrelevantValue\"}}"));
630 base_view->HandlePlatformMessage(response6->WithMessage(
631 "flutter/platform_views",
632 "{\"method\":\"View.update\",\"args\":{\"viewId\":false,\"hitTestable\":"
633 "123,\"focusable\":\"yes\"}}"));
637 response1->ExpectCompleted(
"");
638 response2->ExpectCompleted(
"");
639 response3->ExpectCompleted(
"");
640 response4->ExpectCompleted(
"");
641 response5->ExpectCompleted(
"");
642 response6->ExpectCompleted(
"");
648 MockPlatformViewDelegate delegate;
654 async_get_default_dispatcher()),
660 sk_sp<GrDirectContext> gr_context = GrDirectContext::MakeMock(
663 std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
664 std::make_shared<MockExternalViewEmbedder>();
665 auto CreateSurfaceCallback = [&external_view_embedder, gr_context]() {
666 return std::make_unique<flutter_runner::Surface>(
667 "PlatformViewTest", external_view_embedder, gr_context.get());
670 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
671 .SetCreateSurfaceCallback(CreateSurfaceCallback)
672 .SetExternalViewEmbedder(external_view_embedder)
678 EXPECT_EQ(gr_context.get(), delegate.surface()->GetContext());
679 EXPECT_EQ(external_view_embedder.get(),
687 constexpr float kDPR = 2;
688 constexpr uint32_t
width = 640;
689 constexpr uint32_t
height = 480;
691 MockPlatformViewDelegate delegate;
694 MockParentViewportWatcher watcher;
697 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
698 .SetParentViewportWatcher(watcher.GetHandle())
705 EXPECT_EQ(delegate.metrics(),
707 std::round(
height * kDPR), -1.0, 0));
714 MockPlatformViewDelegate delegate;
718 EXPECT_FALSE(delegate.semantics_enabled());
719 EXPECT_EQ(delegate.semantics_features(), 0);
722 PlatformViewBuilder(delegate, std::move(task_runners)).Build();
728 EXPECT_TRUE(delegate.semantics_enabled());
729 EXPECT_EQ(delegate.semantics_features(),
730 static_cast<int32_t
>(
735 EXPECT_FALSE(delegate.semantics_enabled());
736 EXPECT_EQ(delegate.semantics_features(), 0);
742 MockPlatformViewDelegate delegate;
749 bool wireframe_enabled =
false;
750 auto EnableWireframeCallback = [&wireframe_enabled](
bool should_enable) {
751 wireframe_enabled = should_enable;
754 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
755 .SetEnableWireframeCallback(EnableWireframeCallback)
761 EXPECT_TRUE(base_view);
764 const uint8_t
txt[] =
766 " \"method\":\"View.enableWireframe\","
772 std::unique_ptr<flutter::PlatformMessage>
message =
773 std::make_unique<flutter::PlatformMessage>(
776 base_view->HandlePlatformMessage(std::move(
message));
780 EXPECT_TRUE(wireframe_enabled);
786 MockPlatformViewDelegate delegate;
791 async_get_default_dispatcher()),
800 bool create_view_called =
false;
801 auto CreateViewCallback =
802 [&create_view_called,
this](
806 create_view_called =
true;
808 fuchsia::ui::composition::ContentId content_id;
809 on_view_bound(std::move(content_id), MakeChildViewWatcher());
812 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
813 .SetCreateViewCallback(CreateViewCallback)
819 EXPECT_TRUE(base_view);
822 std::ostringstream create_view_message;
823 create_view_message <<
"{" <<
" \"method\":\"View.create\","
824 <<
" \"args\":{" <<
" \"viewId\":" <<
view_id <<
","
825 <<
" \"hitTestable\":true," <<
" \"focusable\":true"
828 std::string create_view_call = create_view_message.str();
829 std::unique_ptr<flutter::PlatformMessage>
message =
830 std::make_unique<flutter::PlatformMessage>(
831 "flutter/platform_views",
833 create_view_call.size()),
835 base_view->HandlePlatformMessage(std::move(
message));
839 EXPECT_TRUE(create_view_called);
843 std::ostringstream view_connected_expected_out;
844 view_connected_expected_out <<
"{" <<
"\"method\":\"View.viewConnected\","
845 <<
"\"args\":{" <<
" \"viewId\":" <<
view_id
848 ASSERT_NE(delegate.message(),
nullptr);
849 EXPECT_EQ(view_connected_expected_out.str(),
850 ToString(delegate.message()->data()));
856 MockPlatformViewDelegate delegate;
860 std::optional<SkRect> occlusion_hint_for_test;
861 std::optional<bool> hit_testable_for_test;
862 std::optional<bool> focusable_for_test;
863 auto UpdateViewCallback = [&occlusion_hint_for_test, &hit_testable_for_test,
864 &focusable_for_test](
865 int64_t
view_id, SkRect occlusion_hint,
866 bool hit_testable,
bool focusable) {
867 occlusion_hint_for_test = occlusion_hint;
868 hit_testable_for_test = hit_testable;
869 focusable_for_test = focusable;
872 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
873 .SetUpdateViewCallback(UpdateViewCallback)
879 EXPECT_TRUE(base_view);
882 const uint8_t json[] =
884 " \"method\":\"View.update\","
887 " \"hitTestable\":true,"
888 " \"focusable\":true"
891 std::unique_ptr<flutter::PlatformMessage>
message =
892 std::make_unique<flutter::PlatformMessage>(
893 "flutter/platform_views",
896 base_view->HandlePlatformMessage(std::move(
message));
899 ASSERT_TRUE(occlusion_hint_for_test.has_value());
900 ASSERT_TRUE(hit_testable_for_test.has_value());
901 ASSERT_TRUE(focusable_for_test.has_value());
902 EXPECT_EQ(occlusion_hint_for_test.value(), SkRect::MakeEmpty());
903 EXPECT_EQ(hit_testable_for_test.value(),
true);
904 EXPECT_EQ(focusable_for_test.value(),
true);
907 occlusion_hint_for_test.reset();
908 hit_testable_for_test.reset();
909 focusable_for_test.reset();
912 const uint8_t json_false[] =
914 " \"method\":\"View.update\","
917 " \"hitTestable\":false,"
918 " \"focusable\":false"
921 std::unique_ptr<flutter::PlatformMessage> message_false =
922 std::make_unique<flutter::PlatformMessage>(
923 "flutter/platform_views",
926 base_view->HandlePlatformMessage(std::move(message_false));
928 ASSERT_TRUE(occlusion_hint_for_test.has_value());
929 ASSERT_TRUE(hit_testable_for_test.has_value());
930 ASSERT_TRUE(focusable_for_test.has_value());
931 EXPECT_EQ(occlusion_hint_for_test.value(), SkRect::MakeEmpty());
932 EXPECT_EQ(hit_testable_for_test.value(),
false);
933 EXPECT_EQ(focusable_for_test.value(),
false);
936 occlusion_hint_for_test.reset();
937 hit_testable_for_test.reset();
938 focusable_for_test.reset();
941 const uint8_t json_occlusion_hint[] =
943 " \"method\":\"View.update\","
946 " \"hitTestable\":true,"
947 " \"focusable\":true,"
948 " \"viewOcclusionHintLTRB\":[0.1,0.2,0.3,0.4]"
951 std::unique_ptr<flutter::PlatformMessage> message_occlusion_hint =
952 std::make_unique<flutter::PlatformMessage>(
953 "flutter/platform_views",
955 sizeof(json_occlusion_hint)),
957 base_view->HandlePlatformMessage(std::move(message_occlusion_hint));
959 ASSERT_TRUE(occlusion_hint_for_test.has_value());
960 ASSERT_TRUE(hit_testable_for_test.has_value());
961 ASSERT_TRUE(focusable_for_test.has_value());
962 EXPECT_EQ(occlusion_hint_for_test.value(),
963 SkRect::MakeLTRB(0.1, 0.2, 0.3, 0.4));
964 EXPECT_EQ(hit_testable_for_test.value(),
true);
965 EXPECT_EQ(focusable_for_test.value(),
true);
971 MockPlatformViewDelegate delegate;
977 async_get_default_dispatcher()),
983 bool destroy_view_called =
false;
985 auto on_destroy_view = [&destroy_view_called](
988 destroy_view_called =
true;
989 fuchsia::ui::composition::ContentId content_id;
990 on_view_unbound(std::move(content_id));
993 bool create_view_called =
false;
994 auto on_create_view = [&create_view_called,
this](
998 bool hit_testable,
bool focusable) {
999 create_view_called =
true;
1001 fuchsia::ui::composition::ContentId content_id;
1002 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1005 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1006 .SetCreateViewCallback(on_create_view)
1007 .SetDestroyViewCallback(on_destroy_view)
1013 EXPECT_TRUE(base_view);
1015 std::ostringstream create_message;
1016 create_message <<
"{" <<
" \"method\":\"View.create\","
1017 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id <<
","
1018 <<
" \"hitTestable\":true,"
1019 <<
" \"focusable\":true" <<
" }" <<
"}";
1022 base_view->HandlePlatformMessage(create_response->WithMessage(
1023 "flutter/platform_views", create_message.str()));
1029 std::ostringstream dispose_message;
1030 dispose_message <<
"{" <<
" \"method\":\"View.dispose\","
1031 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1034 std::string dispose_view_call = dispose_message.str();
1035 std::unique_ptr<flutter::PlatformMessage>
message =
1036 std::make_unique<flutter::PlatformMessage>(
1037 "flutter/platform_views",
1039 dispose_view_call.size()),
1041 base_view->HandlePlatformMessage(std::move(
message));
1045 EXPECT_TRUE(destroy_view_called);
1049 std::ostringstream view_disconnected_expected_out;
1050 view_disconnected_expected_out
1051 <<
"{" <<
"\"method\":\"View.viewDisconnected\"," <<
"\"args\":{"
1052 <<
" \"viewId\":" <<
view_id <<
" }" <<
"}";
1054 ASSERT_NE(delegate.message(),
nullptr);
1055 EXPECT_EQ(view_disconnected_expected_out.str(),
1056 ToString(delegate.message()->data()));
1063 MockPlatformViewDelegate delegate;
1068 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
1069 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
1071 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1072 .SetViewRefFocused(std::move(vrf_handle))
1078 EXPECT_TRUE(base_view);
1080 std::vector<bool> vrf_states{
false,
true,
true,
false,
1081 true,
false,
true,
true};
1083 for (std::size_t
i = 0;
i < vrf_states.size(); ++
i) {
1086 base_view->HandlePlatformMessage(response1->WithMessage(
1087 "flutter/platform_views",
"{\"method\":\"View.focus.getNext\"}"));
1090 base_view->HandlePlatformMessage(response2->WithMessage(
1091 "flutter/platform_views",
"{\"method\":\"View.focus.getNext\"}"));
1103 base_view->HandlePlatformMessage(response3->WithMessage(
1104 "flutter/platform_views",
"{\"method\":\"View.focus.getCurrent\"}"));
1107 base_view->HandlePlatformMessage(response4->WithMessage(
1108 "flutter/platform_views",
"{\"method\":\"View.focus.getCurrent\"}"));
1112 response1->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1113 response2->ExpectCompleted(
"[null]");
1114 response3->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1115 response4->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1122 MockPlatformViewDelegate delegate;
1126 async_get_default_dispatcher()),
1133 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1134 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1136 bool create_view_called =
false;
1137 auto on_create_view = [&create_view_called,
this](
1141 bool hit_testable,
bool focusable) {
1142 create_view_called =
true;
1144 fuchsia::ui::composition::ContentId content_id;
1145 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1148 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1149 .SetFocuser(std::move(focuser_handle))
1150 .SetCreateViewCallback(on_create_view)
1156 EXPECT_TRUE(base_view);
1160 std::ostringstream create_message;
1161 create_message <<
"{" <<
" \"method\":\"View.create\","
1162 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id <<
","
1163 <<
" \"hitTestable\":true,"
1164 <<
" \"focusable\":true" <<
" }" <<
"}";
1168 base_view->HandlePlatformMessage(create_response->WithMessage(
1169 "flutter/platform_views", create_message.str()));
1174 std::ostringstream focus_message;
1175 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1176 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1181 base_view->HandlePlatformMessage(focus_response->WithMessage(
1182 "flutter/platform_views", focus_message.str()));
1185 focus_response->ExpectCompleted(
"[0]");
1191 MockPlatformViewDelegate delegate;
1195 async_get_default_dispatcher()),
1202 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1203 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1205 bool create_view_called =
false;
1206 auto on_create_view = [&create_view_called,
this](
1210 bool hit_testable,
bool focusable) {
1211 create_view_called =
true;
1213 fuchsia::ui::composition::ContentId content_id;
1214 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1217 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1218 .SetFocuser(std::move(focuser_handle))
1219 .SetCreateViewCallback(on_create_view)
1223 EXPECT_TRUE(base_view);
1227 std::ostringstream focus_message;
1228 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1229 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1234 base_view->HandlePlatformMessage(focus_response->WithMessage(
1235 "flutter/platform_views", focus_message.str()));
1238 focus_response->ExpectCompleted(
"[1]");
1243 MockPlatformViewDelegate delegate;
1247 async_get_default_dispatcher()),
1254 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1255 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1257 bool create_view_called =
false;
1258 auto on_create_view = [&create_view_called,
this](
1262 bool hit_testable,
bool focusable) {
1263 create_view_called =
true;
1265 fuchsia::ui::composition::ContentId content_id;
1266 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1269 bool destroy_view_called =
false;
1271 auto on_destroy_view = [&destroy_view_called](
1274 destroy_view_called =
true;
1275 fuchsia::ui::composition::ContentId content_id;
1276 on_view_unbound(std::move(content_id));
1279 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1280 .SetFocuser(std::move(focuser_handle))
1281 .SetCreateViewCallback(on_create_view)
1282 .SetDestroyViewCallback(on_destroy_view)
1286 EXPECT_TRUE(base_view);
1291 std::ostringstream create_message;
1292 create_message <<
"{" <<
" \"method\":\"View.create\","
1293 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id <<
","
1294 <<
" \"hitTestable\":true,"
1295 <<
" \"focusable\":true" <<
" }" <<
"}";
1298 base_view->HandlePlatformMessage(create_response->WithMessage(
1299 "flutter/platform_views", create_message.str()));
1302 EXPECT_FALSE(destroy_view_called);
1304 std::ostringstream dispose_message;
1305 dispose_message <<
"{" <<
" \"method\":\"View.dispose\","
1306 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1310 base_view->HandlePlatformMessage(dispose_response->WithMessage(
1311 "flutter/platform_views", dispose_message.str()));
1313 EXPECT_TRUE(destroy_view_called);
1316 std::ostringstream focus_message;
1317 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1318 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1322 base_view->HandlePlatformMessage(focus_response->WithMessage(
1323 "flutter/platform_views", focus_message.str()));
1327 focus_response->ExpectCompleted(
"[1]");
1334 fuchsia::ui::input3::KeyEvent event;
1335 fuchsia::ui::input3::KeyEventStatus expected_key_event_status;
1336 std::string expected_platform_message;
1339 MockPlatformViewDelegate delegate;
1343 fuchsia::ui::input3::KeyboardHandle keyboard_service;
1344 MockKeyboard keyboard(keyboard_service.NewRequest());
1346 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1347 .SetKeyboard(std::move(keyboard_service))
1351 std::vector<EventFlow> events;
1354 events.emplace_back(EventFlow{
1355 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1356 fuchsia::input::Key::A),
1357 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1358 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1361 events.emplace_back(EventFlow{
1362 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED, std::nullopt,
1363 fuchsia::input::Key::A),
1364 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1365 R
"({"type":"keyup","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1368 events.emplace_back(EventFlow{
1369 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED,
1370 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1371 fuchsia::input::Key::CAPS_LOCK),
1372 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1373 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1376 events.emplace_back(EventFlow{
1377 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1378 fuchsia::input::Key::A),
1379 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1380 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1383 events.emplace_back(EventFlow{
1384 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED,
1385 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1386 fuchsia::input::Key::CAPS_LOCK),
1387 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1388 R
"({"type":"keyup","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1392 events.emplace_back(EventFlow{
1393 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1394 fuchsia::input::Key::A),
1395 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1396 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1399 for (
const auto& event : events) {
1400 fuchsia::ui::input3::KeyEvent e;
1401 event.event.Clone(&e);
1402 fuchsia::ui::input3::KeyEventStatus key_event_status{0u};
1403 keyboard.listener_->OnKeyEvent(
1405 [&key_event_status](fuchsia::ui::input3::KeyEventStatus status) {
1406 key_event_status = status;
1410 ASSERT_NOTNULL(delegate.message());
1411 EXPECT_EQ(event.expected_platform_message,
1412 ToString(delegate.message()->data()));
1413 EXPECT_EQ(event.expected_key_event_status, key_event_status);
1418 MockPlatformViewDelegate delegate;
1422 uint64_t
width = 200;
1424 std::vector<std::string> shaders = {
"foo.skp",
"bar.skp",
"baz.skp"};
1427 [&](
const std::vector<std::string>& shaders_in,
1428 std::function<void(uint32_t)> completion_callback, uint64_t width_in,
1429 uint64_t height_in) {
1430 ASSERT_EQ(shaders.size(), shaders_in.size());
1431 for (
size_t i = 0;
i < shaders_in.size();
i++) {
1432 ASSERT_EQ(shaders[
i], shaders_in[
i]);
1434 ASSERT_EQ(
width, width_in);
1435 ASSERT_EQ(
height, height_in);
1437 completion_callback(shaders_in.size());
1440 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1441 .SetShaderWarmupCallback(on_shader_warmup_callback)
1444 std::ostringstream shaders_array_ostream;
1445 shaders_array_ostream <<
"[ ";
1446 for (
auto it = shaders.begin(); it != shaders.end(); ++it) {
1447 shaders_array_ostream <<
"\"" << *it <<
"\"";
1448 if (std::next(it) != shaders.end()) {
1449 shaders_array_ostream <<
", ";
1452 shaders_array_ostream <<
"]";
1454 std::string shaders_array_string = shaders_array_ostream.str();
1457 std::ostringstream warmup_shaders_ostream;
1458 warmup_shaders_ostream <<
"{" <<
" \"method\":\"WarmupSkps\","
1460 <<
" \"shaders\":" << shaders_array_string <<
","
1461 <<
" \"width\":" <<
width <<
","
1462 <<
" \"height\":" <<
height <<
" }" <<
"}\n";
1463 std::string warmup_shaders_string = warmup_shaders_ostream.str();
1466 new TestPlatformMessageResponse);
1468 ->HandlePlatformMessage(std::make_unique<flutter::PlatformMessage>(
1469 "fuchsia/shader_warmup",
1471 warmup_shaders_string.size()),
1474 ASSERT_TRUE(response->is_complete());
1476 std::ostringstream expected_result_ostream;
1477 expected_result_ostream <<
"[" << shaders.size() <<
"]";
1478 std::string expected_result_string = expected_result_ostream.str();
1479 EXPECT_EQ(expected_result_string, response->result_string);
1483 constexpr uint32_t
width = 640;
1484 constexpr uint32_t
height = 480;
1485 constexpr std::array<std::array<float, 2>, 2>
kRect = {
1487 constexpr std::array<float, 9>
kIdentity = {1, 0, 0, 0, 1, 0, 0, 0, 1};
1488 constexpr fuchsia::ui::pointer::TouchInteractionId
kIxnOne = {
1489 .device_id = 0u, .pointer_id = 1u, .interaction_id = 2u};
1491 MockPlatformViewDelegate delegate;
1495 MockParentViewportWatcher viewport_watcher;
1497 fidl::BindingSet<fuchsia::ui::pointer::TouchSource> touch_bindings;
1498 auto touch_handle = touch_bindings.AddBinding(&touch_server);
1500 PlatformViewBuilder(delegate, std::move(task_runners))
1501 .SetParentViewportWatcher(viewport_watcher.GetHandle())
1502 .SetTouchSource(std::move(touch_handle))
1505 EXPECT_EQ(delegate.pointer_packets().size(), 0u);
1509 EXPECT_EQ(delegate.metrics(),
1513 std::vector<fuchsia::ui::pointer::TouchEvent> events =
1521 .status = fuchsia::ui::pointer::TouchInteractionStatus::GRANTED})
1527 std::vector<std::unique_ptr<flutter::PointerDataPacket>> packets =
1528 delegate.TakePointerDataPackets();
1529 ASSERT_EQ(packets.size(), 1u);
1530 std::vector<flutter::PointerData> flutter_events;
1531 UnpackPointerPacket(flutter_events, std::move(packets[0]));
1534 ASSERT_EQ(flutter_events.size(), 2u);
1539 EXPECT_EQ(flutter_events[0].physical_x,
width / 2);
1540 EXPECT_EQ(flutter_events[0].physical_y,
height / 2);
1541 EXPECT_EQ(flutter_events[1].physical_x,
width / 2);
1542 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)
impeller::ShaderType type