Adds fix for NAN value and pressure values outside of device reported min and max (#26659)
* Fix for nan pressure values and values outside min and max pressure ranges
This commit is contained in:
parent
a5820011b3
commit
2c558fdb21
@ -98,6 +98,9 @@ typedef GestureForceInterpolation = double Function(double pressureMin, double p
|
||||
/// force touch functionality, with the exception of the iPhone XR. In addition,
|
||||
/// a small handful of Android devices have this functionality as well.
|
||||
///
|
||||
/// Devices with faux screen pressure sensors like the Pixel 2 and 3 will not
|
||||
/// send any force press related callbacks.
|
||||
///
|
||||
/// Reported pressure will always be in the range 0.0 to 1.0, where 1.0 is
|
||||
/// maximum pressure and 0.0 is minimum pressure. If using a custom
|
||||
/// [interpolation] callback, the pressure reported will correspond to that
|
||||
@ -203,10 +206,19 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
|
||||
@override
|
||||
void addPointer(PointerEvent event) {
|
||||
startTrackingPointer(event.pointer);
|
||||
if (_state == _ForceState.ready) {
|
||||
_state = _ForceState.possible;
|
||||
_lastPosition = event.position;
|
||||
assert(event.pressureMax >= 1.0);
|
||||
// If the device has a maximum pressure of less than or equal to 1,
|
||||
// indicating a faux pressure sensor on this device or a device without a
|
||||
// pressure sensor (ie. on a non iOS device) we want do not want any
|
||||
// callbacks to be called.
|
||||
if (!(event is PointerUpEvent) && event.pressureMax == 1.0) {
|
||||
resolve(GestureDisposition.rejected);
|
||||
} else {
|
||||
startTrackingPointer(event.pointer);
|
||||
if (_state == _ForceState.ready) {
|
||||
_state = _ForceState.possible;
|
||||
_lastPosition = event.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,13 +227,20 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
assert(_state != _ForceState.ready);
|
||||
// A static pointer with changes in pressure creates PointerMoveEvent events.
|
||||
if (event is PointerMoveEvent || event is PointerDownEvent) {
|
||||
if (event.pressure > event.pressureMax || event.pressure < event.pressureMin) {
|
||||
debugPrint(
|
||||
'The reported device pressure ' + event.pressure.toString() +
|
||||
' is outside of the device pressure range where: ' +
|
||||
event.pressureMin.toString() + ' <= pressure <= ' + event.pressureMax.toString(),
|
||||
);
|
||||
}
|
||||
|
||||
final double pressure = interpolation(event.pressureMin, event.pressureMax, event.pressure);
|
||||
assert(
|
||||
event.pressure < event.pressureMin || // contract is undefined for underflowing pressures...
|
||||
event.pressure > event.pressureMax || // contract is undefined for overflowing pressures...
|
||||
pressure.isNaN || // and interpolation may return NaN for values it doesn't want to support...
|
||||
(pressure <= 1.0 && pressure >= 0.0) // but if everything is going well, it must be in the range 1.0..0.0.
|
||||
(pressure >= 0.0 && pressure <= 1.0) || // Interpolated pressure must be between 1.0 and 0.0...
|
||||
pressure.isNaN // and interpolation may return NaN for values it doesn't want to support...
|
||||
);
|
||||
|
||||
_lastPosition = event.position;
|
||||
_lastPressure = pressure;
|
||||
|
||||
@ -254,7 +273,7 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
)));
|
||||
}
|
||||
}
|
||||
if (onUpdate != null &&
|
||||
if (onUpdate != null && !pressure.isNaN &&
|
||||
(_state == _ForceState.started || _state == _ForceState.peaked)) {
|
||||
if (onUpdate != null) {
|
||||
invokeCallback<void>('onUpdate', () => onUpdate(ForcePressDetails(
|
||||
@ -306,7 +325,13 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
|
||||
static double _inverseLerp(double min, double max, double t) {
|
||||
assert(min <= max);
|
||||
return (t - min) / (max - min);
|
||||
double value = (t - min) / (max - min);
|
||||
|
||||
// If the device incorrectly reports a pressure outside of pressureMin
|
||||
// and pressureMax, we still want this recognizer to respond normally.
|
||||
if (!value.isNaN)
|
||||
value = value.clamp(0.0, 1.0);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1245,9 +1245,17 @@ void main() {
|
||||
final Offset textfieldStart = tester.getTopLeft(find.byType(CupertinoTextField));
|
||||
|
||||
const int pointerValue = 1;
|
||||
final TestGesture gesture =
|
||||
await tester.startGesture(textfieldStart + const Offset(150.0, 5.0));
|
||||
await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: textfieldStart + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
final TestGesture gesture = await tester.createGesture();
|
||||
await gesture.downWithCustomEvent(
|
||||
textfieldStart + const Offset(150.0, 5.0),
|
||||
PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: textfieldStart + const Offset(150.0, 5.0),
|
||||
pressure: 3.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
// We expect the force press to select a word at the given location.
|
||||
expect(
|
||||
controller.selection,
|
||||
|
@ -109,6 +109,99 @@ void main() {
|
||||
expect(ended, 1);
|
||||
});
|
||||
|
||||
testGesture('Force presses are not recognized on devices with low maxmium pressure', (GestureTester tester) {
|
||||
// Device specific constants that represent those from the iPhone X
|
||||
const double pressureMin = 0;
|
||||
const double pressureMax = 1.0;
|
||||
|
||||
// Interpolated Flutter pressure values.
|
||||
const double startPressure = 0.4; // = Device pressure of 2.66.
|
||||
const double peakPressure = 0.85; // = Device pressure of 5.66.
|
||||
|
||||
int started = 0;
|
||||
int peaked = 0;
|
||||
int updated = 0;
|
||||
int ended = 0;
|
||||
|
||||
void onStart(ForcePressDetails details) {
|
||||
started += 1;
|
||||
}
|
||||
|
||||
final ForcePressGestureRecognizer force = ForcePressGestureRecognizer(startPressure: startPressure, peakPressure: peakPressure);
|
||||
|
||||
force.onStart = onStart;
|
||||
force.onPeak = (ForcePressDetails details) => peaked += 1;
|
||||
force.onUpdate = (ForcePressDetails details) => updated += 1;
|
||||
force.onEnd = (ForcePressDetails details) => ended += 1;
|
||||
|
||||
const int pointerValue = 1;
|
||||
final TestPointer pointer = TestPointer(pointerValue);
|
||||
const PointerDownEvent down = PointerDownEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 0, pressureMin: pressureMin, pressureMax: pressureMax);
|
||||
pointer.setDownInfo(down, const Offset(10.0, 10.0));
|
||||
force.addPointer(down);
|
||||
tester.closeArena(pointerValue);
|
||||
|
||||
expect(started, 0);
|
||||
expect(peaked, 0);
|
||||
expect(updated, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
// Pressure fed into the test environment simulates the values received directly from the device.
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 2.5, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
|
||||
// We have not hit the start pressure, so no events should be true.
|
||||
expect(started, 0);
|
||||
expect(peaked, 0);
|
||||
expect(updated, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 2.8, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
|
||||
// We have just hit the start pressure so just the start event should be triggered and one update call should have occurred.
|
||||
expect(started, 0);
|
||||
expect(peaked, 0);
|
||||
expect(updated, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 3.3, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 4.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 5.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 1.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
|
||||
// We have exceeded the start pressure so update should be greater than 0.
|
||||
expect(started, 0);
|
||||
expect(updated, 0);
|
||||
expect(peaked, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 6.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
|
||||
// We have exceeded the peak pressure so peak pressure should be true.
|
||||
expect(started, 0);
|
||||
expect(updated, 0);
|
||||
expect(peaked, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 3.3, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 4.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 5.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 1.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
|
||||
// Update is still called.
|
||||
expect(started, 0);
|
||||
expect(updated, 0);
|
||||
expect(peaked, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
tester.route(pointer.up());
|
||||
|
||||
// We have ended the gesture so ended should be true.
|
||||
expect(started, 0);
|
||||
expect(updated, 0);
|
||||
expect(peaked, 0);
|
||||
expect(ended, 0);
|
||||
});
|
||||
|
||||
testGesture('If minimum pressure is not reached, start and end callbacks are not called', (GestureTester tester) {
|
||||
// Device specific constants that represent those from the iPhone X
|
||||
const double pressureMin = 0;
|
||||
@ -449,4 +542,110 @@ void main() {
|
||||
expect(peaked, 1);
|
||||
expect(ended, 1);
|
||||
});
|
||||
|
||||
testGesture('A pressure outside of the device reported min and max pressure will not give an error', (GestureTester tester) {
|
||||
// Device specific constants that represent those from the iPhone X
|
||||
const double pressureMin = 0;
|
||||
const double pressureMax = 6.66;
|
||||
|
||||
// Interpolated Flutter pressure values.
|
||||
const double startPressure = 0.4; // = Device pressure of 2.66.
|
||||
const double peakPressure = 0.85; // = Device pressure of 5.66.
|
||||
|
||||
int started = 0;
|
||||
int peaked = 0;
|
||||
int updated = 0;
|
||||
int ended = 0;
|
||||
|
||||
final ForcePressGestureRecognizer force = ForcePressGestureRecognizer(startPressure: startPressure, peakPressure: peakPressure);
|
||||
|
||||
force.onStart = (_) => started += 1;
|
||||
force.onPeak = (_) => peaked += 1;
|
||||
force.onUpdate = (_) => updated += 1;
|
||||
force.onEnd = (_) => ended += 1;
|
||||
|
||||
const int pointerValue = 1;
|
||||
final TestPointer pointer = TestPointer(pointerValue);
|
||||
const PointerDownEvent down = PointerDownEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 0, pressureMin: pressureMin, pressureMax: pressureMax);
|
||||
pointer.setDownInfo(down, const Offset(10.0, 10.0));
|
||||
force.addPointer(down);
|
||||
tester.closeArena(1);
|
||||
|
||||
expect(started, 0);
|
||||
expect(peaked, 0);
|
||||
expect(updated, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
// Pressure fed into the test environment simulates the values received directly from the device.
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 2.5, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
|
||||
// We have not hit the start pressure, so no events should be true.
|
||||
expect(started, 0);
|
||||
expect(peaked, 0);
|
||||
expect(updated, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
// If the case where the pressure is greater than the max pressure were not handled correctly, this move event would throw an error.
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 8.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
tester.route(pointer.up());
|
||||
|
||||
expect(started, 1);
|
||||
expect(peaked, 1);
|
||||
expect(updated, 1);
|
||||
expect(ended, 1);
|
||||
});
|
||||
|
||||
testGesture('A pressure of NAN will not give an error', (GestureTester tester) {
|
||||
// Device specific constants that represent those from the iPhone X
|
||||
const double pressureMin = 0;
|
||||
const double pressureMax = 6.66;
|
||||
|
||||
// Interpolated Flutter pressure values.
|
||||
const double startPressure = 0.4; // = Device pressure of 2.66.
|
||||
const double peakPressure = 0.85; // = Device pressure of 5.66.
|
||||
|
||||
int started = 0;
|
||||
int peaked = 0;
|
||||
int updated = 0;
|
||||
int ended = 0;
|
||||
|
||||
final ForcePressGestureRecognizer force = ForcePressGestureRecognizer(startPressure: startPressure, peakPressure: peakPressure);
|
||||
|
||||
force.onStart = (_) => started += 1;
|
||||
force.onPeak = (_) => peaked += 1;
|
||||
force.onUpdate = (_) => updated += 1;
|
||||
force.onEnd = (_) => ended += 1;
|
||||
|
||||
const int pointerValue = 1;
|
||||
final TestPointer pointer = TestPointer(pointerValue);
|
||||
const PointerDownEvent down = PointerDownEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 0, pressureMin: pressureMin, pressureMax: pressureMax);
|
||||
pointer.setDownInfo(down, const Offset(10.0, 10.0));
|
||||
force.addPointer(down);
|
||||
tester.closeArena(1);
|
||||
|
||||
expect(started, 0);
|
||||
expect(peaked, 0);
|
||||
expect(updated, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
// Pressure fed into the test environment simulates the values received directly from the device.
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 2.5, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
|
||||
// We have not hit the start pressure, so no events should be true.
|
||||
expect(started, 0);
|
||||
expect(peaked, 0);
|
||||
expect(updated, 0);
|
||||
expect(ended, 0);
|
||||
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 6.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
expect(peaked, 1);
|
||||
|
||||
tester.route(const PointerMoveEvent(pointer: pointerValue, position: Offset(10.0, 10.0), pressure: 0.0 / 0.0, pressureMin: pressureMin, pressureMax: pressureMax));
|
||||
tester.route(pointer.up());
|
||||
|
||||
expect(started, 1);
|
||||
expect(peaked, 1);
|
||||
expect(updated, 1);
|
||||
expect(ended, 1);
|
||||
});
|
||||
}
|
||||
|
@ -2190,7 +2190,6 @@ void main() {
|
||||
expect(controller.selection.extentOffset - controller.selection.baseOffset, 0);
|
||||
});
|
||||
|
||||
|
||||
testWidgets('Down and up test 2', (WidgetTester tester) async{
|
||||
await tester.pumpWidget(setupWidget());
|
||||
const String testValue = 'a big house\njumped over a mouse\nOne more line yay'; // 11 \n 19
|
||||
@ -4352,12 +4351,21 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
final Offset textfieldStart = tester.getTopLeft(find.byType(TextField));
|
||||
final Offset offset = tester.getTopLeft(find.byType(TextField)) + const Offset(150.0, 5.0);
|
||||
|
||||
const int pointerValue = 1;
|
||||
final TestGesture gesture =
|
||||
await tester.startGesture(textfieldStart + const Offset(150.0, 5.0));
|
||||
await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: textfieldStart + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
final TestGesture gesture = await tester.createGesture();
|
||||
await gesture.downWithCustomEvent(
|
||||
offset,
|
||||
PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: offset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: offset + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
|
||||
// We don't want this gesture to select any word on Android.
|
||||
expect(controller.selection, const TextSelection.collapsed(offset: -1));
|
||||
@ -4386,8 +4394,19 @@ void main() {
|
||||
final Offset textfieldStart = tester.getTopLeft(find.byType(CupertinoTextField));
|
||||
|
||||
const int pointerValue = 1;
|
||||
final TestGesture gesture =
|
||||
await tester.startGesture(textfieldStart + const Offset(150.0, 5.0));
|
||||
final Offset offset = textfieldStart + const Offset(150.0, 5.0);
|
||||
final TestGesture gesture = await tester.createGesture();
|
||||
await gesture.downWithCustomEvent(
|
||||
offset,
|
||||
PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: offset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
|
||||
await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: textfieldStart + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
// We expect the force press to select a word at the given location.
|
||||
expect(
|
||||
|
@ -8,6 +8,8 @@ import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
|
||||
void main() {
|
||||
const Offset forcePressOffset = Offset(400.0, 50.0);
|
||||
|
||||
testWidgets('Uncontested scrolls start immediately', (WidgetTester tester) async {
|
||||
bool didStartDrag = false;
|
||||
double updatedDragDelta;
|
||||
@ -367,9 +369,20 @@ void main() {
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final TestGesture gesture = await tester.startGesture(const Offset(400.0, 50.0));
|
||||
const int pointerValue = 1;
|
||||
|
||||
final TestGesture gesture = await tester.createGesture();
|
||||
await gesture.downWithCustomEvent(
|
||||
forcePressOffset,
|
||||
const PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: forcePressOffset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.3, pressureMin: 0, pressureMax: 1));
|
||||
|
||||
expect(forcePressStart, 0);
|
||||
@ -428,9 +441,23 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
final TestGesture gesture = await tester.startGesture(const Offset(400.0, 50.0));
|
||||
const int pointerValue = 1;
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(400.0, 50.0), pressure: 0.3, pressureMin: 0, pressureMax: 1));
|
||||
const double maxPressure = 6.0;
|
||||
|
||||
final TestGesture gesture = await tester.createGesture();
|
||||
|
||||
await gesture.downWithCustomEvent(
|
||||
forcePressOffset,
|
||||
const PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: forcePressOffset,
|
||||
pressure: 0.0,
|
||||
pressureMax: maxPressure,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(400.0, 50.0), pressure: 0.3, pressureMin: 0, pressureMax: maxPressure));
|
||||
|
||||
expect(forcePressStart, 0);
|
||||
expect(longPressTimes, 0);
|
||||
@ -442,7 +469,7 @@ void main() {
|
||||
expect(forcePressStart, 0);
|
||||
|
||||
// Failed attempt to trigger the force press.
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(400.0, 50.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(400.0, 50.0), pressure: 0.5, pressureMin: 0, pressureMax: maxPressure));
|
||||
|
||||
expect(longPressTimes, 1);
|
||||
expect(forcePressStart, 0);
|
||||
@ -467,8 +494,21 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
final TestGesture gesture = await tester.startGesture(const Offset(50.0, 50.0));
|
||||
const int pointerValue = 1;
|
||||
|
||||
final TestGesture gesture = await tester.createGesture();
|
||||
|
||||
await gesture.downWithCustomEvent(
|
||||
forcePressOffset,
|
||||
const PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: forcePressOffset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.3, pressureMin: 0, pressureMax: 1));
|
||||
|
||||
expect(forcePressStart, 0);
|
||||
|
@ -13,6 +13,8 @@ void main() {
|
||||
int doubleTapDownCount;
|
||||
int forcePressStartCount;
|
||||
int forcePressEndCount;
|
||||
const Offset forcePressOffset = Offset(400.0, 50.0);
|
||||
|
||||
|
||||
void _handleTapDown(TapDownDetails details) { tapCount++; }
|
||||
void _handleSingleTapUp(TapUpDetails details) { singleTapUpCount++; }
|
||||
@ -155,22 +157,62 @@ void main() {
|
||||
await pumpGestureDetector(tester);
|
||||
|
||||
const int pointerValue = 1;
|
||||
TestGesture gesture = await tester.startGesture(const Offset(400.0, 50.0), pointer: pointerValue);
|
||||
|
||||
final TestGesture gesture = await tester.createGesture();
|
||||
|
||||
await gesture.downWithCustomEvent(
|
||||
forcePressOffset,
|
||||
const PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: forcePressOffset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
await gesture.up();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
gesture = await tester.startGesture(const Offset(400.0, 50.0), pointer: pointerValue);
|
||||
await gesture.downWithCustomEvent(
|
||||
forcePressOffset,
|
||||
const PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: forcePressOffset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
await gesture.up();
|
||||
await tester.pump(const Duration(milliseconds: 20));
|
||||
|
||||
gesture = await tester.startGesture(const Offset(400.0, 50.0), pointer: pointerValue);
|
||||
await gesture.downWithCustomEvent(
|
||||
forcePressOffset,
|
||||
const PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: forcePressOffset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
await gesture.up();
|
||||
await tester.pump(const Duration(milliseconds: 20));
|
||||
|
||||
gesture = await tester.startGesture(const Offset(400.0, 50.0), pointer: pointerValue);
|
||||
await gesture.downWithCustomEvent(
|
||||
forcePressOffset,
|
||||
const PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: forcePressOffset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
await gesture.up();
|
||||
|
||||
@ -181,16 +223,49 @@ void main() {
|
||||
await pumpGestureDetector(tester);
|
||||
|
||||
const int pointerValue = 1;
|
||||
TestGesture gesture = await tester.startGesture(const Offset(400.0, 50.0), pointer: pointerValue);
|
||||
final TestGesture gesture = await tester.createGesture();
|
||||
await gesture.downWithCustomEvent(
|
||||
forcePressOffset,
|
||||
const PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: forcePressOffset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
|
||||
);
|
||||
// Initiate a quick tap.
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.0, pressureMin: 0, pressureMax: 1));
|
||||
await gesture.updateWithCustomEvent(
|
||||
const PointerMoveEvent(
|
||||
pointer: pointerValue,
|
||||
position: Offset(0.0, 0.0),
|
||||
pressure: 0.0,
|
||||
pressureMin: 0,
|
||||
pressureMax: 1
|
||||
)
|
||||
);
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
await gesture.up();
|
||||
|
||||
// Initiate a force tap.
|
||||
gesture = await tester.startGesture(const Offset(400.0, 50.0), pointer: pointerValue);
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(pointer: pointerValue, position: Offset(0.0, 0.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
|
||||
await gesture.downWithCustomEvent(
|
||||
forcePressOffset,
|
||||
const PointerDownEvent(
|
||||
pointer: pointerValue,
|
||||
position: forcePressOffset,
|
||||
pressure: 0.0,
|
||||
pressureMax: 6.0,
|
||||
pressureMin: 0.0
|
||||
),
|
||||
);
|
||||
await gesture.updateWithCustomEvent(const PointerMoveEvent(
|
||||
pointer: pointerValue,
|
||||
position: Offset(0.0, 0.0),
|
||||
pressure: 0.5,
|
||||
pressureMin: 0,
|
||||
pressureMax: 1
|
||||
));
|
||||
expect(forcePressStartCount, 1);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
@ -223,6 +223,16 @@ class TestGesture {
|
||||
});
|
||||
}
|
||||
|
||||
/// Dispatch a pointer down event at the given `downLocation`, caching the
|
||||
/// hit test result with a custom down event.
|
||||
Future<void> downWithCustomEvent(Offset downLocation, PointerDownEvent event) async {
|
||||
_pointer.setDownInfo(event, downLocation);
|
||||
return TestAsyncUtils.guard<void>(() async {
|
||||
_result = _hitTester(downLocation);
|
||||
return _dispatcher(event, _result);
|
||||
});
|
||||
}
|
||||
|
||||
final EventDispatcher _dispatcher;
|
||||
final HitTester _hitTester;
|
||||
final TestPointer _pointer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user