Unverified Commit 4c1d887e authored by Renzo Olivares's avatar Renzo Olivares Committed by GitHub

Set selection on tap down for desktop platforms and tap up for mobile (#105505)

Co-authored-by: 's avatarRenzo Olivares <roliv@google.com>
parent 2c13db3b
...@@ -1454,6 +1454,9 @@ class TextSelectionGestureDetectorBuilder { ...@@ -1454,6 +1454,9 @@ class TextSelectionGestureDetectorBuilder {
/// * [TextSelectionGestureDetector.onTapDown], which triggers this callback. /// * [TextSelectionGestureDetector.onTapDown], which triggers this callback.
@protected @protected
void onTapDown(TapDownDetails details) { void onTapDown(TapDownDetails details) {
if (!delegate.selectionEnabled) {
return;
}
renderEditable.handleTapDown(details); renderEditable.handleTapDown(details);
// The selection overlay should only be shown when the user is interacting // The selection overlay should only be shown when the user is interacting
// through a touch screen (via either a finger or a stylus). A mouse shouldn't // through a touch screen (via either a finger or a stylus). A mouse shouldn't
...@@ -1465,13 +1468,21 @@ class TextSelectionGestureDetectorBuilder { ...@@ -1465,13 +1468,21 @@ class TextSelectionGestureDetectorBuilder {
|| kind == PointerDeviceKind.stylus; || kind == PointerDeviceKind.stylus;
// Handle shift + click selection if needed. // Handle shift + click selection if needed.
if (_isShiftPressed && renderEditable.selection?.baseOffset != null) { final bool isShiftPressedValid = _isShiftPressed && renderEditable.selection?.baseOffset != null;
_isShiftTapping = true; switch (defaultTargetPlatform) {
switch (defaultTargetPlatform) { case TargetPlatform.android:
case TargetPlatform.iOS: case TargetPlatform.fuchsia:
case TargetPlatform.macOS: case TargetPlatform.iOS:
// On these platforms, a shift-tapped unfocused field expands from 0, // On mobile platforms the selection is set on tap up.
// not from the previous selection. if (_isShiftTapping) {
_isShiftTapping = false;
}
break;
case TargetPlatform.macOS:
// On macOS, a shift-tapped unfocused field expands from 0, not from the
// previous selection.
if (isShiftPressedValid) {
_isShiftTapping = true;
final TextSelection? fromSelection = renderEditable.hasFocus final TextSelection? fromSelection = renderEditable.hasFocus
? null ? null
: const TextSelection.collapsed(offset: 0); : const TextSelection.collapsed(offset: 0);
...@@ -1480,14 +1491,23 @@ class TextSelectionGestureDetectorBuilder { ...@@ -1480,14 +1491,23 @@ class TextSelectionGestureDetectorBuilder {
SelectionChangedCause.tap, SelectionChangedCause.tap,
fromSelection, fromSelection,
); );
break; return;
case TargetPlatform.android: }
case TargetPlatform.fuchsia: // On macOS, a tap/click places the selection in a precise position.
case TargetPlatform.linux: // This differs from iOS/iPadOS, where if the gesture is done by a touch
case TargetPlatform.windows: // then the selection moves to the closest word edge, instead of a
// precise position.
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
break;
case TargetPlatform.linux:
case TargetPlatform.windows:
if (isShiftPressedValid) {
_isShiftTapping = true;
_extendSelection(details.globalPosition, SelectionChangedCause.tap); _extendSelection(details.globalPosition, SelectionChangedCause.tap);
break; return;
} }
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
break;
} }
} }
...@@ -1547,15 +1567,42 @@ class TextSelectionGestureDetectorBuilder { ...@@ -1547,15 +1567,42 @@ class TextSelectionGestureDetectorBuilder {
/// this callback. /// this callback.
@protected @protected
void onSingleTapUp(TapUpDetails details) { void onSingleTapUp(TapUpDetails details) {
if (_isShiftTapping) {
_isShiftTapping = false;
return;
}
if (delegate.selectionEnabled) { if (delegate.selectionEnabled) {
// Handle shift + click selection if needed.
final bool isShiftPressedValid = _isShiftPressed && renderEditable.selection?.baseOffset != null;
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.iOS: case TargetPlatform.linux:
case TargetPlatform.macOS: case TargetPlatform.macOS:
case TargetPlatform.windows:
// On desktop platforms the selection is set on tap down.
if (_isShiftTapping) {
_isShiftTapping = false;
}
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
if (isShiftPressedValid) {
_isShiftTapping = true;
_extendSelection(details.globalPosition, SelectionChangedCause.tap);
return;
}
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
break;
case TargetPlatform.iOS:
if (isShiftPressedValid) {
// On iOS, a shift-tapped unfocused field expands from 0, not from
// the previous selection.
_isShiftTapping = true;
final TextSelection? fromSelection = renderEditable.hasFocus
? null
: const TextSelection.collapsed(offset: 0);
_expandSelection(
details.globalPosition,
SelectionChangedCause.tap,
fromSelection,
);
return;
}
switch (details.kind) { switch (details.kind) {
case PointerDeviceKind.mouse: case PointerDeviceKind.mouse:
case PointerDeviceKind.trackpad: case PointerDeviceKind.trackpad:
...@@ -1566,18 +1613,11 @@ class TextSelectionGestureDetectorBuilder { ...@@ -1566,18 +1613,11 @@ class TextSelectionGestureDetectorBuilder {
break; break;
case PointerDeviceKind.touch: case PointerDeviceKind.touch:
case PointerDeviceKind.unknown: case PointerDeviceKind.unknown:
// On macOS/iOS/iPadOS a touch tap places the cursor at the edge // On iOS/iPadOS a touch tap places the cursor at the edge of the word.
// of the word.
renderEditable.selectWordEdge(cause: SelectionChangedCause.tap); renderEditable.selectWordEdge(cause: SelectionChangedCause.tap);
break; break;
} }
break; break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
break;
} }
} }
} }
......
...@@ -475,8 +475,6 @@ void main() { ...@@ -475,8 +475,6 @@ void main() {
final TestGesture down1 = await tester.startGesture(tester.getCenter(find.byType(TextField).first), kind: PointerDeviceKind.mouse); final TestGesture down1 = await tester.startGesture(tester.getCenter(find.byType(TextField).first), kind: PointerDeviceKind.mouse);
await tester.pump(); await tester.pump();
await tester.pumpAndSettle();
await down1.up();
await down1.removePointer(); await down1.removePointer();
expect(focusNodeA.hasFocus, true); expect(focusNodeA.hasFocus, true);
......
...@@ -557,9 +557,9 @@ void main() { ...@@ -557,9 +557,9 @@ void main() {
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
case TargetPlatform.macOS:
expect(renderEditable.selectWordEdgeCalled, isTrue); expect(renderEditable.selectWordEdgeCalled, isTrue);
break; break;
case TargetPlatform.macOS:
case TargetPlatform.android: case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
case TargetPlatform.linux: case TargetPlatform.linux:
......
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