Unverified Commit 33a16f44 authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

Shift tap on an unfocused field (#97543)

parent ea6025ca
...@@ -951,17 +951,20 @@ class TextSelectionGestureDetectorBuilder { ...@@ -951,17 +951,20 @@ class TextSelectionGestureDetectorBuilder {
// Either base or extent will be moved to the last tapped position, whichever // Either base or extent will be moved to the last tapped position, whichever
// is closest. The selection will never shrink or pivot, only grow. // is closest. The selection will never shrink or pivot, only grow.
// //
// If fromSelection is given, will expand from that selection instead of the
// current selection in renderEditable.
//
// See also: // See also:
// //
// * [_extendSelection], which is similar but pivots the selection around // * [_extendSelection], which is similar but pivots the selection around
// the base. // the base.
void _expandSelection(Offset offset, SelectionChangedCause cause) { void _expandSelection(Offset offset, SelectionChangedCause cause, [TextSelection? fromSelection]) {
assert(cause != null); assert(cause != null);
assert(offset != null); assert(offset != null);
assert(renderEditable.selection?.baseOffset != null); assert(renderEditable.selection?.baseOffset != null);
final TextPosition tappedPosition = renderEditable.getPositionForPoint(offset); final TextPosition tappedPosition = renderEditable.getPositionForPoint(offset);
final TextSelection selection = renderEditable.selection!; final TextSelection selection = fromSelection ?? renderEditable.selection!;
final bool baseIsCloser = final bool baseIsCloser =
(tappedPosition.offset - selection.baseOffset).abs() (tappedPosition.offset - selection.baseOffset).abs()
< (tappedPosition.offset - selection.extentOffset).abs(); < (tappedPosition.offset - selection.extentOffset).abs();
...@@ -1069,7 +1072,16 @@ class TextSelectionGestureDetectorBuilder { ...@@ -1069,7 +1072,16 @@ class TextSelectionGestureDetectorBuilder {
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
case TargetPlatform.macOS: case TargetPlatform.macOS:
_expandSelection(details.globalPosition, SelectionChangedCause.tap); // On these platforms, a shift-tapped unfocused field expands from 0,
// not from the previous selection.
final TextSelection? fromSelection = renderEditable.hasFocus
? null
: const TextSelection.collapsed(offset: 0);
_expandSelection(
details.globalPosition,
SelectionChangedCause.tap,
fromSelection,
);
break; break;
case TargetPlatform.android: case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
......
...@@ -5053,6 +5053,62 @@ void main() { ...@@ -5053,6 +5053,62 @@ void main() {
expect(controller.selection.extentOffset, 4); expect(controller.selection.extentOffset, 4);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }));
testWidgets('shift tapping an unfocused field', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
final FocusNode focusNode = FocusNode();
await tester.pumpWidget(
CupertinoApp(
home: Center(
child: CupertinoTextField(
controller: controller,
focusNode: focusNode,
),
),
),
);
expect(focusNode.hasFocus, isFalse);
// Put the cursor at the end of the field.
await tester.tapAt(textOffsetToPosition(tester, controller.text.length));
await tester.pump(kDoubleTapTimeout);
await tester.pumpAndSettle();
expect(focusNode.hasFocus, isTrue);
expect(controller.selection.baseOffset, 35);
expect(controller.selection.extentOffset, 35);
// Unfocus the field, but the selection remains.
focusNode.unfocus();
await tester.pumpAndSettle();
expect(focusNode.hasFocus, isFalse);
expect(controller.selection.baseOffset, 35);
expect(controller.selection.extentOffset, 35);
// Shift tap in the middle of the field.
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 20));
await tester.pumpAndSettle();
expect(focusNode.hasFocus, isTrue);
switch (defaultTargetPlatform) {
// Apple platforms start the selection from 0.
case TargetPlatform.iOS:
case TargetPlatform.macOS:
expect(controller.selection.baseOffset, 0);
break;
// Other platforms start from the previous selection.
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
expect(controller.selection.baseOffset, 35);
break;
}
expect(controller.selection.extentOffset, 20);
}, variant: TargetPlatformVariant.all());
testWidgets('can shift + tap + drag to select with a keyboard (Apple platforms)', (WidgetTester tester) async { testWidgets('can shift + tap + drag to select with a keyboard (Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
......
...@@ -10560,6 +10560,63 @@ void main() { ...@@ -10560,6 +10560,63 @@ void main() {
expect(controller.selection.extentOffset, 4); expect(controller.selection.extentOffset, 4);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }));
testWidgets('shift tapping an unfocused field', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
final FocusNode focusNode = FocusNode();
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: TextField(
controller: controller,
focusNode: focusNode,
),
),
),
),
);
expect(focusNode.hasFocus, isFalse);
// Put the cursor at the end of the field.
await tester.tapAt(textOffsetToPosition(tester, controller.text.length));
await tester.pump(kDoubleTapTimeout);
await tester.pumpAndSettle();
expect(focusNode.hasFocus, isTrue);
expect(controller.selection.baseOffset, 35);
expect(controller.selection.extentOffset, 35);
// Unfocus the field, but the selection remains.
focusNode.unfocus();
await tester.pumpAndSettle();
expect(focusNode.hasFocus, isFalse);
expect(controller.selection.baseOffset, 35);
expect(controller.selection.extentOffset, 35);
// Shift tap in the middle of the field.
await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
await tester.tapAt(textOffsetToPosition(tester, 20));
await tester.pumpAndSettle();
expect(focusNode.hasFocus, isTrue);
switch (defaultTargetPlatform) {
// Apple platforms start the selection from 0.
case TargetPlatform.iOS:
case TargetPlatform.macOS:
expect(controller.selection.baseOffset, 0);
break;
// Other platforms start from the previous selection.
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
expect(controller.selection.baseOffset, 35);
break;
}
expect(controller.selection.extentOffset, 20);
}, variant: TargetPlatformVariant.all());
testWidgets('can shift + tap + drag to select with a keyboard (Apple platforms)', (WidgetTester tester) async { testWidgets('can shift + tap + drag to select with a keyboard (Apple platforms)', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController( final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure', text: 'Atwater Peel Sherbrooke Bonaventure',
......
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