Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
06b301cd
Unverified
Commit
06b301cd
authored
Jul 09, 2020
by
chunhtai
Committed by
GitHub
Jul 09, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix semantics to only send relevant node update (#60925)
parent
b345ecc1
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
233 additions
and
3 deletions
+233
-3
binding.dart
packages/flutter/lib/src/semantics/binding.dart
+11
-1
semantics.dart
packages/flutter/lib/src/semantics/semantics.dart
+4
-2
semantics_update_test.dart
packages/flutter/test/semantics/semantics_update_test.dart
+218
-0
No files found.
packages/flutter/lib/src/semantics/binding.dart
View file @
06b301cd
...
...
@@ -4,7 +4,7 @@
// @dart = 2.8
import
'dart:ui'
as
ui
show
AccessibilityFeatures
;
import
'dart:ui'
as
ui
show
AccessibilityFeatures
,
SemanticsUpdateBuilder
;
import
'package:flutter/foundation.dart'
;
...
...
@@ -34,6 +34,16 @@ mixin SemanticsBinding on BindingBase {
_accessibilityFeatures
=
window
.
accessibilityFeatures
;
}
/// Creates an empty semantics update builder.
///
/// The caller is responsible for filling out the semantics node updates.
///
/// This method is used by the [SemanticsOwner] to create builder for all its
/// semantics updates.
ui
.
SemanticsUpdateBuilder
createSemanticsUpdateBuilder
()
{
return
ui
.
SemanticsUpdateBuilder
();
}
/// The currently active set of [AccessibilityFeatures].
///
/// This is initialized the first time [runApp] is called and updated whenever
...
...
packages/flutter/lib/src/semantics/semantics.dart
View file @
06b301cd
...
...
@@ -2624,13 +2624,15 @@ class SemanticsOwner extends ChangeNotifier {
if
(
node
.
isPartOfNodeMerging
)
{
assert
(
node
.
mergeAllDescendantsIntoThisNode
||
node
.
parent
!=
null
);
// if we're merged into our parent, make sure our parent is added to the dirty list
if
(
node
.
parent
!=
null
&&
node
.
parent
.
isPartOfNodeMerging
)
if
(
node
.
parent
!=
null
&&
node
.
parent
.
isPartOfNodeMerging
)
{
node
.
parent
.
_markDirty
();
// this can add the node to the dirty list
node
.
_dirty
=
false
;
// We don't want to send update for this node.
}
}
}
}
visitedNodes
.
sort
((
SemanticsNode
a
,
SemanticsNode
b
)
=>
a
.
depth
-
b
.
depth
);
final
ui
.
SemanticsUpdateBuilder
builder
=
ui
.
SemanticsUpdateBuilder
();
final
ui
.
SemanticsUpdateBuilder
builder
=
SemanticsBinding
.
instance
.
create
SemanticsUpdateBuilder
();
for
(
final
SemanticsNode
node
in
visitedNodes
)
{
assert
(
node
.
parent
?.
_dirty
!=
true
);
// could be null (no parent) or false (not dirty)
// The _serialize() method marks the node as not dirty, and
...
...
packages/flutter/test/semantics/semantics_update_test.dart
0 → 100644
View file @
06b301cd
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import
'dart:typed_data'
;
import
'dart:ui'
as
ui
;
import
'package:flutter/material.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
SemanticsUpdateTestBinding
();
testWidgets
(
'Semantics update does not send update for merged nodes.'
,
(
WidgetTester
tester
)
async
{
final
SemanticsHandle
handle
=
tester
.
ensureSemantics
();
// Pumps a placeholder to trigger the warm up frame.
await
tester
.
pumpWidget
(
const
Placeholder
(),
// Stops right after the warm up frame.
null
,
EnginePhase
.
build
);
// The warm up frame will send update for an empty semantics tree. We
// ignore this one time update.
SemanticsUpdateBuilderSpy
.
observations
.
clear
();
// Builds the real widget tree.
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MergeSemantics
(
child:
Semantics
(
label:
'outer'
,
// This semantics node should not be part of the semantics update
// because it is under another semantics container.
child:
Semantics
(
label:
'inner'
,
container:
true
,
child:
const
Text
(
'text'
),
),
),
),
),
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
.
length
,
2
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
.
containsKey
(
0
),
isTrue
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
[
0
].
childrenInTraversalOrder
.
length
,
1
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
[
0
].
childrenInTraversalOrder
[
0
],
1
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
.
containsKey
(
1
),
isTrue
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
[
1
].
childrenInTraversalOrder
.
length
,
0
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
[
1
].
label
,
'outer
\n
inner
\n
text'
);
SemanticsUpdateBuilderSpy
.
observations
.
clear
();
// Updates the inner semantics label and verifies it only sends update for
// the merged parent.
await
tester
.
pumpWidget
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MergeSemantics
(
child:
Semantics
(
label:
'outer'
,
// This semantics node should not be part of the semantics update
// because it is under another semantics container.
child:
Semantics
(
label:
'inner-updated'
,
container:
true
,
child:
const
Text
(
'text'
),
),
),
),
),
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
.
length
,
1
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
.
containsKey
(
1
),
isTrue
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
[
1
].
childrenInTraversalOrder
.
length
,
0
);
expect
(
SemanticsUpdateBuilderSpy
.
observations
[
1
].
label
,
'outer
\n
inner-updated
\n
text'
);
SemanticsUpdateBuilderSpy
.
observations
.
clear
();
handle
.
dispose
();
});
}
class
SemanticsUpdateTestBinding
extends
AutomatedTestWidgetsFlutterBinding
{
@override
ui
.
SemanticsUpdateBuilder
createSemanticsUpdateBuilder
()
{
return
SemanticsUpdateBuilderSpy
();
}
}
class
SemanticsUpdateBuilderSpy
extends
ui
.
SemanticsUpdateBuilder
{
static
Map
<
int
,
SemanticsNodeUpdateObservation
>
observations
=
<
int
,
SemanticsNodeUpdateObservation
>{};
@override
void
updateNode
({
@required
int
id
,
@required
int
flags
,
@required
int
actions
,
@required
int
maxValueLength
,
@required
int
currentValueLength
,
@required
int
textSelectionBase
,
@required
int
textSelectionExtent
,
@required
int
platformViewId
,
@required
int
scrollChildren
,
@required
int
scrollIndex
,
@required
double
scrollPosition
,
@required
double
scrollExtentMax
,
@required
double
scrollExtentMin
,
@required
double
elevation
,
@required
double
thickness
,
@required
Rect
rect
,
@required
String
label
,
@required
String
hint
,
@required
String
value
,
@required
String
increasedValue
,
@required
String
decreasedValue
,
TextDirection
textDirection
,
@required
Float64List
transform
,
@required
Int32List
childrenInTraversalOrder
,
@required
Int32List
childrenInHitTestOrder
,
@required
Int32List
additionalActions
,
})
{
// Makes sure we don't send the same id twice.
assert
(!
observations
.
containsKey
(
id
));
observations
[
id
]
=
SemanticsNodeUpdateObservation
(
id:
id
,
flags:
flags
,
actions:
actions
,
maxValueLength:
maxValueLength
,
currentValueLength:
currentValueLength
,
textSelectionBase:
textSelectionBase
,
textSelectionExtent:
textSelectionExtent
,
platformViewId:
platformViewId
,
scrollChildren:
scrollChildren
,
scrollIndex:
scrollIndex
,
scrollPosition:
scrollPosition
,
scrollExtentMax:
scrollExtentMax
,
scrollExtentMin:
scrollExtentMin
,
elevation:
elevation
,
thickness:
thickness
,
rect:
rect
,
label:
label
,
hint:
hint
,
value:
value
,
increasedValue:
increasedValue
,
decreasedValue:
decreasedValue
,
textDirection:
textDirection
,
transform:
transform
,
childrenInTraversalOrder:
childrenInTraversalOrder
,
childrenInHitTestOrder:
childrenInHitTestOrder
,
additionalActions:
additionalActions
,
);
}
}
class
SemanticsNodeUpdateObservation
{
const
SemanticsNodeUpdateObservation
({
@required
this
.
id
,
@required
this
.
flags
,
@required
this
.
actions
,
@required
this
.
maxValueLength
,
@required
this
.
currentValueLength
,
@required
this
.
textSelectionBase
,
@required
this
.
textSelectionExtent
,
@required
this
.
platformViewId
,
@required
this
.
scrollChildren
,
@required
this
.
scrollIndex
,
@required
this
.
scrollPosition
,
@required
this
.
scrollExtentMax
,
@required
this
.
scrollExtentMin
,
@required
this
.
elevation
,
@required
this
.
thickness
,
@required
this
.
rect
,
@required
this
.
label
,
@required
this
.
hint
,
@required
this
.
value
,
@required
this
.
increasedValue
,
@required
this
.
decreasedValue
,
this
.
textDirection
,
@required
this
.
transform
,
@required
this
.
childrenInTraversalOrder
,
@required
this
.
childrenInHitTestOrder
,
@required
this
.
additionalActions
,
});
final
int
id
;
final
int
flags
;
final
int
actions
;
final
int
maxValueLength
;
final
int
currentValueLength
;
final
int
textSelectionBase
;
final
int
textSelectionExtent
;
final
int
platformViewId
;
final
int
scrollChildren
;
final
int
scrollIndex
;
final
double
scrollPosition
;
final
double
scrollExtentMax
;
final
double
scrollExtentMin
;
final
double
elevation
;
final
double
thickness
;
final
Rect
rect
;
final
String
label
;
final
String
hint
;
final
String
value
;
final
String
increasedValue
;
final
String
decreasedValue
;
final
TextDirection
textDirection
;
final
Float64List
transform
;
final
Int32List
childrenInTraversalOrder
;
final
Int32List
childrenInHitTestOrder
;
final
Int32List
additionalActions
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment