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 { ...@@ -478,6 +478,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
if (onTapUp != null) if (onTapUp != null)
invokeCallback<void>('onTapUp', () { invokeCallback<void>('onTapUp', () {
onTapUp!(pointer, TapUpDetails( onTapUp!(pointer, TapUpDetails(
kind: getKindForPointer(pointer),
localPosition: position.local, localPosition: position.local,
globalPosition: position.global, globalPosition: position.global,
)); ));
......
...@@ -59,6 +59,7 @@ typedef GestureTapDownCallback = void Function(TapDownDetails details); ...@@ -59,6 +59,7 @@ typedef GestureTapDownCallback = void Function(TapDownDetails details);
class TapUpDetails { class TapUpDetails {
/// The [globalPosition] argument must not be null. /// The [globalPosition] argument must not be null.
TapUpDetails({ TapUpDetails({
required this.kind,
this.globalPosition = Offset.zero, this.globalPosition = Offset.zero,
Offset? localPosition, Offset? localPosition,
}) : assert(globalPosition != null), }) : assert(globalPosition != null),
...@@ -69,6 +70,9 @@ class TapUpDetails { ...@@ -69,6 +70,9 @@ class TapUpDetails {
/// The local position at which the pointer contacted the screen. /// The local position at which the pointer contacted the screen.
final Offset localPosition; 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 /// Signature for when a pointer that will trigger a tap has stopped contacting
...@@ -512,6 +516,7 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer { ...@@ -512,6 +516,7 @@ class TapGestureRecognizer extends BaseTapGestureRecognizer {
@override @override
void handleTapUp({ required PointerDownEvent down, required PointerUpEvent up}) { void handleTapUp({ required PointerDownEvent down, required PointerUpEvent up}) {
final TapUpDetails details = TapUpDetails( final TapUpDetails details = TapUpDetails(
kind: up.kind,
globalPosition: up.position, globalPosition: up.position,
localPosition: up.localPosition, localPosition: up.localPosition,
); );
......
...@@ -93,8 +93,21 @@ class _TextFieldSelectionGestureDetectorBuilder extends TextSelectionGestureDete ...@@ -93,8 +93,21 @@ class _TextFieldSelectionGestureDetectorBuilder extends TextSelectionGestureDete
switch (Theme.of(_state.context).platform) { switch (Theme.of(_state.context).platform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
case TargetPlatform.macOS: 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); renderEditable.selectWordEdge(cause: SelectionChangedCause.tap);
break; break;
}
break;
case TargetPlatform.android: case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
case TargetPlatform.linux: case TargetPlatform.linux:
......
...@@ -1260,7 +1260,7 @@ class _DefaultSemanticsGestureDelegate extends SemanticsGestureDelegate { ...@@ -1260,7 +1260,7 @@ class _DefaultSemanticsGestureDelegate extends SemanticsGestureDelegate {
if (tap.onTapDown != null) if (tap.onTapDown != null)
tap.onTapDown(TapDownDetails()); tap.onTapDown(TapDownDetails());
if (tap.onTapUp != null) if (tap.onTapUp != null)
tap.onTapUp(TapUpDetails()); tap.onTapUp(TapUpDetails(kind: PointerDeviceKind.unknown));
if (tap.onTap != null) if (tap.onTap != null)
tap.onTap(); tap.onTap();
}; };
......
...@@ -109,6 +109,35 @@ void main() { ...@@ -109,6 +109,35 @@ void main() {
tap.dispose(); 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) { testGesture('No duplicate tap events', (GestureTester tester) {
final TapGestureRecognizer tap = TapGestureRecognizer(); final TapGestureRecognizer tap = TapGestureRecognizer();
......
...@@ -6110,6 +6110,41 @@ void main() { ...@@ -6110,6 +6110,41 @@ void main() {
expect(find.byType(CupertinoButton), findsNothing); expect(find.byType(CupertinoButton), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })); }, 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 { testWidgets('tap moves cursor to the position tapped', (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