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