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
/// {@endtemplate}
GestureRecognizer({
this.debugOwner,
Set<PointerDeviceKind>? supportedDevices,
this.supportedDevices,
AllowedButtonsFilter? allowedButtonsFilter,
}) : _supportedDevices = supportedDevices,
_allowedButtonsFilter = allowedButtonsFilter ?? _defaultButtonAcceptBehavior;
}) : _allowedButtonsFilter = allowedButtonsFilter ?? _defaultButtonAcceptBehavior;
/// The recognizer's owner.
///
......@@ -97,7 +96,7 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
/// `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
/// tracked and recognized.
final Set<PointerDeviceKind>? _supportedDevices;
Set<PointerDeviceKind>? supportedDevices;
/// {@template flutter.gestures.multidrag._allowedButtonsFilter}
/// Called when interaction starts. This limits the dragging behavior
......@@ -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.
@protected
bool isPointerAllowed(PointerDownEvent event) {
return (_supportedDevices == null ||
_supportedDevices!.contains(event.kind)) &&
return (supportedDevices == null ||
supportedDevices!.contains(event.kind)) &&
_allowedButtonsFilter(event.buttons);
}
......@@ -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.
@protected
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.
......
......@@ -1050,7 +1050,8 @@ class GestureDetector extends StatelessWidget {
..onTertiaryTapDown = onTertiaryTapDown
..onTertiaryTapUp = onTertiaryTapUp
..onTertiaryTapCancel = onTertiaryTapCancel
..gestureSettings = gestureSettings;
..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
},
);
}
......@@ -1065,7 +1066,8 @@ class GestureDetector extends StatelessWidget {
..onDoubleTapDown = onDoubleTapDown
..onDoubleTap = onDoubleTap
..onDoubleTapCancel = onDoubleTapCancel
..gestureSettings = gestureSettings;
..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
},
);
}
......@@ -1116,7 +1118,8 @@ class GestureDetector extends StatelessWidget {
..onTertiaryLongPressMoveUpdate = onTertiaryLongPressMoveUpdate
..onTertiaryLongPressUp = onTertiaryLongPressUp
..onTertiaryLongPressEnd = onTertiaryLongPressEnd
..gestureSettings = gestureSettings;
..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
},
);
}
......@@ -1136,7 +1139,8 @@ class GestureDetector extends StatelessWidget {
..onEnd = onVerticalDragEnd
..onCancel = onVerticalDragCancel
..dragStartBehavior = dragStartBehavior
..gestureSettings = gestureSettings;
..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
},
);
}
......@@ -1156,7 +1160,8 @@ class GestureDetector extends StatelessWidget {
..onEnd = onHorizontalDragEnd
..onCancel = onHorizontalDragCancel
..dragStartBehavior = dragStartBehavior
..gestureSettings = gestureSettings;
..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
},
);
}
......@@ -1176,7 +1181,8 @@ class GestureDetector extends StatelessWidget {
..onEnd = onPanEnd
..onCancel = onPanCancel
..dragStartBehavior = dragStartBehavior
..gestureSettings = gestureSettings;
..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
},
);
}
......@@ -1192,7 +1198,8 @@ class GestureDetector extends StatelessWidget {
..dragStartBehavior = dragStartBehavior
..gestureSettings = gestureSettings
..trackpadScrollCausesScale = trackpadScrollCausesScale
..trackpadScrollToScaleFactor = trackpadScrollToScaleFactor;
..trackpadScrollToScaleFactor = trackpadScrollToScaleFactor
..supportedDevices = supportedDevices;
},
);
}
......@@ -1209,7 +1216,8 @@ class GestureDetector extends StatelessWidget {
..onPeak = onForcePressPeak
..onUpdate = onForcePressUpdate
..onEnd = onForcePressEnd
..gestureSettings = gestureSettings;
..gestureSettings = gestureSettings
..supportedDevices = supportedDevices;
},
);
}
......
......@@ -630,7 +630,8 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
..maxFlingVelocity = _physics?.maxFlingVelocity
..velocityTrackerBuilder = _configuration.velocityTrackerBuilder(context)
..dragStartBehavior = widget.dragStartBehavior
..gestureSettings = _mediaQueryGestureSettings;
..gestureSettings = _mediaQueryGestureSettings
..supportedDevices = _configuration.dragDevices;
},
),
};
......@@ -651,7 +652,8 @@ class ScrollableState extends State<Scrollable> with TickerProviderStateMixin, R
..maxFlingVelocity = _physics?.maxFlingVelocity
..velocityTrackerBuilder = _configuration.velocityTrackerBuilder(context)
..dragStartBehavior = widget.dragStartBehavior
..gestureSettings = _mediaQueryGestureSettings;
..gestureSettings = _mediaQueryGestureSettings
..supportedDevices = _configuration.dragDevices;
},
),
};
......
......@@ -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 {
bool didStartPan = false;
Offset? panDelta;
......
......@@ -1471,6 +1471,40 @@ void main() {
await tester.pump();
}, 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 {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
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