Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitefa81a7

Browse files
authored
Reland #163662 [web][a11y]Delete _childContainerElement (#165434)
Reland #163662 with some changes 1. when a node's role changes and reparenting it, append children to it 2. Merge optimization from /pull/165352fix:flutter/flutter#45205 ## Pre-launch Checklist- [ ] I read the [Contributor Guide] and followed the process outlinedthere for submitting PRs.- [ ] I read the [Tree Hygiene] wiki page, which explains myresponsibilities.- [ ] I read and followed the [Flutter Style Guide], including [Featureswe expect every widget to implement].- [ ] I signed the [CLA].- [ ] I listed at least one issue that this PR fixes in the descriptionabove.- [ ] I updated/added relevant documentation (doc comments with `///`).- [ ] I added new tests to check the change I am making, or this PR is[test-exempt].- [ ] I followed the [breaking change policy] and added [Data DrivenFixes] where supported.- [ ] All existing and new tests are passing.If you need help, consider asking for advice on the #hackers-new channelon [Discord].<!-- Links -->[Contributor Guide]:https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview[Tree Hygiene]:https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md[test-exempt]:https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests[Flutter Style Guide]:https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md[Features we expect every widget to implement]:https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement[CLA]:https://cla.developers.google.com/[flutter/tests]:https://github.com/flutter/tests[breaking change policy]:https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes[Discord]:https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md[Data Driven Fixes]:https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1 parent66df85a commitefa81a7

File tree

6 files changed

+354
-268
lines changed

6 files changed

+354
-268
lines changed

