Flutter iOS Embedder
SemanticsObjectTest.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #import <OCMock/OCMock.h>
6 #import <XCTest/XCTest.h>
7 
11 
13 
14 @interface SemanticsObjectTest : XCTestCase
15 @end
16 
17 @implementation SemanticsObjectTest
18 
19 - (void)testCreate {
20  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
21  new flutter::MockAccessibilityBridge());
22  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
23  SemanticsObject* object = [[SemanticsObject alloc] initWithBridge:bridge uid:0];
24  XCTAssertNotNil(object);
25 }
26 
27 - (void)testSetChildren {
28  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
29  new flutter::MockAccessibilityBridge());
30  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
31  SemanticsObject* parent = [[SemanticsObject alloc] initWithBridge:bridge uid:0];
32  SemanticsObject* child = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
33  parent.children = @[ child ];
34  XCTAssertEqual(parent, child.parent);
35  parent.children = @[];
36  XCTAssertNil(child.parent);
37 }
38 
39 - (void)testAccessibilityHitTestFocusAtLeaf {
40  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
41  new flutter::MockAccessibilityBridge());
42  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
43  SemanticsObject* object0 = [[SemanticsObject alloc] initWithBridge:bridge uid:0];
44  SemanticsObject* object1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
45  SemanticsObject* object2 = [[SemanticsObject alloc] initWithBridge:bridge uid:2];
46  SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3];
47  object0.children = @[ object1 ];
48  object0.childrenInHitTestOrder = @[ object1 ];
49  object1.children = @[ object2, object3 ];
50  object1.childrenInHitTestOrder = @[ object2, object3 ];
51 
52  flutter::SemanticsNode node0;
53  node0.id = 0;
54  node0.rect = SkRect::MakeXYWH(0, 0, 200, 200);
55  node0.label = "0";
56  [object0 setSemanticsNode:&node0];
57 
58  flutter::SemanticsNode node1;
59  node1.id = 1;
60  node1.rect = SkRect::MakeXYWH(0, 0, 200, 200);
61  node1.label = "1";
62  [object1 setSemanticsNode:&node1];
63 
64  flutter::SemanticsNode node2;
65  node2.id = 2;
66  node2.rect = SkRect::MakeXYWH(0, 0, 100, 100);
67  node2.label = "2";
68  [object2 setSemanticsNode:&node2];
69 
70  flutter::SemanticsNode node3;
71  node3.id = 3;
72  node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
73  node3.label = "3";
74  [object3 setSemanticsNode:&node3];
75 
76  CGPoint point = CGPointMake(10, 10);
77  id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil];
78 
79  // Focus to object2 because it's the first object in hit test order
80  XCTAssertEqual(hitTestResult, object2);
81 }
82 
83 - (void)testAccessibilityHitTestNoFocusableItem {
84  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
85  new flutter::MockAccessibilityBridge());
86  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
87  SemanticsObject* object0 = [[SemanticsObject alloc] initWithBridge:bridge uid:0];
88  SemanticsObject* object1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
89  SemanticsObject* object2 = [[SemanticsObject alloc] initWithBridge:bridge uid:2];
90  SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3];
91  object0.children = @[ object1 ];
92  object0.childrenInHitTestOrder = @[ object1 ];
93  object1.children = @[ object2, object3 ];
94  object1.childrenInHitTestOrder = @[ object2, object3 ];
95 
96  flutter::SemanticsNode node0;
97  node0.id = 0;
98  node0.rect = SkRect::MakeXYWH(0, 0, 200, 200);
99  [object0 setSemanticsNode:&node0];
100 
101  flutter::SemanticsNode node1;
102  node1.id = 1;
103  node1.rect = SkRect::MakeXYWH(0, 0, 200, 200);
104  [object1 setSemanticsNode:&node1];
105 
106  flutter::SemanticsNode node2;
107  node2.id = 2;
108  node2.rect = SkRect::MakeXYWH(0, 0, 100, 100);
109  [object2 setSemanticsNode:&node2];
110 
111  flutter::SemanticsNode node3;
112  node3.id = 3;
113  node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
114  [object3 setSemanticsNode:&node3];
115 
116  CGPoint point = CGPointMake(10, 10);
117  id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil];
118 
119  XCTAssertNil(hitTestResult);
120 }
121 
122 - (void)testAccessibilityScrollToVisible {
123  fml::WeakPtrFactory<flutter::MockAccessibilityBridge> factory(
124  new flutter::MockAccessibilityBridge());
125  fml::WeakPtr<flutter::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
126  SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3];
127 
128  flutter::SemanticsNode node3;
129  node3.id = 3;
130  node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
131  [object3 setSemanticsNode:&node3];
132 
134 
135  XCTAssertTrue(bridge->observations.size() == 1);
136  XCTAssertTrue(bridge->observations[0].id == 3);
137  XCTAssertTrue(bridge->observations[0].action == flutter::SemanticsAction::kShowOnScreen);
138 }
139 
140 - (void)testAccessibilityScrollToVisibleWithChild {
141  fml::WeakPtrFactory<flutter::MockAccessibilityBridge> factory(
142  new flutter::MockAccessibilityBridge());
143  fml::WeakPtr<flutter::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
144  SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3];
145 
146  flutter::SemanticsNode node3;
147  node3.id = 3;
148  node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
149  [object3 setSemanticsNode:&node3];
150 
151  [object3 accessibilityScrollToVisibleWithChild:object3];
152 
153  XCTAssertTrue(bridge->observations.size() == 1);
154  XCTAssertTrue(bridge->observations[0].id == 3);
155  XCTAssertTrue(bridge->observations[0].action == flutter::SemanticsAction::kShowOnScreen);
156 }
157 
158 - (void)testAccessibilityHitTestOutOfRect {
159  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
160  new flutter::MockAccessibilityBridge());
161  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
162  SemanticsObject* object0 = [[SemanticsObject alloc] initWithBridge:bridge uid:0];
163  SemanticsObject* object1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
164  SemanticsObject* object2 = [[SemanticsObject alloc] initWithBridge:bridge uid:2];
165  SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3];
166  object0.children = @[ object1 ];
167  object0.childrenInHitTestOrder = @[ object1 ];
168  object1.children = @[ object2, object3 ];
169  object1.childrenInHitTestOrder = @[ object2, object3 ];
170 
171  flutter::SemanticsNode node0;
172  node0.id = 0;
173  node0.rect = SkRect::MakeXYWH(0, 0, 200, 200);
174  node0.label = "0";
175  [object0 setSemanticsNode:&node0];
176 
177  flutter::SemanticsNode node1;
178  node1.id = 1;
179  node1.rect = SkRect::MakeXYWH(0, 0, 200, 200);
180  node1.label = "1";
181  [object1 setSemanticsNode:&node1];
182 
183  flutter::SemanticsNode node2;
184  node2.id = 2;
185  node2.rect = SkRect::MakeXYWH(0, 0, 100, 100);
186  node2.label = "2";
187  [object2 setSemanticsNode:&node2];
188 
189  flutter::SemanticsNode node3;
190  node3.id = 3;
191  node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
192  node3.label = "3";
193  [object3 setSemanticsNode:&node3];
194 
195  CGPoint point = CGPointMake(300, 300);
196  id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil];
197 
198  XCTAssertNil(hitTestResult);
199 }
200 
201 - (void)testReplaceChildAtIndex {
202  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
203  new flutter::MockAccessibilityBridge());
204  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
205  SemanticsObject* parent = [[SemanticsObject alloc] initWithBridge:bridge uid:0];
206  SemanticsObject* child1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
207  SemanticsObject* child2 = [[SemanticsObject alloc] initWithBridge:bridge uid:2];
208  parent.children = @[ child1 ];
209  [parent replaceChildAtIndex:0 withChild:child2];
210  XCTAssertNil(child1.parent);
211  XCTAssertEqual(parent, child2.parent);
212  XCTAssertEqualObjects(parent.children, @[ child2 ]);
213 }
214 
215 - (void)testPlainSemanticsObjectWithLabelHasStaticTextTrait {
216  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
217  new flutter::MockAccessibilityBridge());
218  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
219  flutter::SemanticsNode node;
220  node.label = "foo";
221  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
222  [object setSemanticsNode:&node];
223  XCTAssertEqual([object accessibilityTraits], UIAccessibilityTraitStaticText);
224 }
225 
226 - (void)testNodeWithImplicitScrollIsAnAccessibilityElementWhenItisHidden {
227  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
228  new flutter::MockAccessibilityBridge());
229  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
230  flutter::SemanticsNode node;
231  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling) |
232  static_cast<int32_t>(flutter::SemanticsFlags::kIsHidden);
233  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
234  [object setSemanticsNode:&node];
235  XCTAssertEqual(object.isAccessibilityElement, YES);
236 }
237 
238 - (void)testNodeWithImplicitScrollIsNotAnAccessibilityElementWhenItisNotHidden {
239  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
240  new flutter::MockAccessibilityBridge());
241  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
242  flutter::SemanticsNode node;
243  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
244  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
245  [object setSemanticsNode:&node];
246  XCTAssertEqual(object.isAccessibilityElement, NO);
247 }
248 
249 - (void)testIntresetingSemanticsObjectWithLabelHasStaticTextTrait {
250  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
251  new flutter::MockAccessibilityBridge());
252  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
253  flutter::SemanticsNode node;
254  node.label = "foo";
255  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
256  SemanticsObject* child1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
257  object.children = @[ child1 ];
258  [object setSemanticsNode:&node];
259  XCTAssertEqual([object accessibilityTraits], UIAccessibilityTraitNone);
260 }
261 
262 - (void)testIntresetingSemanticsObjectWithLabelHasStaticTextTrait1 {
263  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
264  new flutter::MockAccessibilityBridge());
265  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
266  flutter::SemanticsNode node;
267  node.label = "foo";
268  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kIsTextField);
269  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
270  [object setSemanticsNode:&node];
271  XCTAssertEqual([object accessibilityTraits], UIAccessibilityTraitNone);
272 }
273 
274 - (void)testIntresetingSemanticsObjectWithLabelHasStaticTextTrait2 {
275  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
276  new flutter::MockAccessibilityBridge());
277  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
278  flutter::SemanticsNode node;
279  node.label = "foo";
280  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kIsButton);
281  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
282  [object setSemanticsNode:&node];
283  XCTAssertEqual([object accessibilityTraits], UIAccessibilityTraitButton);
284 }
285 
286 - (void)testVerticalFlutterScrollableSemanticsObject {
287  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
288  new flutter::MockAccessibilityBridge());
289  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
290 
291  float transformScale = 0.5f;
292  float screenScale = [[bridge->view() window] screen].scale;
293  float effectivelyScale = transformScale / screenScale;
294  float x = 10;
295  float y = 10;
296  float w = 100;
297  float h = 200;
298  float scrollExtentMax = 500.0;
299  float scrollPosition = 150.0;
300 
301  flutter::SemanticsNode node;
302  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
303  node.actions = flutter::kVerticalScrollSemanticsActions;
304  node.rect = SkRect::MakeXYWH(x, y, w, h);
305  node.scrollExtentMax = scrollExtentMax;
306  node.scrollPosition = scrollPosition;
307  node.transform = {
308  transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
310  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:0];
311  [scrollable setSemanticsNode:&node];
313  UIScrollView* scrollView = [scrollable nativeAccessibility];
314  XCTAssertTrue(
315  CGRectEqualToRect(scrollView.frame, CGRectMake(x * effectivelyScale, y * effectivelyScale,
316  w * effectivelyScale, h * effectivelyScale)));
317  XCTAssertTrue(CGSizeEqualToSize(
318  scrollView.contentSize,
319  CGSizeMake(w * effectivelyScale, (h + scrollExtentMax) * effectivelyScale)));
320  XCTAssertTrue(CGPointEqualToPoint(scrollView.contentOffset,
321  CGPointMake(0, scrollPosition * effectivelyScale)));
322 }
323 
324 - (void)testVerticalFlutterScrollableSemanticsObjectNoWindowDoesNotCrash {
325  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
326  new flutter::MockAccessibilityBridgeNoWindow());
327  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
328 
329  float transformScale = 0.5f;
330  float x = 10;
331  float y = 10;
332  float w = 100;
333  float h = 200;
334  float scrollExtentMax = 500.0;
335  float scrollPosition = 150.0;
336 
337  flutter::SemanticsNode node;
338  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
339  node.actions = flutter::kVerticalScrollSemanticsActions;
340  node.rect = SkRect::MakeXYWH(x, y, w, h);
341  node.scrollExtentMax = scrollExtentMax;
342  node.scrollPosition = scrollPosition;
343  node.transform = {
344  transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
346  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:0];
347  [scrollable setSemanticsNode:&node];
349  XCTAssertNoThrow([scrollable accessibilityBridgeDidFinishUpdate]);
350 }
351 
352 - (void)testHorizontalFlutterScrollableSemanticsObject {
353  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
354  new flutter::MockAccessibilityBridge());
355  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
356 
357  float transformScale = 0.5f;
358  float screenScale = [[bridge->view() window] screen].scale;
359  float effectivelyScale = transformScale / screenScale;
360  float x = 10;
361  float y = 10;
362  float w = 100;
363  float h = 200;
364  float scrollExtentMax = 500.0;
365  float scrollPosition = 150.0;
366 
367  flutter::SemanticsNode node;
368  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
369  node.actions = flutter::kHorizontalScrollSemanticsActions;
370  node.rect = SkRect::MakeXYWH(x, y, w, h);
371  node.scrollExtentMax = scrollExtentMax;
372  node.scrollPosition = scrollPosition;
373  node.transform = {
374  transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
376  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:0];
377  [scrollable setSemanticsNode:&node];
379  UIScrollView* scrollView = [scrollable nativeAccessibility];
380  XCTAssertTrue(
381  CGRectEqualToRect(scrollView.frame, CGRectMake(x * effectivelyScale, y * effectivelyScale,
382  w * effectivelyScale, h * effectivelyScale)));
383  XCTAssertTrue(CGSizeEqualToSize(
384  scrollView.contentSize,
385  CGSizeMake((w + scrollExtentMax) * effectivelyScale, h * effectivelyScale)));
386  XCTAssertTrue(CGPointEqualToPoint(scrollView.contentOffset,
387  CGPointMake(scrollPosition * effectivelyScale, 0)));
388 }
389 
390 - (void)testCanHandleInfiniteScrollExtent {
391  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
392  new flutter::MockAccessibilityBridge());
393  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
394 
395  float transformScale = 0.5f;
396  float screenScale = [[bridge->view() window] screen].scale;
397  float effectivelyScale = transformScale / screenScale;
398  float x = 10;
399  float y = 10;
400  float w = 100;
401  float h = 200;
402  float scrollExtentMax = INFINITY;
403  float scrollPosition = 150.0;
404 
405  flutter::SemanticsNode node;
406  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
407  node.actions = flutter::kVerticalScrollSemanticsActions;
408  node.rect = SkRect::MakeXYWH(x, y, w, h);
409  node.scrollExtentMax = scrollExtentMax;
410  node.scrollPosition = scrollPosition;
411  node.transform = {
412  transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
414  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:0];
415  [scrollable setSemanticsNode:&node];
417  UIScrollView* scrollView = [scrollable nativeAccessibility];
418  XCTAssertTrue(
419  CGRectEqualToRect(scrollView.frame, CGRectMake(x * effectivelyScale, y * effectivelyScale,
420  w * effectivelyScale, h * effectivelyScale)));
421  XCTAssertTrue(CGSizeEqualToSize(
422  scrollView.contentSize,
423  CGSizeMake(w * effectivelyScale,
424  (h + kScrollExtentMaxForInf + scrollPosition) * effectivelyScale)));
425  XCTAssertTrue(CGPointEqualToPoint(scrollView.contentOffset,
426  CGPointMake(0, scrollPosition * effectivelyScale)));
427 }
428 
429 - (void)testCanHandleNaNScrollExtentAndScrollPoisition {
430  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
431  new flutter::MockAccessibilityBridge());
432  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
433 
434  float transformScale = 0.5f;
435  float screenScale = [[bridge->view() window] screen].scale;
436  float effectivelyScale = transformScale / screenScale;
437  float x = 10;
438  float y = 10;
439  float w = 100;
440  float h = 200;
441  float scrollExtentMax = std::nan("");
442  float scrollPosition = std::nan("");
443 
444  flutter::SemanticsNode node;
445  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
446  node.actions = flutter::kVerticalScrollSemanticsActions;
447  node.rect = SkRect::MakeXYWH(x, y, w, h);
448  node.scrollExtentMax = scrollExtentMax;
449  node.scrollPosition = scrollPosition;
450  node.transform = {
451  transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
453  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:0];
454  [scrollable setSemanticsNode:&node];
456  UIScrollView* scrollView = [scrollable nativeAccessibility];
457  XCTAssertTrue(
458  CGRectEqualToRect(scrollView.frame, CGRectMake(x * effectivelyScale, y * effectivelyScale,
459  w * effectivelyScale, h * effectivelyScale)));
460  // Content size equal to the scrollable size.
461  XCTAssertTrue(CGSizeEqualToSize(scrollView.contentSize,
462  CGSizeMake(w * effectivelyScale, h * effectivelyScale)));
463  XCTAssertTrue(CGPointEqualToPoint(scrollView.contentOffset, CGPointMake(0, 0)));
464 }
465 
466 - (void)testFlutterScrollableSemanticsObjectIsNotHittestable {
467  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
468  new flutter::MockAccessibilityBridge());
469  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
470 
471  flutter::SemanticsNode node;
472  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
473  node.actions = flutter::kHorizontalScrollSemanticsActions;
474  node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
475  node.scrollExtentMax = 100.0;
476  node.scrollPosition = 0.0;
477 
479  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:0];
480  [scrollable setSemanticsNode:&node];
482  UIScrollView* scrollView = [scrollable nativeAccessibility];
483  XCTAssertEqual([scrollView hitTest:CGPointMake(10, 10) withEvent:nil], nil);
484 }
485 
486 - (void)testFlutterScrollableSemanticsObjectIsHiddenWhenVoiceOverIsRunning {
487  flutter::MockAccessibilityBridge* mock = new flutter::MockAccessibilityBridge();
488  mock->isVoiceOverRunningValue = false;
489  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
490  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
491 
492  flutter::SemanticsNode node;
493  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
494  node.actions = flutter::kHorizontalScrollSemanticsActions;
495  node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
496  node.scrollExtentMax = 100.0;
497  node.scrollPosition = 0.0;
498 
500  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:0];
501  [scrollable setSemanticsNode:&node];
503  UIScrollView* scrollView = [scrollable nativeAccessibility];
504  XCTAssertTrue(scrollView.isAccessibilityElement);
505  mock->isVoiceOverRunningValue = true;
506  XCTAssertFalse(scrollView.isAccessibilityElement);
507 }
508 
509 - (void)testFlutterScrollableSemanticsObjectWithLabelValueHintIsNotHiddenWhenVoiceOverIsRunning {
510  flutter::MockAccessibilityBridge* mock = new flutter::MockAccessibilityBridge();
511  mock->isVoiceOverRunningValue = true;
512  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
513  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
514 
515  flutter::SemanticsNode node;
516  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
517  node.actions = flutter::kHorizontalScrollSemanticsActions;
518  node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
519  node.label = "label";
520  node.value = "value";
521  node.hint = "hint";
522  node.scrollExtentMax = 100.0;
523  node.scrollPosition = 0.0;
524 
526  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:0];
527  [scrollable setSemanticsNode:&node];
529  UIScrollView* scrollView = [scrollable nativeAccessibility];
530  XCTAssertTrue(scrollView.isAccessibilityElement);
531  XCTAssertTrue(
532  [scrollView.accessibilityLabel isEqualToString:NSLocalizedString(@"label", @"test")]);
533  XCTAssertTrue(
534  [scrollView.accessibilityValue isEqualToString:NSLocalizedString(@"value", @"test")]);
535  XCTAssertTrue([scrollView.accessibilityHint isEqualToString:NSLocalizedString(@"hint", @"test")]);
536 }
537 
538 - (void)testFlutterSemanticsObjectMergeTooltipToLabel {
539  flutter::MockAccessibilityBridge* mock = new flutter::MockAccessibilityBridge();
540  mock->isVoiceOverRunningValue = true;
541  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
542  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
543 
544  flutter::SemanticsNode node;
545  node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
546  node.label = "label";
547  node.tooltip = "tooltip";
548  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
549  [object setSemanticsNode:&node];
550  XCTAssertTrue(object.isAccessibilityElement);
551  XCTAssertTrue([object.accessibilityLabel isEqualToString:@"label\ntooltip"]);
552 }
553 
554 - (void)testFlutterSemanticsObjectAttributedStringsDoNotCrashWhenEmpty {
555  flutter::MockAccessibilityBridge* mock = new flutter::MockAccessibilityBridge();
556  mock->isVoiceOverRunningValue = true;
557  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
558  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
559 
560  flutter::SemanticsNode node;
561  node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
562  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
563  [object setSemanticsNode:&node];
564  XCTAssertTrue(object.accessibilityAttributedLabel == nil);
565 }
566 
567 - (void)testFlutterScrollableSemanticsObjectReturnsParentContainerIfNoChildren {
568  flutter::MockAccessibilityBridge* mock = new flutter::MockAccessibilityBridge();
569  mock->isVoiceOverRunningValue = true;
570  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
571  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
572 
573  flutter::SemanticsNode parent;
574  parent.id = 0;
575  parent.rect = SkRect::MakeXYWH(0, 0, 100, 200);
576  parent.label = "label";
577  parent.value = "value";
578  parent.hint = "hint";
579 
580  flutter::SemanticsNode node;
581  node.id = 1;
582  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
583  node.actions = flutter::kHorizontalScrollSemanticsActions;
584  node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
585  node.label = "label";
586  node.value = "value";
587  node.hint = "hint";
588  node.scrollExtentMax = 100.0;
589  node.scrollPosition = 0.0;
590  parent.childrenInTraversalOrder.push_back(1);
591 
592  FlutterSemanticsObject* parentObject = [[FlutterSemanticsObject alloc] initWithBridge:bridge
593  uid:0];
594  [parentObject setSemanticsNode:&parent];
595 
597  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:1];
598  [scrollable setSemanticsNode:&node];
599  UIScrollView* scrollView = [scrollable nativeAccessibility];
600 
601  parentObject.children = @[ scrollable ];
602  [parentObject accessibilityBridgeDidFinishUpdate];
604  XCTAssertTrue(scrollView.isAccessibilityElement);
605  SemanticsObjectContainer* container =
606  static_cast<SemanticsObjectContainer*>(scrollable.accessibilityContainer);
607  XCTAssertEqual(container.semanticsObject, parentObject);
608 }
609 
610 - (void)testFlutterScrollableSemanticsObjectHidesScrollBar {
611  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
612  new flutter::MockAccessibilityBridge());
613  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
614 
615  flutter::SemanticsNode node;
616  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
617  node.actions = flutter::kHorizontalScrollSemanticsActions;
618  node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
619  node.scrollExtentMax = 100.0;
620  node.scrollPosition = 0.0;
621 
623  [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:0];
624  [scrollable setSemanticsNode:&node];
626  UIScrollView* scrollView = [scrollable nativeAccessibility];
627 
628  XCTAssertFalse(scrollView.showsHorizontalScrollIndicator);
629  XCTAssertFalse(scrollView.showsVerticalScrollIndicator);
630 }
631 
632 - (void)testSemanticsObjectBuildsAttributedString {
633  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
634  new flutter::MockAccessibilityBridge());
635  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
636  flutter::SemanticsNode node;
637  node.label = "label";
638  std::shared_ptr<flutter::SpellOutStringAttribute> attribute =
639  std::make_shared<flutter::SpellOutStringAttribute>();
640  attribute->start = 1;
641  attribute->end = 2;
642  attribute->type = flutter::StringAttributeType::kSpellOut;
643  node.labelAttributes.push_back(attribute);
644  node.value = "value";
645  attribute = std::make_shared<flutter::SpellOutStringAttribute>();
646  attribute->start = 2;
647  attribute->end = 3;
648  attribute->type = flutter::StringAttributeType::kSpellOut;
649  node.valueAttributes.push_back(attribute);
650  node.hint = "hint";
651  std::shared_ptr<flutter::LocaleStringAttribute> local_attribute =
652  std::make_shared<flutter::LocaleStringAttribute>();
653  local_attribute->start = 3;
654  local_attribute->end = 4;
655  local_attribute->type = flutter::StringAttributeType::kLocale;
656  local_attribute->locale = "en-MX";
657  node.hintAttributes.push_back(local_attribute);
658  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
659  [object setSemanticsNode:&node];
660  NSMutableAttributedString* expectedAttributedLabel =
661  [[NSMutableAttributedString alloc] initWithString:NSLocalizedString(@"label", @"test")];
662  NSDictionary* attributeDict = @{
663  UIAccessibilitySpeechAttributeSpellOut : @YES,
664  };
665  [expectedAttributedLabel setAttributes:attributeDict range:NSMakeRange(1, 1)];
666  XCTAssertTrue(
667  [object.accessibilityAttributedLabel isEqualToAttributedString:expectedAttributedLabel]);
668 
669  NSMutableAttributedString* expectedAttributedValue =
670  [[NSMutableAttributedString alloc] initWithString:NSLocalizedString(@"value", @"test")];
671  attributeDict = @{
672  UIAccessibilitySpeechAttributeSpellOut : @YES,
673  };
674  [expectedAttributedValue setAttributes:attributeDict range:NSMakeRange(2, 1)];
675  XCTAssertTrue(
676  [object.accessibilityAttributedValue isEqualToAttributedString:expectedAttributedValue]);
677 
678  NSMutableAttributedString* expectedAttributedHint =
679  [[NSMutableAttributedString alloc] initWithString:NSLocalizedString(@"hint", @"test")];
680  attributeDict = @{
681  UIAccessibilitySpeechAttributeLanguage : @"en-MX",
682  };
683  [expectedAttributedHint setAttributes:attributeDict range:NSMakeRange(3, 1)];
684  XCTAssertTrue(
685  [object.accessibilityAttributedHint isEqualToAttributedString:expectedAttributedHint]);
686 }
687 
688 - (void)testShouldTriggerAnnouncement {
689  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
690  new flutter::MockAccessibilityBridge());
691  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
692  SemanticsObject* object = [[SemanticsObject alloc] initWithBridge:bridge uid:0];
693 
694  // Handle nil with no node set.
695  XCTAssertFalse([object nodeShouldTriggerAnnouncement:nil]);
696 
697  // Handle initial setting of node with liveRegion
698  flutter::SemanticsNode node;
699  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kIsLiveRegion);
700  node.label = "foo";
701  XCTAssertTrue([object nodeShouldTriggerAnnouncement:&node]);
702 
703  // Handle nil with node set.
704  [object setSemanticsNode:&node];
705  XCTAssertFalse([object nodeShouldTriggerAnnouncement:nil]);
706 
707  // Handle new node, still has live region, same label.
708  XCTAssertFalse([object nodeShouldTriggerAnnouncement:&node]);
709 
710  // Handle update node with new label, still has live region.
711  flutter::SemanticsNode updatedNode;
712  updatedNode.flags = static_cast<int32_t>(flutter::SemanticsFlags::kIsLiveRegion);
713  updatedNode.label = "bar";
714  XCTAssertTrue([object nodeShouldTriggerAnnouncement:&updatedNode]);
715 
716  // Handle dropping the live region flag.
717  updatedNode.flags = 0;
718  XCTAssertFalse([object nodeShouldTriggerAnnouncement:&updatedNode]);
719 
720  // Handle adding the flag when the label has not changed.
721  updatedNode.label = "foo";
722  [object setSemanticsNode:&updatedNode];
723  XCTAssertTrue([object nodeShouldTriggerAnnouncement:&node]);
724 }
725 
726 - (void)testShouldDispatchShowOnScreenActionForHeader {
727  fml::WeakPtrFactory<flutter::MockAccessibilityBridge> factory(
728  new flutter::MockAccessibilityBridge());
729  fml::WeakPtr<flutter::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
730  SemanticsObject* object = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
731 
732  // Handle initial setting of node with header.
733  flutter::SemanticsNode node;
734  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kIsHeader);
735  node.label = "foo";
736 
737  [object setSemanticsNode:&node];
738 
739  // Simulate accessibility focus.
740  [object accessibilityElementDidBecomeFocused];
741 
742  XCTAssertTrue(bridge->observations.size() == 1);
743  XCTAssertTrue(bridge->observations[0].id == 1);
744  XCTAssertTrue(bridge->observations[0].action == flutter::SemanticsAction::kShowOnScreen);
745 }
746 
747 - (void)testShouldDispatchShowOnScreenActionForHidden {
748  fml::WeakPtrFactory<flutter::MockAccessibilityBridge> factory(
749  new flutter::MockAccessibilityBridge());
750  fml::WeakPtr<flutter::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
751  SemanticsObject* object = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
752 
753  // Handle initial setting of node with hidden.
754  flutter::SemanticsNode node;
755  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kIsHidden);
756  node.label = "foo";
757 
758  [object setSemanticsNode:&node];
759 
760  // Simulate accessibility focus.
761  [object accessibilityElementDidBecomeFocused];
762 
763  XCTAssertTrue(bridge->observations.size() == 1);
764  XCTAssertTrue(bridge->observations[0].id == 1);
765  XCTAssertTrue(bridge->observations[0].action == flutter::SemanticsAction::kShowOnScreen);
766 }
767 
768 - (void)testFlutterSwitchSemanticsObjectMatchesUISwitch {
769  fml::WeakPtrFactory<flutter::MockAccessibilityBridge> factory(
770  new flutter::MockAccessibilityBridge());
771  fml::WeakPtr<flutter::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
772  FlutterSwitchSemanticsObject* object = [[FlutterSwitchSemanticsObject alloc] initWithBridge:bridge
773  uid:1];
774 
775  // Handle initial setting of node with header.
776  flutter::SemanticsNode node;
777  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasToggledState) |
778  static_cast<int32_t>(flutter::SemanticsFlags::kIsToggled) |
779  static_cast<int32_t>(flutter::SemanticsFlags::kIsEnabled);
780  node.label = "foo";
781  [object setSemanticsNode:&node];
782  // Create ab real UISwitch to compare the FlutterSwitchSemanticsObject with.
783  UISwitch* nativeSwitch = [[UISwitch alloc] init];
784  nativeSwitch.on = YES;
785 
786  XCTAssertEqual(object.accessibilityTraits, nativeSwitch.accessibilityTraits);
787  XCTAssertEqualObjects(object.accessibilityValue, nativeSwitch.accessibilityValue);
788 
789  // Set the toggled to false;
790  flutter::SemanticsNode update;
791  update.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasToggledState) |
792  static_cast<int32_t>(flutter::SemanticsFlags::kIsEnabled);
793  update.label = "foo";
794  [object setSemanticsNode:&update];
795 
796  nativeSwitch.on = NO;
797 
798  XCTAssertEqual(object.accessibilityTraits, nativeSwitch.accessibilityTraits);
799  XCTAssertEqualObjects(object.accessibilityValue, nativeSwitch.accessibilityValue);
800 }
801 
802 - (void)testFlutterSemanticsObjectOfRadioButton {
803  fml::WeakPtrFactory<flutter::MockAccessibilityBridge> factory(
804  new flutter::MockAccessibilityBridge());
805  fml::WeakPtr<flutter::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
806  FlutterSemanticsObject* object = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
807 
808  // Handle initial setting of node with header.
809  flutter::SemanticsNode node;
810  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kIsInMutuallyExclusiveGroup) |
811  static_cast<int32_t>(flutter::SemanticsFlags::kHasCheckedState) |
812  static_cast<int32_t>(flutter::SemanticsFlags::kHasEnabledState) |
813  static_cast<int32_t>(flutter::SemanticsFlags::kIsEnabled);
814  node.label = "foo";
815  [object setSemanticsNode:&node];
816  XCTAssertTrue((object.accessibilityTraits & UIAccessibilityTraitButton) > 0);
817  XCTAssertNil(object.accessibilityValue);
818 }
819 
820 - (void)testFlutterSwitchSemanticsObjectMatchesUISwitchDisabled {
821  fml::WeakPtrFactory<flutter::MockAccessibilityBridge> factory(
822  new flutter::MockAccessibilityBridge());
823  fml::WeakPtr<flutter::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
824  FlutterSwitchSemanticsObject* object = [[FlutterSwitchSemanticsObject alloc] initWithBridge:bridge
825  uid:1];
826 
827  // Handle initial setting of node with header.
828  flutter::SemanticsNode node;
829  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasToggledState) |
830  static_cast<int32_t>(flutter::SemanticsFlags::kIsToggled);
831  node.label = "foo";
832  [object setSemanticsNode:&node];
833  // Create ab real UISwitch to compare the FlutterSwitchSemanticsObject with.
834  UISwitch* nativeSwitch = [[UISwitch alloc] init];
835  nativeSwitch.on = YES;
836  nativeSwitch.enabled = NO;
837 
838  XCTAssertEqual(object.accessibilityTraits, nativeSwitch.accessibilityTraits);
839  XCTAssertEqualObjects(object.accessibilityValue, nativeSwitch.accessibilityValue);
840 }
841 
842 - (void)testSemanticsObjectDeallocated {
843  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
844  new flutter::MockAccessibilityBridge());
845  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
846  SemanticsObject* parent = [[SemanticsObject alloc] initWithBridge:bridge uid:0];
847  SemanticsObject* child = [[SemanticsObject alloc] initWithBridge:bridge uid:1];
848  parent.children = @[ child ];
849  // Validate SemanticsObject deallocation does not crash.
850  // https://github.com/flutter/flutter/issues/66032
851  __weak SemanticsObject* weakObject = parent;
852  parent = nil;
853  XCTAssertNil(weakObject);
854 }
855 
856 - (void)testFlutterSemanticsObjectReturnsNilContainerWhenBridgeIsNotAlive {
857  FlutterSemanticsObject* parentObject;
859  FlutterSemanticsObject* object2;
860 
861  flutter::SemanticsNode parent;
862  parent.id = 0;
863  parent.rect = SkRect::MakeXYWH(0, 0, 100, 200);
864  parent.label = "label";
865  parent.value = "value";
866  parent.hint = "hint";
867 
868  flutter::SemanticsNode node;
869  node.id = 1;
870  node.flags = static_cast<int32_t>(flutter::SemanticsFlags::kHasImplicitScrolling);
871  node.actions = flutter::kHorizontalScrollSemanticsActions;
872  node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
873  node.label = "label";
874  node.value = "value";
875  node.hint = "hint";
876  node.scrollExtentMax = 100.0;
877  node.scrollPosition = 0.0;
878  parent.childrenInTraversalOrder.push_back(1);
879 
880  flutter::SemanticsNode node2;
881  node2.id = 2;
882  node2.rect = SkRect::MakeXYWH(0, 0, 100, 200);
883  node2.label = "label";
884  node2.value = "value";
885  node2.hint = "hint";
886  node2.scrollExtentMax = 100.0;
887  node2.scrollPosition = 0.0;
888  parent.childrenInTraversalOrder.push_back(2);
889 
890  {
891  flutter::MockAccessibilityBridge* mock = new flutter::MockAccessibilityBridge();
892  mock->isVoiceOverRunningValue = true;
893  fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
894  fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
895 
896  parentObject = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:0];
897  [parentObject setSemanticsNode:&parent];
898 
899  scrollable = [[FlutterScrollableSemanticsObject alloc] initWithBridge:bridge uid:1];
900  [scrollable setSemanticsNode:&node];
902 
903  object2 = [[FlutterSemanticsObject alloc] initWithBridge:bridge uid:2];
904  [object2 setSemanticsNode:&node2];
905 
906  parentObject.children = @[ scrollable, object2 ];
907  [parentObject accessibilityBridgeDidFinishUpdate];
910 
911  // Returns the correct container if the bridge is alive.
912  SemanticsObjectContainer* container =
913  static_cast<SemanticsObjectContainer*>(scrollable.accessibilityContainer);
914  XCTAssertEqual(container.semanticsObject, parentObject);
915  SemanticsObjectContainer* container2 =
916  static_cast<SemanticsObjectContainer*>(object2.accessibilityContainer);
917  XCTAssertEqual(container2.semanticsObject, parentObject);
918  }
919  // The bridge pointer went out of scope and was deallocated.
920 
921  XCTAssertNil(scrollable.accessibilityContainer);
922  XCTAssertNil(object2.accessibilityContainer);
923 }
924 
925 @end
FLUTTER_ASSERT_ARC
#define FLUTTER_ASSERT_ARC
Definition: FlutterMacros.h:44
-[SemanticsObject accessibilityScrollToVisible]
BOOL accessibilityScrollToVisible()
-[SemanticsObject replaceChildAtIndex:withChild:]
void replaceChildAtIndex:withChild:(NSInteger index,[withChild] SemanticsObject *child)
Definition: SemanticsObject.mm:393
SemanticsObject::parent
SemanticsObject * parent
Definition: SemanticsObject.h:41
SemanticsObjectTestMocks.h
SemanticsObjectContainer::semanticsObject
SemanticsObject * semanticsObject
Definition: SemanticsObject.h:234
-[SemanticsObject accessibilityScrollToVisibleWithChild:]
BOOL accessibilityScrollToVisibleWithChild:(id child)
-[SemanticsObject setSemanticsNode:]
void setSemanticsNode:(const flutter::SemanticsNode *NS_REQUIRES_SUPER)
Definition: SemanticsObject.mm:352
FlutterMacros.h
FlutterSemanticsObject
Definition: SemanticsObject.h:154
SemanticsObject::childrenInHitTestOrder
NSArray< SemanticsObject * > * childrenInHitTestOrder
Definition: SemanticsObject.h:73
kScrollExtentMaxForInf
constexpr float kScrollExtentMaxForInf
Definition: SemanticsObject.h:17
-[SemanticsObject _accessibilityHitTest:withEvent:]
id _accessibilityHitTest:withEvent:(CGPoint point,[withEvent] UIEvent *event)
FlutterSwitchSemanticsObject
Definition: SemanticsObject.h:182
SemanticsObject::children
NSArray< SemanticsObject * > * children
Definition: SemanticsObject.h:67
SemanticsObject::nativeAccessibility
id nativeAccessibility
Definition: SemanticsObject.h:82
SemanticsObject.h
-[SemanticsObject accessibilityBridgeDidFinishUpdate]
void accessibilityBridgeDidFinishUpdate()
Definition: SemanticsObject.mm:356
SemanticsObjectContainer
Definition: SemanticsObject.h:226
SemanticsObjectTest
Definition: SemanticsObjectTest.mm:14
FlutterScrollableSemanticsObject
Definition: SemanticsObject.h:188
SemanticsObject
Definition: SemanticsObject.h:30