Unverified Commit 24f0d285 authored by Tomasz Gucio's avatar Tomasz Gucio Committed by GitHub

Adjust selection drag start position for viewport offset changes (#80047)

parent 884fdf2e
......@@ -952,7 +952,7 @@ class TextSelectionGestureDetectorBuilder {
@protected
final TextSelectionGestureDetectorBuilderDelegate delegate;
/// Returns true iff lastSecondaryTapDownPosition was on selection.
/// Returns true if lastSecondaryTapDownPosition was on selection.
bool get _lastSecondaryTapWasOnSelection {
assert(renderEditable.lastSecondaryTapDownPosition != null);
if (renderEditable.selection == null) {
......@@ -985,6 +985,9 @@ class TextSelectionGestureDetectorBuilder {
@protected
RenderEditable get renderEditable => editableText.renderEditable;
/// The viewport offset pixels of the [RenderEditable] at the last drag start.
double _dragStartViewportOffset = 0.0;
/// Handler for [TextSelectionGestureDetector.onTapDown].
///
/// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets
......@@ -1197,6 +1200,8 @@ class TextSelectionGestureDetectorBuilder {
from: details.globalPosition,
cause: SelectionChangedCause.drag,
);
_dragStartViewportOffset = renderEditable.offset.pixels;
}
/// Handler for [TextSelectionGestureDetector.onDragSelectionUpdate].
......@@ -1212,8 +1217,14 @@ class TextSelectionGestureDetectorBuilder {
void onDragSelectionUpdate(DragStartDetails startDetails, DragUpdateDetails updateDetails) {
if (!delegate.selectionEnabled)
return;
// Adjust the drag start offset for possible viewport offset changes.
final Offset startOffset = renderEditable.maxLines == 1
? Offset(renderEditable.offset.pixels - _dragStartViewportOffset, 0.0)
: Offset(0.0, renderEditable.offset.pixels - _dragStartViewportOffset);
renderEditable.selectPositionAt(
from: startDetails.globalPosition,
from: startDetails.globalPosition - startOffset,
to: updateDetails.globalPosition,
cause: SelectionChangedCause.drag,
);
......@@ -1618,7 +1629,7 @@ class ClipboardStatusNotifier extends ValueNotifier<ClipboardStatus> with Widget
}) : super(value);
bool _disposed = false;
/// True iff this instance has been disposed.
/// True if this instance has been disposed.
bool get disposed => _disposed;
/// Check the [Clipboard] and update [value] if needed.
......
......@@ -624,6 +624,44 @@ void main() {
expect(editableText.selectionOverlay!.toolbarIsVisible, isFalse);
});
testWidgets('test TextSelectionGestureDetectorBuilder drag with RenderEditable viewport offset change', (WidgetTester tester) async {
await pumpTextSelectionGestureDetectorBuilder(tester);
final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
// Reconfigure the RenderEditable for multi-line.
renderEditable.maxLines = null;
renderEditable.offset = ViewportOffset.fixed(20.0);
renderEditable.layout(const BoxConstraints.tightFor(width: 400, height: 300.0));
await tester.pumpAndSettle();
final TestGesture gesture = await tester.startGesture(
const Offset(200.0, 200.0),
kind: PointerDeviceKind.mouse,
);
addTearDown(gesture.removePointer);
await tester.pumpAndSettle();
expect(renderEditable.selectPositionAtCalled, isFalse);
await gesture.moveTo(const Offset(300.0, 200.0));
await tester.pumpAndSettle();
expect(renderEditable.selectPositionAtCalled, isTrue);
expect(renderEditable.selectPositionAtFrom, const Offset(200.0, 200.0));
expect(renderEditable.selectPositionAtTo, const Offset(300.0, 200.0));
// Move the viewport offset (scroll).
renderEditable.offset = ViewportOffset.fixed(150.0);
renderEditable.layout(const BoxConstraints.tightFor(width: 400, height: 300.0));
await tester.pumpAndSettle();
await gesture.moveTo(const Offset(300.0, 400.0));
await tester.pumpAndSettle();
await gesture.up();
await tester.pumpAndSettle();
expect(renderEditable.selectPositionAtCalled, isTrue);
expect(renderEditable.selectPositionAtFrom, const Offset(200.0, 70.0));
expect(renderEditable.selectPositionAtTo, const Offset(300.0, 400.0));
});
testWidgets('test TextSelectionGestureDetectorBuilder selection disabled', (WidgetTester tester) async {
await pumpTextSelectionGestureDetectorBuilder(tester, selectionEnabled: false);
final TestGesture gesture = await tester.startGesture(
......@@ -863,9 +901,13 @@ class FakeRenderEditable extends RenderEditable {
}
bool selectPositionAtCalled = false;
Offset? selectPositionAtFrom;
Offset? selectPositionAtTo;
@override
void selectPositionAt({ required Offset from, Offset? to, required SelectionChangedCause cause }) {
selectPositionAtCalled = true;
selectPositionAtFrom = from;
selectPositionAtTo = to;
}
bool selectWordCalled = false;
......
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