Unverified Commit 778b3fa3 authored by xubaolin's avatar xubaolin Committed by GitHub

support updating dragDecices at runtime (#120336)

parent ed35c80d
...@@ -78,10 +78,9 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT ...@@ -78,10 +78,9 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
/// {@endtemplate} /// {@endtemplate}
GestureRecognizer({ GestureRecognizer({
this.debugOwner, this.debugOwner,
Set<PointerDeviceKind>? supportedDevices, this.supportedDevices,
AllowedButtonsFilter? allowedButtonsFilter, AllowedButtonsFilter? allowedButtonsFilter,
}) : _supportedDevices = supportedDevices, }) : _allowedButtonsFilter = allowedButtonsFilter ?? _defaultButtonAcceptBehavior;
_allowedButtonsFilter = allowedButtonsFilter ?? _defaultButtonAcceptBehavior;
/// The recognizer's owner. /// The recognizer's owner.
/// ///
...@@ -97,7 +96,7 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT ...@@ -97,7 +96,7 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
/// `supportedDevices` in the constructor, or the currently deprecated `kind`. /// `supportedDevices` in the constructor, or the currently deprecated `kind`.
/// These cannot both be set. If both are null, events from all device kinds will be /// These cannot both be set. If both are null, events from all device kinds will be
/// tracked and recognized. /// tracked and recognized.
final Set<PointerDeviceKind>? _supportedDevices; Set<PointerDeviceKind>? supportedDevices;
/// {@template flutter.gestures.multidrag._allowedButtonsFilter} /// {@template flutter.gestures.multidrag._allowedButtonsFilter}
/// Called when interaction starts. This limits the dragging behavior /// Called when interaction starts. This limits the dragging behavior
...@@ -209,8 +208,8 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT ...@@ -209,8 +208,8 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
/// Checks whether or not a pointer is allowed to be tracked by this recognizer. /// Checks whether or not a pointer is allowed to be tracked by this recognizer.
@protected @protected
bool isPointerAllowed(PointerDownEvent event) { bool isPointerAllowed(PointerDownEvent event) {
return (_supportedDevices == null || return (supportedDevices == null ||
_supportedDevices!.contains(event.kind)) && supportedDevices!.contains(event.kind)) &&
_allowedButtonsFilter(event.buttons); _allowedButtonsFilter(event.buttons);
} }
...@@ -223,7 +222,7 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT ...@@ -223,7 +222,7 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
/// Checks whether or not a pointer pan/zoom is allowed to be tracked by this recognizer. /// Checks whether or not a pointer pan/zoom is allowed to be tracked by this recognizer.
@protected @protected
bool isPointerPanZoomAllowed(PointerPanZoomStartEvent event) { bool isPointerPanZoomAllowed(PointerPanZoomStartEvent event) {
return _supportedDevices == null || _supportedDevices!.contains(event.kind); return supportedDevices == null || supportedDevices!.contains(event.kind);
} }
/// For a given pointer ID, returns the device kind associated with it. /// For a given pointer ID, returns the device kind associated with it.
......
...@@ -1050,7 +1050,8 @@ class GestureDetector extends StatelessWidget { ...@@ -1050,7 +1050,8 @@ class GestureDetector extends StatelessWidget {
..onTertiaryTapDown = onTertiaryTapDown ..onTertiaryTapDown = onTertiaryTapDown
..onTertiaryTapUp = onTertiaryTapUp ..onTertiaryTapUp = onTertiaryTapUp
..onTertiaryTapCancel = onTertiaryTapCancel ..onTertiaryTapCancel = onTertiaryTapCancel
..gestureSettings = gestureSettings; ..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
}, },
); );
} }
...@@ -1065,7 +1066,8 @@ class GestureDetector extends StatelessWidget { ...@@ -1065,7 +1066,8 @@ class GestureDetector extends StatelessWidget {
..onDoubleTapDown = onDoubleTapDown ..onDoubleTapDown = onDoubleTapDown
..onDoubleTap = onDoubleTap ..onDoubleTap = onDoubleTap
..onDoubleTapCancel = onDoubleTapCancel ..onDoubleTapCancel = onDoubleTapCancel
..gestureSettings = gestureSettings; ..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
}, },
); );
} }
...@@ -1116,7 +1118,8 @@ class GestureDetector extends StatelessWidget { ...@@ -1116,7 +1118,8 @@ class GestureDetector extends StatelessWidget {
..onTertiaryLongPressMoveUpdate = onTertiaryLongPressMoveUpdate ..onTertiaryLongPressMoveUpdate = onTertiaryLongPressMoveUpdate
..onTertiaryLongPressUp = onTertiaryLongPressUp ..onTertiaryLongPressUp = onTertiaryLongPressUp
..onTertiaryLongPressEnd = onTertiaryLongPressEnd ..onTertiaryLongPressEnd = onTertiaryLongPressEnd
..gestureSettings = gestureSettings; ..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
}, },
); );
} }
...@@ -1136,7 +1139,8 @@ class GestureDetector extends StatelessWidget { ...@@ -1136,7 +1139,8 @@ class GestureDetector extends StatelessWidget {
..onEnd = onVerticalDragEnd ..onEnd = onVerticalDragEnd
..onCancel = onVerticalDragCancel ..onCancel = onVerticalDragCancel
..dragStartBehavior = dragStartBehavior ..dragStartBehavior = dragStartBehavior
..gestureSettings = gestureSettings; ..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
}, },
); );
} }
...@@ -1156,7 +1160,8 @@ class GestureDetector extends StatelessWidget { ...@@ -1156,7 +1160,8 @@ class GestureDetector extends StatelessWidget {
..onEnd = onHorizontalDragEnd ..onEnd = onHorizontalDragEnd
..onCancel = onHorizontalDragCancel ..onCancel = onHorizontalDragCancel
..dragStartBehavior = dragStartBehavior ..dragStartBehavior = dragStartBehavior
..gestureSettings = gestureSettings; ..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
}, },
); );
} }
...@@ -1176,7 +1181,8 @@ class GestureDetector extends StatelessWidget { ...@@ -1176,7 +1181,8 @@ class GestureDetector extends StatelessWidget {
..onEnd = onPanEnd ..onEnd = onPanEnd
..onCancel = onPanCancel ..onCancel = onPanCancel
..dragStartBehavior = dragStartBehavior ..dragStartBehavior = dragStartBehavior
..gestureSettings = gestureSettings; ..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
}, },
); );
} }
...@@ -1192,7 +1198,8 @@ class GestureDetector extends StatelessWidget { ...@@ -1192,7 +1198,8 @@ class GestureDetector extends StatelessWidget {
..dragStartBehavior = dragStartBehavior ..dragStartBehavior = dragStartBehavior
..gestureSettings = gestureSettings ..gestureSettings = gestureSettings
..trackpadScrollCausesScale = trackpadScrollCausesScale ..trackpadScrollCausesScale = trackpadScrollCausesScale
..trackpadScrollToScaleFactor = trackpadScrollToScaleFactor; ..trackpadScrollToScaleFactor = trackpadScrollToScaleFactor
..supportedDevices = supportedDevices;
}, },
); );
} }
...@@ -1209,7 +1216,8 @@ class GestureDetector extends StatelessWidget { ...@@ -1209,7 +1216,8 @@ class GestureDetector extends StatelessWidget {
..onPeak = onForcePressPeak ..onPeak = onForcePressPeak
..onUpdate = onForcePressUpdate ..onUpdate = onForcePressUpdate
..onEnd = onForcePressEnd ..onEnd = onForcePressEnd
..gestureSettings = gestureSettings; ..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
}, },
); );
} }
......
...@@ -630,7 +630,8 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R ...@@ -630,7 +630,8 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
..maxFlingVelocity = _physics?.maxFlingVelocity ..maxFlingVelocity = _physics?.maxFlingVelocity
..velocityTrackerBuilder = _configuration.velocityTrackerBuilder(context) ..velocityTrackerBuilder = _configuration.velocityTrackerBuilder(context)
..dragStartBehavior = widget.dragStartBehavior ..dragStartBehavior = widget.dragStartBehavior
..gestureSettings = _mediaQueryGestureSettings; ..gestureSettings = _mediaQueryGestureSettings
..supportedDevices = _configuration.dragDevices;
}, },
), ),
}; };
...@@ -651,7 +652,8 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R ...@@ -651,7 +652,8 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
..maxFlingVelocity = _physics?.maxFlingVelocity ..maxFlingVelocity = _physics?.maxFlingVelocity
..velocityTrackerBuilder = _configuration.velocityTrackerBuilder(context) ..velocityTrackerBuilder = _configuration.velocityTrackerBuilder(context)
..dragStartBehavior = widget.dragStartBehavior ..dragStartBehavior = widget.dragStartBehavior
..gestureSettings = _mediaQueryGestureSettings; ..gestureSettings = _mediaQueryGestureSettings
..supportedDevices = _configuration.dragDevices;
}, },
), ),
}; };
......
...@@ -876,6 +876,76 @@ void main() { ...@@ -876,6 +876,76 @@ void main() {
}); });
}); });
testWidgets('supportedDevices update test', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/111716
bool didStartPan = false;
Offset? panDelta;
bool didEndPan = false;
Widget buildFrame(Set<PointerDeviceKind>? supportedDevices) {
return GestureDetector(
onPanStart: (DragStartDetails details) {
didStartPan = true;
},
onPanUpdate: (DragUpdateDetails details) {
panDelta = (panDelta ?? Offset.zero) + details.delta;
},
onPanEnd: (DragEndDetails details) {
didEndPan = true;
},
supportedDevices: supportedDevices,
child: Container(
color: const Color(0xFF00FF00),
)
);
}
await tester.pumpWidget(buildFrame(<PointerDeviceKind>{PointerDeviceKind.mouse}));
expect(didStartPan, isFalse);
expect(panDelta, isNull);
expect(didEndPan, isFalse);
await tester.dragFrom(const Offset(10.0, 10.0), const Offset(20.0, 30.0), kind: PointerDeviceKind.mouse);
// Matching device should allow gesture.
expect(didStartPan, isTrue);
expect(panDelta!.dx, 20.0);
expect(panDelta!.dy, 30.0);
expect(didEndPan, isTrue);
didStartPan = false;
panDelta = null;
didEndPan = false;
await tester.pumpWidget(buildFrame(<PointerDeviceKind>{PointerDeviceKind.stylus}));
await tester.dragFrom(const Offset(10.0, 10.0), const Offset(20.0, 30.0), kind: PointerDeviceKind.mouse);
// Non-matching device should not lead to any callbacks.
expect(didStartPan, isFalse);
expect(panDelta, isNull);
expect(didEndPan, isFalse);
await tester.dragFrom(const Offset(10.0, 10.0), const Offset(20.0, 30.0), kind: PointerDeviceKind.stylus);
// Matching device should allow gesture.
expect(didStartPan, isTrue);
expect(panDelta!.dx, 20.0);
expect(panDelta!.dy, 30.0);
expect(didEndPan, isTrue);
didStartPan = false;
panDelta = null;
didEndPan = false;
// If set to null, events from all device types will be recognized
await tester.pumpWidget(buildFrame(null));
await tester.dragFrom(const Offset(10.0, 10.0), const Offset(20.0, 30.0), kind: PointerDeviceKind.unknown);
expect(didStartPan, isTrue);
expect(panDelta!.dx, 20.0);
expect(panDelta!.dy, 30.0);
expect(didEndPan, isTrue);
});
testWidgets('supportedDevices is respected', (WidgetTester tester) async { testWidgets('supportedDevices is respected', (WidgetTester tester) async {
bool didStartPan = false; bool didStartPan = false;
Offset? panDelta; Offset? panDelta;
......
...@@ -1471,6 +1471,40 @@ void main() { ...@@ -1471,6 +1471,40 @@ void main() {
await tester.pump(); await tester.pump();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS, TargetPlatform.android })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS, TargetPlatform.android }));
testWidgets("Support updating 'ScrollBehavior.dragDevices' at runtime", (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/111716
Widget buildFrame(Set<ui.PointerDeviceKind>? dragDevices) {
return MaterialApp(
scrollBehavior: const NoScrollbarBehavior().copyWith(
dragDevices: dragDevices,
),
home: ListView.builder(
itemCount: 1000,
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
},
),
);
}
await tester.pumpWidget(buildFrame(<ui.PointerDeviceKind>{ui.PointerDeviceKind.mouse}));
await tester.drag(find.byType(Scrollable), const Offset(0.0, -100.0), kind: ui.PointerDeviceKind.mouse);
// Matching device should allow user scrolling.
expect(getScrollOffset(tester), 100.0);
await tester.pumpWidget(buildFrame(<ui.PointerDeviceKind>{ui.PointerDeviceKind.stylus}));
await tester.drag(find.byType(Scrollable), const Offset(0.0, -100.0), kind: ui.PointerDeviceKind.mouse);
// Non-matching device should not allow user scrolling.
expect(getScrollOffset(tester), 100.0);
await tester.drag(find.byType(Scrollable), const Offset(0.0, -100.0), kind: ui.PointerDeviceKind.stylus);
// Matching device should allow user scrolling.
expect(getScrollOffset(tester), 200.0);
});
testWidgets('Does scroll with mouse pointer drag when behavior is not configured to ignore them', (WidgetTester tester) async { testWidgets('Does scroll with mouse pointer drag when behavior is not configured to ignore them', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride); await pumpTest(tester, debugDefaultTargetPlatformOverride);
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true), kind: ui.PointerDeviceKind.mouse); final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true), kind: ui.PointerDeviceKind.mouse);
......
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