7#include <UIAutomation.h>
32#include "gmock/gmock.h"
33#include "gtest/gtest.h"
39using ::testing::InSequence;
40using ::testing::NiceMock;
41using ::testing::Return;
52struct TestResponseHandle {
57static bool test_response =
false;
59constexpr uint64_t kKeyEventFromChannel = 0x11;
60constexpr uint64_t kKeyEventFromEmbedder = 0x22;
61static std::vector<int> key_event_logs;
63std::unique_ptr<std::vector<uint8_t>> keyHandlingResponse(
bool handled) {
64 rapidjson::Document document;
65 auto&
allocator = document.GetAllocator();
67 document.AddMember(
"handled", test_response,
allocator);
73FlutterProjectBundle GetTestProject() {
75 properties.
assets_path = L
"C:\\foo\\flutter_assets";
80 return FlutterProjectBundle{properties};
83class ViewTestEGLManager :
public egl::MockManager {
85 ViewTestEGLManager() {
86 ON_CALL(*
this, CreateWindowSurface).WillByDefault([](HWND,
size_t,
size_t) {
87 auto surface = std::make_unique<NiceMock<egl::MockWindowSurface>>();
88 ON_CALL(*surface, IsValid).WillByDefault(Return(
true));
89 ON_CALL(*surface, MakeCurrent).WillByDefault(Return(
true));
90 ON_CALL(*surface, SetVSyncEnabled).WillByDefault(Return(
true));
91 ON_CALL(*surface, Destroy).WillByDefault(Return(
true));
94 ON_CALL(*
this, render_context).WillByDefault(Return(&mock_context_));
95 ON_CALL(*
this, resource_context).WillByDefault(Return(&mock_context_));
96 ON_CALL(mock_context_, ClearCurrent).WillByDefault(Return(
true));
97 ON_CALL(mock_context_, MakeCurrent).WillByDefault(Return(
true));
101 NiceMock<egl::MockContext> mock_context_;
107std::unique_ptr<FlutterWindowsEngine> GetTestEngine(
108 std::shared_ptr<WindowsProcTable> windows_proc_table =
nullptr) {
109 auto engine = std::make_unique<FlutterWindowsEngine>(
110 GetTestProject(), std::move(windows_proc_table));
112 EngineModifier modifier(
engine.get());
113 modifier.SetEGLManager(std::make_unique<NiceMock<ViewTestEGLManager>>());
130 size_t locales_count) {
return kSuccess; }));
133 UpdateAccessibilityFeatures,
143 auto key_response_controller = std::make_shared<MockKeyResponseController>();
144 key_response_controller->SetChannelResponse(
146 key_event_logs.push_back(kKeyEventFromChannel);
149 key_response_controller->SetEmbedderResponse(
152 key_event_logs.push_back(kKeyEventFromEmbedder);
155 modifier.embedder_api().NotifyDisplayUpdate =
157 ([engine_instance =
engine.get()](
161 size_t display_count) {
return kSuccess; }));
169class MockFlutterWindowsEngine :
public FlutterWindowsEngine {
171 explicit MockFlutterWindowsEngine(
172 std::shared_ptr<WindowsProcTable> windows_proc_table =
nullptr)
173 : FlutterWindowsEngine(GetTestProject(),
std::move(windows_proc_table)) {}
175 MOCK_METHOD(
bool, running, (), (
const));
176 MOCK_METHOD(
bool, Stop, (), ());
178 MOCK_METHOD(
bool, PostRasterThreadTask, (
fml::closure), (
const));
188TEST(FlutterWindowsViewTest, SubMenuExpandedState) {
189 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
196 auto window_binding_handler =
197 std::make_unique<NiceMock<MockWindowBindingHandler>>();
198 std::unique_ptr<FlutterWindowsView>
view =
199 engine->CreateView(std::move(window_binding_handler),
203 view->OnUpdateSemanticsEnabled(
true);
205 auto bridge =
view->accessibility_bridge().lock();
213 root.increased_value =
"";
214 root.decreased_value =
"";
215 root.child_count = 0;
216 root.custom_accessibility_actions_count = 0;
220 root.flags2 = &flags;
222 bridge->AddFlutterSemanticsNodeUpdate(root);
224 bridge->CommitUpdates();
227 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
231 IAccessible* native_view = root_node->GetNativeViewAccessible();
232 ASSERT_TRUE(native_view !=
nullptr);
235 VARIANT varchild = {};
239 varchild.lVal = CHILDID_SELF;
240 VARIANT native_state = {};
241 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
242 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_EXPANDED);
245 IRawElementProviderSimple* uia_node;
246 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
247 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
248 UIA_ExpandCollapseExpandCollapseStatePropertyId, &native_state)));
249 EXPECT_EQ(native_state.lVal, ExpandCollapseState_Expanded);
251 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
252 UIA_AriaPropertiesPropertyId, &native_state)));
253 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"expanded=true"),
nullptr);
260 root.flags2 = &updated_flags;
262 bridge->AddFlutterSemanticsNodeUpdate(root);
263 bridge->CommitUpdates();
266 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
270 IAccessible* native_view = root_node->GetNativeViewAccessible();
271 ASSERT_TRUE(native_view !=
nullptr);
274 VARIANT varchild = {};
278 varchild.lVal = CHILDID_SELF;
279 VARIANT native_state = {};
280 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
281 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_COLLAPSED);
284 IRawElementProviderSimple* uia_node;
285 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
286 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
287 UIA_ExpandCollapseExpandCollapseStatePropertyId, &native_state)));
288 EXPECT_EQ(native_state.lVal, ExpandCollapseState_Collapsed);
290 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
291 UIA_AriaPropertiesPropertyId, &native_state)));
292 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"expanded=false"),
nullptr);
298TEST(FlutterWindowsViewTest, Shutdown) {
299 auto engine = std::make_unique<MockFlutterWindowsEngine>();
300 auto window_binding_handler =
301 std::make_unique<NiceMock<MockWindowBindingHandler>>();
302 auto egl_manager = std::make_unique<egl::MockManager>();
303 auto surface = std::make_unique<egl::MockWindowSurface>();
306 auto engine_ptr =
engine.get();
307 auto surface_ptr =
surface.get();
308 auto egl_manager_ptr = egl_manager.get();
311 modifier.SetEGLManager(std::move(egl_manager));
314 std::unique_ptr<FlutterWindowsView>
view;
318 EXPECT_CALL(*egl_manager_ptr, CreateWindowSurface)
319 .WillOnce(Return(std::move(
surface)));
320 EXPECT_CALL(*engine_ptr, running).WillOnce(Return(
false));
321 EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(
true));
322 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
323 EXPECT_CALL(*surface_ptr, SetVSyncEnabled).WillOnce(Return(
true));
324 EXPECT_CALL(*egl_manager_ptr, render_context)
325 .WillOnce(Return(&render_context));
326 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
328 view =
engine->CreateView(std::move(window_binding_handler),
false,
337 EXPECT_CALL(*engine_ptr, running).WillOnce(Return(
true));
338 EXPECT_CALL(*engine_ptr, RemoveView(
view_id)).Times(1);
339 EXPECT_CALL(*engine_ptr, running).WillOnce(Return(
true));
340 EXPECT_CALL(*engine_ptr, PostRasterThreadTask)
345 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
349TEST(FlutterWindowsViewTest, KeySequence) {
350 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
352 test_response =
false;
354 std::unique_ptr<FlutterWindowsView>
view =
355 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
359 [](
bool handled) {});
361 EXPECT_EQ(key_event_logs.size(), 2);
362 EXPECT_EQ(key_event_logs[0], kKeyEventFromEmbedder);
363 EXPECT_EQ(key_event_logs[1], kKeyEventFromChannel);
365 key_event_logs.clear();
368TEST(FlutterWindowsViewTest, KeyEventCallback) {
369 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
371 std::unique_ptr<FlutterWindowsView>
view =
372 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
377 MOCK_METHOD(
void, Call, ());
380 NiceMock<MockCallback> callback_with_valid_view;
381 NiceMock<MockCallback> callback_with_invalid_view;
383 auto trigger_key_event = [&](NiceMock<MockCallback>&
callback) {
388 EXPECT_CALL(callback_with_valid_view, Call()).Times(1);
389 EXPECT_CALL(callback_with_invalid_view, Call()).Times(0);
391 trigger_key_event(callback_with_valid_view);
393 trigger_key_event(callback_with_invalid_view);
395 key_event_logs.clear();
398TEST(FlutterWindowsViewTest, EnableSemantics) {
399 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
402 bool semantics_enabled =
false;
404 UpdateSemanticsEnabled,
407 semantics_enabled = enabled;
411 auto window_binding_handler =
412 std::make_unique<NiceMock<MockWindowBindingHandler>>();
413 std::unique_ptr<FlutterWindowsView>
view =
414 engine->CreateView(std::move(window_binding_handler),
417 view->OnUpdateSemanticsEnabled(
true);
418 EXPECT_TRUE(semantics_enabled);
421TEST(FlutterWindowsViewTest, AddSemanticsNodeUpdate) {
422 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
429 auto window_binding_handler =
430 std::make_unique<NiceMock<MockWindowBindingHandler>>();
431 std::unique_ptr<FlutterWindowsView>
view =
432 engine->CreateView(std::move(window_binding_handler),
436 view->OnUpdateSemanticsEnabled(
true);
438 auto bridge =
view->accessibility_bridge().lock();
444 node.value =
"value";
445 node.platform_view_id = -1;
447 node.flags2 = &flags;
448 bridge->AddFlutterSemanticsNodeUpdate(node);
449 bridge->CommitUpdates();
452 auto node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
458 ASSERT_TRUE(native_view !=
nullptr);
463 varchild.lVal = CHILDID_SELF;
466 BSTR bname =
nullptr;
467 ASSERT_EQ(native_view->get_accName(varchild, &bname), S_OK);
468 std::string
name(_com_util::ConvertBSTRToString(bname));
469 EXPECT_EQ(
name,
"name");
472 BSTR bvalue =
nullptr;
473 ASSERT_EQ(native_view->get_accValue(varchild, &bvalue), S_OK);
474 std::string
value(_com_util::ConvertBSTRToString(bvalue));
475 EXPECT_EQ(
value,
"value");
480 ASSERT_EQ(native_view->get_accRole(varchild, &varrole), S_OK);
481 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_STATICTEXT);
484 IRawElementProviderSimple* uia_view;
485 native_view->QueryInterface(IID_PPV_ARGS(&uia_view));
486 ASSERT_TRUE(uia_view !=
nullptr);
490 ASSERT_EQ(uia_view->GetPropertyValue(UIA_NamePropertyId, &varname), S_OK);
491 EXPECT_EQ(varname.vt, VT_BSTR);
492 name = _com_util::ConvertBSTRToString(varname.bstrVal);
493 EXPECT_EQ(
name,
"name");
497 ASSERT_EQ(uia_view->GetPropertyValue(UIA_ValueValuePropertyId, &varvalue),
499 EXPECT_EQ(varvalue.vt, VT_BSTR);
500 value = _com_util::ConvertBSTRToString(varvalue.bstrVal);
501 EXPECT_EQ(
value,
"value");
505 ASSERT_EQ(uia_view->GetPropertyValue(UIA_ControlTypePropertyId, &varrole),
507 EXPECT_EQ(varrole.vt, VT_I4);
508 EXPECT_EQ(varrole.lVal, UIA_TextControlTypeId);
523TEST(FlutterWindowsViewTest, AddSemanticsNodeUpdateWithChildren) {
524 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
531 std::unique_ptr<FlutterWindowsView>
view =
532 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
536 view->OnUpdateSemanticsEnabled(
true);
538 auto bridge =
view->accessibility_bridge().lock();
543 std::vector<int32_t> node0_children{1, 2};
545 node0.children_in_traversal_order = node0_children.data();
546 node0.children_in_hit_test_order = node0_children.data();
548 node0.flags2 = &empty_flags;
551 node1.
label =
"prefecture";
552 node1.value =
"Kyoto";
553 node1.flags2 = &empty_flags;
555 std::vector<int32_t> node2_children{3};
557 node2.children_in_traversal_order = node2_children.data();
558 node2.children_in_hit_test_order = node2_children.data();
559 node2.flags2 = &empty_flags;
561 node3.
label =
"city";
563 node3.flags2 = &empty_flags;
565 bridge->AddFlutterSemanticsNodeUpdate(node0);
566 bridge->AddFlutterSemanticsNodeUpdate(node1);
567 bridge->AddFlutterSemanticsNodeUpdate(node2);
568 bridge->AddFlutterSemanticsNodeUpdate(node3);
569 bridge->CommitUpdates();
572 auto node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
578 ASSERT_TRUE(node0_accessible !=
nullptr);
583 varchild.lVal = CHILDID_SELF;
588 ASSERT_EQ(node0_accessible->get_accRole(varchild, &varrole), S_OK);
589 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_GROUPING);
592 long node0_child_count = 0;
593 ASSERT_EQ(node0_accessible->get_accChildCount(&node0_child_count), S_OK);
594 EXPECT_EQ(node0_child_count, 2);
599 IDispatch* node1_dispatch =
nullptr;
600 ASSERT_EQ(node0_accessible->get_accChild(varchild, &node1_dispatch), S_OK);
601 ASSERT_TRUE(node1_dispatch !=
nullptr);
603 ASSERT_EQ(node1_dispatch->QueryInterface(
604 IID_IAccessible,
reinterpret_cast<void**
>(&node1_accessible)),
606 ASSERT_TRUE(node1_accessible !=
nullptr);
609 varchild.lVal = CHILDID_SELF;
610 BSTR bname =
nullptr;
611 ASSERT_EQ(node1_accessible->get_accName(varchild, &bname), S_OK);
612 std::string
name(_com_util::ConvertBSTRToString(bname));
613 EXPECT_EQ(
name,
"prefecture");
616 BSTR bvalue =
nullptr;
617 ASSERT_EQ(node1_accessible->get_accValue(varchild, &bvalue), S_OK);
618 std::string
value(_com_util::ConvertBSTRToString(bvalue));
619 EXPECT_EQ(
value,
"Kyoto");
624 ASSERT_EQ(node1_accessible->get_accRole(varchild, &varrole), S_OK);
625 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_STATICTEXT);
628 IDispatch* parent_dispatch;
629 node1_accessible->get_accParent(&parent_dispatch);
632 parent_dispatch->QueryInterface(
633 IID_IAccessible,
reinterpret_cast<void**
>(&parent_accessible)),
635 EXPECT_EQ(parent_accessible, node0_accessible);
640 IDispatch* node2_dispatch =
nullptr;
641 ASSERT_EQ(node0_accessible->get_accChild(varchild, &node2_dispatch), S_OK);
642 ASSERT_TRUE(node2_dispatch !=
nullptr);
644 ASSERT_EQ(node2_dispatch->QueryInterface(
645 IID_IAccessible,
reinterpret_cast<void**
>(&node2_accessible)),
647 ASSERT_TRUE(node2_accessible !=
nullptr);
651 long node2_child_count = 0;
652 ASSERT_EQ(node2_accessible->get_accChildCount(&node2_child_count), S_OK);
653 EXPECT_EQ(node2_child_count, 1);
656 varchild.lVal = CHILDID_SELF;
659 ASSERT_EQ(node2_accessible->get_accRole(varchild, &varrole), S_OK);
660 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_GROUPING);
663 IDispatch* parent_dispatch;
664 node2_accessible->get_accParent(&parent_dispatch);
667 parent_dispatch->QueryInterface(
668 IID_IAccessible,
reinterpret_cast<void**
>(&parent_accessible)),
670 EXPECT_EQ(parent_accessible, node0_accessible);
676 IDispatch* node3_dispatch =
nullptr;
677 ASSERT_EQ(node2_accessible->get_accChild(varchild, &node3_dispatch), S_OK);
678 ASSERT_TRUE(node3_dispatch !=
nullptr);
680 ASSERT_EQ(node3_dispatch->QueryInterface(
681 IID_IAccessible,
reinterpret_cast<void**
>(&node3_accessible)),
683 ASSERT_TRUE(node3_accessible !=
nullptr);
686 varchild.lVal = CHILDID_SELF;
687 BSTR bname =
nullptr;
688 ASSERT_EQ(node3_accessible->get_accName(varchild, &bname), S_OK);
689 std::string
name(_com_util::ConvertBSTRToString(bname));
690 EXPECT_EQ(
name,
"city");
693 BSTR bvalue =
nullptr;
694 ASSERT_EQ(node3_accessible->get_accValue(varchild, &bvalue), S_OK);
695 std::string
value(_com_util::ConvertBSTRToString(bvalue));
696 EXPECT_EQ(
value,
"Uji");
701 ASSERT_EQ(node3_accessible->get_accRole(varchild, &varrole), S_OK);
702 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_STATICTEXT);
705 IDispatch* parent_dispatch;
706 node3_accessible->get_accParent(&parent_dispatch);
709 parent_dispatch->QueryInterface(
710 IID_IAccessible,
reinterpret_cast<void**
>(&parent_accessible)),
712 EXPECT_EQ(parent_accessible, node2_accessible);
725TEST(FlutterWindowsViewTest, NonZeroSemanticsRoot) {
726 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
733 std::unique_ptr<FlutterWindowsView>
view =
734 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
738 view->OnUpdateSemanticsEnabled(
true);
740 auto bridge =
view->accessibility_bridge().lock();
745 std::vector<int32_t> node1_children{2};
747 node1.children_in_traversal_order = node1_children.data();
748 node1.children_in_hit_test_order = node1_children.data();
750 node1.flags2 = &empty_flags;
753 node2.
label =
"prefecture";
754 node2.value =
"Kyoto";
755 node2.flags2 = &empty_flags;
756 bridge->AddFlutterSemanticsNodeUpdate(node1);
757 bridge->AddFlutterSemanticsNodeUpdate(node2);
758 bridge->CommitUpdates();
761 auto root_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
762 ASSERT_TRUE(root_delegate);
763 EXPECT_EQ(root_delegate->GetChildCount(), 1);
766 auto child_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(2).lock();
767 ASSERT_TRUE(child_delegate);
768 EXPECT_EQ(child_delegate->GetChildCount(), 0);
771 auto fake_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
775 IAccessible* node1_accessible = root_delegate->GetNativeViewAccessible();
776 ASSERT_TRUE(node1_accessible !=
nullptr);
781 varchild.lVal = CHILDID_SELF;
786 ASSERT_EQ(node1_accessible->get_accRole(varchild, &varrole), S_OK);
787 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_GROUPING);
790 long node1_child_count = 0;
791 ASSERT_EQ(node1_accessible->get_accChildCount(&node1_child_count), S_OK);
792 EXPECT_EQ(node1_child_count, 1);
797 IDispatch* node2_dispatch =
nullptr;
798 ASSERT_EQ(node1_accessible->get_accChild(varchild, &node2_dispatch), S_OK);
799 ASSERT_TRUE(node2_dispatch !=
nullptr);
801 ASSERT_EQ(node2_dispatch->QueryInterface(
802 IID_IAccessible,
reinterpret_cast<void**
>(&node2_accessible)),
804 ASSERT_TRUE(node2_accessible !=
nullptr);
807 varchild.lVal = CHILDID_SELF;
808 BSTR bname =
nullptr;
809 ASSERT_EQ(node2_accessible->get_accName(varchild, &bname), S_OK);
810 std::string
name(_com_util::ConvertBSTRToString(bname));
811 EXPECT_EQ(
name,
"prefecture");
814 BSTR bvalue =
nullptr;
815 ASSERT_EQ(node2_accessible->get_accValue(varchild, &bvalue), S_OK);
816 std::string
value(_com_util::ConvertBSTRToString(bvalue));
817 EXPECT_EQ(
value,
"Kyoto");
822 ASSERT_EQ(node2_accessible->get_accRole(varchild, &varrole), S_OK);
823 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_STATICTEXT);
826 IDispatch* parent_dispatch;
827 node2_accessible->get_accParent(&parent_dispatch);
830 parent_dispatch->QueryInterface(
831 IID_IAccessible,
reinterpret_cast<void**
>(&parent_accessible)),
833 EXPECT_EQ(parent_accessible, node1_accessible);
854TEST(FlutterWindowsViewTest, AccessibilityHitTesting) {
859 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
866 std::unique_ptr<FlutterWindowsView>
view =
867 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
871 view->OnUpdateSemanticsEnabled(
true);
873 auto bridge =
view->accessibility_bridge().lock();
879 std::vector<int32_t> node0_children{1, 2};
880 node0.rect = {0, 0, 500, 500};
881 node0.transform = kIdentityTransform;
882 node0.child_count = node0_children.size();
883 node0.children_in_traversal_order = node0_children.data();
884 node0.children_in_hit_test_order = node0_children.data();
885 node0.flags2 = &empty_flags;
889 node1.
rect = {0, 0, 250, 500};
890 node1.transform = kIdentityTransform;
891 node1.label =
"prefecture";
892 node1.value =
"Kyoto";
893 node1.flags2 = &empty_flags;
897 std::vector<int32_t> node2_children{3};
898 node2.
rect = {0, 0, 250, 500};
899 node2.transform = {1, 0, 250, 0, 1, 0, 0, 0, 1};
900 node2.child_count = node2_children.size();
901 node2.children_in_traversal_order = node2_children.data();
902 node2.children_in_hit_test_order = node2_children.data();
903 node2.flags2 = &empty_flags;
907 node3.
rect = {0, 0, 250, 250};
908 node3.transform = {1, 0, 0, 0, 1, 250, 0, 0, 1};
909 node3.label =
"city";
911 node3.flags2 = &empty_flags;
913 bridge->AddFlutterSemanticsNodeUpdate(node0);
914 bridge->AddFlutterSemanticsNodeUpdate(node1);
915 bridge->AddFlutterSemanticsNodeUpdate(node2);
916 bridge->AddFlutterSemanticsNodeUpdate(node3);
917 bridge->CommitUpdates();
920 auto node0_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
921 ASSERT_TRUE(node0_delegate);
922 auto node1_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
923 ASSERT_TRUE(node1_delegate);
924 auto node2_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(2).lock();
925 ASSERT_TRUE(node2_delegate);
926 auto node3_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(3).lock();
927 ASSERT_TRUE(node3_delegate);
930 IAccessible* node0_accessible = node0_delegate->GetNativeViewAccessible();
931 ASSERT_TRUE(node0_accessible !=
nullptr);
935 ASSERT_TRUE(
SUCCEEDED(node0_accessible->accHitTest(150, 150, &varchild)));
936 EXPECT_EQ(varchild.vt, VT_DISPATCH);
937 EXPECT_EQ(varchild.pdispVal, node1_delegate->GetNativeViewAccessible());
941 ASSERT_TRUE(
SUCCEEDED(node0_accessible->accHitTest(450, 150, &varchild)));
942 EXPECT_EQ(varchild.vt, VT_DISPATCH);
943 EXPECT_EQ(varchild.pdispVal, node2_delegate->GetNativeViewAccessible());
947 ASSERT_TRUE(
SUCCEEDED(node0_accessible->accHitTest(450, 450, &varchild)));
948 EXPECT_EQ(varchild.vt, VT_DISPATCH);
949 EXPECT_EQ(varchild.pdispVal, node3_delegate->GetNativeViewAccessible());
952TEST(FlutterWindowsViewTest, WindowResizeTests) {
953 auto windows_proc_table = std::make_shared<NiceMock<MockWindowsProcTable>>();
954 std::unique_ptr<FlutterWindowsEngine>
engine =
955 GetTestEngine(windows_proc_table);
959 PostRenderThreadTask,
965 auto egl_manager = std::make_unique<egl::MockManager>();
966 auto surface = std::make_unique<egl::MockWindowSurface>();
967 auto resized_surface = std::make_unique<egl::MockWindowSurface>();
970 auto surface_ptr =
surface.get();
971 auto resized_surface_ptr = resized_surface.get();
974 EXPECT_CALL(*egl_manager, CreateWindowSurface)
975 .WillOnce(Return(std::move(
surface)));
976 EXPECT_CALL(*surface_ptr, IsValid).WillRepeatedly(Return(
true));
977 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
978 EXPECT_CALL(*surface_ptr, SetVSyncEnabled).WillOnce(Return(
true));
979 EXPECT_CALL(*egl_manager, render_context).WillOnce(Return(&render_context));
980 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
983 EXPECT_CALL(*surface_ptr, Destroy).WillOnce(Return(
true));
984 EXPECT_CALL(*egl_manager.get(),
985 CreateWindowSurface(_, 500, 500))
986 .WillOnce(Return(std::move((resized_surface))));
987 EXPECT_CALL(*resized_surface_ptr, MakeCurrent).WillOnce(Return(
true));
988 EXPECT_CALL(*resized_surface_ptr, SetVSyncEnabled).WillOnce(Return(
true));
989 EXPECT_CALL(*windows_proc_table.get(), DwmFlush).WillOnce(Return(S_OK));
991 EXPECT_CALL(*resized_surface_ptr, Destroy).WillOnce(Return(
true));
993 engine_modifier.SetEGLManager(std::move(egl_manager));
995 std::unique_ptr<FlutterWindowsView>
view =
996 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1001 SendWindowMetricsEvent,
1002 ([&metrics_sent_latch](
auto engine,
1004 metrics_sent_latch.
Signal();
1009 std::thread frame_thread([&metrics_sent_latch, &
view]() {
1010 metrics_sent_latch.
Wait();
1012 EXPECT_TRUE(
view->OnFrameGenerated(500, 500));
1013 view->OnFramePresented();
1019 EXPECT_TRUE(
view->OnWindowSizeChanged(500, 500));
1020 frame_thread.join();
1024TEST(FlutterWindowsViewTest, TestEmptyFrameResizes) {
1025 auto windows_proc_table = std::make_shared<NiceMock<MockWindowsProcTable>>();
1026 std::unique_ptr<FlutterWindowsEngine>
engine =
1027 GetTestEngine(windows_proc_table);
1031 PostRenderThreadTask,
1037 auto egl_manager = std::make_unique<egl::MockManager>();
1038 auto surface = std::make_unique<egl::MockWindowSurface>();
1039 auto resized_surface = std::make_unique<egl::MockWindowSurface>();
1040 auto resized_surface_ptr = resized_surface.get();
1042 EXPECT_CALL(*
surface.get(), IsValid).WillRepeatedly(Return(
true));
1043 EXPECT_CALL(*
surface.get(), Destroy).WillOnce(Return(
true));
1045 EXPECT_CALL(*egl_manager.get(),
1046 CreateWindowSurface(_, 500, 300))
1047 .WillOnce(Return(std::move((resized_surface))));
1048 EXPECT_CALL(*resized_surface_ptr, MakeCurrent).WillOnce(Return(
true));
1049 EXPECT_CALL(*resized_surface_ptr, SetVSyncEnabled).WillOnce(Return(
true));
1050 EXPECT_CALL(*windows_proc_table.get(), DwmFlush).WillOnce(Return(S_OK));
1052 EXPECT_CALL(*resized_surface_ptr, Destroy).WillOnce(Return(
true));
1056 SendWindowMetricsEvent,
1057 ([&metrics_sent_latch](
auto engine,
1059 metrics_sent_latch.
Signal();
1063 std::unique_ptr<FlutterWindowsView>
view =
1064 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1068 engine_modifier.SetEGLManager(std::move(egl_manager));
1069 view_modifier.SetSurface(std::move(
surface));
1072 std::thread frame_thread([&metrics_sent_latch, &
view]() {
1073 metrics_sent_latch.
Wait();
1076 EXPECT_TRUE(
view->OnEmptyFrameGenerated());
1077 view->OnFramePresented();
1082 EXPECT_TRUE(
view->OnWindowSizeChanged(500, 300));
1083 frame_thread.join();
1089TEST(FlutterWindowsViewTest, WindowResizeRace) {
1090 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1094 PostRenderThreadTask,
1100 auto egl_manager = std::make_unique<egl::MockManager>();
1101 auto surface = std::make_unique<egl::MockWindowSurface>();
1103 EXPECT_CALL(*
surface.get(), IsValid).WillRepeatedly(Return(
true));
1104 EXPECT_CALL(*
surface.get(), Destroy).WillOnce(Return(
true));
1106 std::unique_ptr<FlutterWindowsView>
view =
1107 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1112 view_modifier.SetSurface(std::move(
surface));
1115 ASSERT_TRUE(
view->OnFrameGenerated(100, 100));
1119 EXPECT_FALSE(
view->OnWindowSizeChanged(500, 500));
1124 view->OnFramePresented();
1129TEST(FlutterWindowsViewTest, WindowResizeInvalidSurface) {
1130 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1134 PostRenderThreadTask,
1140 auto egl_manager = std::make_unique<egl::MockManager>();
1141 auto surface = std::make_unique<egl::MockWindowSurface>();
1143 EXPECT_CALL(*egl_manager.get(), CreateWindowSurface).Times(0);
1144 EXPECT_CALL(*
surface.get(), IsValid).WillRepeatedly(Return(
false));
1145 EXPECT_CALL(*
surface.get(), Destroy).WillOnce(Return(
false));
1147 std::unique_ptr<FlutterWindowsView>
view =
1148 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1153 view_modifier.SetSurface(std::move(
surface));
1155 auto metrics_sent =
false;
1157 SendWindowMetricsEvent,
1159 metrics_sent =
true;
1163 view->OnWindowSizeChanged(500, 500);
1168TEST(FlutterWindowsViewTest, WindowResizeWithoutSurface) {
1169 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1172 auto egl_manager = std::make_unique<egl::MockManager>();
1174 EXPECT_CALL(*egl_manager.get(), CreateWindowSurface).Times(0);
1176 std::unique_ptr<FlutterWindowsView>
view =
1177 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1182 auto metrics_sent =
false;
1184 SendWindowMetricsEvent,
1186 metrics_sent =
true;
1190 view->OnWindowSizeChanged(500, 500);
1193TEST(FlutterWindowsViewTest, WindowRepaintTests) {
1194 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1198 std::make_unique<flutter::FlutterWindow>(
1199 100, 100,
engine->display_manager()),
1202 bool schedule_frame_called =
false;
1205 schedule_frame_called =
true;
1209 view.OnWindowRepaint();
1210 EXPECT_TRUE(schedule_frame_called);
1219TEST(FlutterWindowsViewTest, CheckboxNativeState) {
1220 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1227 std::unique_ptr<FlutterWindowsView>
view =
1228 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1232 view->OnUpdateSemanticsEnabled(
true);
1234 auto bridge =
view->accessibility_bridge().lock();
1235 ASSERT_TRUE(bridge);
1239 root.label =
"root";
1242 root.increased_value =
"";
1243 root.decreased_value =
"";
1244 root.child_count = 0;
1245 root.custom_accessibility_actions_count = 0;
1249 root.flags2 = &flags;
1250 bridge->AddFlutterSemanticsNodeUpdate(root);
1252 bridge->CommitUpdates();
1255 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1257 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1261 IAccessible* native_view = root_node->GetNativeViewAccessible();
1262 ASSERT_TRUE(native_view !=
nullptr);
1265 VARIANT varchild = {};
1266 varchild.vt = VT_I4;
1269 varchild.lVal = CHILDID_SELF;
1270 VARIANT native_state = {};
1271 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1272 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_CHECKED);
1275 IRawElementProviderSimple* uia_node;
1276 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1277 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1278 UIA_ToggleToggleStatePropertyId, &native_state)));
1279 EXPECT_EQ(native_state.lVal, ToggleState_On);
1281 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1282 UIA_AriaPropertiesPropertyId, &native_state)));
1283 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"checked=true"),
nullptr);
1290 root.flags2 = &updated_flags;
1291 bridge->AddFlutterSemanticsNodeUpdate(root);
1292 bridge->CommitUpdates();
1295 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1297 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1301 IAccessible* native_view = root_node->GetNativeViewAccessible();
1302 ASSERT_TRUE(native_view !=
nullptr);
1305 VARIANT varchild = {};
1306 varchild.vt = VT_I4;
1309 varchild.lVal = CHILDID_SELF;
1310 VARIANT native_state = {};
1311 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1312 EXPECT_FALSE(native_state.lVal & STATE_SYSTEM_CHECKED);
1315 IRawElementProviderSimple* uia_node;
1316 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1317 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1318 UIA_ToggleToggleStatePropertyId, &native_state)));
1319 EXPECT_EQ(native_state.lVal, ToggleState_Off);
1321 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1322 UIA_AriaPropertiesPropertyId, &native_state)));
1323 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"checked=false"),
nullptr);
1330 root.flags2 = &updated_mixe_flags;
1331 bridge->AddFlutterSemanticsNodeUpdate(root);
1332 bridge->CommitUpdates();
1335 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1337 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1341 IAccessible* native_view = root_node->GetNativeViewAccessible();
1342 ASSERT_TRUE(native_view !=
nullptr);
1345 VARIANT varchild = {};
1346 varchild.vt = VT_I4;
1349 varchild.lVal = CHILDID_SELF;
1350 VARIANT native_state = {};
1351 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1352 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_MIXED);
1355 IRawElementProviderSimple* uia_node;
1356 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1357 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1358 UIA_ToggleToggleStatePropertyId, &native_state)));
1359 EXPECT_EQ(native_state.lVal, ToggleState_Indeterminate);
1361 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1362 UIA_AriaPropertiesPropertyId, &native_state)));
1363 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"checked=mixed"),
nullptr);
1368TEST(FlutterWindowsViewTest, SwitchNativeState) {
1369 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1376 std::unique_ptr<FlutterWindowsView>
view =
1377 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1381 view->OnUpdateSemanticsEnabled(
true);
1383 auto bridge =
view->accessibility_bridge().lock();
1384 ASSERT_TRUE(bridge);
1388 root.label =
"root";
1391 root.increased_value =
"";
1392 root.decreased_value =
"";
1393 root.child_count = 0;
1394 root.custom_accessibility_actions_count = 0;
1399 root.flags2 = &flags;
1400 bridge->AddFlutterSemanticsNodeUpdate(root);
1402 bridge->CommitUpdates();
1405 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1407 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1411 IAccessible* native_view = root_node->GetNativeViewAccessible();
1412 ASSERT_TRUE(native_view !=
nullptr);
1415 VARIANT varchild = {};
1416 varchild.vt = VT_I4;
1418 varchild.lVal = CHILDID_SELF;
1419 VARIANT varrole = {};
1422 ASSERT_EQ(native_view->get_accRole(varchild, &varrole), S_OK);
1423 ASSERT_EQ(varrole.lVal, ROLE_SYSTEM_CHECKBUTTON);
1426 VARIANT native_state = {};
1427 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1428 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_PRESSED);
1429 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_CHECKED);
1432 IRawElementProviderSimple* uia_node;
1433 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1434 ASSERT_EQ(uia_node->GetPropertyValue(UIA_ControlTypePropertyId, &varrole),
1436 EXPECT_EQ(varrole.lVal, UIA_ButtonControlTypeId);
1437 ASSERT_EQ(uia_node->GetPropertyValue(UIA_ToggleToggleStatePropertyId,
1440 EXPECT_EQ(native_state.lVal, ToggleState_On);
1442 uia_node->GetPropertyValue(UIA_AriaPropertiesPropertyId, &native_state),
1444 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"pressed=true"),
nullptr);
1451 root.flags2 = &updated_flags;
1453 bridge->AddFlutterSemanticsNodeUpdate(root);
1454 bridge->CommitUpdates();
1457 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1459 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1463 IAccessible* native_view = root_node->GetNativeViewAccessible();
1464 ASSERT_TRUE(native_view !=
nullptr);
1467 VARIANT varchild = {};
1468 varchild.vt = VT_I4;
1471 varchild.lVal = CHILDID_SELF;
1472 VARIANT native_state = {};
1473 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1474 EXPECT_FALSE(native_state.lVal & STATE_SYSTEM_PRESSED);
1475 EXPECT_FALSE(native_state.lVal & STATE_SYSTEM_CHECKED);
1478 IRawElementProviderSimple* uia_node;
1479 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1480 ASSERT_EQ(uia_node->GetPropertyValue(UIA_ToggleToggleStatePropertyId,
1483 EXPECT_EQ(native_state.lVal, ToggleState_Off);
1485 uia_node->GetPropertyValue(UIA_AriaPropertiesPropertyId, &native_state),
1487 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"pressed=false"),
nullptr);
1491TEST(FlutterWindowsViewTest, TooltipNodeData) {
1492 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1499 std::unique_ptr<FlutterWindowsView>
view =
1500 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1504 view->OnUpdateSemanticsEnabled(
true);
1506 auto bridge =
view->accessibility_bridge().lock();
1507 ASSERT_TRUE(bridge);
1511 root.label =
"root";
1514 root.increased_value =
"";
1515 root.decreased_value =
"";
1516 root.tooltip =
"tooltip";
1517 root.child_count = 0;
1518 root.custom_accessibility_actions_count = 0;
1522 root.flags2 = &flags;
1523 bridge->AddFlutterSemanticsNodeUpdate(root);
1525 bridge->CommitUpdates();
1526 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1527 std::string tooltip = root_node->GetData().GetStringAttribute(
1529 EXPECT_EQ(tooltip,
"tooltip");
1532 IAccessible* native_view = bridge->GetFlutterPlatformNodeDelegateFromID(0)
1534 ->GetNativeViewAccessible();
1535 VARIANT varchild = {.vt = VT_I4, .lVal = CHILDID_SELF};
1537 ASSERT_EQ(native_view->get_accName(varchild, &bname), S_OK);
1538 EXPECT_NE(std::wcsstr(bname, L
"tooltip"),
nullptr);
1541 IRawElementProviderSimple* uia_node;
1542 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1544 ASSERT_EQ(uia_node->GetPropertyValue(UIA_HelpTextPropertyId, &varname), S_OK);
1545 std::string uia_tooltip = _com_util::ConvertBSTRToString(varname.bstrVal);
1546 EXPECT_EQ(uia_tooltip,
"tooltip");
1551TEST(FlutterWindowsViewTest, DisablesVSyncAtStartup) {
1552 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1553 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1554 auto egl_manager = std::make_unique<egl::MockManager>();
1556 auto surface = std::make_unique<egl::MockWindowSurface>();
1557 auto surface_ptr =
surface.get();
1559 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
false));
1560 EXPECT_CALL(*
engine.get(), PostRasterThreadTask).Times(0);
1562 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1563 .WillOnce(Return(
true));
1565 EXPECT_CALL(*egl_manager.get(), render_context)
1566 .WillOnce(Return(&render_context));
1567 EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(
true));
1570 EXPECT_CALL(*egl_manager.get(), CreateWindowSurface)
1571 .WillOnce(Return(std::move(
surface)));
1572 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
1573 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
false)).WillOnce(Return(
true));
1574 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
1576 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1579 modifier.SetEGLManager(std::move(egl_manager));
1581 std::unique_ptr<FlutterWindowsView>
view =
1582 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1588TEST(FlutterWindowsViewTest, EnablesVSyncAtStartup) {
1589 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1590 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1591 auto egl_manager = std::make_unique<egl::MockManager>();
1593 auto surface = std::make_unique<egl::MockWindowSurface>();
1594 auto surface_ptr =
surface.get();
1596 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
false));
1597 EXPECT_CALL(*
engine.get(), PostRasterThreadTask).Times(0);
1598 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1599 .WillOnce(Return(
false));
1601 EXPECT_CALL(*egl_manager.get(), render_context)
1602 .WillOnce(Return(&render_context));
1603 EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(
true));
1606 EXPECT_CALL(*egl_manager.get(), CreateWindowSurface)
1607 .WillOnce(Return(std::move(
surface)));
1608 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
1609 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
true)).WillOnce(Return(
true));
1610 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
1612 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1615 modifier.SetEGLManager(std::move(egl_manager));
1617 std::unique_ptr<FlutterWindowsView>
view =
1618 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1624TEST(FlutterWindowsViewTest, DisablesVSyncAfterStartup) {
1625 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1626 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1627 auto egl_manager = std::make_unique<egl::MockManager>();
1629 auto surface = std::make_unique<egl::MockWindowSurface>();
1630 auto surface_ptr =
surface.get();
1632 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
true));
1633 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1634 .WillOnce(Return(
true));
1636 EXPECT_CALL(*egl_manager.get(), render_context)
1637 .WillOnce(Return(&render_context));
1638 EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(
true));
1641 EXPECT_CALL(*egl_manager.get(), CreateWindowSurface)
1642 .WillOnce(Return(std::move(
surface)));
1643 EXPECT_CALL(*
engine.get(), PostRasterThreadTask)
1648 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
1649 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
false)).WillOnce(Return(
true));
1650 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
1651 EXPECT_CALL(*
engine.get(), PostRasterThreadTask)
1656 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1659 modifier.SetEGLManager(std::move(egl_manager));
1661 std::unique_ptr<FlutterWindowsView>
view =
1662 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1668TEST(FlutterWindowsViewTest, EnablesVSyncAfterStartup) {
1669 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1670 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1671 auto egl_manager = std::make_unique<egl::MockManager>();
1673 auto surface = std::make_unique<egl::MockWindowSurface>();
1674 auto surface_ptr =
surface.get();
1676 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
true));
1678 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1679 .WillOnce(Return(
false));
1681 EXPECT_CALL(*egl_manager.get(), render_context)
1682 .WillOnce(Return(&render_context));
1683 EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(
true));
1686 EXPECT_CALL(*egl_manager.get(), CreateWindowSurface)
1687 .WillOnce(Return(std::move(
surface)));
1688 EXPECT_CALL(*
engine.get(), PostRasterThreadTask)
1694 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
1695 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
true)).WillOnce(Return(
true));
1696 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
1698 EXPECT_CALL(*
engine.get(), PostRasterThreadTask)
1703 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1706 modifier.SetEGLManager(std::move(egl_manager));
1708 std::unique_ptr<FlutterWindowsView>
view =
1709 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1716TEST(FlutterWindowsViewTest, UpdatesVSyncOnDwmUpdates) {
1717 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1718 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1719 auto egl_manager = std::make_unique<egl::MockManager>();
1721 auto surface = std::make_unique<egl::MockWindowSurface>();
1722 auto surface_ptr =
surface.get();
1724 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
true));
1726 EXPECT_CALL(*
engine.get(), PostRasterThreadTask)
1732 EXPECT_CALL(*egl_manager.get(), render_context)
1733 .WillRepeatedly(Return(&render_context));
1735 EXPECT_CALL(*surface_ptr, IsValid).WillRepeatedly(Return(
true));
1736 EXPECT_CALL(*surface_ptr, MakeCurrent).WillRepeatedly(Return(
true));
1737 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1738 EXPECT_CALL(render_context, ClearCurrent).WillRepeatedly(Return(
true));
1743 std::unique_ptr<FlutterWindowsView>
view;
1745 EXPECT_CALL(*egl_manager, CreateWindowSurface)
1746 .WillOnce(Return(std::move(
surface)));
1747 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1748 .WillOnce(Return(
true));
1749 EXPECT_CALL(*surface_ptr, SetVSyncEnabled).WillOnce(Return(
true));
1752 engine_modifier.SetEGLManager(std::move(egl_manager));
1755 std::make_unique<NiceMock<MockWindowBindingHandler>>(),
false,
1761 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1762 .WillOnce(Return(
false));
1763 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
true)).WillOnce(Return(
true));
1765 engine->OnDwmCompositionChanged();
1770 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1771 .WillOnce(Return(
true));
1772 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
false)).WillOnce(Return(
true));
1774 engine->OnDwmCompositionChanged();
1778TEST(FlutterWindowsViewTest, FocusTriggersWindowFocus) {
1779 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1780 auto window_binding_handler =
1781 std::make_unique<NiceMock<MockWindowBindingHandler>>();
1782 EXPECT_CALL(*window_binding_handler, Focus()).WillOnce(Return(
true));
1783 std::unique_ptr<FlutterWindowsView>
view =
1784 engine->CreateView(std::move(window_binding_handler),
1786 EXPECT_TRUE(
view->Focus());
1789TEST(FlutterWindowsViewTest, OnFocusTriggersSendFocusViewEvent) {
1790 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1791 auto window_binding_handler =
1792 std::make_unique<NiceMock<MockWindowBindingHandler>>();
1793 std::unique_ptr<FlutterWindowsView>
view =
1794 engine->CreateView(std::move(window_binding_handler),
1798 bool received_focus_event =
false;
1806 received_focus_event =
true;
1811 EXPECT_TRUE(received_focus_event);
1814TEST(FlutterWindowsViewTest, WindowMetricsEventContainsDisplayId) {
1815 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1818 auto window_binding_handler =
1819 std::make_unique<NiceMock<MockWindowBindingHandler>>();
1820 EXPECT_CALL(*window_binding_handler, GetDisplayId)
1821 .WillOnce(testing::Return(12));
1823 std::move(window_binding_handler),
false,
1827 EXPECT_EQ(event.display_id, 12);
1830TEST(FlutterWindowsViewTest, SizeChangeTriggersMetricsEventWhichHasDisplayId) {
1831 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1834 auto window_binding_handler =
1835 std::make_unique<NiceMock<MockWindowBindingHandler>>();
1836 EXPECT_CALL(*window_binding_handler, GetDisplayId)
1837 .WillOnce(testing::Return(12));
1839 std::move(window_binding_handler),
false,
1842 bool received_metrics =
false;
1844 SendWindowMetricsEvent,
1845 ([&received_metrics](
auto engine,
1847 received_metrics =
true;
1851 view.OnWindowSizeChanged(100, 100);
1852 EXPECT_TRUE(received_metrics);
1857TEST(FlutterWindowsViewTest, FirstFrameCallbackFiresOnFramePresented) {
1858 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1860 std::unique_ptr<FlutterWindowsView>
view =
1861 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1864 bool callback_fired =
false;
1865 view->SetFirstFrameCallback([&callback_fired]() { callback_fired =
true; });
1868 view->OnFramePresented();
1872 engine->task_runner()->ProcessTasks();
1874 EXPECT_TRUE(callback_fired);
1879TEST(FlutterWindowsViewTest, FirstFrameCallbackFiresOnSoftwareBitmapPresent) {
1880 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1882 auto window_binding_handler =
1883 std::make_unique<NiceMock<MockWindowBindingHandler>>();
1884 EXPECT_CALL(*window_binding_handler, OnBitmapSurfaceUpdated)
1885 .WillOnce(Return(
true));
1887 std::unique_ptr<FlutterWindowsView>
view =
1888 engine->CreateView(std::move(window_binding_handler),
1891 bool callback_fired =
false;
1892 view->SetFirstFrameCallback([&callback_fired]() { callback_fired =
true; });
1895 const uint32_t pixel = 0;
1896 view->PresentSoftwareBitmap(&pixel,
sizeof(pixel), 1);
1899 engine->task_runner()->ProcessTasks();
1901 EXPECT_TRUE(callback_fired);
1906TEST(FlutterWindowsViewTest, FirstFrameCallbackFiresOnlyOnce) {
1907 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1909 std::unique_ptr<FlutterWindowsView>
view =
1910 engine->CreateView(std::make_unique<NiceMock<MockWindowBindingHandler>>(),
1913 int callback_count = 0;
1914 view->SetFirstFrameCallback([&callback_count]() { callback_count++; });
1917 view->OnFramePresented();
1918 view->OnFramePresented();
1921 engine->task_runner()->ProcessTasks();
1923 EXPECT_EQ(callback_count, 1);
1928TEST(FlutterWindowsViewTest, FirstFrameCallbackSkippedOnFailedSoftwarePresent) {
1929 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1931 auto window_binding_handler =
1932 std::make_unique<NiceMock<MockWindowBindingHandler>>();
1933 EXPECT_CALL(*window_binding_handler, OnBitmapSurfaceUpdated)
1934 .WillOnce(Return(
false));
1936 std::unique_ptr<FlutterWindowsView>
view =
1937 engine->CreateView(std::move(window_binding_handler),
1940 bool callback_fired =
false;
1941 view->SetFirstFrameCallback([&callback_fired]() { callback_fired =
true; });
1943 const uint32_t pixel = 0;
1944 view->PresentSoftwareBitmap(&pixel,
sizeof(pixel), 1);
1946 engine->task_runner()->ProcessTasks();
1948 EXPECT_FALSE(callback_fired);
std::shared_ptr< FlutterPlatformNodeDelegateWindows > node_delegate
void SetEGLManager(std::unique_ptr< egl::Manager > egl_manager)
FlutterEngineProcTable & embedder_api()
Controls a view that displays Flutter content.
static const JsonMessageCodec & GetInstance()
std::unique_ptr< std::vector< uint8_t > > EncodeMessage(const T &message) const
std::function< void(bool)> ResponseCallback
Mock for the |Context| base class.
@ kFlutterCheckStateTrue
The semantics node is checked.
@ kFlutterCheckStateFalse
The semantics node is not checked.
@ kFlutterCheckStateMixed
The semantics node represents a checkbox in mixed state.
#define FLUTTER_API_SYMBOL(symbol)
@ kFocused
Specifies that a view has platform focus.
FlutterAccessibilityFeature
void(* VoidCallback)(void *)
FlutterEngineDisplaysUpdateType
@ kFlutterTristateTrue
The property is applicable and its state is "true" or "on".
@ kFlutterTristateFalse
The property is applicable and its state is "false" or "off".
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS FlutterViewId view_id
void(* FlutterDesktopBinaryReply)(const uint8_t *data, size_t data_size, void *user_data)
FlutterDesktopBinaryReply callback
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
std::shared_ptr< ImpellerAllocator > allocator
constexpr uint64_t kScanCodeKeyA
constexpr uint64_t kVirtualKeyA
void MockEmbedderApiForKeyboard(EngineModifier &modifier, std::shared_ptr< MockKeyResponseController > response_controller)
TEST(NativeAssetsManagerTest, NoAvailableAssets)
constexpr int64_t kImplicitViewId
DEF_SWITCHES_START aot vmservice shared library name
static void ScheduleFrame(JNIEnv *env, jobject jcaller, jlong shell_holder)
std::function< void()> closure
#define MOCK_ENGINE_PROC(proc, mock_impl)
std::shared_ptr< ContextGLES > context
const char * aot_library_path
const char * icu_data_path
FlutterDesktopImpellerSwitch impeller_switch
FlutterEngineScheduleFrameFnPtr ScheduleFrame
FlutterEngineSendWindowMetricsEventFnPtr SendWindowMetricsEvent
FlutterEngineSendViewFocusEventFnPtr SendViewFocusEvent
FlutterEngineUpdateSemanticsEnabledFnPtr UpdateSemanticsEnabled
FlutterEnginePostRenderThreadTaskFnPtr PostRenderThreadTask
FlutterTristate is_toggled
FlutterTristate is_expanded
Whether a semantic node that is currently expanded.
bool is_text_field
Whether the semantic node represents a text field.
FlutterCheckState is_checked
Whether a semantics node is checked.
int32_t id
The unique identifier for this node.
FlutterRect rect
The bounding box for this node in its coordinate system.
size_t child_count
The number of children this node has.
const char * label
A textual description of the node.
FlutterViewFocusState state
The focus state of the view.
FlutterViewFocusDirection direction
The direction in which the focus transitioned across [FlutterView]s.
FlutterViewId view_id
The identifier of the view that received the focus event.
FlutterEngineDisplayId display_id
The identifier of the display the view is rendering on.