Unverified Commit a5658485 authored by Jason Simmons's avatar Jason Simmons Committed by GitHub

Ignore text selection boxes when assembling semantics for placeholder runs (#70487)

parent 5f56db0a
......@@ -902,13 +902,33 @@ class RenderParagraph extends RenderBox
RenderBox? child = firstChild;
final Queue<SemanticsNode> newChildCache = Queue<SemanticsNode>();
for (final InlineSpanSemanticsInformation info in _combineSemanticsInfo()) {
final TextDirection initialDirection = currentDirection;
final TextSelection selection = TextSelection(
baseOffset: start,
extentOffset: start + info.text.length,
);
final List<ui.TextBox> rects = getBoxesForSelection(selection);
start += info.text.length;
if (info.isPlaceholder) {
// A placeholder span may have 0 to multple semantics nodes, we need
// to annotate all of the semantics nodes belong to this span.
while (children.length > childIndex &&
children.elementAt(childIndex).isTagged(PlaceholderSpanIndexSemanticsTag(placeholderIndex))) {
final SemanticsNode childNode = children.elementAt(childIndex);
final TextParentData parentData = child!.parentData! as TextParentData;
childNode.rect = Rect.fromLTWH(
childNode.rect.left,
childNode.rect.top,
childNode.rect.width * parentData.scale!,
childNode.rect.height * parentData.scale!,
);
newChildren.add(childNode);
childIndex += 1;
}
child = childAfter(child!);
placeholderIndex += 1;
} else {
final TextDirection initialDirection = currentDirection;
final List<ui.TextBox> rects = getBoxesForSelection(selection);
if (rects.isEmpty) {
continue;
}
......@@ -934,26 +954,6 @@ class RenderParagraph extends RenderBox
rect.right.ceilToDouble() + 4.0,
rect.bottom.ceilToDouble() + 4.0,
);
if (info.isPlaceholder) {
// A placeholder span may have 0 to multple semantics nodes, we need
// to annotate all of the semantics nodes belong to this span.
while (children.length > childIndex &&
children.elementAt(childIndex).isTagged(PlaceholderSpanIndexSemanticsTag(placeholderIndex))) {
final SemanticsNode childNode = children.elementAt(childIndex);
final TextParentData parentData = child!.parentData! as TextParentData;
childNode.rect = Rect.fromLTWH(
childNode.rect.left,
childNode.rect.top,
childNode.rect.width * parentData.scale!,
childNode.rect.height * parentData.scale!,
);
newChildren.add(childNode);
childIndex += 1;
}
child = childAfter(child!);
placeholderIndex += 1;
} else {
final SemanticsConfiguration configuration = SemanticsConfiguration()
..sortKey = OrdinalSortKey(ordinal++)
..textDirection = initialDirection
......
......@@ -37,6 +37,26 @@ class RenderParagraphWithEmptySelectionBoxList extends RenderParagraph {
}
}
// A subclass of RenderParagraph that returns an empty list in getBoxesForSelection
// for a selection representing a WidgetSpan.
// This is intended to simulate how SkParagraph's implementation of Paragraph.getBoxesForRange
// can return an empty list for a WidgetSpan with empty dimensions.
class RenderParagraphWithEmptyBoxListForWidgetSpan extends RenderParagraph {
RenderParagraphWithEmptyBoxListForWidgetSpan(
InlineSpan text, {
required List<RenderBox> children,
required TextDirection textDirection,
}) : super(text, children: children, textDirection: textDirection);
@override
List<ui.TextBox> getBoxesForSelection(TextSelection selection) {
if (text.getSpanForPosition(selection.base) is WidgetSpan) {
return <ui.TextBox>[];
}
return super.getBoxesForSelection(selection);
}
}
void main() {
test('getOffsetForCaret control test', () {
final RenderParagraph paragraph = RenderParagraph(
......@@ -588,4 +608,25 @@ void main() {
paragraph.assembleSemanticsNode(node, SemanticsConfiguration(), <SemanticsNode>[]);
expect(node.childrenCount, 2);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/61020
test('assembleSemanticsNode handles empty WidgetSpans that do not yield selection boxes', () {
final TextSpan text = TextSpan(text: '', children: <InlineSpan>[
TextSpan(text: 'A', recognizer: TapGestureRecognizer()..onTap = () {}),
const WidgetSpan(child: SizedBox(width: 0, height: 0)),
TextSpan(text: 'C', recognizer: TapGestureRecognizer()..onTap = () {}),
]);
final List<RenderBox> renderBoxes = <RenderBox>[
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
];
final RenderParagraph paragraph = RenderParagraphWithEmptyBoxListForWidgetSpan(
text,
children: renderBoxes,
textDirection: TextDirection.ltr,
);
layout(paragraph);
final SemanticsNode node = SemanticsNode();
paragraph.assembleSemanticsNode(node, SemanticsConfiguration(), <SemanticsNode>[]);
expect(node.childrenCount, 2);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/61020
}
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