mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Performance improvements for semantics tree compilation (#12682)
* Without checking compatibility * ++ * ++ * ++ * more docs
This commit is contained in:
parent
3206fb63ad
commit
141a6355ce
@ -2251,27 +2251,17 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
|
||||
void _updateSemantics() {
|
||||
assert(_semanticsConfiguration.isSemanticBoundary || parent is! RenderObject);
|
||||
final _SemanticsFragment fragment = _getSemanticsForParent(
|
||||
parentClippingRect: _semanticsClippingRect,
|
||||
mergeIntoParent: _semantics?.parent?.isPartOfNodeMerging ?? false,
|
||||
);
|
||||
assert(fragment is _InterestingSemanticsFragment);
|
||||
final _InterestingSemanticsFragment interestingFragment = fragment;
|
||||
final SemanticsNode node = interestingFragment.compileChildren().single;
|
||||
final SemanticsNode node = interestingFragment.compileChildren(_semantics?.parentClipRect).single;
|
||||
// Fragment only wants to add this node's SemanticsNode to the parent.
|
||||
assert(interestingFragment.config == null && node == _semantics);
|
||||
}
|
||||
|
||||
/// Clip that needs to be applied to any [SemanticsNode] owned by this
|
||||
/// [RenderObject].
|
||||
///
|
||||
/// Can be null if no clip is to be applied.
|
||||
///
|
||||
/// Updated by [_getSemanticsForParent].
|
||||
Rect _semanticsClippingRect;
|
||||
|
||||
/// Returns the semantics that this node would like to add to its parent.
|
||||
_SemanticsFragment _getSemanticsForParent({
|
||||
@required Rect parentClippingRect,
|
||||
@required bool mergeIntoParent,
|
||||
}) {
|
||||
assert(mergeIntoParent != null);
|
||||
@ -2279,16 +2269,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
|
||||
final SemanticsConfiguration config = _semanticsConfiguration;
|
||||
bool dropSemanticsOfPreviousSiblings = config.isBlockingSemanticsOfPreviouslyPaintedNodes;
|
||||
|
||||
final _SemanticsGeometry geometry = new _SemanticsGeometry(
|
||||
owner: this,
|
||||
parentClippingRect: parentClippingRect,
|
||||
);
|
||||
_semanticsClippingRect = geometry.clipRect;
|
||||
|
||||
// Shortcut if this fragment cannot be exposed to user.
|
||||
if (_semanticsConfiguration.isSemanticBoundary && !mergeIntoParent && geometry.isInvisible)
|
||||
return new _ContainerSemanticsFragment(dropsSemanticsOfPreviousSiblings: dropSemanticsOfPreviousSiblings);
|
||||
|
||||
final bool producesForkingFragment = !config.hasBeenAnnotated && !config.isSemanticBoundary;
|
||||
final List<_InterestingSemanticsFragment> fragments = <_InterestingSemanticsFragment>[];
|
||||
final Set<_InterestingSemanticsFragment> toBeMarkedExplicit = new Set<_InterestingSemanticsFragment>();
|
||||
@ -2296,7 +2276,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
|
||||
|
||||
visitChildrenForSemantics((RenderObject renderChild) {
|
||||
final _SemanticsFragment fragment = renderChild._getSemanticsForParent(
|
||||
parentClippingRect: _semanticsClippingRect,
|
||||
mergeIntoParent: childrenMergeIntoParent,
|
||||
);
|
||||
if (fragment.dropsSemanticsOfPreviousSiblings) {
|
||||
@ -2308,7 +2287,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
|
||||
// Figure out which child fragments are to be made explicit.
|
||||
for (_InterestingSemanticsFragment fragment in fragment.interestingFragments) {
|
||||
fragments.add(fragment);
|
||||
fragment.geometry.addAncestor(this);
|
||||
fragment.addAncestor(this);
|
||||
fragment.addTags(config.tagsForChildren);
|
||||
if (config.explicitChildNodes || parent is! RenderObject) {
|
||||
fragment.markAsExplicit();
|
||||
@ -2347,7 +2326,6 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
|
||||
} else {
|
||||
result = new _SwitchableSemanticsFragment(
|
||||
config: config,
|
||||
geometry: geometry,
|
||||
mergeIntoParent: mergeIntoParent,
|
||||
owner: this,
|
||||
dropsSemanticsOfPreviousSiblings: dropSemanticsOfPreviousSiblings,
|
||||
@ -2998,18 +2976,20 @@ class _ContainerSemanticsFragment extends _SemanticsFragment {
|
||||
/// merged into the parent's [SemanticsNode].
|
||||
abstract class _InterestingSemanticsFragment extends _SemanticsFragment {
|
||||
_InterestingSemanticsFragment({
|
||||
this.geometry,
|
||||
@required this.owner,
|
||||
@required RenderObject owner,
|
||||
@required bool dropsSemanticsOfPreviousSiblings
|
||||
}) : assert(owner != null),
|
||||
_ancestorChain = <RenderObject>[owner],
|
||||
super(dropsSemanticsOfPreviousSiblings: dropsSemanticsOfPreviousSiblings);
|
||||
|
||||
/// The [RenderObject] that owns this fragment (and any new [SemanticNode]
|
||||
/// introduced by it).
|
||||
final RenderObject owner;
|
||||
RenderObject get owner => _ancestorChain.first;
|
||||
|
||||
final List<RenderObject> _ancestorChain;
|
||||
|
||||
/// The children to be added to the parent.
|
||||
Iterable<SemanticsNode> compileChildren();
|
||||
Iterable<SemanticsNode> compileChildren(Rect parentClipRect);
|
||||
|
||||
/// The [SemanticsConfiguration] the child wants to merge into the parent's
|
||||
/// [SemanticsNode] or null if it doesn't want to merge anything.
|
||||
@ -3033,8 +3013,6 @@ abstract class _InterestingSemanticsFragment extends _SemanticsFragment {
|
||||
@override
|
||||
void addAll(Iterable<_InterestingSemanticsFragment> fragments);
|
||||
|
||||
final _SemanticsGeometry geometry;
|
||||
|
||||
/// Whether this fragment wants to add any semantic information to the parent
|
||||
/// [SemanticsNode].
|
||||
bool get hasConfigForParent => config != null;
|
||||
@ -3053,6 +3031,18 @@ abstract class _InterestingSemanticsFragment extends _SemanticsFragment {
|
||||
_tagsForChildren ??= new Set<SemanticsTag>();
|
||||
_tagsForChildren.addAll(tags);
|
||||
}
|
||||
|
||||
/// Adds the geometric information of `ancestor` to this object.
|
||||
///
|
||||
/// Those information are required to properly compute the value for
|
||||
/// [SemanticsNode.transform], [SemanticsNode.clipRect], and
|
||||
/// [SemanticsNode.rect].
|
||||
///
|
||||
/// Ancestors have to be added in order from [owner] up until the next
|
||||
/// [RenderObject] that owns a [SemanticsNode] is reached.
|
||||
void addAncestor(RenderObject ancestor) {
|
||||
_ancestorChain.add(ancestor);
|
||||
}
|
||||
}
|
||||
|
||||
/// A [_InterestingSemanticsFragment] that produces the root [SemanticsNode] of
|
||||
@ -3067,16 +3057,28 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment {
|
||||
}) : super(owner: owner, dropsSemanticsOfPreviousSiblings: dropsSemanticsOfPreviousSiblings);
|
||||
|
||||
@override
|
||||
Iterable<SemanticsNode> compileChildren() sync* {
|
||||
Iterable<SemanticsNode> compileChildren(Rect parentClipRect) sync* {
|
||||
assert(_tagsForChildren == null || _tagsForChildren.isEmpty);
|
||||
assert(parentClipRect == null);
|
||||
assert(_ancestorChain.length == 1);
|
||||
|
||||
owner._semantics ??= new SemanticsNode.root(
|
||||
showOnScreen: owner.showOnScreen,
|
||||
owner: owner.owner.semanticsOwner,
|
||||
);
|
||||
final SemanticsNode node = owner._semantics;
|
||||
assert(MatrixUtils.matrixEquals(node.transform, new Matrix4.identity()));
|
||||
assert(!node.wasAffectedByClip);
|
||||
assert(node.parentClipRect == null);
|
||||
|
||||
node.rect = owner.semanticBounds;
|
||||
|
||||
final List<SemanticsNode> children = <SemanticsNode>[];
|
||||
for (_InterestingSemanticsFragment fragment in _children) {
|
||||
assert(fragment.config == null);
|
||||
children.addAll(fragment.compileChildren(parentClipRect));
|
||||
}
|
||||
node.updateWith(config: null, childrenInInversePaintOrder: children);
|
||||
|
||||
assert(!node.isInvisible);
|
||||
yield node;
|
||||
}
|
||||
@ -3084,6 +3086,8 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment {
|
||||
@override
|
||||
SemanticsConfiguration get config => null;
|
||||
|
||||
final List<_InterestingSemanticsFragment> _children = <_InterestingSemanticsFragment>[];
|
||||
|
||||
@override
|
||||
void markAsExplicit() {
|
||||
// nothing to do, we are always explicit.
|
||||
@ -3091,13 +3095,7 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment {
|
||||
|
||||
@override
|
||||
void addAll(Iterable<_InterestingSemanticsFragment> fragments) {
|
||||
final SemanticsNode root = compileChildren().first;
|
||||
final List<SemanticsNode> children = <SemanticsNode>[];
|
||||
for (_InterestingSemanticsFragment fragment in fragments) {
|
||||
assert(fragment.config == null);
|
||||
children.addAll(fragment.compileChildren());
|
||||
}
|
||||
root.updateWith(config: null, childrenInInversePaintOrder: children);
|
||||
_children.addAll(fragments);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3123,40 +3121,59 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
|
||||
_SwitchableSemanticsFragment({
|
||||
@required bool mergeIntoParent,
|
||||
@required SemanticsConfiguration config,
|
||||
@required _SemanticsGeometry geometry,
|
||||
@required RenderObject owner,
|
||||
@required bool dropsSemanticsOfPreviousSiblings,
|
||||
}) : _mergeIntoParent = mergeIntoParent,
|
||||
_config = config,
|
||||
assert(mergeIntoParent != null),
|
||||
assert(config != null),
|
||||
super(geometry: geometry, owner: owner, dropsSemanticsOfPreviousSiblings: dropsSemanticsOfPreviousSiblings);
|
||||
super(owner: owner, dropsSemanticsOfPreviousSiblings: dropsSemanticsOfPreviousSiblings);
|
||||
|
||||
final bool _mergeIntoParent;
|
||||
SemanticsConfiguration _config;
|
||||
bool _isConfigWritable = false;
|
||||
final List<SemanticsNode> _children = <SemanticsNode>[];
|
||||
final List<_InterestingSemanticsFragment> _children = <_InterestingSemanticsFragment>[];
|
||||
|
||||
@override
|
||||
Iterable<SemanticsNode> compileChildren() sync* {
|
||||
Iterable<SemanticsNode> compileChildren(Rect parentClipRect) sync* {
|
||||
if (!_isExplicit) {
|
||||
owner._semantics = null;
|
||||
yield* _children;
|
||||
for (_InterestingSemanticsFragment fragment in _children) {
|
||||
assert(_ancestorChain.first == fragment._ancestorChain.last);
|
||||
fragment._ancestorChain.addAll(_ancestorChain.sublist(1));
|
||||
yield* fragment.compileChildren(parentClipRect);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!_mergeIntoParent && geometry.rect.isEmpty)
|
||||
|
||||
final _SemanticsGeometry geometry = _needsGeometryUpdate
|
||||
? new _SemanticsGeometry(parentClipRect: parentClipRect, ancestors: _ancestorChain)
|
||||
: null;
|
||||
|
||||
if (!_mergeIntoParent && (geometry?.isInvisible == true))
|
||||
return; // Drop the node, it's not going to be visible.
|
||||
|
||||
owner._semantics ??= new SemanticsNode(showOnScreen: owner.showOnScreen);
|
||||
final SemanticsNode node = owner._semantics
|
||||
..isMergedIntoParent = _mergeIntoParent
|
||||
..tags = _tagsForChildren;
|
||||
|
||||
geometry.updateNode(node);
|
||||
if (geometry != null) {
|
||||
assert(_needsGeometryUpdate);
|
||||
node
|
||||
..rect = geometry.rect
|
||||
..transform = geometry.transform
|
||||
..parentClipRect = geometry.clipRect;
|
||||
}
|
||||
|
||||
final List<SemanticsNode> children = <SemanticsNode>[];
|
||||
for (_InterestingSemanticsFragment fragment in _children)
|
||||
children.addAll(fragment.compileChildren(node.parentClipRect));
|
||||
|
||||
if (_config.isSemanticBoundary) {
|
||||
owner.assembleSemanticsNode(node, _config, _children);
|
||||
owner.assembleSemanticsNode(node, _config, children);
|
||||
} else {
|
||||
node.updateWith(config: _config, childrenInInversePaintOrder: _children);
|
||||
node.updateWith(config: _config, childrenInInversePaintOrder: children);
|
||||
}
|
||||
|
||||
yield node;
|
||||
@ -3170,7 +3187,7 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
|
||||
@override
|
||||
void addAll(Iterable<_InterestingSemanticsFragment> fragments) {
|
||||
for (_InterestingSemanticsFragment fragment in fragments) {
|
||||
_children.addAll(fragment.compileChildren());
|
||||
_children.add(fragment);
|
||||
if (fragment.config == null)
|
||||
continue;
|
||||
if (!_isConfigWritable) {
|
||||
@ -3187,6 +3204,8 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
|
||||
void markAsExplicit() {
|
||||
_isExplicit = true;
|
||||
}
|
||||
|
||||
bool get _needsGeometryUpdate => _ancestorChain.length > 1;
|
||||
}
|
||||
|
||||
/// Helper class that keeps track of the geometry of a [SemanticsNode].
|
||||
@ -3195,109 +3214,68 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
|
||||
/// [SemanticsNode.rect] and [SemanticsNode.transform].
|
||||
class _SemanticsGeometry {
|
||||
|
||||
/// `parentClippingRect` may be null if no clip is to be applied.
|
||||
/// The `parentClippingRect` may be null if no clip is to be applied.
|
||||
///
|
||||
/// The `ancestors` list has to include all [RenderObject] in order that are
|
||||
/// located between the [SemanticsNode] whose geometry is represented here
|
||||
/// (first [RenderObject] in the list) and its closest ancestor [RenderObject]
|
||||
/// that also owns its own [SemanticsNode] (last [RenderObject] in the list).
|
||||
_SemanticsGeometry({
|
||||
@required RenderObject owner,
|
||||
@required Rect parentClippingRect
|
||||
}) : assert(owner != null),
|
||||
_ancestorChain = <RenderObject>[owner],
|
||||
_parentClippingRect = parentClippingRect;
|
||||
|
||||
final Rect _parentClippingRect;
|
||||
final List<RenderObject> _ancestorChain;
|
||||
|
||||
RenderObject get _owner => _ancestorChain.first;
|
||||
|
||||
/// The current clip [Rect] that would be applied to the [SemanticsNode]
|
||||
/// owned by [owner].
|
||||
Rect get clipRect {
|
||||
if (!_isClipRectValid) {
|
||||
__clipRect = _computeClipRect();
|
||||
_isClipRectValid = true;
|
||||
}
|
||||
return __clipRect;
|
||||
@required Rect parentClipRect,
|
||||
@required List<RenderObject> ancestors,
|
||||
}) {
|
||||
_computeValues(parentClipRect, ancestors);
|
||||
}
|
||||
Rect __clipRect;
|
||||
bool _isClipRectValid = false;
|
||||
|
||||
Rect _computeClipRect() {
|
||||
if (_owner.parent is! RenderObject)
|
||||
return null;
|
||||
final RenderObject parent = _owner.parent;
|
||||
Rect _clipRect;
|
||||
Matrix4 _transform;
|
||||
Rect _rect;
|
||||
|
||||
// Clip rect in parent's coordinate system.
|
||||
Rect clip = parent.describeApproximatePaintClip(_owner);
|
||||
if (clip == null) {
|
||||
if (_parentClippingRect == null)
|
||||
return null;
|
||||
clip = _parentClippingRect;
|
||||
} else if (_parentClippingRect != null) {
|
||||
clip = _parentClippingRect.intersect(clip);
|
||||
/// Value for [SemanticsNode.transform].
|
||||
Matrix4 get transform => _transform;
|
||||
|
||||
/// Value for [SemanticsNode.parentClipRect].
|
||||
Rect get clipRect => _clipRect;
|
||||
|
||||
/// Value for [SemanticsNode.rect].
|
||||
Rect get rect => _rect;
|
||||
|
||||
void _computeValues(Rect parentClipRect, List<RenderObject> ancestors) {
|
||||
assert(ancestors.length > 1);
|
||||
|
||||
_transform = new Matrix4.identity();
|
||||
_clipRect = parentClipRect;
|
||||
for (int index = ancestors.length-1; index > 0; index -= 1) {
|
||||
final RenderObject parent = ancestors[index];
|
||||
final RenderObject child = ancestors[index-1];
|
||||
_clipRect = _intersectClipRect(parent.describeApproximatePaintClip(child));
|
||||
if (_clipRect != null) {
|
||||
if (_clipRect.isEmpty) {
|
||||
_clipRect = Rect.zero;
|
||||
} else {
|
||||
final Matrix4 clipTransform = new Matrix4.identity();
|
||||
parent.applyPaintTransform(child, clipTransform);
|
||||
_clipRect = MatrixUtils.inverseTransformRect(clipTransform, _clipRect);
|
||||
}
|
||||
}
|
||||
parent.applyPaintTransform(child, _transform);
|
||||
}
|
||||
|
||||
assert(clip != null);
|
||||
if (clip.isEmpty)
|
||||
return Rect.zero;
|
||||
|
||||
// Translate clip into owner's coordinate system.
|
||||
final Matrix4 clipTransform = new Matrix4.identity();
|
||||
parent.applyPaintTransform(_owner, clipTransform);
|
||||
return MatrixUtils.inverseTransformRect(clipTransform, clip);
|
||||
final RenderObject owner = ancestors.first;
|
||||
_rect = _clipRect == null ? owner.semanticBounds : _clipRect.intersect(owner.semanticBounds);
|
||||
}
|
||||
|
||||
/// The value for [SemanticsNode.rect].
|
||||
///
|
||||
/// This is essentially [RenderObject.semanticsBound] with [clipRect] applied.
|
||||
Rect get rect {
|
||||
if (__rect == null)
|
||||
__rect = _computeRect();
|
||||
return __rect;
|
||||
}
|
||||
Rect __rect;
|
||||
|
||||
Rect _computeRect() {
|
||||
if (clipRect == null)
|
||||
return _owner.semanticBounds;
|
||||
return clipRect.intersect(_owner.semanticBounds);
|
||||
}
|
||||
|
||||
Matrix4 _computeTransformation() {
|
||||
assert(_ancestorChain.length > 1);
|
||||
final Matrix4 transform = new Matrix4.identity();
|
||||
for (int index = _ancestorChain.length-1; index > 0; index -= 1) {
|
||||
final RenderObject parent = _ancestorChain[index];
|
||||
final RenderObject child = _ancestorChain[index - 1];
|
||||
parent.applyPaintTransform(child, transform);
|
||||
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
/// Annotates `node` with the latest geometry information.
|
||||
///
|
||||
/// It sets [SemanticsNode.rect], [SemanticsNode.transform], and
|
||||
/// [SemanticsNode.wasAffectedByClip] to the current values.
|
||||
void updateNode(SemanticsNode node) {
|
||||
if (_ancestorChain.length > 1)
|
||||
node.transform = _computeTransformation();
|
||||
node.rect = rect;
|
||||
node.wasAffectedByClip = rect != _owner.semanticBounds;
|
||||
}
|
||||
|
||||
/// Adds the geometric information of `ancestor` to this object.
|
||||
///
|
||||
/// Those information are required to properly compute the value for
|
||||
/// [SemanticsNode.transform].
|
||||
///
|
||||
/// Ancestors have to be added in order from [owner] up until the next
|
||||
/// [RenderObject] that owns a [SemanticsNode] is reached.
|
||||
void addAncestor(RenderObject ancestor) {
|
||||
_ancestorChain.add(ancestor);
|
||||
Rect _intersectClipRect(Rect other) {
|
||||
if (_clipRect == null)
|
||||
return other;
|
||||
if (other == null)
|
||||
return _clipRect;
|
||||
return _clipRect.intersect(other);
|
||||
}
|
||||
|
||||
/// Whether a [SemanticsNode] annotated with the geometric information tracked
|
||||
/// by this object would be visible on screen.
|
||||
bool get isInvisible {
|
||||
return clipRect != null && clipRect.isEmpty || rect.isEmpty;
|
||||
return _rect.isEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3086,7 +3086,6 @@ class RenderSemanticsGestureHandler extends RenderProxyBox {
|
||||
|
||||
_innerNode ??= new SemanticsNode(showOnScreen: showOnScreen);
|
||||
_innerNode
|
||||
..wasAffectedByClip = node.wasAffectedByClip
|
||||
..isMergedIntoParent = node.isPartOfNodeMerging
|
||||
..rect = Offset.zero & node.rect.size;
|
||||
_annotatedNode = _innerNode;
|
||||
|
||||
@ -253,12 +253,11 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether [rect] was affected by a clip from an ancestors.
|
||||
/// The clip rect from an ancestor that was applied to this node.
|
||||
///
|
||||
/// If this is true it means that an ancestor imposed a clip on this
|
||||
/// [SemanticsNode]. However, it does not mean that the clip had any effect
|
||||
/// on the [rect] whatsoever.
|
||||
bool wasAffectedByClip = false;
|
||||
/// Expressed in the coordinate system of the node. May be null if no clip has
|
||||
/// been applied.
|
||||
Rect parentClipRect;
|
||||
|
||||
/// Whether the node is invisible.
|
||||
///
|
||||
@ -488,7 +487,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
|
||||
return _label != config.label ||
|
||||
_flags != config._flags ||
|
||||
_textDirection != config.textDirection ||
|
||||
_actionsAsBitMap(_actions) != _actionsAsBitMap(config._actions) ||
|
||||
_actionsAsBits != config._actionsAsBits ||
|
||||
_mergeAllDescendantsIntoThisNode != config.isMergingSemanticsOfDescendants;
|
||||
}
|
||||
|
||||
@ -496,6 +495,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
|
||||
|
||||
Map<SemanticsAction, VoidCallback> _actions = _kEmptyConfig._actions;
|
||||
|
||||
int _actionsAsBits = _kEmptyConfig._actionsAsBits;
|
||||
|
||||
/// The [SemanticsTag]s this node is tagged with.
|
||||
///
|
||||
/// Tags are used during the construction of the semantics tree. They are not
|
||||
@ -519,10 +520,6 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
|
||||
TextDirection get textDirection => _textDirection;
|
||||
TextDirection _textDirection = _kEmptyConfig.textDirection;
|
||||
|
||||
int _actionsAsBitMap(Map<SemanticsAction, VoidCallback> actions) {
|
||||
return actions.keys.fold(0, (int prev, SemanticsAction action) => prev |= action.index);
|
||||
}
|
||||
|
||||
bool _canPerformAction(SemanticsAction action) => _actions.containsKey(action);
|
||||
|
||||
static final SemanticsConfiguration _kEmptyConfig = new SemanticsConfiguration();
|
||||
@ -539,6 +536,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
|
||||
_flags = config._flags;
|
||||
_textDirection = config.textDirection;
|
||||
_actions = new Map<SemanticsAction, VoidCallback>.from(config._actions);
|
||||
_actionsAsBits = config._actionsAsBits;
|
||||
_mergeAllDescendantsIntoThisNode = config.isMergingSemanticsOfDescendants;
|
||||
_replaceChildren(childrenInInversePaintOrder ?? const <SemanticsNode>[]);
|
||||
}
|
||||
@ -551,7 +549,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
|
||||
/// returned data matches the data on this node.
|
||||
SemanticsData getSemanticsData() {
|
||||
int flags = _flags;
|
||||
int actions = _actionsAsBitMap(_actions);
|
||||
int actions = _actionsAsBits;
|
||||
String label = _label;
|
||||
TextDirection textDirection = _textDirection;
|
||||
Set<SemanticsTag> mergedTags = tags == null ? null : new Set<SemanticsTag>.from(tags);
|
||||
@ -560,7 +558,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
|
||||
_visitDescendants((SemanticsNode node) {
|
||||
assert(node.isMergedIntoParent);
|
||||
flags |= node._flags;
|
||||
actions |= _actionsAsBitMap(node._actions);
|
||||
actions |= node._actionsAsBits;
|
||||
textDirection ??= node._textDirection;
|
||||
if (node.tags != null) {
|
||||
mergedTags ??= new Set<SemanticsTag>();
|
||||
@ -673,7 +671,6 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
|
||||
}
|
||||
properties.add(new DiagnosticsProperty<Rect>('rect', rect, description: description, showName: false));
|
||||
}
|
||||
properties.add(new FlagProperty('wasAffectedByClip', value: wasAffectedByClip, ifTrue: 'clipped'));
|
||||
final List<String> actions = _actions.keys.map((SemanticsAction action) => describeEnum(action)).toList()..sort();
|
||||
properties.add(new IterableProperty<String>('actions', actions, ifEmpty: null));
|
||||
if (_hasFlag(SemanticsFlags.hasCheckedState))
|
||||
@ -871,7 +868,7 @@ class SemanticsOwner extends ChangeNotifier {
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
return node._canPerformAction(action) ? node._actions[action] : null;
|
||||
return node._actions[action];
|
||||
}
|
||||
|
||||
/// Asks the [SemanticsNode] at the given position to perform the given action.
|
||||
@ -985,11 +982,14 @@ class SemanticsConfiguration {
|
||||
/// * [addAction] to add an action.
|
||||
final Map<SemanticsAction, VoidCallback> _actions = <SemanticsAction, VoidCallback>{};
|
||||
|
||||
int _actionsAsBits = 0;
|
||||
|
||||
/// Adds an `action` to the semantics tree.
|
||||
///
|
||||
/// Whenever the user performs `action` the provided `handler` is called.
|
||||
void addAction(SemanticsAction action, VoidCallback handler) {
|
||||
_actions[action] = handler;
|
||||
_actionsAsBits |= action.index;
|
||||
_hasBeenAnnotated = true;
|
||||
}
|
||||
|
||||
@ -1083,7 +1083,7 @@ class SemanticsConfiguration {
|
||||
bool isCompatibleWith(SemanticsConfiguration other) {
|
||||
if (other == null || !other.hasBeenAnnotated || !hasBeenAnnotated)
|
||||
return true;
|
||||
if (_actions.keys.toSet().intersection(other._actions.keys.toSet()).isNotEmpty)
|
||||
if (_actionsAsBits & other._actionsAsBits != 0)
|
||||
return false;
|
||||
if ((_flags & other._flags) != 0)
|
||||
return false;
|
||||
@ -1105,6 +1105,7 @@ class SemanticsConfiguration {
|
||||
return;
|
||||
|
||||
_actions.addAll(other._actions);
|
||||
_actionsAsBits |= other._actionsAsBits;
|
||||
_flags |= other._flags;
|
||||
|
||||
textDirection ??= other.textDirection;
|
||||
@ -1138,6 +1139,7 @@ class SemanticsConfiguration {
|
||||
.._textDirection = _textDirection
|
||||
.._label = _label
|
||||
.._flags = _flags
|
||||
.._actionsAsBits = _actionsAsBits
|
||||
.._actions.addAll(_actions);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,12 +40,12 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 2,
|
||||
id: 1,
|
||||
label: 'I am text!\nMoar text!!1',
|
||||
textDirection: TextDirection.ltr,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 1,
|
||||
id: 2,
|
||||
label: 'Button',
|
||||
textDirection: TextDirection.ltr,
|
||||
actions: SemanticsAction.tap.index,
|
||||
|
||||
@ -95,7 +95,7 @@ void main() {
|
||||
expect(semantics, hasSemantics(new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 7,
|
||||
id: 1,
|
||||
rect: new Rect.fromLTWH(0.0, 0.0, 800.0, 56.0),
|
||||
transform: null,
|
||||
flags: SemanticsFlags.hasCheckedState.index | SemanticsFlags.isChecked.index,
|
||||
@ -103,7 +103,7 @@ void main() {
|
||||
label: 'aaa\nAAA',
|
||||
),
|
||||
new TestSemantics.rootChild(
|
||||
id: 8,
|
||||
id: 4,
|
||||
rect: new Rect.fromLTWH(0.0, 0.0, 800.0, 56.0),
|
||||
transform: new Matrix4.translationValues(0.0, 56.0, 0.0),
|
||||
flags: SemanticsFlags.hasCheckedState.index | SemanticsFlags.isChecked.index,
|
||||
@ -111,7 +111,7 @@ void main() {
|
||||
label: 'bbb\nBBB',
|
||||
),
|
||||
new TestSemantics.rootChild(
|
||||
id: 9,
|
||||
id: 7,
|
||||
rect: new Rect.fromLTWH(0.0, 0.0, 800.0, 56.0),
|
||||
transform: new Matrix4.translationValues(0.0, 112.0, 0.0),
|
||||
flags: SemanticsFlags.hasCheckedState.index,
|
||||
|
||||
@ -1011,11 +1011,11 @@ void main() {
|
||||
final TestSemantics expectedSemantics = new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
rect: TestSemantics.fullScreen,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 1,
|
||||
id: 2,
|
||||
actions: SemanticsAction.tap.index,
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
label: 'TAB #0\nTab 1 of 2',
|
||||
@ -1023,7 +1023,7 @@ void main() {
|
||||
transform: new Matrix4.translationValues(0.0, 276.0, 0.0),
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 2,
|
||||
id: 3,
|
||||
actions: SemanticsAction.tap.index,
|
||||
label: 'TAB #1\nTab 2 of 2',
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 108.0, kTextTabBarHeight),
|
||||
@ -1261,11 +1261,11 @@ void main() {
|
||||
final TestSemantics expectedSemantics = new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 25,
|
||||
id: 23,
|
||||
rect: TestSemantics.fullScreen,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 23,
|
||||
id: 24,
|
||||
actions: SemanticsAction.tap.index,
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
label: 'Semantics override 0\nTab 1 of 2',
|
||||
@ -1273,7 +1273,7 @@ void main() {
|
||||
transform: new Matrix4.translationValues(0.0, 276.0, 0.0),
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 24,
|
||||
id: 25,
|
||||
actions: SemanticsAction.tap.index,
|
||||
label: 'Semantics override 1\nTab 2 of 2',
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 108.0, kTextTabBarHeight),
|
||||
|
||||
@ -198,7 +198,7 @@ void main() {
|
||||
|
||||
expect(
|
||||
minimalProperties.toStringDeep(minLevel: DiagnosticLevel.hidden),
|
||||
'SemanticsNode#16(owner: null, isPartOfNodeMerging: false, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), wasAffectedByClip: false, actions: [], isSelected: false, label: "", isButton: false, textDirection: null)\n',
|
||||
'SemanticsNode#16(owner: null, isPartOfNodeMerging: false, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0), actions: [], isSelected: false, label: "", isButton: false, textDirection: null)\n',
|
||||
);
|
||||
|
||||
final SemanticsConfiguration config = new SemanticsConfiguration()
|
||||
@ -214,11 +214,10 @@ void main() {
|
||||
final SemanticsNode allProperties = new SemanticsNode()
|
||||
..rect = new Rect.fromLTWH(50.0, 10.0, 20.0, 30.0)
|
||||
..transform = new Matrix4.translation(new Vector3(10.0, 10.0, 0.0))
|
||||
..wasAffectedByClip = true
|
||||
..updateWith(config: config, childrenInInversePaintOrder: null);
|
||||
expect(
|
||||
allProperties.toStringDeep(),
|
||||
'SemanticsNode#17(STALE, owner: null, leaf merge, Rect.fromLTRB(60.0, 20.0, 80.0, 50.0), clipped, actions: [longPress, scrollUp, showOnScreen], unchecked, selected, label: "Use all the properties", button, textDirection: rtl)\n',
|
||||
'SemanticsNode#17(STALE, owner: null, leaf merge, Rect.fromLTRB(60.0, 20.0, 80.0, 50.0), actions: [longPress, scrollUp, showOnScreen], unchecked, selected, label: "Use all the properties", button, textDirection: rtl)\n',
|
||||
);
|
||||
expect(
|
||||
allProperties.getSemanticsData().toString(),
|
||||
|
||||
@ -229,20 +229,20 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 8,
|
||||
id: 5,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 5,
|
||||
id: 6,
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
label: 'node 1',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 6,
|
||||
id: 7,
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
label: 'node 2',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 7,
|
||||
id: 8,
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
label: 'node 3',
|
||||
),
|
||||
|
||||
@ -104,11 +104,11 @@ void main() {
|
||||
final TestSemantics expectedSemantics = new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 2,
|
||||
id: 1,
|
||||
rect: TestSemantics.fullScreen,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 1,
|
||||
id: 2,
|
||||
rect: TestSemantics.fullScreen,
|
||||
actions: SemanticsAction.tap.index,
|
||||
),
|
||||
|
||||
@ -53,17 +53,17 @@ void main() {
|
||||
expect(semantics, hasSemantics(new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
rect: TestSemantics.fullScreen,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 1,
|
||||
id: 2,
|
||||
label: 'child1',
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 10.0),
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 2,
|
||||
id: 3,
|
||||
label: 'child2',
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 10.0),
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
@ -107,7 +107,7 @@ void main() {
|
||||
expect(semantics, hasSemantics(new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
label: 'child1',
|
||||
rect: TestSemantics.fullScreen,
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
@ -149,7 +149,7 @@ void main() {
|
||||
expect(semantics, hasSemantics(new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
rect: TestSemantics.fullScreen,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
@ -159,7 +159,7 @@ void main() {
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 2,
|
||||
id: 3,
|
||||
label: 'child2',
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 10.0),
|
||||
flags: SemanticsFlags.isSelected.index,
|
||||
|
||||
@ -53,22 +53,22 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
label: 'L1',
|
||||
rect: TestSemantics.fullScreen,
|
||||
),
|
||||
new TestSemantics.rootChild(
|
||||
id: 4,
|
||||
id: 2,
|
||||
label: 'L2',
|
||||
rect: TestSemantics.fullScreen,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 1,
|
||||
id: 3,
|
||||
flags: SemanticsFlags.hasCheckedState.index | SemanticsFlags.isChecked.index,
|
||||
rect: TestSemantics.fullScreen,
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 2,
|
||||
id: 4,
|
||||
flags: SemanticsFlags.hasCheckedState.index,
|
||||
rect: TestSemantics.fullScreen,
|
||||
),
|
||||
@ -113,12 +113,12 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
label: 'L1',
|
||||
rect: TestSemantics.fullScreen,
|
||||
),
|
||||
new TestSemantics.rootChild(
|
||||
id: 4,
|
||||
id: 2,
|
||||
label: 'L2',
|
||||
flags: SemanticsFlags.hasCheckedState.index | SemanticsFlags.isChecked.index,
|
||||
rect: TestSemantics.fullScreen,
|
||||
@ -158,7 +158,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 4,
|
||||
id: 2,
|
||||
label: 'L2',
|
||||
flags: SemanticsFlags.hasCheckedState.index | SemanticsFlags.isChecked.index,
|
||||
rect: TestSemantics.fullScreen,
|
||||
|
||||
@ -55,7 +55,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
flags: SemanticsFlags.hasCheckedState.index | SemanticsFlags.isChecked.index,
|
||||
label: label,
|
||||
rect: TestSemantics.fullScreen,
|
||||
@ -111,7 +111,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
flags: SemanticsFlags.hasCheckedState.index | SemanticsFlags.isChecked.index,
|
||||
label: label,
|
||||
rect: TestSemantics.fullScreen,
|
||||
|
||||
@ -41,7 +41,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
flags: SemanticsFlags.hasCheckedState.index | SemanticsFlags.isChecked.index,
|
||||
label: 'label',
|
||||
textDirection: TextDirection.ltr,
|
||||
@ -79,7 +79,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 3,
|
||||
id: 1,
|
||||
flags: SemanticsFlags.hasCheckedState.index | SemanticsFlags.isChecked.index,
|
||||
label: 'label',
|
||||
textDirection: TextDirection.ltr,
|
||||
|
||||
@ -60,12 +60,6 @@ void main() {
|
||||
ignoreTransform: true,
|
||||
));
|
||||
|
||||
final SemanticsNode node1 = tester.renderObject(find.byWidget(const Text('1'))).debugSemantics;
|
||||
final SemanticsNode node2 = tester.renderObject(find.byWidget(const Text('2'))).debugSemantics;
|
||||
|
||||
expect(node1.wasAffectedByClip, false);
|
||||
expect(node2.wasAffectedByClip, true);
|
||||
|
||||
semantics.dispose();
|
||||
});
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 4,
|
||||
id: 1,
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.useTwoPaneSemantics],
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
@ -58,15 +58,15 @@ void main() {
|
||||
actions: SemanticsAction.scrollUp.index,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 1,
|
||||
id: 2,
|
||||
label: 'Item 0',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 2,
|
||||
id: 3,
|
||||
label: 'Item 1',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 3,
|
||||
id: 4,
|
||||
label: 'Semantics Test with Slivers',
|
||||
),
|
||||
],
|
||||
@ -88,7 +88,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 4,
|
||||
id: 1,
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.useTwoPaneSemantics],
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
@ -96,11 +96,11 @@ void main() {
|
||||
actions: SemanticsAction.scrollUp.index | SemanticsAction.scrollDown.index,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 1,
|
||||
id: 2,
|
||||
label: 'Item 0',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 2,
|
||||
id: 3,
|
||||
label: 'Item 1',
|
||||
),
|
||||
new TestSemantics(
|
||||
@ -110,7 +110,7 @@ void main() {
|
||||
],
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 3,
|
||||
id: 4,
|
||||
label: 'Semantics Test with Slivers',
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.excludeFromScrolling],
|
||||
),
|
||||
@ -131,7 +131,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 4,
|
||||
id: 1,
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.useTwoPaneSemantics],
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
@ -139,11 +139,11 @@ void main() {
|
||||
actions: SemanticsAction.scrollUp.index | SemanticsAction.scrollDown.index,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 1,
|
||||
id: 2,
|
||||
label: 'Item 0',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 2,
|
||||
id: 3,
|
||||
label: 'Item 1',
|
||||
),
|
||||
new TestSemantics(
|
||||
@ -151,7 +151,7 @@ void main() {
|
||||
label: 'Item 2',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 3,
|
||||
id: 4,
|
||||
label: 'Semantics Test with Slivers',
|
||||
),
|
||||
],
|
||||
@ -202,7 +202,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 9,
|
||||
id: 7,
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.useTwoPaneSemantics],
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
@ -210,12 +210,12 @@ void main() {
|
||||
actions: SemanticsAction.scrollUp.index | SemanticsAction.scrollDown.index,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 7,
|
||||
id: 8,
|
||||
label: 'Item 2',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 8,
|
||||
id: 9,
|
||||
label: 'Item 1',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
@ -256,34 +256,34 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 16,
|
||||
id: 11,
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.useTwoPaneSemantics],
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 17,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 11,
|
||||
id: 12,
|
||||
label: 'Item 4',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 12,
|
||||
id: 13,
|
||||
label: 'Item 3',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 13,
|
||||
id: 14,
|
||||
label: 'Item 2',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 14,
|
||||
id: 15,
|
||||
label: 'Item 1',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 15,
|
||||
id: 16,
|
||||
label: 'Item 0',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
@ -337,7 +337,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 22,
|
||||
id: 18,
|
||||
rect: TestSemantics.fullScreen,
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.useTwoPaneSemantics],
|
||||
children: <TestSemantics>[
|
||||
@ -348,20 +348,20 @@ void main() {
|
||||
children: <TestSemantics>[
|
||||
// Item 0 is missing because its covered by the app bar.
|
||||
new TestSemantics(
|
||||
id: 18,
|
||||
id: 19,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
// Item 1 starts 20.0dp below edge, so there would be room for Item 0.
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 20.0, 0.0)),
|
||||
label: 'Item 1',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 19,
|
||||
id: 20,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 220.0, 0.0)),
|
||||
label: 'Item 2',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 20,
|
||||
id: 21,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 420.0, 0.0)),
|
||||
label: 'Item 3',
|
||||
@ -369,7 +369,7 @@ void main() {
|
||||
],
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 21,
|
||||
id: 22,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 120.0, 20.0),
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.excludeFromScrolling],
|
||||
label: 'AppBar',
|
||||
@ -420,7 +420,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 28,
|
||||
id: 24,
|
||||
rect: TestSemantics.fullScreen,
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.useTwoPaneSemantics],
|
||||
children: <TestSemantics>[
|
||||
@ -430,19 +430,19 @@ void main() {
|
||||
rect: TestSemantics.fullScreen,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 24,
|
||||
id: 25,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 420.0, 0.0)),
|
||||
label: 'Item 3',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 25,
|
||||
id: 26,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 220.0, 0.0)),
|
||||
label: 'Item 2',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 26,
|
||||
id: 27,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
// Item 1 starts 20.0dp below edge, so there would be room for Item 0.
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 20.0, 0.0)),
|
||||
@ -452,7 +452,7 @@ void main() {
|
||||
],
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 27,
|
||||
id: 28,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 120.0, 20.0),
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.excludeFromScrolling],
|
||||
label: 'AppBar'
|
||||
@ -505,7 +505,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 34,
|
||||
id: 30,
|
||||
rect: TestSemantics.fullScreen,
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.useTwoPaneSemantics],
|
||||
children: <TestSemantics>[
|
||||
@ -516,20 +516,20 @@ void main() {
|
||||
children: <TestSemantics>[
|
||||
// Item 0 is missing because its covered by the app bar.
|
||||
new TestSemantics(
|
||||
id: 30,
|
||||
id: 31,
|
||||
// Item 1 ends at 580dp, so there would be 20dp space for Item 0.
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 380.0, 0.0)),
|
||||
label: 'Item 1',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 31,
|
||||
id: 32,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 180.0, 0.0)),
|
||||
label: 'Item 2',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 32,
|
||||
id: 33,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, -20.0, 0.0)),
|
||||
label: 'Item 3',
|
||||
@ -537,7 +537,7 @@ void main() {
|
||||
],
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 33,
|
||||
id: 34,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 120.0, 20.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 544.0, 0.0)),
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.excludeFromScrolling],
|
||||
@ -590,7 +590,7 @@ void main() {
|
||||
new TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics.rootChild(
|
||||
id: 40,
|
||||
id: 36,
|
||||
rect: TestSemantics.fullScreen,
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.useTwoPaneSemantics],
|
||||
children: <TestSemantics>[
|
||||
@ -600,19 +600,19 @@ void main() {
|
||||
rect: TestSemantics.fullScreen,
|
||||
children: <TestSemantics>[
|
||||
new TestSemantics(
|
||||
id: 36,
|
||||
id: 37,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, -20.0, 0.0)),
|
||||
label: 'Item 3',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 37,
|
||||
id: 38,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 180.0, 0.0)),
|
||||
label: 'Item 2',
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 38,
|
||||
id: 39,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
|
||||
// Item 1 ends at 580dp, so there would be 20dp space for Item 0.
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 380.0, 0.0)),
|
||||
@ -622,7 +622,7 @@ void main() {
|
||||
],
|
||||
),
|
||||
new TestSemantics(
|
||||
id: 39,
|
||||
id: 40,
|
||||
rect: new Rect.fromLTRB(0.0, 0.0, 120.0, 20.0),
|
||||
transform: new Matrix4.translation(new Vector3(0.0, 544.0, 0.0)),
|
||||
tags: <SemanticsTag>[RenderSemanticsGestureHandler.excludeFromScrolling],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user