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();