‎engine/src/flutter/lib/web_ui/lib/src/engine/semantics/scrollable.dart‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class SemanticScrollable extends SemanticRole {
7070
finalbool doScrollForward= _domScrollPosition> _effectiveNeutralScrollPosition;
7171
_neutralizeDomScrollPosition();
7272
semanticsObject.recomputePositionAndSize();
73+
semanticsObject.updateChildrenPositionAndSize();
7374

7475
finalint semanticsId= semanticsObject.id;
7576
if (doScrollForward) {
@@ -131,6 +132,7 @@ class SemanticScrollable extends SemanticRole {
131132
semanticsObject.owner.addOneTimePostUpdateCallback(() {
132133
_neutralizeDomScrollPosition();
133134
semanticsObject.recomputePositionAndSize();
135+
semanticsObject.updateChildrenPositionAndSize();
134136
});
135137

136138
if (_scrollListener==null) {
@@ -203,8 +205,8 @@ class SemanticScrollable extends SemanticRole {
203205
// Read back because the effective value depends on the amount of content.
204206
_effectiveNeutralScrollPosition= element.scrollTop.toInt();
205207
semanticsObject
206-
..verticalContainerAdjustment= _effectiveNeutralScrollPosition.toDouble()
207-
..horizontalContainerAdjustment=0.0;
208+
..verticalScrollAdjustment= _effectiveNeutralScrollPosition.toDouble()
209+
..horizontalScrollAdjustment=0.0;
208210
}else {
209211
// Place the _scrollOverflowElement at the end of the content and
210212
// make sure that when we neutralize the scrolling position,
@@ -219,8 +221,8 @@ class SemanticScrollable extends SemanticRole {
219221
// Read back because the effective value depends on the amount of content.
220222
_effectiveNeutralScrollPosition= element.scrollLeft.toInt();
221223
semanticsObject
222-
..verticalContainerAdjustment=0.0
223-
..horizontalContainerAdjustment= _effectiveNeutralScrollPosition.toDouble();
224+
..verticalScrollAdjustment=0.0
225+
..horizontalScrollAdjustment= _effectiveNeutralScrollPosition.toDouble();
224226
}
225227
}
226228

‎engine/src/flutter/lib/web_ui/lib/src/engine/semantics/semantics.dart‎

Lines changed: 70 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,33 +1383,6 @@ class SemanticsObject {
13831383
/// The dom element of this semantics object.
13841384
DomElementget element=> semanticRole!.element;
13851385

1386-
/// Returns the HTML element that contains the HTML elements of direct
1387-
/// children of this object.
1388-
///
1389-
/// The element is created lazily. When the child list is empty this element
1390-
/// is not created. This is necessary for "aria-label" to function correctly.
1391-
/// The browser will ignore the[label] of HTML element that contain child
1392-
/// elements.
1393-
DomElement?getOrCreateChildContainer() {
1394-
if (_childContainerElement==null) {
1395-
_childContainerElement=createDomElement('flt-semantics-container');
1396-
_childContainerElement!.style
1397-
..position='absolute'
1398-
// Ignore pointer events on child container so that platform views
1399-
// behind it can be reached.
1400-
..pointerEvents='none';
1401-
element.append(_childContainerElement!);
1402-
}
1403-
return _childContainerElement;
1404-
}
1405-
1406-
/// The element that contains the elements belonging to the child semantics
1407-
/// nodes.
1408-
///
1409-
/// This element is used to correct for[_rect] offsets. It is only non-`null`
1410-
/// when there are non-zero children (i.e. when[hasChildren] is`true`).
1411-
DomElement? _childContainerElement;
1412-
14131386
/// The parent of this semantics object.
14141387
///
14151388
/// This value is not final until the tree is finalized. It is not safe to
@@ -1677,12 +1650,6 @@ class SemanticsObject {
16771650
// Apply updates to the DOM.
16781651
_updateRole();
16791652

1680-
// All properties that affect positioning and sizing are checked together
1681-
// any one of them triggers position and size recomputation.
1682-
if (isRectDirty|| isTransformDirty|| isScrollPositionDirty) {
1683-
recomputePositionAndSize();
1684-
}
1685-
16861653
if (semanticRole!.acceptsPointerEvents) {
16871654
element.style.pointerEvents='all';
16881655
}else {
@@ -1710,22 +1677,15 @@ class SemanticsObject {
17101677
// Trivial case: remove all children.
17111678
if (_childrenInHitTestOrder==null|| _childrenInHitTestOrder!.isEmpty) {
17121679
if (_currentChildrenInRenderOrder==null|| _currentChildrenInRenderOrder!.isEmpty) {
1713-
// A container element must not have been created when child list is empty.
1714-
assert(_childContainerElement==null);
17151680
_currentChildrenInRenderOrder=null;
17161681
return;
17171682
}
17181683

1719-
// A container element must have been created when child list is not empty.
1720-
assert(_childContainerElement!=null);
1721-
17221684
// Remove all children from this semantics object.
17231685
finalint len= _currentChildrenInRenderOrder!.length;
17241686
for (int i=0; i< len; i++) {
17251687
owner._detachObject(_currentChildrenInRenderOrder![i].id);
17261688
}
1727-
_childContainerElement!.remove();
1728-
_childContainerElement=null;
17291689
_currentChildrenInRenderOrder=null;
17301690
return;
17311691
}
@@ -1734,7 +1694,6 @@ class SemanticsObject {
17341694
finalInt32List childrenInTraversalOrder= _childrenInTraversalOrder!;
17351695
finalInt32List childrenInHitTestOrder= _childrenInHitTestOrder!;
17361696
finalint childCount= childrenInHitTestOrder.length;
1737-
finalDomElement? containerElement=getOrCreateChildContainer();
17381697

17391698
assert(childrenInTraversalOrder.length== childrenInHitTestOrder.length);
17401699

@@ -1766,7 +1725,7 @@ class SemanticsObject {
17661725
// Trivial case: previous list was empty => just populate the container.
17671726
if (_currentChildrenInRenderOrder==null|| _currentChildrenInRenderOrder!.isEmpty) {
17681727
for (finalSemanticsObject childin childrenInRenderOrder) {
1769-
containerElement!.append(child.element);
1728+
element.append(child.element);
17701729
owner._attachObject(parent:this, child: child);
17711730
}
17721731
_currentChildrenInRenderOrder= childrenInRenderOrder;
@@ -1850,9 +1809,9 @@ class SemanticsObject {
18501809
finalSemanticsObject child= childrenInRenderOrder[i];
18511810
if (!stationaryIds.contains(child.id)) {
18521811
if (refNode==null) {
1853-
containerElement!.append(child.element);
1812+
element.append(child.element);
18541813
}else {
1855-
containerElement!.insertBefore(child.element, refNode);
1814+
element.insertBefore(child.element, refNode);
18561815
}
18571816
owner._attachObject(parent:this, child: child);
18581817
}else {
@@ -2030,9 +1989,10 @@ class SemanticsObject {
20301989

20311990
// Reparent element.
20321991
if (previousElement!= element) {
2033-
finalDomElement? container= _childContainerElement;
2034-
if (container!=null) {
2035-
element.append(container);
1992+
if (_currentChildrenInRenderOrder!=null) {
1993+
for (final childin _currentChildrenInRenderOrder!) {
1994+
element.append(child.element);
1995+
}
20361996
}
20371997
finalDomElement? parent= previousElement?.parent;
20381998
if (parent!=null) {
@@ -2127,60 +2087,79 @@ class SemanticsObject {
21272087
/// Indicates whether the node is currently expanded.
21282088
boolget isExpanded=>hasFlag(ui.SemanticsFlag.isExpanded);
21292089

2130-
/// Role-specific adjustment of the vertical position of thechild container.
2090+
/// Role-specific adjustment of the vertical position of thechildren.
21312091
///
21322092
/// This is used, for example, by the[SemanticScrollable] to compensate for the
21332093
///`scrollTop` offset in the DOM.
21342094
///
21352095
/// This field must not be null.
2136-
doubleverticalContainerAdjustment=0.0;
2096+
doubleverticalScrollAdjustment=0.0;
21372097

2138-
/// Role-specific adjustment of the horizontal position of the child
2139-
/// container.
2098+
/// Role-specific adjustment of the horizontal position of children.
21402099
///
21412100
/// This is used, for example, by the[SemanticScrollable] to compensate for the
21422101
///`scrollLeft` offset in the DOM.
21432102
///
21442103
/// This field must not be null.
2145-
double horizontalContainerAdjustment=0.0;
2104+
double horizontalScrollAdjustment=0.0;
2105+
2106+
double verticalAdjustmentFromParent=0.0;
2107+
double horizontalAdjustmentFromParent=0.0;
2108+
2109+
/// If this element[hasChildren], computes the parent adjustment for each child.
2110+
voidrecomputeChildrenAdjustment(Set<SemanticsObject> dirtyNodes) {
2111+
if (!hasChildren) {
2112+
return;
2113+
}
2114+
// If this node has children, we need to compensate for the parent's rect and
2115+
// pass down the scroll adjustments.
2116+
finaldouble translateX=-_rect!.left+ horizontalScrollAdjustment;
2117+
finaldouble translateY=-_rect!.top+ verticalScrollAdjustment;
2118+
2119+
for (final childIndexin _childrenInTraversalOrder!) {
2120+
final child= owner._semanticsTree[childIndex]!;
2121+
2122+
if (child.horizontalAdjustmentFromParent!= translateX||
2123+
child.verticalAdjustmentFromParent!= translateY) {
2124+
child.horizontalAdjustmentFromParent= translateX;
2125+
child.verticalAdjustmentFromParent= translateY;
2126+
dirtyNodes.add(child);
2127+
}
2128+
}
2129+
}
21462130

2147-
/// Computes the size and position of[element] and, if this element
2148-
///[hasChildren], of[getOrCreateChildContainer].
2131+
/// Computes the size and position of[element]
21492132
voidrecomputePositionAndSize() {
21502133
element.style
21512134
..width='${_rect!.width}px'
21522135
..height='${_rect!.height}px';
21532136

2154-
finalDomElement? containerElement= hasChildren?getOrCreateChildContainer():null;
2155-
21562137
finalbool hasZeroRectOffset= _rect!.top==0.0&& _rect!.left==0.0;
21572138
finalFloat32List? transform= _transform;
21582139
finalbool hasIdentityTransform=
21592140
transform==null||isIdentityFloat32ListTransform(transform);
21602141

21612142
if (hasZeroRectOffset&&
21622143
hasIdentityTransform&&
2163-
verticalContainerAdjustment==0.0&&
2164-
horizontalContainerAdjustment==0.0) {
2144+
verticalAdjustmentFromParent==0.0&&
2145+
horizontalAdjustmentFromParent==0.0) {
21652146
_clearSemanticElementTransform(element);
2166-
if (containerElement!=null) {
2167-
_clearSemanticElementTransform(containerElement);
2168-
}
21692147
return;
21702148
}
21712149

21722150
lateMatrix4 effectiveTransform;
21732151
bool effectiveTransformIsIdentity=true;
2174-
if (!hasZeroRectOffset) {
2152+
2153+
finaldouble left= _rect!.left+ horizontalAdjustmentFromParent;
2154+
finaldouble top= _rect!.top+ verticalAdjustmentFromParent;
2155+
2156+
if (left!=0.0|| top!=0.0) {
21752157
if (transform==null) {
2176-
finaldouble left= _rect!.left;
2177-
finaldouble top= _rect!.top;
21782158
effectiveTransform=Matrix4.translationValues(left, top,0.0);
2179-
effectiveTransformIsIdentity=left==0.0&& top==0.0;
2159+
effectiveTransformIsIdentity=false;
21802160
}else {
21812161
// Clone to avoid mutating _transform.
2182-
effectiveTransform=
2183-
Matrix4.fromFloat32List(transform).clone()..translate(_rect!.left, _rect!.top);
2162+
effectiveTransform=Matrix4.fromFloat32List(transform).clone()..translate(left, top);
21842163
effectiveTransformIsIdentity= effectiveTransform.isIdentity();
21852164
}
21862165
}elseif (!hasIdentityTransform) {
@@ -2195,19 +2174,15 @@ class SemanticsObject {
21952174
}else {
21962175
_clearSemanticElementTransform(element);
21972176
}
2177+
}
21982178

2199-
if (containerElement!=null) {
2200-
if (!hasZeroRectOffset||
2201-
verticalContainerAdjustment!=0.0||
2202-
horizontalContainerAdjustment!=0.0) {
2203-
finaldouble translateX=-_rect!.left+ horizontalContainerAdjustment;
2204-
finaldouble translateY=-_rect!.top+ verticalContainerAdjustment;
2205-
containerElement.style
2206-
..top='${translateY}px'
2207-
..left='${translateX}px';
2208-
}else {
2209-
_clearSemanticElementTransform(containerElement);
2210-
}
2179+
/// Computes the size and position of children.
2180+
voidupdateChildrenPositionAndSize() {
2181+
finalSet<SemanticsObject> dirtyNodes=<SemanticsObject>{};
2182+
recomputeChildrenAdjustment(dirtyNodes);
2183+
2184+
for (final nodein dirtyNodes) {
2185+
node.recomputePositionAndSize();
22112186
}
22122187
}
22132188

@@ -2769,7 +2744,7 @@ class EngineSemanticsOwner {
27692744
removals.add(node);
27702745
}else {
27712746
assert(node._parent== parent);
2772-
assert(node.element.parentNode== parent._childContainerElement);
2747+
assert(node.element.parentNode== parent.element);
27732748
}
27742749
returntrue;
27752750
});
@@ -2872,14 +2847,29 @@ class EngineSemanticsOwner {
28722847
object.updateSelf(nodeUpdate);
28732848
}
28742849

2850+
finalSet<SemanticsObject> nodesWithDirtyPositionsAndSizes=<SemanticsObject>{};
28752851
// Second, fix the tree structure. This is moved out into its own loop,
28762852
// because each object's own information must be updated first.
28772853
for (finalSemanticsNodeUpdate nodeUpdatein nodeUpdates) {
28782854
finalSemanticsObject object= _semanticsTree[nodeUpdate.id]!;
28792855
object.updateChildren();
2856+
2857+
if (object.isRectDirty||
2858+
object.isTransformDirty||
2859+
object.isScrollPositionDirty||
2860+
object.isChildrenInTraversalOrderDirty) {
2861+
nodesWithDirtyPositionsAndSizes.add(object);
2862+
2863+
object.recomputeChildrenAdjustment(nodesWithDirtyPositionsAndSizes);
2864+
}
2865+
28802866
object._dirtyFields=0;
28812867
}
28822868

2869+
for (final nodein nodesWithDirtyPositionsAndSizes) {
2870+
node.recomputePositionAndSize();
2871+
}
2872+
28832873
finalSemanticsObject root= _semanticsTree[0]!;
28842874
if (_rootSemanticsElement==null) {
28852875
_rootSemanticsElement= root.element;
@@ -2913,9 +2903,6 @@ AFTER: $description
29132903
// Dirty fields should be cleared after the tree has been finalized.
29142904
assert(object._dirtyFields==0);
29152905

2916-
// Make sure a child container is created only when there are children.
2917-
assert(object._childContainerElement==null|| object.hasChildren);
2918-
29192906
// Ensure child ID list is consistent with the parent-child
29202907
// relationship of the semantics tree.
29212908
if (object._childrenInTraversalOrder!=null) {

‎engine/src/flutter/lib/web_ui/test/common/matchers.dart‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,6 @@ class HtmlPatternMatcher extends Matcher {
274274
staticbool_areTagsEqual(html.Element a, html.Element b) {
275275
constMap<String,String> synonyms=<String,String>{
276276
'sem':'flt-semantics',
277-
'sem-c':'flt-semantics-container',
278277
'sem-img':'flt-semantics-img',
279278
'sem-tf':'flt-semantics-text-field',
280279
};

‎engine/src/flutter/lib/web_ui/test/engine/semantics/semantics_multi_view_test.dart‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,11 @@ Future<void> testMain() async {
9999
// Test that each view renders its own semantics tree.
100100
expectSemanticsTree(view1.semantics,'''
101101
<sem style="filter: opacity(0%); color: rgba(0, 0, 0, 0)">
102-
<sem-c>
103102
<sem flt-tappable="" role="button"></sem>
104-
</sem-c>
105103
</sem>''');
106104
expectSemanticsTree(view2.semantics,'''
107105
<sem style="filter: opacity(0%); color: rgba(0, 0, 0, 0)">
108-
<sem-c>
109106
<sem aria-label="d"><input aria-valuemax="1" aria-valuemin="1" aria-valuenow="1" aria-valuetext="" role="slider"></sem>
110-
</sem-c>
111107
</sem>
112108
''');
113109

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2026 Movatter.jp