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

Use strut box heights to calculate selection rectangles in order to ensure...

Use strut box heights to calculate selection rectangles in order to ensure that they remain within visible bounds (#50354)
parent ac67a1b7
...@@ -591,7 +591,7 @@ class _SelectableTextState extends State<SelectableText> with AutomaticKeepAlive ...@@ -591,7 +591,7 @@ class _SelectableTextState extends State<SelectableText> with AutomaticKeepAlive
showCursor: widget.showCursor, showCursor: widget.showCursor,
controller: _controller, controller: _controller,
focusNode: focusNode, focusNode: focusNode,
strutStyle: widget.strutStyle ?? StrutStyle.disabled, strutStyle: widget.strutStyle ?? const StrutStyle(),
textAlign: widget.textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start, textAlign: widget.textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start,
textDirection: widget.textDirection, textDirection: widget.textDirection,
textScaleFactor: widget.textScaleFactor, textScaleFactor: widget.textScaleFactor,
......
...@@ -641,7 +641,9 @@ class TextPainter { ...@@ -641,7 +641,9 @@ class TextPainter {
List<TextBox> boxes = <TextBox>[]; List<TextBox> boxes = <TextBox>[];
while (boxes.isEmpty && flattenedText != null) { while (boxes.isEmpty && flattenedText != null) {
final int prevRuneOffset = offset - graphemeClusterLength; final int prevRuneOffset = offset - graphemeClusterLength;
boxes = _paragraph.getBoxesForRange(prevRuneOffset, offset); // Use BoxHeightStyle.strut to ensure that the caret's height fits within
// the line's height and is consistent throughout the line.
boxes = _paragraph.getBoxesForRange(prevRuneOffset, offset, boxHeightStyle: ui.BoxHeightStyle.strut);
// When the range does not include a full cluster, no boxes will be returned. // When the range does not include a full cluster, no boxes will be returned.
if (boxes.isEmpty) { if (boxes.isEmpty) {
// When we are at the beginning of the line, a non-surrogate position will // When we are at the beginning of the line, a non-surrogate position will
...@@ -690,7 +692,9 @@ class TextPainter { ...@@ -690,7 +692,9 @@ class TextPainter {
List<TextBox> boxes = <TextBox>[]; List<TextBox> boxes = <TextBox>[];
while (boxes.isEmpty && flattenedText != null) { while (boxes.isEmpty && flattenedText != null) {
final int nextRuneOffset = offset + graphemeClusterLength; final int nextRuneOffset = offset + graphemeClusterLength;
boxes = _paragraph.getBoxesForRange(offset, nextRuneOffset); // Use BoxHeightStyle.strut to ensure that the caret's height fits within
// the line's height and is consistent throughout the line.
boxes = _paragraph.getBoxesForRange(offset, nextRuneOffset, boxHeightStyle: ui.BoxHeightStyle.strut);
// When the range does not include a full cluster, no boxes will be returned. // When the range does not include a full cluster, no boxes will be returned.
if (boxes.isEmpty) { if (boxes.isEmpty) {
// When we are at the end of the line, a non-surrogate position will // When we are at the end of the line, a non-surrogate position will
......
...@@ -564,7 +564,7 @@ class EditableText extends StatefulWidget { ...@@ -564,7 +564,7 @@ class EditableText extends StatefulWidget {
/// [TextStyle] instead. See [StrutStyle.inheritFromTextStyle]. /// [TextStyle] instead. See [StrutStyle.inheritFromTextStyle].
StrutStyle get strutStyle { StrutStyle get strutStyle {
if (_strutStyle == null) { if (_strutStyle == null) {
return style != null ? StrutStyle.fromTextStyle(style, forceStrutHeight: true) : StrutStyle.disabled; return style != null ? StrutStyle.fromTextStyle(style, forceStrutHeight: true) : const StrutStyle();
} }
return _strutStyle.inheritFromTextStyle(style); return _strutStyle.inheritFromTextStyle(style);
} }
......
...@@ -4028,7 +4028,8 @@ void main() { ...@@ -4028,7 +4028,8 @@ void main() {
await tester.longPressAt(textfieldStart + const Offset(50.0, 2.0)); await tester.longPressAt(textfieldStart + const Offset(50.0, 2.0));
await tester.pump(const Duration(milliseconds: 150)); await tester.pump(const Duration(milliseconds: 150));
await tester.tapAt(textfieldStart + const Offset(20.0, 146.0)); // Tap the Select All button.
await tester.tapAt(textfieldStart + const Offset(20.0, 100.0));
await tester.pump(const Duration(milliseconds: 300)); await tester.pump(const Duration(milliseconds: 300));
await expectLater( await expectLater(
...@@ -4074,7 +4075,8 @@ void main() { ...@@ -4074,7 +4075,8 @@ void main() {
await tester.longPressAt(textfieldStart + const Offset(50.0, 2.0)); await tester.longPressAt(textfieldStart + const Offset(50.0, 2.0));
await tester.pump(const Duration(milliseconds: 150)); await tester.pump(const Duration(milliseconds: 150));
await tester.tapAt(textfieldStart + const Offset(20.0, 146.0)); // Tap the Select All button.
await tester.tapAt(textfieldStart + const Offset(20.0, 100.0));
await tester.pump(const Duration(milliseconds: 300)); await tester.pump(const Duration(milliseconds: 300));
await expectLater( await expectLater(
......
...@@ -2352,7 +2352,6 @@ void main() { ...@@ -2352,7 +2352,6 @@ void main() {
controller: controller, controller: controller,
style: const TextStyle(color: Colors.black, fontSize: 34.0), style: const TextStyle(color: Colors.black, fontSize: 34.0),
maxLines: 3, maxLines: 3,
strutStyle: StrutStyle.disabled,
), ),
), ),
); );
...@@ -3740,7 +3739,6 @@ void main() { ...@@ -3740,7 +3739,6 @@ void main() {
child: TextField( child: TextField(
controller: controller, controller: controller,
maxLines: 3, maxLines: 3,
strutStyle: StrutStyle.disabled,
), ),
), ),
), ),
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart'; import 'package:flutter/painting.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -816,4 +817,20 @@ void main() { ...@@ -816,4 +817,20 @@ void main() {
// issue or similar. See https://github.com/flutter/flutter/issues/43763 // issue or similar. See https://github.com/flutter/flutter/issues/43763
// for more info. // for more info.
}, skip: true); }, skip: true);
test('TextPainter caret height and line height', () {
final TextPainter painter = TextPainter()
..textDirection = TextDirection.ltr
..strutStyle = const StrutStyle(fontSize: 50.0);
const String text = 'A';
painter.text = const TextSpan(text: text, style: TextStyle(height: 1.0));
painter.layout();
final double caretHeight = painter.getFullHeightForCaret(
const ui.TextPosition(offset: 0),
ui.Rect.zero,
);
expect(caretHeight, 50.0);
}, skip: kIsWeb);
} }
...@@ -658,7 +658,6 @@ void main() { ...@@ -658,7 +658,6 @@ void main() {
controller: controller, controller: controller,
focusNode: focusNode, focusNode: focusNode,
style: textStyle, style: textStyle,
strutStyle: StrutStyle.disabled,
), ),
), ),
), ),
......
...@@ -995,7 +995,6 @@ void main() { ...@@ -995,7 +995,6 @@ void main() {
dragStartBehavior: DragStartBehavior.down, dragStartBehavior: DragStartBehavior.down,
style: TextStyle(color: Colors.black, fontSize: 34.0), style: TextStyle(color: Colors.black, fontSize: 34.0),
maxLines: 3, maxLines: 3,
strutStyle: StrutStyle.disabled,
), ),
), ),
); );
...@@ -1316,7 +1315,6 @@ void main() { ...@@ -1316,7 +1315,6 @@ void main() {
child: SelectableText( child: SelectableText(
text, text,
maxLines: 3, maxLines: 3,
strutStyle: StrutStyle.disabled,
), ),
), ),
), ),
......
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