Unverified Commit c53501d8 authored by Callum Moffat's avatar Callum Moffat Committed by GitHub

Send text direction in selection rects (#117436)

parent e599e5c9
...@@ -1316,11 +1316,16 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin, ...@@ -1316,11 +1316,16 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
/// Returns a list of rects that bound the given selection. /// Returns a list of rects that bound the given selection.
/// ///
/// See [TextPainter.getBoxesForSelection] for more details. /// See [TextPainter.getBoxesForSelection] for more details.
List<Rect> getBoxesForSelection(TextSelection selection) { List<TextBox> getBoxesForSelection(TextSelection selection) {
_computeTextMetricsIfNeeded(); _computeTextMetricsIfNeeded();
return _textPainter.getBoxesForSelection(selection) return _textPainter.getBoxesForSelection(selection)
.map((TextBox textBox) => textBox.toRect().shift(_paintOffset)) .map((TextBox textBox) => TextBox.fromLTRBD(
.toList(); textBox.left + _paintOffset.dx,
textBox.top + _paintOffset.dy,
textBox.right + _paintOffset.dx,
textBox.bottom + _paintOffset.dy,
textBox.direction
)).toList();
} }
@override @override
......
...@@ -1211,7 +1211,11 @@ abstract class ScribbleClient { ...@@ -1211,7 +1211,11 @@ abstract class ScribbleClient {
class SelectionRect { class SelectionRect {
/// Constructor for creating a [SelectionRect] from a text [position] and /// Constructor for creating a [SelectionRect] from a text [position] and
/// [bounds]. /// [bounds].
const SelectionRect({required this.position, required this.bounds}); const SelectionRect({
required this.position,
required this.bounds,
this.direction = TextDirection.ltr,
});
/// The position of this selection rect within the text String. /// The position of this selection rect within the text String.
final int position; final int position;
...@@ -1220,6 +1224,9 @@ class SelectionRect { ...@@ -1220,6 +1224,9 @@ class SelectionRect {
/// currently focused [RenderEditable]'s coordinate space. /// currently focused [RenderEditable]'s coordinate space.
final Rect bounds; final Rect bounds;
/// The direction text flows within this selection rect.
final TextDirection direction;
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (identical(this, other)) { if (identical(this, other)) {
...@@ -1230,7 +1237,8 @@ class SelectionRect { ...@@ -1230,7 +1237,8 @@ class SelectionRect {
} }
return other is SelectionRect return other is SelectionRect
&& other.position == position && other.position == position
&& other.bounds == bounds; && other.bounds == bounds
&& other.direction == direction;
} }
@override @override
...@@ -2321,7 +2329,14 @@ class _PlatformTextInputControl with TextInputControl { ...@@ -2321,7 +2329,14 @@ class _PlatformTextInputControl with TextInputControl {
_channel.invokeMethod<void>( _channel.invokeMethod<void>(
'TextInput.setSelectionRects', 'TextInput.setSelectionRects',
selectionRects.map((SelectionRect rect) { selectionRects.map((SelectionRect rect) {
return <num>[rect.bounds.left, rect.bounds.top, rect.bounds.width, rect.bounds.height, rect.position]; return <num>[
rect.bounds.left,
rect.bounds.top,
rect.bounds.width,
rect.bounds.height,
rect.position,
rect.direction.index,
];
}).toList(), }).toList(),
); );
} }
......
...@@ -3279,7 +3279,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -3279,7 +3279,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (selection.isCollapsed) { if (selection.isCollapsed) {
rectToReveal = targetOffset.rect; rectToReveal = targetOffset.rect;
} else { } else {
final List<Rect> selectionBoxes = renderEditable.getBoxesForSelection(selection); final List<TextBox> selectionBoxes = renderEditable.getBoxesForSelection(selection);
// selectionBoxes may be empty if, for example, the selection does not // selectionBoxes may be empty if, for example, the selection does not
// encompass a full character, like if it only contained part of an // encompass a full character, like if it only contained part of an
// extended grapheme cluster. // extended grapheme cluster.
...@@ -3287,7 +3287,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -3287,7 +3287,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
rectToReveal = targetOffset.rect; rectToReveal = targetOffset.rect;
} else { } else {
rectToReveal = selection.baseOffset < selection.extentOffset ? rectToReveal = selection.baseOffset < selection.extentOffset ?
selectionBoxes.last : selectionBoxes.first; selectionBoxes.last.toRect() : selectionBoxes.first.toRect();
} }
} }
...@@ -3590,11 +3590,11 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -3590,11 +3590,11 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
final CharacterRange characterRange = CharacterRange(plainText); final CharacterRange characterRange = CharacterRange(plainText);
while (characterRange.moveNext()) { while (characterRange.moveNext()) {
final int graphemeEnd = graphemeStart + characterRange.current.length; final int graphemeEnd = graphemeStart + characterRange.current.length;
final List<Rect> boxes = renderEditable.getBoxesForSelection( final List<TextBox> boxes = renderEditable.getBoxesForSelection(
TextSelection(baseOffset: graphemeStart, extentOffset: graphemeEnd), TextSelection(baseOffset: graphemeStart, extentOffset: graphemeEnd),
); );
final Rect? box = boxes.isEmpty ? null : boxes.first; final TextBox? box = boxes.isEmpty ? null : boxes.first;
if (box != null) { if (box != null) {
final Rect paintBounds = renderEditable.paintBounds; final Rect paintBounds = renderEditable.paintBounds;
// Stop early when characters are already below the bottom edge of the // Stop early when characters are already below the bottom edge of the
...@@ -3602,8 +3602,8 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -3602,8 +3602,8 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (paintBounds.bottom <= box.top) { if (paintBounds.bottom <= box.top) {
break; break;
} }
if (paintBounds.contains(box.topLeft) || paintBounds.contains(box.bottomRight)) { if (paintBounds.contains(Offset(box.left, box.top)) || paintBounds.contains(Offset(box.right, box.bottom))) {
rects.add(SelectionRect(position: graphemeStart, bounds: box)); rects.add(SelectionRect(position: graphemeStart, bounds: box.toRect(), direction: box.direction));
} }
} }
graphemeStart = graphemeEnd; graphemeStart = graphemeEnd;
......
...@@ -906,10 +906,20 @@ void main() { ...@@ -906,10 +906,20 @@ void main() {
expect(fakeTextChannel.outgoingCalls.length, 6); expect(fakeTextChannel.outgoingCalls.length, 6);
expect(fakeTextChannel.outgoingCalls.last.method, 'TextInput.setEditableSizeAndTransform'); expect(fakeTextChannel.outgoingCalls.last.method, 'TextInput.setEditableSizeAndTransform');
connection.setSelectionRects(const <SelectionRect>[SelectionRect(position: 0, bounds: Rect.zero)]); connection.setSelectionRects(const <SelectionRect>[SelectionRect(position: 1, bounds: Rect.fromLTWH(2, 3, 4, 5), direction: TextDirection.rtl)]);
expectedMethodCalls.add('setSelectionRects'); expectedMethodCalls.add('setSelectionRects');
expect(control.methodCalls, expectedMethodCalls); expect(control.methodCalls, expectedMethodCalls);
expect(fakeTextChannel.outgoingCalls.length, 7); expect(fakeTextChannel.outgoingCalls.length, 7);
expect(fakeTextChannel.outgoingCalls.last.arguments, const TypeMatcher<List<List<num>>>());
final List<List<num>> sentList = fakeTextChannel.outgoingCalls.last.arguments as List<List<num>>;
expect(sentList.length, 1);
expect(sentList[0].length, 6);
expect(sentList[0][0], 2); // left
expect(sentList[0][1], 3); // top
expect(sentList[0][2], 4); // width
expect(sentList[0][3], 5); // height
expect(sentList[0][4], 1); // position
expect(sentList[0][5], TextDirection.rtl.index); // direction
expect(fakeTextChannel.outgoingCalls.last.method, 'TextInput.setSelectionRects'); expect(fakeTextChannel.outgoingCalls.last.method, 'TextInput.setSelectionRects');
connection.setStyle( connection.setStyle(
......
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