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"
37#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));
120 void OnPlatformViewDispatchKeyDataPacket(
121 std::unique_ptr<flutter::KeyDataPacket> packet,
122 std::function<
void(
bool)>
callback) {}
124 void OnPlatformViewDispatchSemanticsAction(int64_t
view_id,
129 void OnPlatformViewSetSemanticsEnabled(
bool enabled) {
130 semantics_enabled_ = enabled;
133 void OnPlatformViewSetAccessibilityFeatures(int32_t flags) {
134 semantics_features_ = flags;
137 void OnPlatformViewRegisterTexture(
138 std::shared_ptr<flutter::Texture>
texture) {}
140 void OnPlatformViewUnregisterTexture(int64_t
texture_id) {}
142 void OnPlatformViewMarkTextureFrameAvailable(int64_t
texture_id) {}
144 std::unique_ptr<std::vector<std::string>> ComputePlatformViewResolvedLocale(
145 const std::vector<std::string>& supported_locale_data) {
149 void LoadDartDeferredLibrary(
150 intptr_t loading_unit_id,
151 std::unique_ptr<const fml::Mapping> snapshot_data,
152 std::unique_ptr<const fml::Mapping> snapshot_instructions) {}
154 void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
155 const std::string error_message,
158 void UpdateAssetResolverByType(
159 std::unique_ptr<flutter::AssetResolver> updated_asset_resolver,
168 int32_t semantics_features()
const {
return semantics_features_; }
169 bool semantics_enabled()
const {
return semantics_enabled_; }
170 const std::vector<std::unique_ptr<flutter::PointerDataPacket>>&
171 pointer_packets()
const {
172 return pointer_packets_;
174 std::vector<std::unique_ptr<flutter::PointerDataPacket>>
175 TakePointerDataPackets() {
176 auto tmp = std::move(pointer_packets_);
177 pointer_packets_.clear();
182 std::unique_ptr<flutter::Surface>
surface_;
183 std::unique_ptr<flutter::PlatformMessage> message_;
185 std::vector<std::unique_ptr<flutter::PointerDataPacket>> pointer_packets_;
186 int32_t semantics_features_ = 0;
187 bool semantics_enabled_ =
false;
193 MOCK_METHOD(
void, Complete, (std::unique_ptr<fml::Mapping>
data), (
override));
194 MOCK_METHOD(
void, CompleteEmpty, (), (
override));
199 TestPlatformMessageResponse() {}
200 void Complete(std::unique_ptr<fml::Mapping>
data)
override {
202 reinterpret_cast<const char*
>(
data->GetMapping()),
data->GetSize());
205 void CompleteEmpty()
override { is_complete_ =
true; }
210class MockKeyboard :
public fuchsia::ui::input3::testing::Keyboard_TestBase {
212 explicit MockKeyboard(
213 fidl::InterfaceRequest<fuchsia::ui::input3::Keyboard> keyboard)
215 ~MockKeyboard() =
default;
217 void AddListener(fuchsia::ui::views::ViewRef view_ref,
218 fuchsia::ui::input3::KeyboardListenerHandle listener,
219 AddListenerCallback
callback)
override {
223 view_ref_ = std::move(view_ref);
228 void NotImplemented_(
const std::string&
name)
override { FAIL(); }
232 fuchsia::ui::views::ViewRef view_ref_{};
237class MockChildViewWatcher
238 :
public fuchsia::ui::composition::testing::ChildViewWatcher_TestBase {
240 explicit MockChildViewWatcher(
241 fidl::InterfaceRequest<fuchsia::ui::composition::ChildViewWatcher>
244 ~MockChildViewWatcher() =
default;
247 void GetStatus(GetStatusCallback
callback)
override {
249 if (get_status_returned_) {
252 callback(fuchsia::ui::composition::ChildViewStatus::CONTENT_HAS_PRESENTED);
257 void GetViewRef(GetViewRefCallback
callback)
override {
260 fuchsia::ui::views::ViewRefControl view_ref_control;
261 fuchsia::ui::views::ViewRef view_ref;
262 auto status = zx::eventpair::create(
263 0u, &view_ref_control.reference, &view_ref.reference);
264 ZX_ASSERT(status == ZX_OK);
265 view_ref_control.reference.replace(
266 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
267 &view_ref_control.reference);
268 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
273 void NotImplemented_(
const std::string&
name)
override { FAIL(); }
275 fidl::Binding<fuchsia::ui::composition::ChildViewWatcher>
binding_;
282class MockParentViewportWatcher
283 :
public fuchsia::ui::composition::testing::ParentViewportWatcher_TestBase {
285 explicit MockParentViewportWatcher() :
binding_(this,
handle_.NewRequest()) {}
286 ~MockParentViewportWatcher() =
default;
289 void GetStatus(GetStatusCallback
callback)
override {
291 if (get_status_returned_) {
295 fuchsia::ui::composition::ParentViewportStatus::CONNECTED_TO_DISPLAY);
300 void GetLayout(GetLayoutCallback
callback)
override {
301 if (layout_changed_) {
310 void SetLayout(uint32_t logical_size_x,
311 uint32_t logical_size_y,
313 ::fuchsia::math::SizeU logical_size;
314 logical_size.width = logical_size_x;
315 logical_size.height = logical_size_y;
316 layout_.set_logical_size(logical_size);
317 layout_.set_device_pixel_ratio({DPR, DPR});
319 if (pending_callback_valid_) {
327 fuchsia::ui::composition::ParentViewportWatcherHandle GetHandle() {
329 return std::move(handle_);
332 void NotImplemented_(
const std::string&
name)
override { FAIL(); }
334 fuchsia::ui::composition::ParentViewportWatcherHandle
handle_;
335 fidl::Binding<fuchsia::ui::composition::ParentViewportWatcher>
binding_;
352class PlatformViewBuilder {
357 fuchsia::ui::views::ViewRefControl view_ref_control;
358 fuchsia::ui::views::ViewRef view_ref;
359 auto status = zx::eventpair::create(
360 0u, &view_ref_control.reference, &view_ref.reference);
361 ZX_ASSERT(status == ZX_OK);
362 view_ref_control.reference.replace(
363 ZX_DEFAULT_EVENTPAIR_RIGHTS & (~ZX_RIGHT_DUPLICATE),
364 &view_ref_control.reference);
365 view_ref.reference.replace(ZX_RIGHTS_BASIC, &view_ref.reference);
367 std::make_pair(std::move(view_ref_control), std::move(view_ref));
368 view_ref_pair_ = std::move(view_ref_pair);
371 PlatformViewBuilder& SetExternalViewEmbedder(
372 std::shared_ptr<flutter::ExternalViewEmbedder> embedder) {
373 external_external_view_embedder_ = embedder;
377 PlatformViewBuilder& SetImeService(
378 fuchsia::ui::input::ImeServiceHandle ime_service) {
379 ime_service_ = std::move(ime_service);
383 PlatformViewBuilder& SetKeyboard(
384 fuchsia::ui::input3::KeyboardHandle keyboard) {
389 PlatformViewBuilder& SetTouchSource(
390 fuchsia::ui::pointer::TouchSourceHandle touch_source) {
391 touch_source_ = std::move(touch_source);
395 PlatformViewBuilder& SetMouseSource(
396 fuchsia::ui::pointer::MouseSourceHandle mouse_source) {
397 mouse_source_ = std::move(mouse_source);
401 PlatformViewBuilder& SetFocuser(fuchsia::ui::views::FocuserHandle focuser) {
402 focuser_ = std::move(focuser);
406 PlatformViewBuilder& SetViewRefFocused(
407 fuchsia::ui::views::ViewRefFocusedHandle view_ref_focused) {
408 view_ref_focused_ = std::move(view_ref_focused);
412 PlatformViewBuilder& SetPointerInjectorRegistry(
413 fuchsia::ui::pointerinjector::RegistryHandle pointerinjector_registry) {
414 pointerinjector_registry_ = std::move(pointerinjector_registry);
418 PlatformViewBuilder& SetEnableWireframeCallback(
420 wireframe_enabled_callback_ = std::move(
callback);
424 PlatformViewBuilder& SetParentViewportWatcher(
425 fuchsia::ui::composition::ParentViewportWatcherHandle
426 parent_viewport_watcher) {
427 parent_viewport_watcher_ = std::move(parent_viewport_watcher);
432 on_create_view_callback_ = std::move(
callback);
437 on_destroy_view_callback_ = std::move(
callback);
442 on_update_view_callback_ = std::move(
callback);
446 PlatformViewBuilder& SetCreateSurfaceCallback(
448 on_create_surface_callback_ = std::move(
callback);
452 PlatformViewBuilder& SetShaderWarmupCallback(
454 on_shader_warmup_callback_ = std::move(
callback);
459 PlatformView Build() {
460 EXPECT_FALSE(std::exchange(built_,
true))
461 <<
"Build() was already called, this builder is good for one use only.";
463 delegate_, task_runners_, std::move(view_ref_pair_.second),
464 external_external_view_embedder_, std::move(ime_service_),
465 std::move(keyboard_), std::move(touch_source_),
466 std::move(mouse_source_), std::move(focuser_),
467 std::move(view_ref_focused_), std::move(parent_viewport_watcher_),
468 std::move(pointerinjector_registry_),
469 std::move(wireframe_enabled_callback_),
470 std::move(on_create_view_callback_),
471 std::move(on_update_view_callback_),
472 std::move(on_destroy_view_callback_),
473 std::move(on_create_surface_callback_),
474 std::move(on_semantics_node_update_callback_),
475 std::move(on_request_announce_callback_),
476 std::move(on_shader_warmup_callback_), [](
auto...) {}, [](
auto...) {},
481 PlatformViewBuilder() =
delete;
485 std::pair<fuchsia::ui::views::ViewRefControl, fuchsia::ui::views::ViewRef>
488 std::shared_ptr<flutter::ExternalViewEmbedder>
489 external_external_view_embedder_;
490 fuchsia::ui::input::ImeServiceHandle ime_service_;
491 fuchsia::ui::input3::KeyboardHandle
keyboard_;
492 fuchsia::ui::pointer::TouchSourceHandle touch_source_;
493 fuchsia::ui::pointer::MouseSourceHandle mouse_source_;
494 fuchsia::ui::views::ViewRefFocusedHandle view_ref_focused_;
495 fuchsia::ui::views::FocuserHandle focuser_;
496 fuchsia::ui::pointerinjector::RegistryHandle pointerinjector_registry_;
497 fit::closure on_session_listener_error_callback_;
499 fuchsia::ui::composition::ParentViewportWatcherHandle
500 parent_viewport_watcher_;
519 std::unique_ptr<flutter::PointerDataPacket> packet) {
520 for (
size_t i = 0;
i < packet->GetLength();
i++) {
522 output.push_back(pointer_data);
533 async_dispatcher_t*
dispatcher() {
return loop_.dispatcher(); }
536 loop_.RunUntilIdle();
541 loop_.Run(zx::time::infinite(),
true);
547 std::optional<fuchsia::ui::input3::Modifiers> modifiers,
548 fuchsia::input::Key
key) {
549 fuchsia::ui::input3::KeyEvent event;
550 event.set_timestamp(++event_timestamp_);
552 if (modifiers.has_value()) {
553 event.set_modifiers(modifiers.value());
560 fuchsia::ui::composition::ChildViewWatcherPtr ptr;
561 auto watcher = std::make_unique<MockChildViewWatcher>(
562 ptr.NewRequest(loop_.dispatcher()));
563 child_view_watchers_.push_back(std::move(watcher));
570 uint64_t event_timestamp_{42};
572 std::vector<std::unique_ptr<MockChildViewWatcher>> child_view_watchers_;
580 MockPlatformViewDelegate delegate;
585 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
586 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
588 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
589 .SetViewRefFocused(std::move(vrf_handle))
595 EXPECT_TRUE(base_view);
599 base_view->HandlePlatformMessage(response1->WithMessage(
600 "flutter/invalid",
"{\"method\":\"Invalid.invalidMethod\"}"));
604 base_view->HandlePlatformMessage(
605 response2->WithMessage(
"flutter/platform_views",
"{Invalid JSON"));
609 base_view->HandlePlatformMessage(response3->WithMessage(
610 "flutter/platform_views",
"{\"method\":\"View.focus.invalidMethod\"}"));
614 base_view->HandlePlatformMessage(response4->WithMessage(
615 "flutter/platform_views",
"{\"method\":\"View.update\"}"));
617 base_view->HandlePlatformMessage(
618 response5->WithMessage(
"flutter/platform_views",
619 "{\"method\":\"View.update\",\"args\":{"
620 "\"irrelevantField\":\"irrelevantValue\"}}"));
624 base_view->HandlePlatformMessage(response6->WithMessage(
625 "flutter/platform_views",
626 "{\"method\":\"View.update\",\"args\":{\"viewId\":false,\"hitTestable\":"
627 "123,\"focusable\":\"yes\"}}"));
631 response1->ExpectCompleted(
"");
632 response2->ExpectCompleted(
"");
633 response3->ExpectCompleted(
"");
634 response4->ExpectCompleted(
"");
635 response5->ExpectCompleted(
"");
636 response6->ExpectCompleted(
"");
642 MockPlatformViewDelegate delegate;
648 async_get_default_dispatcher()),
654 sk_sp<GrDirectContext> gr_context = GrDirectContext::MakeMock(
657 std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
658 std::make_shared<MockExternalViewEmbedder>();
659 auto CreateSurfaceCallback = [&external_view_embedder, gr_context]() {
660 return std::make_unique<flutter_runner::Surface>(
661 "PlatformViewTest", external_view_embedder, gr_context.get());
664 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
665 .SetCreateSurfaceCallback(CreateSurfaceCallback)
666 .SetExternalViewEmbedder(external_view_embedder)
672 EXPECT_EQ(gr_context.get(), delegate.surface()->GetContext());
673 EXPECT_EQ(external_view_embedder.get(),
681 constexpr float kDPR = 2;
682 constexpr uint32_t
width = 640;
683 constexpr uint32_t
height = 480;
685 MockPlatformViewDelegate delegate;
688 MockParentViewportWatcher watcher;
691 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
692 .SetParentViewportWatcher(watcher.GetHandle())
699 EXPECT_EQ(delegate.metrics(),
701 std::round(
height * kDPR), -1.0, 0));
708 MockPlatformViewDelegate delegate;
712 EXPECT_FALSE(delegate.semantics_enabled());
713 EXPECT_EQ(delegate.semantics_features(), 0);
716 PlatformViewBuilder(delegate, std::move(task_runners)).Build();
722 EXPECT_TRUE(delegate.semantics_enabled());
723 EXPECT_EQ(delegate.semantics_features(),
724 static_cast<int32_t
>(
729 EXPECT_FALSE(delegate.semantics_enabled());
730 EXPECT_EQ(delegate.semantics_features(), 0);
736 MockPlatformViewDelegate delegate;
743 bool wireframe_enabled =
false;
744 auto EnableWireframeCallback = [&wireframe_enabled](
bool should_enable) {
745 wireframe_enabled = should_enable;
748 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
749 .SetEnableWireframeCallback(EnableWireframeCallback)
755 EXPECT_TRUE(base_view);
758 const uint8_t
txt[] =
760 " \"method\":\"View.enableWireframe\","
766 std::unique_ptr<flutter::PlatformMessage>
message =
767 std::make_unique<flutter::PlatformMessage>(
770 base_view->HandlePlatformMessage(std::move(
message));
774 EXPECT_TRUE(wireframe_enabled);
780 MockPlatformViewDelegate delegate;
785 async_get_default_dispatcher()),
794 bool create_view_called =
false;
795 auto CreateViewCallback =
796 [&create_view_called,
this](
800 create_view_called =
true;
802 fuchsia::ui::composition::ContentId content_id;
803 on_view_bound(std::move(content_id), MakeChildViewWatcher());
806 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
807 .SetCreateViewCallback(CreateViewCallback)
813 EXPECT_TRUE(base_view);
816 std::ostringstream create_view_message;
817 create_view_message <<
"{" <<
" \"method\":\"View.create\","
818 <<
" \"args\":{" <<
" \"viewId\":" <<
view_id <<
","
819 <<
" \"hitTestable\":true," <<
" \"focusable\":true"
822 std::string create_view_call = create_view_message.str();
823 std::unique_ptr<flutter::PlatformMessage>
message =
824 std::make_unique<flutter::PlatformMessage>(
825 "flutter/platform_views",
827 create_view_call.size()),
829 base_view->HandlePlatformMessage(std::move(
message));
833 EXPECT_TRUE(create_view_called);
837 std::ostringstream view_connected_expected_out;
838 view_connected_expected_out <<
"{" <<
"\"method\":\"View.viewConnected\","
839 <<
"\"args\":{" <<
" \"viewId\":" <<
view_id
842 ASSERT_NE(delegate.message(),
nullptr);
843 EXPECT_EQ(view_connected_expected_out.str(),
844 ToString(delegate.message()->data()));
850 MockPlatformViewDelegate delegate;
854 std::optional<SkRect> occlusion_hint_for_test;
855 std::optional<bool> hit_testable_for_test;
856 std::optional<bool> focusable_for_test;
857 auto UpdateViewCallback = [&occlusion_hint_for_test, &hit_testable_for_test,
858 &focusable_for_test](
859 int64_t
view_id, SkRect occlusion_hint,
860 bool hit_testable,
bool focusable) {
861 occlusion_hint_for_test = occlusion_hint;
862 hit_testable_for_test = hit_testable;
863 focusable_for_test = focusable;
866 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
867 .SetUpdateViewCallback(UpdateViewCallback)
873 EXPECT_TRUE(base_view);
876 const uint8_t json[] =
878 " \"method\":\"View.update\","
881 " \"hitTestable\":true,"
882 " \"focusable\":true"
885 std::unique_ptr<flutter::PlatformMessage>
message =
886 std::make_unique<flutter::PlatformMessage>(
887 "flutter/platform_views",
890 base_view->HandlePlatformMessage(std::move(
message));
893 ASSERT_TRUE(occlusion_hint_for_test.has_value());
894 ASSERT_TRUE(hit_testable_for_test.has_value());
895 ASSERT_TRUE(focusable_for_test.has_value());
896 EXPECT_EQ(occlusion_hint_for_test.value(), SkRect::MakeEmpty());
897 EXPECT_EQ(hit_testable_for_test.value(),
true);
898 EXPECT_EQ(focusable_for_test.value(),
true);
901 occlusion_hint_for_test.reset();
902 hit_testable_for_test.reset();
903 focusable_for_test.reset();
906 const uint8_t json_false[] =
908 " \"method\":\"View.update\","
911 " \"hitTestable\":false,"
912 " \"focusable\":false"
915 std::unique_ptr<flutter::PlatformMessage> message_false =
916 std::make_unique<flutter::PlatformMessage>(
917 "flutter/platform_views",
920 base_view->HandlePlatformMessage(std::move(message_false));
922 ASSERT_TRUE(occlusion_hint_for_test.has_value());
923 ASSERT_TRUE(hit_testable_for_test.has_value());
924 ASSERT_TRUE(focusable_for_test.has_value());
925 EXPECT_EQ(occlusion_hint_for_test.value(), SkRect::MakeEmpty());
926 EXPECT_EQ(hit_testable_for_test.value(),
false);
927 EXPECT_EQ(focusable_for_test.value(),
false);
930 occlusion_hint_for_test.reset();
931 hit_testable_for_test.reset();
932 focusable_for_test.reset();
935 const uint8_t json_occlusion_hint[] =
937 " \"method\":\"View.update\","
940 " \"hitTestable\":true,"
941 " \"focusable\":true,"
942 " \"viewOcclusionHintLTRB\":[0.1,0.2,0.3,0.4]"
945 std::unique_ptr<flutter::PlatformMessage> message_occlusion_hint =
946 std::make_unique<flutter::PlatformMessage>(
947 "flutter/platform_views",
949 sizeof(json_occlusion_hint)),
951 base_view->HandlePlatformMessage(std::move(message_occlusion_hint));
953 ASSERT_TRUE(occlusion_hint_for_test.has_value());
954 ASSERT_TRUE(hit_testable_for_test.has_value());
955 ASSERT_TRUE(focusable_for_test.has_value());
956 EXPECT_EQ(occlusion_hint_for_test.value(),
957 SkRect::MakeLTRB(0.1, 0.2, 0.3, 0.4));
958 EXPECT_EQ(hit_testable_for_test.value(),
true);
959 EXPECT_EQ(focusable_for_test.value(),
true);
965 MockPlatformViewDelegate delegate;
971 async_get_default_dispatcher()),
977 bool destroy_view_called =
false;
979 auto on_destroy_view = [&destroy_view_called](
982 destroy_view_called =
true;
983 fuchsia::ui::composition::ContentId content_id;
984 on_view_unbound(std::move(content_id));
987 bool create_view_called =
false;
988 auto on_create_view = [&create_view_called,
this](
992 bool hit_testable,
bool focusable) {
993 create_view_called =
true;
995 fuchsia::ui::composition::ContentId content_id;
996 on_view_bound(std::move(content_id), MakeChildViewWatcher());
999 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1000 .SetCreateViewCallback(on_create_view)
1001 .SetDestroyViewCallback(on_destroy_view)
1007 EXPECT_TRUE(base_view);
1009 std::ostringstream create_message;
1010 create_message <<
"{" <<
" \"method\":\"View.create\","
1011 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id <<
","
1012 <<
" \"hitTestable\":true,"
1013 <<
" \"focusable\":true" <<
" }" <<
"}";
1016 base_view->HandlePlatformMessage(create_response->WithMessage(
1017 "flutter/platform_views", create_message.str()));
1023 std::ostringstream dispose_message;
1024 dispose_message <<
"{" <<
" \"method\":\"View.dispose\","
1025 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1028 std::string dispose_view_call = dispose_message.str();
1029 std::unique_ptr<flutter::PlatformMessage>
message =
1030 std::make_unique<flutter::PlatformMessage>(
1031 "flutter/platform_views",
1033 dispose_view_call.size()),
1035 base_view->HandlePlatformMessage(std::move(
message));
1039 EXPECT_TRUE(destroy_view_called);
1043 std::ostringstream view_disconnected_expected_out;
1044 view_disconnected_expected_out
1045 <<
"{" <<
"\"method\":\"View.viewDisconnected\"," <<
"\"args\":{"
1046 <<
" \"viewId\":" <<
view_id <<
" }" <<
"}";
1048 ASSERT_NE(delegate.message(),
nullptr);
1049 EXPECT_EQ(view_disconnected_expected_out.str(),
1050 ToString(delegate.message()->data()));
1057 MockPlatformViewDelegate delegate;
1062 fidl::BindingSet<fuchsia::ui::views::ViewRefFocused> vrf_bindings;
1063 auto vrf_handle = vrf_bindings.AddBinding(&vrf);
1065 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1066 .SetViewRefFocused(std::move(vrf_handle))
1072 EXPECT_TRUE(base_view);
1074 std::vector<bool> vrf_states{
false,
true,
true,
false,
1075 true,
false,
true,
true};
1077 for (std::size_t
i = 0;
i < vrf_states.size(); ++
i) {
1080 base_view->HandlePlatformMessage(response1->WithMessage(
1081 "flutter/platform_views",
"{\"method\":\"View.focus.getNext\"}"));
1084 base_view->HandlePlatformMessage(response2->WithMessage(
1085 "flutter/platform_views",
"{\"method\":\"View.focus.getNext\"}"));
1097 base_view->HandlePlatformMessage(response3->WithMessage(
1098 "flutter/platform_views",
"{\"method\":\"View.focus.getCurrent\"}"));
1101 base_view->HandlePlatformMessage(response4->WithMessage(
1102 "flutter/platform_views",
"{\"method\":\"View.focus.getCurrent\"}"));
1106 response1->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1107 response2->ExpectCompleted(
"[null]");
1108 response3->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1109 response4->ExpectCompleted(vrf_states[
i] ?
"[true]" :
"[false]");
1116 MockPlatformViewDelegate delegate;
1120 async_get_default_dispatcher()),
1127 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1128 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1130 bool create_view_called =
false;
1131 auto on_create_view = [&create_view_called,
this](
1135 bool hit_testable,
bool focusable) {
1136 create_view_called =
true;
1138 fuchsia::ui::composition::ContentId content_id;
1139 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1142 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1143 .SetFocuser(std::move(focuser_handle))
1144 .SetCreateViewCallback(on_create_view)
1150 EXPECT_TRUE(base_view);
1154 std::ostringstream create_message;
1155 create_message <<
"{" <<
" \"method\":\"View.create\","
1156 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id <<
","
1157 <<
" \"hitTestable\":true,"
1158 <<
" \"focusable\":true" <<
" }" <<
"}";
1162 base_view->HandlePlatformMessage(create_response->WithMessage(
1163 "flutter/platform_views", create_message.str()));
1168 std::ostringstream focus_message;
1169 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1170 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1175 base_view->HandlePlatformMessage(focus_response->WithMessage(
1176 "flutter/platform_views", focus_message.str()));
1179 focus_response->ExpectCompleted(
"[0]");
1185 MockPlatformViewDelegate delegate;
1189 async_get_default_dispatcher()),
1196 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1197 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1199 bool create_view_called =
false;
1200 auto on_create_view = [&create_view_called,
this](
1204 bool hit_testable,
bool focusable) {
1205 create_view_called =
true;
1207 fuchsia::ui::composition::ContentId content_id;
1208 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1211 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1212 .SetFocuser(std::move(focuser_handle))
1213 .SetCreateViewCallback(on_create_view)
1217 EXPECT_TRUE(base_view);
1221 std::ostringstream focus_message;
1222 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1223 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1228 base_view->HandlePlatformMessage(focus_response->WithMessage(
1229 "flutter/platform_views", focus_message.str()));
1232 focus_response->ExpectCompleted(
"[1]");
1237 MockPlatformViewDelegate delegate;
1241 async_get_default_dispatcher()),
1248 fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
1249 auto focuser_handle = focuser_bindings.AddBinding(&focuser);
1251 bool create_view_called =
false;
1252 auto on_create_view = [&create_view_called,
this](
1256 bool hit_testable,
bool focusable) {
1257 create_view_called =
true;
1259 fuchsia::ui::composition::ContentId content_id;
1260 on_view_bound(std::move(content_id), MakeChildViewWatcher());
1263 bool destroy_view_called =
false;
1265 auto on_destroy_view = [&destroy_view_called](
1268 destroy_view_called =
true;
1269 fuchsia::ui::composition::ContentId content_id;
1270 on_view_unbound(std::move(content_id));
1273 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1274 .SetFocuser(std::move(focuser_handle))
1275 .SetCreateViewCallback(on_create_view)
1276 .SetDestroyViewCallback(on_destroy_view)
1280 EXPECT_TRUE(base_view);
1285 std::ostringstream create_message;
1286 create_message <<
"{" <<
" \"method\":\"View.create\","
1287 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id <<
","
1288 <<
" \"hitTestable\":true,"
1289 <<
" \"focusable\":true" <<
" }" <<
"}";
1292 base_view->HandlePlatformMessage(create_response->WithMessage(
1293 "flutter/platform_views", create_message.str()));
1296 EXPECT_FALSE(destroy_view_called);
1298 std::ostringstream dispose_message;
1299 dispose_message <<
"{" <<
" \"method\":\"View.dispose\","
1300 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1304 base_view->HandlePlatformMessage(dispose_response->WithMessage(
1305 "flutter/platform_views", dispose_message.str()));
1307 EXPECT_TRUE(destroy_view_called);
1310 std::ostringstream focus_message;
1311 focus_message <<
"{" <<
" \"method\":\"View.focus.requestById\","
1312 <<
" \"args\": {" <<
" \"viewId\":" <<
view_id
1316 base_view->HandlePlatformMessage(focus_response->WithMessage(
1317 "flutter/platform_views", focus_message.str()));
1321 focus_response->ExpectCompleted(
"[1]");
1328 fuchsia::ui::input3::KeyEvent event;
1329 fuchsia::ui::input3::KeyEventStatus expected_key_event_status;
1330 std::string expected_platform_message;
1333 MockPlatformViewDelegate delegate;
1337 fuchsia::ui::input3::KeyboardHandle keyboard_service;
1338 MockKeyboard keyboard(keyboard_service.NewRequest());
1340 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1341 .SetKeyboard(std::move(keyboard_service))
1345 std::vector<EventFlow> events;
1348 events.emplace_back(EventFlow{
1349 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1350 fuchsia::input::Key::A),
1351 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1352 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1355 events.emplace_back(EventFlow{
1356 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED, std::nullopt,
1357 fuchsia::input::Key::A),
1358 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1359 R
"({"type":"keyup","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
1362 events.emplace_back(EventFlow{
1363 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED,
1364 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1365 fuchsia::input::Key::CAPS_LOCK),
1366 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1367 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1370 events.emplace_back(EventFlow{
1371 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1372 fuchsia::input::Key::A),
1373 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1374 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1377 events.emplace_back(EventFlow{
1378 MakeEvent(fuchsia::ui::input3::KeyEventType::RELEASED,
1379 fuchsia::ui::input3::Modifiers::CAPS_LOCK,
1380 fuchsia::input::Key::CAPS_LOCK),
1381 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1382 R
"({"type":"keyup","keymap":"fuchsia","hidUsage":458809,"codePoint":0,"modifiers":1})",
1386 events.emplace_back(EventFlow{
1387 MakeEvent(fuchsia::ui::input3::KeyEventType::PRESSED, std::nullopt,
1388 fuchsia::input::Key::A),
1389 fuchsia::ui::input3::KeyEventStatus::HANDLED,
1390 R
"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":65,"modifiers":1})",
1393 for (
const auto& event : events) {
1394 fuchsia::ui::input3::KeyEvent e;
1395 event.event.Clone(&e);
1396 fuchsia::ui::input3::KeyEventStatus key_event_status{0u};
1397 keyboard.listener_->OnKeyEvent(
1399 [&key_event_status](fuchsia::ui::input3::KeyEventStatus status) {
1400 key_event_status = status;
1404 ASSERT_NOTNULL(delegate.message());
1405 EXPECT_EQ(event.expected_platform_message,
1406 ToString(delegate.message()->data()));
1407 EXPECT_EQ(event.expected_key_event_status, key_event_status);
1412 MockPlatformViewDelegate delegate;
1416 uint64_t
width = 200;
1418 std::vector<std::string> shaders = {
"foo.skp",
"bar.skp",
"baz.skp"};
1421 [&](
const std::vector<std::string>& shaders_in,
1422 std::function<void(uint32_t)> completion_callback, uint64_t width_in,
1423 uint64_t height_in) {
1424 ASSERT_EQ(shaders.size(), shaders_in.size());
1425 for (
size_t i = 0;
i < shaders_in.size();
i++) {
1426 ASSERT_EQ(shaders[
i], shaders_in[
i]);
1428 ASSERT_EQ(
width, width_in);
1429 ASSERT_EQ(
height, height_in);
1431 completion_callback(shaders_in.size());
1434 auto platform_view = PlatformViewBuilder(delegate, std::move(task_runners))
1435 .SetShaderWarmupCallback(on_shader_warmup_callback)
1438 std::ostringstream shaders_array_ostream;
1439 shaders_array_ostream <<
"[ ";
1440 for (
auto it = shaders.begin(); it != shaders.end(); ++it) {
1441 shaders_array_ostream <<
"\"" << *it <<
"\"";
1442 if (std::next(it) != shaders.end()) {
1443 shaders_array_ostream <<
", ";
1446 shaders_array_ostream <<
"]";
1448 std::string shaders_array_string = shaders_array_ostream.str();
1451 std::ostringstream warmup_shaders_ostream;
1452 warmup_shaders_ostream <<
"{" <<
" \"method\":\"WarmupSkps\","
1454 <<
" \"shaders\":" << shaders_array_string <<
","
1455 <<
" \"width\":" <<
width <<
","
1456 <<
" \"height\":" <<
height <<
" }" <<
"}\n";
1457 std::string warmup_shaders_string = warmup_shaders_ostream.str();
1460 new TestPlatformMessageResponse);
1462 ->HandlePlatformMessage(std::make_unique<flutter::PlatformMessage>(
1463 "fuchsia/shader_warmup",
1465 warmup_shaders_string.size()),
1468 ASSERT_TRUE(response->is_complete());
1470 std::ostringstream expected_result_ostream;
1471 expected_result_ostream <<
"[" << shaders.size() <<
"]";
1472 std::string expected_result_string = expected_result_ostream.str();
1473 EXPECT_EQ(expected_result_string, response->result_string);
1477 constexpr uint32_t
width = 640;
1478 constexpr uint32_t
height = 480;
1479 constexpr std::array<std::array<float, 2>, 2>
kRect = {
1481 constexpr std::array<float, 9>
kIdentity = {1, 0, 0, 0, 1, 0, 0, 0, 1};
1482 constexpr fuchsia::ui::pointer::TouchInteractionId
kIxnOne = {
1483 .device_id = 0u, .pointer_id = 1u, .interaction_id = 2u};
1485 MockPlatformViewDelegate delegate;
1489 MockParentViewportWatcher viewport_watcher;
1491 fidl::BindingSet<fuchsia::ui::pointer::TouchSource> touch_bindings;
1492 auto touch_handle = touch_bindings.AddBinding(&touch_server);
1494 PlatformViewBuilder(delegate, std::move(task_runners))
1495 .SetParentViewportWatcher(viewport_watcher.GetHandle())
1496 .SetTouchSource(std::move(touch_handle))
1499 EXPECT_EQ(delegate.pointer_packets().size(), 0u);
1503 EXPECT_EQ(delegate.metrics(),
1507 std::vector<fuchsia::ui::pointer::TouchEvent> events =
1515 .status = fuchsia::ui::pointer::TouchInteractionStatus::GRANTED})
1521 std::vector<std::unique_ptr<flutter::PointerDataPacket>> packets =
1522 delegate.TakePointerDataPackets();
1523 ASSERT_EQ(packets.size(), 1u);
1524 std::vector<flutter::PointerData> flutter_events;
1525 UnpackPointerPacket(flutter_events, std::move(packets[0]));
1528 ASSERT_EQ(flutter_events.size(), 2u);
1533 EXPECT_EQ(flutter_events[0].physical_x,
width / 2);
1534 EXPECT_EQ(flutter_events[0].physical_y,
height / 2);
1535 EXPECT_EQ(flutter_events[1].physical_x,
width / 2);
1536 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 GBytes * message
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.
std::function< void()> closure
const char * ToString(ax::mojom::Event event)
std::shared_ptr< const fml::Mapping > data