Unverified Commit d13b56a0 authored by Mouad Debbar's avatar Mouad Debbar Committed by GitHub

Don't move to word edge when tapping with a mouse (#60177)

parent 63381814
......@@ -478,6 +478,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
if (onTapUp != null)
invokeCallback<void>('onTapUp', () {
onTapUp!(pointer, TapUpDetails(
kind: getKindForPointer(pointer),
localPosition: position.local,
globalPosition: position.global,
));
......
......@@ -59,6 +59,7 @@ typedef GestureTapDownCallback = void Function(TapDownDetails details);
class TapUpDetails {
/// The [globalPosition] argument must not be null.
TapUpDetails({
required this.kind,
this.globalPosition = Offset.zero,
Offset? localPosition,
}) : assert(globalPosition != null),
......@@ -69,6 +70,9 @@ class TapUpDetails {
/// The local position at which the pointer contacted the screen.
final Offset localPosition;
/// The kind of the device that initiated the event.
final PointerDeviceKind kind;
}
/// Signature for when a pointer that will trigger a tap has stopped contacting
......@@ -512,6 +516,7 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer {
@override
void handleTapUp({ required PointerDownEvent down, required PointerUpEvent up}) {
final TapUpDetails details = TapUpDetails(
kind: up.kind,
globalPosition: up.position,
localPosition: up.localPosition,
);
......
......@@ -93,8 +93,21 @@ class _TextFieldSelectionGestureDetectorBuilder extends TextSelectionGestureDete
switch (Theme.of(_state.context).platform) {
case TargetPlatform.iOS:
case TargetPlatform.macOS:
switch (details.kind) {
case PointerDeviceKind.mouse:
case PointerDeviceKind.stylus:
case PointerDeviceKind.invertedStylus:
// Precise devices should place the cursor at a precise position.
renderEditable.selectPosition(cause: SelectionChangedCause.tap);
break;
case PointerDeviceKind.touch:
case PointerDeviceKind.unknown:
// On macOS/iOS/iPadOS a touch tap places the cursor at the edge
// of the word.
renderEditable.selectWordEdge(cause: SelectionChangedCause.tap);
break;
}
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
......
......@@ -1260,7 +1260,7 @@ class _DefaultSemanticsGestureDelegate extends SemanticsGestureDelegate {
if (tap.onTapDown != null)
tap.onTapDown(TapDownDetails());
if (tap.onTapUp != null)
tap.onTapUp(TapUpDetails());
tap.onTapUp(TapUpDetails(kind: PointerDeviceKind.unknown));
if (tap.onTap != null)
tap.onTap();
};
......
......@@ -109,6 +109,35 @@ void main() {
tap.dispose();
});
testGesture('Details contain the correct device kind', (GestureTester tester) {
final TapGestureRecognizer tap = TapGestureRecognizer();
TapDownDetails lastDownDetails;
TapUpDetails lastUpDetails;
tap.onTapDown = (TapDownDetails details) {
lastDownDetails = details;
};
tap.onTapUp = (TapUpDetails details) {
lastUpDetails = details;
};
const PointerDownEvent mouseDown =
PointerDownEvent(pointer: 1, kind: PointerDeviceKind.mouse);
const PointerUpEvent mouseUp =
PointerUpEvent(pointer: 1, kind: PointerDeviceKind.mouse);
tap.addPointer(mouseDown);
tester.closeArena(1);
tester.route(mouseDown);
expect(lastDownDetails.kind, PointerDeviceKind.mouse);
tester.route(mouseUp);
expect(lastUpDetails.kind, PointerDeviceKind.mouse);
tap.dispose();
});
testGesture('No duplicate tap events', (GestureTester tester) {
final TapGestureRecognizer tap = TapGestureRecognizer();
......
......@@ -6110,6 +6110,41 @@ void main() {
expect(find.byType(CupertinoButton), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets(
'tap with a mouse does not move cursor to the edge of the word',
(WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
text: 'Atwater Peel Sherbrooke Bonaventure',
);
await tester.pumpWidget(
MaterialApp(
home: Material(
child: Center(
child: TextField(
controller: controller,
),
),
),
),
);
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
final TestGesture gesture = await tester.startGesture(
textfieldStart + const Offset(50.0, 9.0),
pointer: 1,
kind: PointerDeviceKind.mouse,
);
addTearDown(gesture.removePointer);
await gesture.up();
// Cursor at tap position, not at word edge.
expect(
controller.selection,
const TextSelection.collapsed(offset: 3, affinity: TextAffinity.downstream),
);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('tap moves cursor to the position tapped', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(
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