Commit 141a6355 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Performance improvements for semantics tree compilation (#12682)

* Without checking compatibility

* ++

* ++

* ++

* more docs
parent 3206fb63
......@@ -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;
assert(clip != null);
if (clip.isEmpty)
return Rect.zero;
/// Value for [SemanticsNode.parentClipRect].
Rect get clipRect => _clipRect;
// Translate clip into owner's coordinate system.
final Matrix4 clipTransform = new Matrix4.identity();
parent.applyPaintTransform(_owner, clipTransform);
return MatrixUtils.inverseTransformRect(clipTransform, clip);
}
/// Value for [SemanticsNode.rect].
Rect get rect => _rect;
/// 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;
void _computeValues(Rect parentClipRect, List<RenderObject> ancestors) {
assert(ancestors.length > 1);
Rect _computeRect() {
if (clipRect == null)
return _owner.semanticBounds;
return clipRect.intersect(_owner.semanticBounds);
_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);
}
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;
parent.applyPaintTransform(child, _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;
final RenderObject owner = ancestors.first;
_rect = _clipRect == null ? owner.semanticBounds : _clipRect.intersect(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],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment