137TEST(FlutterWindowsViewTest, SubMenuExpandedState) {
138 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
145 auto window_binding_handler =
146 std::make_unique<NiceMock<MockWindowBindingHandler>>();
147 std::unique_ptr<FlutterWindowsView>
view =
148 engine->CreateView(std::move(window_binding_handler));
151 view->OnUpdateSemanticsEnabled(
true);
153 auto bridge =
view->accessibility_bridge().lock();
161 root.increased_value =
"";
162 root.decreased_value =
"";
163 root.child_count = 0;
164 root.custom_accessibility_actions_count = 0;
168 root.flags2 = &flags;
170 bridge->AddFlutterSemanticsNodeUpdate(root);
172 bridge->CommitUpdates();
175 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
179 IAccessible* native_view = root_node->GetNativeViewAccessible();
180 ASSERT_TRUE(native_view !=
nullptr);
183 VARIANT varchild = {};
187 varchild.lVal = CHILDID_SELF;
188 VARIANT native_state = {};
189 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
190 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_EXPANDED);
193 IRawElementProviderSimple* uia_node;
194 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
195 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
196 UIA_ExpandCollapseExpandCollapseStatePropertyId, &native_state)));
197 EXPECT_EQ(native_state.lVal, ExpandCollapseState_Expanded);
199 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
200 UIA_AriaPropertiesPropertyId, &native_state)));
201 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"expanded=true"),
nullptr);
208 root.flags2 = &updated_flags;
210 bridge->AddFlutterSemanticsNodeUpdate(root);
211 bridge->CommitUpdates();
214 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
218 IAccessible* native_view = root_node->GetNativeViewAccessible();
219 ASSERT_TRUE(native_view !=
nullptr);
222 VARIANT varchild = {};
226 varchild.lVal = CHILDID_SELF;
227 VARIANT native_state = {};
228 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
229 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_COLLAPSED);
232 IRawElementProviderSimple* uia_node;
233 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
234 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
235 UIA_ExpandCollapseExpandCollapseStatePropertyId, &native_state)));
236 EXPECT_EQ(native_state.lVal, ExpandCollapseState_Collapsed);
238 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
239 UIA_AriaPropertiesPropertyId, &native_state)));
240 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"expanded=false"),
nullptr);
246TEST(FlutterWindowsViewTest, Shutdown) {
247 auto engine = std::make_unique<MockFlutterWindowsEngine>();
248 auto window_binding_handler =
249 std::make_unique<NiceMock<MockWindowBindingHandler>>();
250 auto egl_manager = std::make_unique<egl::MockManager>();
251 auto surface = std::make_unique<egl::MockWindowSurface>();
254 auto engine_ptr =
engine.get();
255 auto surface_ptr =
surface.get();
256 auto egl_manager_ptr = egl_manager.get();
259 modifier.SetEGLManager(std::move(egl_manager));
262 std::unique_ptr<FlutterWindowsView>
view;
266 EXPECT_CALL(*egl_manager_ptr, CreateWindowSurface)
267 .WillOnce(Return(std::move(
surface)));
268 EXPECT_CALL(*engine_ptr, running).WillOnce(Return(
false));
269 EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(
true));
270 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
271 EXPECT_CALL(*surface_ptr, SetVSyncEnabled).WillOnce(Return(
true));
272 EXPECT_CALL(*egl_manager_ptr, render_context)
273 .WillOnce(Return(&render_context));
274 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
276 view =
engine->CreateView(std::move(window_binding_handler));
284 EXPECT_CALL(*engine_ptr, running).WillOnce(Return(
true));
285 EXPECT_CALL(*engine_ptr, RemoveView(
view_id)).Times(1);
286 EXPECT_CALL(*engine_ptr, running).WillOnce(Return(
true));
287 EXPECT_CALL(*engine_ptr, PostRasterThreadTask)
292 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
365TEST(FlutterWindowsViewTest, AddSemanticsNodeUpdate) {
366 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
373 auto window_binding_handler =
374 std::make_unique<NiceMock<MockWindowBindingHandler>>();
375 std::unique_ptr<FlutterWindowsView>
view =
376 engine->CreateView(std::move(window_binding_handler));
379 view->OnUpdateSemanticsEnabled(
true);
381 auto bridge =
view->accessibility_bridge().lock();
387 node.value =
"value";
388 node.platform_view_id = -1;
390 node.flags2 = &flags;
391 bridge->AddFlutterSemanticsNodeUpdate(node);
392 bridge->CommitUpdates();
395 auto node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
400 IAccessible* native_view =
node_delegate->GetNativeViewAccessible();
401 ASSERT_TRUE(native_view !=
nullptr);
406 varchild.lVal = CHILDID_SELF;
409 BSTR bname =
nullptr;
410 ASSERT_EQ(native_view->get_accName(varchild, &bname), S_OK);
411 std::string
name(_com_util::ConvertBSTRToString(bname));
412 EXPECT_EQ(
name,
"name");
415 BSTR bvalue =
nullptr;
416 ASSERT_EQ(native_view->get_accValue(varchild, &bvalue), S_OK);
417 std::string
value(_com_util::ConvertBSTRToString(bvalue));
418 EXPECT_EQ(
value,
"value");
423 ASSERT_EQ(native_view->get_accRole(varchild, &varrole), S_OK);
424 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_STATICTEXT);
427 IRawElementProviderSimple* uia_view;
428 native_view->QueryInterface(IID_PPV_ARGS(&uia_view));
429 ASSERT_TRUE(uia_view !=
nullptr);
433 ASSERT_EQ(uia_view->GetPropertyValue(UIA_NamePropertyId, &varname), S_OK);
434 EXPECT_EQ(varname.vt, VT_BSTR);
435 name = _com_util::ConvertBSTRToString(varname.bstrVal);
436 EXPECT_EQ(
name,
"name");
440 ASSERT_EQ(uia_view->GetPropertyValue(UIA_ValueValuePropertyId, &varvalue),
442 EXPECT_EQ(varvalue.vt, VT_BSTR);
443 value = _com_util::ConvertBSTRToString(varvalue.bstrVal);
444 EXPECT_EQ(
value,
"value");
448 ASSERT_EQ(uia_view->GetPropertyValue(UIA_ControlTypePropertyId, &varrole),
450 EXPECT_EQ(varrole.vt, VT_I4);
451 EXPECT_EQ(varrole.lVal, UIA_TextControlTypeId);
466TEST(FlutterWindowsViewTest, AddSemanticsNodeUpdateWithChildren) {
467 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
474 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
475 std::make_unique<NiceMock<MockWindowBindingHandler>>());
478 view->OnUpdateSemanticsEnabled(
true);
480 auto bridge =
view->accessibility_bridge().lock();
485 std::vector<int32_t> node0_children{1, 2};
487 node0.children_in_traversal_order = node0_children.data();
488 node0.children_in_hit_test_order = node0_children.data();
490 node0.flags2 = &empty_flags;
493 node1.
label =
"prefecture";
494 node1.value =
"Kyoto";
495 node1.flags2 = &empty_flags;
497 std::vector<int32_t> node2_children{3};
499 node2.children_in_traversal_order = node2_children.data();
500 node2.children_in_hit_test_order = node2_children.data();
501 node2.flags2 = &empty_flags;
503 node3.
label =
"city";
505 node3.flags2 = &empty_flags;
507 bridge->AddFlutterSemanticsNodeUpdate(node0);
508 bridge->AddFlutterSemanticsNodeUpdate(node1);
509 bridge->AddFlutterSemanticsNodeUpdate(node2);
510 bridge->AddFlutterSemanticsNodeUpdate(node3);
511 bridge->CommitUpdates();
514 auto node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
519 IAccessible* node0_accessible =
node_delegate->GetNativeViewAccessible();
520 ASSERT_TRUE(node0_accessible !=
nullptr);
525 varchild.lVal = CHILDID_SELF;
530 ASSERT_EQ(node0_accessible->get_accRole(varchild, &varrole), S_OK);
531 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_GROUPING);
534 long node0_child_count = 0;
535 ASSERT_EQ(node0_accessible->get_accChildCount(&node0_child_count), S_OK);
536 EXPECT_EQ(node0_child_count, 2);
541 IDispatch* node1_dispatch =
nullptr;
542 ASSERT_EQ(node0_accessible->get_accChild(varchild, &node1_dispatch), S_OK);
543 ASSERT_TRUE(node1_dispatch !=
nullptr);
544 IAccessible* node1_accessible =
nullptr;
545 ASSERT_EQ(node1_dispatch->QueryInterface(
546 IID_IAccessible,
reinterpret_cast<void**
>(&node1_accessible)),
548 ASSERT_TRUE(node1_accessible !=
nullptr);
551 varchild.lVal = CHILDID_SELF;
552 BSTR bname =
nullptr;
553 ASSERT_EQ(node1_accessible->get_accName(varchild, &bname), S_OK);
554 std::string
name(_com_util::ConvertBSTRToString(bname));
555 EXPECT_EQ(
name,
"prefecture");
558 BSTR bvalue =
nullptr;
559 ASSERT_EQ(node1_accessible->get_accValue(varchild, &bvalue), S_OK);
560 std::string
value(_com_util::ConvertBSTRToString(bvalue));
561 EXPECT_EQ(
value,
"Kyoto");
566 ASSERT_EQ(node1_accessible->get_accRole(varchild, &varrole), S_OK);
567 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_STATICTEXT);
570 IDispatch* parent_dispatch;
571 node1_accessible->get_accParent(&parent_dispatch);
572 IAccessible* parent_accessible;
574 parent_dispatch->QueryInterface(
575 IID_IAccessible,
reinterpret_cast<void**
>(&parent_accessible)),
577 EXPECT_EQ(parent_accessible, node0_accessible);
582 IDispatch* node2_dispatch =
nullptr;
583 ASSERT_EQ(node0_accessible->get_accChild(varchild, &node2_dispatch), S_OK);
584 ASSERT_TRUE(node2_dispatch !=
nullptr);
585 IAccessible* node2_accessible =
nullptr;
586 ASSERT_EQ(node2_dispatch->QueryInterface(
587 IID_IAccessible,
reinterpret_cast<void**
>(&node2_accessible)),
589 ASSERT_TRUE(node2_accessible !=
nullptr);
593 long node2_child_count = 0;
594 ASSERT_EQ(node2_accessible->get_accChildCount(&node2_child_count), S_OK);
595 EXPECT_EQ(node2_child_count, 1);
598 varchild.lVal = CHILDID_SELF;
601 ASSERT_EQ(node2_accessible->get_accRole(varchild, &varrole), S_OK);
602 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_GROUPING);
605 IDispatch* parent_dispatch;
606 node2_accessible->get_accParent(&parent_dispatch);
607 IAccessible* parent_accessible;
609 parent_dispatch->QueryInterface(
610 IID_IAccessible,
reinterpret_cast<void**
>(&parent_accessible)),
612 EXPECT_EQ(parent_accessible, node0_accessible);
618 IDispatch* node3_dispatch =
nullptr;
619 ASSERT_EQ(node2_accessible->get_accChild(varchild, &node3_dispatch), S_OK);
620 ASSERT_TRUE(node3_dispatch !=
nullptr);
621 IAccessible* node3_accessible =
nullptr;
622 ASSERT_EQ(node3_dispatch->QueryInterface(
623 IID_IAccessible,
reinterpret_cast<void**
>(&node3_accessible)),
625 ASSERT_TRUE(node3_accessible !=
nullptr);
628 varchild.lVal = CHILDID_SELF;
629 BSTR bname =
nullptr;
630 ASSERT_EQ(node3_accessible->get_accName(varchild, &bname), S_OK);
631 std::string
name(_com_util::ConvertBSTRToString(bname));
632 EXPECT_EQ(
name,
"city");
635 BSTR bvalue =
nullptr;
636 ASSERT_EQ(node3_accessible->get_accValue(varchild, &bvalue), S_OK);
637 std::string
value(_com_util::ConvertBSTRToString(bvalue));
638 EXPECT_EQ(
value,
"Uji");
643 ASSERT_EQ(node3_accessible->get_accRole(varchild, &varrole), S_OK);
644 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_STATICTEXT);
647 IDispatch* parent_dispatch;
648 node3_accessible->get_accParent(&parent_dispatch);
649 IAccessible* parent_accessible;
651 parent_dispatch->QueryInterface(
652 IID_IAccessible,
reinterpret_cast<void**
>(&parent_accessible)),
654 EXPECT_EQ(parent_accessible, node2_accessible);
667TEST(FlutterWindowsViewTest, NonZeroSemanticsRoot) {
668 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
675 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
676 std::make_unique<NiceMock<MockWindowBindingHandler>>());
679 view->OnUpdateSemanticsEnabled(
true);
681 auto bridge =
view->accessibility_bridge().lock();
686 std::vector<int32_t> node1_children{2};
688 node1.children_in_traversal_order = node1_children.data();
689 node1.children_in_hit_test_order = node1_children.data();
691 node1.flags2 = &empty_flags;
694 node2.
label =
"prefecture";
695 node2.value =
"Kyoto";
696 node2.flags2 = &empty_flags;
697 bridge->AddFlutterSemanticsNodeUpdate(node1);
698 bridge->AddFlutterSemanticsNodeUpdate(node2);
699 bridge->CommitUpdates();
702 auto root_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
703 ASSERT_TRUE(root_delegate);
704 EXPECT_EQ(root_delegate->GetChildCount(), 1);
707 auto child_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(2).lock();
708 ASSERT_TRUE(child_delegate);
709 EXPECT_EQ(child_delegate->GetChildCount(), 0);
712 auto fake_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
716 IAccessible* node1_accessible = root_delegate->GetNativeViewAccessible();
717 ASSERT_TRUE(node1_accessible !=
nullptr);
722 varchild.lVal = CHILDID_SELF;
727 ASSERT_EQ(node1_accessible->get_accRole(varchild, &varrole), S_OK);
728 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_GROUPING);
731 long node1_child_count = 0;
732 ASSERT_EQ(node1_accessible->get_accChildCount(&node1_child_count), S_OK);
733 EXPECT_EQ(node1_child_count, 1);
738 IDispatch* node2_dispatch =
nullptr;
739 ASSERT_EQ(node1_accessible->get_accChild(varchild, &node2_dispatch), S_OK);
740 ASSERT_TRUE(node2_dispatch !=
nullptr);
741 IAccessible* node2_accessible =
nullptr;
742 ASSERT_EQ(node2_dispatch->QueryInterface(
743 IID_IAccessible,
reinterpret_cast<void**
>(&node2_accessible)),
745 ASSERT_TRUE(node2_accessible !=
nullptr);
748 varchild.lVal = CHILDID_SELF;
749 BSTR bname =
nullptr;
750 ASSERT_EQ(node2_accessible->get_accName(varchild, &bname), S_OK);
751 std::string
name(_com_util::ConvertBSTRToString(bname));
752 EXPECT_EQ(
name,
"prefecture");
755 BSTR bvalue =
nullptr;
756 ASSERT_EQ(node2_accessible->get_accValue(varchild, &bvalue), S_OK);
757 std::string
value(_com_util::ConvertBSTRToString(bvalue));
758 EXPECT_EQ(
value,
"Kyoto");
763 ASSERT_EQ(node2_accessible->get_accRole(varchild, &varrole), S_OK);
764 EXPECT_EQ(varrole.lVal, ROLE_SYSTEM_STATICTEXT);
767 IDispatch* parent_dispatch;
768 node2_accessible->get_accParent(&parent_dispatch);
769 IAccessible* parent_accessible;
771 parent_dispatch->QueryInterface(
772 IID_IAccessible,
reinterpret_cast<void**
>(&parent_accessible)),
774 EXPECT_EQ(parent_accessible, node1_accessible);
795TEST(FlutterWindowsViewTest, AccessibilityHitTesting) {
800 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
807 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
808 std::make_unique<NiceMock<MockWindowBindingHandler>>());
811 view->OnUpdateSemanticsEnabled(
true);
813 auto bridge =
view->accessibility_bridge().lock();
819 std::vector<int32_t> node0_children{1, 2};
820 node0.rect = {0, 0, 500, 500};
821 node0.transform = kIdentityTransform;
822 node0.child_count = node0_children.size();
823 node0.children_in_traversal_order = node0_children.data();
824 node0.children_in_hit_test_order = node0_children.data();
825 node0.flags2 = &empty_flags;
829 node1.
rect = {0, 0, 250, 500};
830 node1.transform = kIdentityTransform;
831 node1.label =
"prefecture";
832 node1.value =
"Kyoto";
833 node1.flags2 = &empty_flags;
837 std::vector<int32_t> node2_children{3};
838 node2.
rect = {0, 0, 250, 500};
839 node2.transform = {1, 0, 250, 0, 1, 0, 0, 0, 1};
840 node2.child_count = node2_children.size();
841 node2.children_in_traversal_order = node2_children.data();
842 node2.children_in_hit_test_order = node2_children.data();
843 node2.flags2 = &empty_flags;
847 node3.
rect = {0, 0, 250, 250};
848 node3.transform = {1, 0, 0, 0, 1, 250, 0, 0, 1};
849 node3.label =
"city";
851 node3.flags2 = &empty_flags;
853 bridge->AddFlutterSemanticsNodeUpdate(node0);
854 bridge->AddFlutterSemanticsNodeUpdate(node1);
855 bridge->AddFlutterSemanticsNodeUpdate(node2);
856 bridge->AddFlutterSemanticsNodeUpdate(node3);
857 bridge->CommitUpdates();
860 auto node0_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
861 ASSERT_TRUE(node0_delegate);
862 auto node1_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
863 ASSERT_TRUE(node1_delegate);
864 auto node2_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(2).lock();
865 ASSERT_TRUE(node2_delegate);
866 auto node3_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(3).lock();
867 ASSERT_TRUE(node3_delegate);
870 IAccessible* node0_accessible = node0_delegate->GetNativeViewAccessible();
871 ASSERT_TRUE(node0_accessible !=
nullptr);
875 ASSERT_TRUE(
SUCCEEDED(node0_accessible->accHitTest(150, 150, &varchild)));
876 EXPECT_EQ(varchild.vt, VT_DISPATCH);
877 EXPECT_EQ(varchild.pdispVal, node1_delegate->GetNativeViewAccessible());
881 ASSERT_TRUE(
SUCCEEDED(node0_accessible->accHitTest(450, 150, &varchild)));
882 EXPECT_EQ(varchild.vt, VT_DISPATCH);
883 EXPECT_EQ(varchild.pdispVal, node2_delegate->GetNativeViewAccessible());
887 ASSERT_TRUE(
SUCCEEDED(node0_accessible->accHitTest(450, 450, &varchild)));
888 EXPECT_EQ(varchild.vt, VT_DISPATCH);
889 EXPECT_EQ(varchild.pdispVal, node3_delegate->GetNativeViewAccessible());
892TEST(FlutterWindowsViewTest, WindowResizeTests) {
893 auto windows_proc_table = std::make_shared<NiceMock<MockWindowsProcTable>>();
894 std::unique_ptr<FlutterWindowsEngine>
engine =
895 GetTestEngine(windows_proc_table);
899 PostRenderThreadTask,
905 auto egl_manager = std::make_unique<egl::MockManager>();
906 auto surface = std::make_unique<egl::MockWindowSurface>();
907 auto resized_surface = std::make_unique<egl::MockWindowSurface>();
910 auto surface_ptr =
surface.get();
911 auto resized_surface_ptr = resized_surface.get();
914 EXPECT_CALL(*egl_manager, CreateWindowSurface)
915 .WillOnce(Return(std::move(
surface)));
916 EXPECT_CALL(*surface_ptr, IsValid).WillRepeatedly(Return(
true));
917 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
918 EXPECT_CALL(*surface_ptr, SetVSyncEnabled).WillOnce(Return(
true));
919 EXPECT_CALL(*egl_manager, render_context).WillOnce(Return(&render_context));
920 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
923 EXPECT_CALL(*surface_ptr, Destroy).WillOnce(Return(
true));
924 EXPECT_CALL(*egl_manager.get(),
925 CreateWindowSurface(_, 500, 500))
926 .WillOnce(Return(std::move((resized_surface))));
927 EXPECT_CALL(*resized_surface_ptr, MakeCurrent).WillOnce(Return(
true));
928 EXPECT_CALL(*resized_surface_ptr, SetVSyncEnabled).WillOnce(Return(
true));
929 EXPECT_CALL(*windows_proc_table.get(), DwmFlush).WillOnce(Return(S_OK));
931 EXPECT_CALL(*resized_surface_ptr, Destroy).WillOnce(Return(
true));
933 engine_modifier.SetEGLManager(std::move(egl_manager));
935 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
936 std::make_unique<NiceMock<MockWindowBindingHandler>>());
940 SendWindowMetricsEvent,
941 ([&metrics_sent_latch](
auto engine,
943 metrics_sent_latch.
Signal();
948 std::thread frame_thread([&metrics_sent_latch, &
view]() {
949 metrics_sent_latch.
Wait();
951 EXPECT_TRUE(
view->OnFrameGenerated(500, 500));
952 view->OnFramePresented();
958 EXPECT_TRUE(
view->OnWindowSizeChanged(500, 500));
963TEST(FlutterWindowsViewTest, TestEmptyFrameResizes) {
964 auto windows_proc_table = std::make_shared<NiceMock<MockWindowsProcTable>>();
965 std::unique_ptr<FlutterWindowsEngine>
engine =
966 GetTestEngine(windows_proc_table);
970 PostRenderThreadTask,
976 auto egl_manager = std::make_unique<egl::MockManager>();
977 auto surface = std::make_unique<egl::MockWindowSurface>();
978 auto resized_surface = std::make_unique<egl::MockWindowSurface>();
979 auto resized_surface_ptr = resized_surface.get();
981 EXPECT_CALL(*
surface.get(), IsValid).WillRepeatedly(Return(
true));
982 EXPECT_CALL(*
surface.get(), 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));
995 SendWindowMetricsEvent,
996 ([&metrics_sent_latch](
auto engine,
998 metrics_sent_latch.
Signal();
1002 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
1003 std::make_unique<NiceMock<MockWindowBindingHandler>>());
1006 engine_modifier.SetEGLManager(std::move(egl_manager));
1010 std::thread frame_thread([&metrics_sent_latch, &
view]() {
1011 metrics_sent_latch.
Wait();
1014 EXPECT_TRUE(
view->OnEmptyFrameGenerated());
1015 view->OnFramePresented();
1020 EXPECT_TRUE(
view->OnWindowSizeChanged(500, 500));
1021 frame_thread.join();
1153TEST(FlutterWindowsViewTest, CheckboxNativeState) {
1154 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1161 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
1162 std::make_unique<NiceMock<MockWindowBindingHandler>>());
1165 view->OnUpdateSemanticsEnabled(
true);
1167 auto bridge =
view->accessibility_bridge().lock();
1168 ASSERT_TRUE(bridge);
1172 root.label =
"root";
1175 root.increased_value =
"";
1176 root.decreased_value =
"";
1177 root.child_count = 0;
1178 root.custom_accessibility_actions_count = 0;
1182 root.flags2 = &flags;
1183 bridge->AddFlutterSemanticsNodeUpdate(root);
1185 bridge->CommitUpdates();
1188 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1190 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1194 IAccessible* native_view = root_node->GetNativeViewAccessible();
1195 ASSERT_TRUE(native_view !=
nullptr);
1198 VARIANT varchild = {};
1199 varchild.vt = VT_I4;
1202 varchild.lVal = CHILDID_SELF;
1203 VARIANT native_state = {};
1204 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1205 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_CHECKED);
1208 IRawElementProviderSimple* uia_node;
1209 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1210 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1211 UIA_ToggleToggleStatePropertyId, &native_state)));
1212 EXPECT_EQ(native_state.lVal, ToggleState_On);
1214 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1215 UIA_AriaPropertiesPropertyId, &native_state)));
1216 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"checked=true"),
nullptr);
1223 root.flags2 = &updated_flags;
1224 bridge->AddFlutterSemanticsNodeUpdate(root);
1225 bridge->CommitUpdates();
1228 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1230 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1234 IAccessible* native_view = root_node->GetNativeViewAccessible();
1235 ASSERT_TRUE(native_view !=
nullptr);
1238 VARIANT varchild = {};
1239 varchild.vt = VT_I4;
1242 varchild.lVal = CHILDID_SELF;
1243 VARIANT native_state = {};
1244 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1245 EXPECT_FALSE(native_state.lVal & STATE_SYSTEM_CHECKED);
1248 IRawElementProviderSimple* uia_node;
1249 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1250 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1251 UIA_ToggleToggleStatePropertyId, &native_state)));
1252 EXPECT_EQ(native_state.lVal, ToggleState_Off);
1254 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1255 UIA_AriaPropertiesPropertyId, &native_state)));
1256 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"checked=false"),
nullptr);
1263 root.flags2 = &updated_mixe_flags;
1264 bridge->AddFlutterSemanticsNodeUpdate(root);
1265 bridge->CommitUpdates();
1268 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1270 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1274 IAccessible* native_view = root_node->GetNativeViewAccessible();
1275 ASSERT_TRUE(native_view !=
nullptr);
1278 VARIANT varchild = {};
1279 varchild.vt = VT_I4;
1282 varchild.lVal = CHILDID_SELF;
1283 VARIANT native_state = {};
1284 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1285 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_MIXED);
1288 IRawElementProviderSimple* uia_node;
1289 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1290 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1291 UIA_ToggleToggleStatePropertyId, &native_state)));
1292 EXPECT_EQ(native_state.lVal, ToggleState_Indeterminate);
1294 ASSERT_TRUE(
SUCCEEDED(uia_node->GetPropertyValue(
1295 UIA_AriaPropertiesPropertyId, &native_state)));
1296 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"checked=mixed"),
nullptr);
1301TEST(FlutterWindowsViewTest, SwitchNativeState) {
1302 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1309 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
1310 std::make_unique<NiceMock<MockWindowBindingHandler>>());
1313 view->OnUpdateSemanticsEnabled(
true);
1315 auto bridge =
view->accessibility_bridge().lock();
1316 ASSERT_TRUE(bridge);
1320 root.label =
"root";
1323 root.increased_value =
"";
1324 root.decreased_value =
"";
1325 root.child_count = 0;
1326 root.custom_accessibility_actions_count = 0;
1331 root.flags2 = &flags;
1332 bridge->AddFlutterSemanticsNodeUpdate(root);
1334 bridge->CommitUpdates();
1337 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1339 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1343 IAccessible* native_view = root_node->GetNativeViewAccessible();
1344 ASSERT_TRUE(native_view !=
nullptr);
1347 VARIANT varchild = {};
1348 varchild.vt = VT_I4;
1350 varchild.lVal = CHILDID_SELF;
1351 VARIANT varrole = {};
1354 ASSERT_EQ(native_view->get_accRole(varchild, &varrole), S_OK);
1355 ASSERT_EQ(varrole.lVal, ROLE_SYSTEM_CHECKBUTTON);
1358 VARIANT native_state = {};
1359 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1360 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_PRESSED);
1361 EXPECT_TRUE(native_state.lVal & STATE_SYSTEM_CHECKED);
1364 IRawElementProviderSimple* uia_node;
1365 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1366 ASSERT_EQ(uia_node->GetPropertyValue(UIA_ControlTypePropertyId, &varrole),
1368 EXPECT_EQ(varrole.lVal, UIA_ButtonControlTypeId);
1369 ASSERT_EQ(uia_node->GetPropertyValue(UIA_ToggleToggleStatePropertyId,
1372 EXPECT_EQ(native_state.lVal, ToggleState_On);
1374 uia_node->GetPropertyValue(UIA_AriaPropertiesPropertyId, &native_state),
1376 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"pressed=true"),
nullptr);
1383 root.flags2 = &updated_flags;
1385 bridge->AddFlutterSemanticsNodeUpdate(root);
1386 bridge->CommitUpdates();
1389 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1391 EXPECT_EQ(root_node->GetData().GetCheckedState(),
1395 IAccessible* native_view = root_node->GetNativeViewAccessible();
1396 ASSERT_TRUE(native_view !=
nullptr);
1399 VARIANT varchild = {};
1400 varchild.vt = VT_I4;
1403 varchild.lVal = CHILDID_SELF;
1404 VARIANT native_state = {};
1405 ASSERT_TRUE(
SUCCEEDED(native_view->get_accState(varchild, &native_state)));
1406 EXPECT_FALSE(native_state.lVal & STATE_SYSTEM_PRESSED);
1407 EXPECT_FALSE(native_state.lVal & STATE_SYSTEM_CHECKED);
1410 IRawElementProviderSimple* uia_node;
1411 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1412 ASSERT_EQ(uia_node->GetPropertyValue(UIA_ToggleToggleStatePropertyId,
1415 EXPECT_EQ(native_state.lVal, ToggleState_Off);
1417 uia_node->GetPropertyValue(UIA_AriaPropertiesPropertyId, &native_state),
1419 EXPECT_NE(std::wcsstr(native_state.bstrVal, L
"pressed=false"),
nullptr);
1423TEST(FlutterWindowsViewTest, TooltipNodeData) {
1424 std::unique_ptr<FlutterWindowsEngine>
engine = GetTestEngine();
1431 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
1432 std::make_unique<NiceMock<MockWindowBindingHandler>>());
1435 view->OnUpdateSemanticsEnabled(
true);
1437 auto bridge =
view->accessibility_bridge().lock();
1438 ASSERT_TRUE(bridge);
1442 root.label =
"root";
1445 root.increased_value =
"";
1446 root.decreased_value =
"";
1447 root.tooltip =
"tooltip";
1448 root.child_count = 0;
1449 root.custom_accessibility_actions_count = 0;
1453 root.flags2 = &flags;
1454 bridge->AddFlutterSemanticsNodeUpdate(root);
1456 bridge->CommitUpdates();
1457 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
1458 std::string tooltip = root_node->GetData().GetStringAttribute(
1460 EXPECT_EQ(tooltip,
"tooltip");
1463 IAccessible* native_view = bridge->GetFlutterPlatformNodeDelegateFromID(0)
1465 ->GetNativeViewAccessible();
1466 VARIANT varchild = {.vt = VT_I4, .lVal = CHILDID_SELF};
1468 ASSERT_EQ(native_view->get_accName(varchild, &bname), S_OK);
1469 EXPECT_NE(std::wcsstr(bname, L
"tooltip"),
nullptr);
1472 IRawElementProviderSimple* uia_node;
1473 native_view->QueryInterface(IID_PPV_ARGS(&uia_node));
1475 ASSERT_EQ(uia_node->GetPropertyValue(UIA_HelpTextPropertyId, &varname), S_OK);
1476 std::string uia_tooltip = _com_util::ConvertBSTRToString(varname.bstrVal);
1477 EXPECT_EQ(uia_tooltip,
"tooltip");
1482TEST(FlutterWindowsViewTest, DisablesVSyncAtStartup) {
1483 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1484 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1485 auto egl_manager = std::make_unique<egl::MockManager>();
1487 auto surface = std::make_unique<egl::MockWindowSurface>();
1488 auto surface_ptr =
surface.get();
1490 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
false));
1491 EXPECT_CALL(*
engine.get(), PostRasterThreadTask).Times(0);
1493 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1494 .WillOnce(Return(
true));
1496 EXPECT_CALL(*egl_manager.get(), render_context)
1497 .WillOnce(Return(&render_context));
1498 EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(
true));
1501 EXPECT_CALL(*egl_manager.get(), CreateWindowSurface)
1502 .WillOnce(Return(std::move(
surface)));
1503 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
1504 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
false)).WillOnce(Return(
true));
1505 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
1507 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1510 modifier.SetEGLManager(std::move(egl_manager));
1512 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
1513 std::make_unique<NiceMock<MockWindowBindingHandler>>());
1518TEST(FlutterWindowsViewTest, EnablesVSyncAtStartup) {
1519 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1520 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1521 auto egl_manager = std::make_unique<egl::MockManager>();
1523 auto surface = std::make_unique<egl::MockWindowSurface>();
1524 auto surface_ptr =
surface.get();
1526 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
false));
1527 EXPECT_CALL(*
engine.get(), PostRasterThreadTask).Times(0);
1528 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1529 .WillOnce(Return(
false));
1531 EXPECT_CALL(*egl_manager.get(), render_context)
1532 .WillOnce(Return(&render_context));
1533 EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(
true));
1536 EXPECT_CALL(*egl_manager.get(), CreateWindowSurface)
1537 .WillOnce(Return(std::move(
surface)));
1538 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
1539 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
true)).WillOnce(Return(
true));
1540 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
1542 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1545 modifier.SetEGLManager(std::move(egl_manager));
1547 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
1548 std::make_unique<NiceMock<MockWindowBindingHandler>>());
1553TEST(FlutterWindowsViewTest, DisablesVSyncAfterStartup) {
1554 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1555 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1556 auto egl_manager = std::make_unique<egl::MockManager>();
1558 auto surface = std::make_unique<egl::MockWindowSurface>();
1559 auto surface_ptr =
surface.get();
1561 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
true));
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(*
engine.get(), PostRasterThreadTask)
1577 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
1578 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
false)).WillOnce(Return(
true));
1579 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
1580 EXPECT_CALL(*
engine.get(), PostRasterThreadTask)
1585 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1588 modifier.SetEGLManager(std::move(egl_manager));
1590 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
1591 std::make_unique<NiceMock<MockWindowBindingHandler>>());
1596TEST(FlutterWindowsViewTest, EnablesVSyncAfterStartup) {
1597 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1598 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1599 auto egl_manager = std::make_unique<egl::MockManager>();
1601 auto surface = std::make_unique<egl::MockWindowSurface>();
1602 auto surface_ptr =
surface.get();
1604 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
true));
1606 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1607 .WillOnce(Return(
false));
1609 EXPECT_CALL(*egl_manager.get(), render_context)
1610 .WillOnce(Return(&render_context));
1611 EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(
true));
1614 EXPECT_CALL(*egl_manager.get(), CreateWindowSurface)
1615 .WillOnce(Return(std::move(
surface)));
1616 EXPECT_CALL(*
engine.get(), PostRasterThreadTask)
1622 EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(
true));
1623 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
true)).WillOnce(Return(
true));
1624 EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(
true));
1626 EXPECT_CALL(*
engine.get(), PostRasterThreadTask)
1631 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1634 modifier.SetEGLManager(std::move(egl_manager));
1636 std::unique_ptr<FlutterWindowsView>
view =
engine->CreateView(
1637 std::make_unique<NiceMock<MockWindowBindingHandler>>());
1643TEST(FlutterWindowsViewTest, UpdatesVSyncOnDwmUpdates) {
1644 auto windows_proc_table = std::make_shared<MockWindowsProcTable>();
1645 auto engine = std::make_unique<MockFlutterWindowsEngine>(windows_proc_table);
1646 auto egl_manager = std::make_unique<egl::MockManager>();
1648 auto surface = std::make_unique<egl::MockWindowSurface>();
1649 auto surface_ptr =
surface.get();
1651 EXPECT_CALL(*
engine.get(), running).WillRepeatedly(Return(
true));
1653 EXPECT_CALL(*
engine.get(), PostRasterThreadTask)
1659 EXPECT_CALL(*egl_manager.get(), render_context)
1660 .WillRepeatedly(Return(&render_context));
1662 EXPECT_CALL(*surface_ptr, IsValid).WillRepeatedly(Return(
true));
1663 EXPECT_CALL(*surface_ptr, MakeCurrent).WillRepeatedly(Return(
true));
1664 EXPECT_CALL(*surface_ptr, Destroy).Times(1);
1665 EXPECT_CALL(render_context, ClearCurrent).WillRepeatedly(Return(
true));
1670 std::unique_ptr<FlutterWindowsView>
view;
1672 EXPECT_CALL(*egl_manager, CreateWindowSurface)
1673 .WillOnce(Return(std::move(
surface)));
1674 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1675 .WillOnce(Return(
true));
1676 EXPECT_CALL(*surface_ptr, SetVSyncEnabled).WillOnce(Return(
true));
1679 engine_modifier.SetEGLManager(std::move(egl_manager));
1682 std::make_unique<NiceMock<MockWindowBindingHandler>>());
1687 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1688 .WillOnce(Return(
false));
1689 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
true)).WillOnce(Return(
true));
1691 engine->OnDwmCompositionChanged();
1696 EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled)
1697 .WillOnce(Return(
true));
1698 EXPECT_CALL(*surface_ptr, SetVSyncEnabled(
false)).WillOnce(Return(
true));
1700 engine->OnDwmCompositionChanged();