5#include "flutter/shell/platform/windows/accessibility_bridge_windows.h"
13#include "flutter/fml/macros.h"
14#include "flutter/shell/platform/embedder/embedder.h"
15#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
16#include "flutter/shell/platform/windows/flutter_platform_node_delegate_windows.h"
17#include "flutter/shell/platform/windows/flutter_windows_engine.h"
18#include "flutter/shell/platform/windows/flutter_windows_view.h"
19#include "flutter/shell/platform/windows/testing/engine_modifier.h"
20#include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
21#include "flutter/shell/platform/windows/testing/test_keyboard.h"
22#include "gmock/gmock.h"
23#include "gtest/gtest.h"
29using ::testing::NiceMock;
38class AccessibilityBridgeWindowsSpy :
public AccessibilityBridgeWindows {
42 explicit AccessibilityBridgeWindowsSpy(FlutterWindowsEngine*
engine,
43 FlutterWindowsView* view)
44 : AccessibilityBridgeWindows(view) {}
46 void DispatchWinAccessibilityEvent(
47 std::shared_ptr<FlutterPlatformNodeDelegateWindows>
node_delegate,
52 void SetFocus(std::shared_ptr<FlutterPlatformNodeDelegateWindows>
58 dispatched_events_.clear();
59 focused_nodes_.clear();
62 const std::vector<MsaaEvent>& dispatched_events()
const {
63 return dispatched_events_;
66 const std::vector<int32_t> focused_nodes()
const {
67 std::vector<int32_t> ids;
69 std::back_inserter(ids),
70 [](std::shared_ptr<FlutterPlatformNodeDelegate> node) {
71 return node->GetAXNode()->id();
77 std::weak_ptr<FlutterPlatformNodeDelegate> GetFocusedNode()
override {
78 return focused_nodes_.back();
82 std::vector<MsaaEvent> dispatched_events_;
83 std::vector<std::shared_ptr<FlutterPlatformNodeDelegate>> focused_nodes_;
90class FlutterWindowsViewSpy :
public FlutterWindowsView {
92 FlutterWindowsViewSpy(FlutterWindowsEngine*
engine,
93 std::unique_ptr<WindowBindingHandler> handler)
97 virtual std::shared_ptr<AccessibilityBridgeWindows>
98 CreateAccessibilityBridge()
override {
99 return std::make_shared<AccessibilityBridgeWindowsSpy>(GetEngine(),
this);
109std::unique_ptr<FlutterWindowsEngine> GetTestEngine() {
114 FlutterProjectBundle project(properties);
115 auto engine = std::make_unique<FlutterWindowsEngine>(project);
117 EngineModifier modifier(
engine.get());
118 modifier.embedder_api().UpdateSemanticsEnabled =
124 std::make_shared<MockKeyResponseController>());
140void PopulateAXTree(std::shared_ptr<AccessibilityBridge> bridge) {
143 std::vector<int32_t> node0_children{1, 2};
145 node0.children_in_traversal_order = node0_children.data();
146 node0.children_in_hit_test_order = node0_children.data();
150 node1.
label =
"prefecture";
151 node1.value =
"Kyoto";
155 std::vector<int32_t> node2_children{3, 4};
157 node2.children_in_traversal_order = node2_children.data();
158 node2.children_in_hit_test_order = node2_children.data();
162 node3.
label =
"city";
168 bridge->AddFlutterSemanticsNodeUpdate(node0);
169 bridge->AddFlutterSemanticsNodeUpdate(node1);
170 bridge->AddFlutterSemanticsNodeUpdate(node2);
171 bridge->AddFlutterSemanticsNodeUpdate(node3);
172 bridge->AddFlutterSemanticsNodeUpdate(node4);
173 bridge->CommitUpdates();
176ui::AXNode* AXNodeFromID(std::shared_ptr<AccessibilityBridge> bridge,
178 auto node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(
id).lock();
182std::shared_ptr<AccessibilityBridgeWindowsSpy> GetAccessibilityBridgeSpy(
183 FlutterWindowsView& view) {
184 return std::static_pointer_cast<AccessibilityBridgeWindowsSpy>(
185 view.accessibility_bridge().lock());
188void ExpectWinEventFromAXEvent(int32_t node_id,
191 auto engine = GetTestEngine();
192 FlutterWindowsViewSpy view{
193 engine.get(), std::make_unique<NiceMock<MockWindowBindingHandler>>()};
194 EngineModifier modifier{
engine.get()};
195 modifier.SetImplicitView(&view);
196 view.OnUpdateSemanticsEnabled(
true);
198 auto bridge = GetAccessibilityBridgeSpy(view);
199 PopulateAXTree(bridge);
201 bridge->ResetRecords();
202 bridge->OnAccessibilityEvent({AXNodeFromID(bridge, node_id),
204 ASSERT_EQ(bridge->dispatched_events().size(), 1);
205 EXPECT_EQ(bridge->dispatched_events()[0].event_type, expected_event);
208void ExpectWinEventFromAXEventOnFocusNode(int32_t node_id,
212 auto engine = GetTestEngine();
213 FlutterWindowsViewSpy view{
214 engine.get(), std::make_unique<NiceMock<MockWindowBindingHandler>>()};
215 EngineModifier modifier{
engine.get()};
216 modifier.SetImplicitView(&view);
217 view.OnUpdateSemanticsEnabled(
true);
219 auto bridge = GetAccessibilityBridgeSpy(view);
220 PopulateAXTree(bridge);
222 bridge->ResetRecords();
223 auto focus_delegate =
224 bridge->GetFlutterPlatformNodeDelegateFromID(focus_id).lock();
225 bridge->SetFocus(std::static_pointer_cast<FlutterPlatformNodeDelegateWindows>(
227 bridge->OnAccessibilityEvent({AXNodeFromID(bridge, node_id),
229 ASSERT_EQ(bridge->dispatched_events().size(), 1);
230 EXPECT_EQ(bridge->dispatched_events()[0].event_type, expected_event);
231 EXPECT_EQ(bridge->dispatched_events()[0].node_delegate->GetAXNode()->id(),
238 auto engine = GetTestEngine();
239 FlutterWindowsViewSpy view{
240 engine.get(), std::make_unique<NiceMock<MockWindowBindingHandler>>()};
242 modifier.SetImplicitView(&view);
243 view.OnUpdateSemanticsEnabled(
true);
245 auto bridge = view.accessibility_bridge().lock();
246 PopulateAXTree(bridge);
248 auto node0_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
249 auto node1_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
250 EXPECT_EQ(node0_delegate->GetNativeViewAccessible(),
251 node1_delegate->GetParent());
255 auto engine = GetTestEngine();
256 FlutterWindowsViewSpy view{
257 engine.get(), std::make_unique<NiceMock<MockWindowBindingHandler>>()};
259 modifier.SetImplicitView(&view);
260 view.OnUpdateSemanticsEnabled(
true);
262 auto bridge = view.accessibility_bridge().lock();
263 PopulateAXTree(bridge);
265 auto node0_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
266 ASSERT_TRUE(node0_delegate->GetParent() ==
nullptr);
270 auto engine = GetTestEngine();
271 FlutterWindowsViewSpy view{
272 engine.get(), std::make_unique<NiceMock<MockWindowBindingHandler>>()};
274 modifier.SetImplicitView(&view);
275 view.OnUpdateSemanticsEnabled(
true);
277 auto bridge = view.accessibility_bridge().lock();
278 PopulateAXTree(bridge);
285 size_t data_length) {
306 auto engine = GetTestEngine();
307 FlutterWindowsViewSpy view{
308 engine.get(), std::make_unique<NiceMock<MockWindowBindingHandler>>()};
310 modifier.SetImplicitView(&view);
311 view.OnUpdateSemanticsEnabled(
true);
313 auto bridge = GetAccessibilityBridgeSpy(view);
314 PopulateAXTree(bridge);
316 bridge->ResetRecords();
317 bridge->OnAccessibilityEvent({AXNodeFromID(bridge, 1),
321 ASSERT_EQ(bridge->dispatched_events().size(), 1);
322 EXPECT_EQ(bridge->dispatched_events()[0].event_type,
325 ASSERT_EQ(bridge->focused_nodes().size(), 1);
326 EXPECT_EQ(bridge->focused_nodes()[0], 1);
336 ExpectWinEventFromAXEvent(
352 ExpectWinEventFromAXEvent(
358 ExpectWinEventFromAXEvent(
369 ExpectWinEventFromAXEvent(
385 ExpectWinEventFromAXEvent(
391 ExpectWinEventFromAXEventOnFocusNode(
std::shared_ptr< FlutterPlatformNodeDelegateWindows > node_delegate
ax::mojom::Event event_type
void DispatchAccessibilityAction(AccessibilityNodeId target, FlutterSemanticsAction action, fml::MallocMapping data) override
Dispatch accessibility action back to the Flutter framework. These actions are generated in the nativ...
void OnAccessibilityEvent(ui::AXEventGenerator::TargetedEvent targeted_event) override
Handle accessibility events generated due to accessibility tree changes. These events are needed to b...
@ DOCUMENT_SELECTION_CHANGED
@ SCROLL_HORIZONTAL_POSITION_CHANGED
@ IMAGE_ANNOTATION_CHANGED
@ WIN_IACCESSIBLE_STATE_CHANGED
@ SCROLL_VERTICAL_POSITION_CHANGED
@ SELECTED_CHILDREN_CHANGED
struct _FlutterEngine * FLUTTER_API_SYMBOL(FlutterEngine)
@ kFlutterSemanticsActionCopy
Copy the current selection to the clipboard.
@ kFlutterSemanticsActionTap
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
@ kSelectedChildrenChanged
@ kDocumentSelectionChanged
void MockEmbedderApiForKeyboard(EngineModifier &modifier, std::shared_ptr< MockKeyResponseController > response_controller)
TEST(DisplayListComplexity, EmptyDisplayList)
constexpr int64_t kImplicitViewId
static void DispatchSemanticsAction(JNIEnv *env, jobject jcaller, jlong shell_holder, jint id, jint action, jobject args, jint args_position)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
#define MOCK_ENGINE_PROC(proc, mock_impl)
const char * aot_library_path
const char * icu_data_path
size_t child_count
The number of children this node has.
const char * label
A textual description of the node.