Unverified Commit 0e85609c authored by fzyzcjy's avatar fzyzcjy Committed by GitHub

Fix that RenderEditable (TextField) ignores offset in painting, making text...

Fix that RenderEditable (TextField) ignores offset in painting, making text selections shifted when offset is nonzero (#109287)

Small fix in text layout math, unlikely to affect most normal usages.
parent 5d2a13b4
...@@ -2540,14 +2540,14 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin, ...@@ -2540,14 +2540,14 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
} }
} }
void _paintHandleLayers(PaintingContext context, List<TextSelectionPoint> endpoints) { void _paintHandleLayers(PaintingContext context, List<TextSelectionPoint> endpoints, Offset offset) {
Offset startPoint = endpoints[0].point; Offset startPoint = endpoints[0].point;
startPoint = Offset( startPoint = Offset(
clampDouble(startPoint.dx, 0.0, size.width), clampDouble(startPoint.dx, 0.0, size.width),
clampDouble(startPoint.dy, 0.0, size.height), clampDouble(startPoint.dy, 0.0, size.height),
); );
context.pushLayer( context.pushLayer(
LeaderLayer(link: startHandleLayerLink, offset: startPoint), LeaderLayer(link: startHandleLayerLink, offset: startPoint + offset),
super.paint, super.paint,
Offset.zero, Offset.zero,
); );
...@@ -2558,7 +2558,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin, ...@@ -2558,7 +2558,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
clampDouble(endPoint.dy, 0.0, size.height), clampDouble(endPoint.dy, 0.0, size.height),
); );
context.pushLayer( context.pushLayer(
LeaderLayer(link: endHandleLayerLink, offset: endPoint), LeaderLayer(link: endHandleLayerLink, offset: endPoint + offset),
super.paint, super.paint,
Offset.zero, Offset.zero,
); );
...@@ -2582,7 +2582,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin, ...@@ -2582,7 +2582,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
_paintContents(context, offset); _paintContents(context, offset);
} }
if (selection!.isValid) { if (selection!.isValid) {
_paintHandleLayers(context, getEndpointsForSelection(selection!)); _paintHandleLayers(context, getEndpointsForSelection(selection!), offset);
} }
} }
......
...@@ -113,6 +113,37 @@ void main() { ...@@ -113,6 +113,37 @@ void main() {
expect(visited, true); expect(visited, true);
}); });
test('RenderEditable.paint respects offset argument', () {
const BoxConstraints viewport = BoxConstraints(maxHeight: 1000.0, maxWidth: 1000.0);
final TestPushLayerPaintingContext context = TestPushLayerPaintingContext();
const Offset paintOffset = Offset(100, 200);
const double fontSize = 20.0;
const Offset endpoint = Offset(0.0, fontSize);
final RenderEditable editable = RenderEditable(
text: const TextSpan(
text: 'text',
style: TextStyle(
fontSize: fontSize,
height: 1.0,
),
),
textDirection: TextDirection.ltr,
startHandleLayerLink: LayerLink(),
endHandleLayerLink: LayerLink(),
offset: ViewportOffset.zero(),
textSelectionDelegate: _FakeEditableTextState(),
selection: const TextSelection(baseOffset: 0, extentOffset: 0),
);
layout(editable, constraints: viewport, phase: EnginePhase.composite);
editable.paint(context, paintOffset);
final List<LeaderLayer> leaderLayers = context.pushedLayers.whereType<LeaderLayer>().toList();
expect(leaderLayers, hasLength(1), reason: '_paintHandleLayers will paint a LeaderLayer');
expect(leaderLayers.single.offset, endpoint + paintOffset, reason: 'offset should respect paintOffset');
});
test('editable intrinsics', () { test('editable intrinsics', () {
final TextSelectionDelegate delegate = _FakeEditableTextState(); final TextSelectionDelegate delegate = _FakeEditableTextState();
final RenderEditable editable = RenderEditable( final RenderEditable editable = RenderEditable(
......
...@@ -365,6 +365,23 @@ class TestClipPaintingContext extends PaintingContext { ...@@ -365,6 +365,23 @@ class TestClipPaintingContext extends PaintingContext {
Clip clipBehavior = Clip.none; Clip clipBehavior = Clip.none;
} }
class TestPushLayerPaintingContext extends PaintingContext {
TestPushLayerPaintingContext() : super(ContainerLayer(), Rect.zero);
final List<ContainerLayer> pushedLayers = <ContainerLayer>[];
@override
void pushLayer(
ContainerLayer childLayer,
PaintingContextCallback painter,
Offset offset, {
Rect? childPaintBounds
}) {
pushedLayers.add(childLayer);
super.pushLayer(childLayer, painter, offset, childPaintBounds: childPaintBounds);
}
}
void expectOverflowedErrors() { void expectOverflowedErrors() {
final FlutterErrorDetails errorDetails = TestRenderingFlutterBinding.instance.takeFlutterErrorDetails()!; final FlutterErrorDetails errorDetails = TestRenderingFlutterBinding.instance.takeFlutterErrorDetails()!;
final bool overflowed = errorDetails.toString().contains('overflowed'); final bool overflowed = errorDetails.toString().contains('overflowed');
......
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