Add Supported devices to the TapGestureRecognizer (#96560)
diff --git a/packages/flutter/lib/src/gestures/tap.dart b/packages/flutter/lib/src/gestures/tap.dart
index 8209fa4..4df877f 100644
--- a/packages/flutter/lib/src/gestures/tap.dart
+++ b/packages/flutter/lib/src/gestures/tap.dart
@@ -136,8 +136,10 @@
/// any buttons.
abstract class BaseTapGestureRecognizer extends PrimaryPointerGestureRecognizer {
/// Creates a tap gesture recognizer.
- BaseTapGestureRecognizer({ Object? debugOwner })
- : super(deadline: kPressTimeout , debugOwner: debugOwner);
+ ///
+ /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
+ BaseTapGestureRecognizer({ Object? debugOwner, Set<PointerDeviceKind>? supportedDevices })
+ : super(deadline: kPressTimeout , debugOwner: debugOwner, supportedDevices: supportedDevices);
bool _sentTapDown = false;
bool _wonArenaForPrimaryPointer = false;
@@ -346,7 +348,10 @@
/// * [MultiTapGestureRecognizer]
class TapGestureRecognizer extends BaseTapGestureRecognizer {
/// Creates a tap gesture recognizer.
- TapGestureRecognizer({ Object? debugOwner }) : super(debugOwner: debugOwner);
+ ///
+ /// {@macro flutter.gestures.GestureRecognizer.supportedDevices}
+ TapGestureRecognizer({ Object? debugOwner, Set<PointerDeviceKind>? supportedDevices })
+ : super(debugOwner: debugOwner, supportedDevices: supportedDevices);
/// A pointer has contacted the screen at a particular location with a primary
/// button, which might be the start of a tap.
diff --git a/packages/flutter/test/gestures/tap_test.dart b/packages/flutter/test/gestures/tap_test.dart
index 89ab65e..77e5d93 100644
--- a/packages/flutter/test/gestures/tap_test.dart
+++ b/packages/flutter/test/gestures/tap_test.dart
@@ -119,6 +119,84 @@
tap.dispose();
});
+ testGesture('Should recognize tap for supported devices only', (GestureTester tester) {
+ final TapGestureRecognizer tap = TapGestureRecognizer(
+ supportedDevices: <PointerDeviceKind>{ PointerDeviceKind.mouse, PointerDeviceKind.stylus },
+ );
+
+ bool tapRecognized = false;
+ tap.onTap = () {
+ tapRecognized = true;
+ };
+ const PointerDownEvent touchDown = PointerDownEvent(
+ pointer: 1,
+ position: Offset(10.0, 10.0),
+ );
+ const PointerUpEvent touchUp = PointerUpEvent(
+ pointer: 1,
+ position: Offset(11.0, 9.0),
+ );
+
+ tap.addPointer(touchDown);
+ tester.closeArena(1);
+ expect(tapRecognized, isFalse);
+ tester.route(touchDown);
+ expect(tapRecognized, isFalse);
+
+ tester.route(touchUp);
+ expect(tapRecognized, isFalse);
+ GestureBinding.instance!.gestureArena.sweep(1);
+ expect(tapRecognized, isFalse);
+
+ const PointerDownEvent mouseDown = PointerDownEvent(
+ kind: PointerDeviceKind.mouse,
+ pointer: 1,
+ position: Offset(10.0, 10.0),
+ );
+ const PointerUpEvent mouseUp = PointerUpEvent(
+ kind: PointerDeviceKind.mouse,
+ pointer: 1,
+ position: Offset(11.0, 9.0),
+ );
+
+ tap.addPointer(mouseDown);
+ tester.closeArena(1);
+ expect(tapRecognized, isFalse);
+ tester.route(mouseDown);
+ expect(tapRecognized, isFalse);
+
+ tester.route(mouseUp);
+ expect(tapRecognized, isTrue);
+ GestureBinding.instance!.gestureArena.sweep(1);
+ expect(tapRecognized, isTrue);
+
+ tapRecognized = false;
+
+ const PointerDownEvent stylusDown = PointerDownEvent(
+ kind: PointerDeviceKind.stylus,
+ pointer: 1,
+ position: Offset(10.0, 10.0),
+ );
+ const PointerUpEvent stylusUp = PointerUpEvent(
+ kind: PointerDeviceKind.stylus,
+ pointer: 1,
+ position: Offset(11.0, 9.0),
+ );
+
+ tap.addPointer(stylusDown);
+ tester.closeArena(1);
+ expect(tapRecognized, isFalse);
+ tester.route(stylusDown);
+ expect(tapRecognized, isFalse);
+
+ tester.route(stylusUp);
+ expect(tapRecognized, isTrue);
+ GestureBinding.instance!.gestureArena.sweep(1);
+ expect(tapRecognized, isTrue);
+
+ tap.dispose();
+ });
+
testGesture('Details contain the correct device kind', (GestureTester tester) {
final TapGestureRecognizer tap = TapGestureRecognizer();