Unverified Commit 48457d73 authored by Callum Moffat's avatar Callum Moffat Committed by GitHub

WidgetController.startGesture trackpad support (#114631)

parent e1166e43
......@@ -1086,12 +1086,14 @@ abstract class WidgetController {
);
}
/// Creates a gesture with an initial down gesture at a particular point, and
/// returns the [TestGesture] object which you can use to continue the
/// gesture.
/// Creates a gesture with an initial appropriate starting gesture at a
/// particular point, and returns the [TestGesture] object which you can use
/// to continue the gesture. Usually, the starting gesture will be a down event,
/// but if [kind] is set to [PointerDeviceKind.trackpad], the gesture will start
/// with a panZoomStart gesture.
///
/// You can use [createGesture] if your gesture doesn't begin with an initial
/// down gesture.
/// down or panZoomStart gesture.
///
/// See also:
/// * [WidgetController.drag], a method to simulate a drag.
......@@ -1110,7 +1112,11 @@ abstract class WidgetController {
kind: kind,
buttons: buttons,
);
await result.down(downLocation);
if (kind == PointerDeviceKind.trackpad) {
await result.panZoomStart(downLocation);
} else {
await result.down(downLocation);
}
return result;
}
......
......@@ -455,6 +455,7 @@ class TestGesture {
/// Dispatch a pointer down event at the given `downLocation`, caching the
/// hit test result.
Future<void> down(Offset downLocation, { Duration timeStamp = Duration.zero }) async {
assert(_pointer.kind != PointerDeviceKind.trackpad, 'Trackpads are expected to send panZoomStart events, not down events.');
return TestAsyncUtils.guard<void>(() async {
return _dispatcher(_pointer.down(downLocation, timeStamp: timeStamp));
});
......@@ -463,6 +464,7 @@ 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 {
assert(_pointer.kind != PointerDeviceKind.trackpad, 'Trackpads are expected to send panZoomStart events, not down events');
_pointer.setDownInfo(event, downLocation);
return TestAsyncUtils.guard<void>(() async {
return _dispatcher(event);
......@@ -507,7 +509,15 @@ class TestGesture {
/// * [WidgetController.fling], a method to simulate a fling.
Future<void> moveBy(Offset offset, { Duration timeStamp = Duration.zero }) {
assert(_pointer.location != null);
return moveTo(_pointer.location! + offset, timeStamp: timeStamp);
if (_pointer.isPanZoomActive) {
return panZoomUpdate(
_pointer.location!,
pan: (_pointer.pan ?? Offset.zero) + offset,
timeStamp: timeStamp
);
} else {
return moveTo(_pointer.location! + offset, timeStamp: timeStamp);
}
}
/// Send a move event moving the pointer to the given location.
......@@ -521,6 +531,7 @@ class TestGesture {
/// It sends move events at a given frequency and it is useful when there are listeners involved.
/// * [WidgetController.fling], a method to simulate a fling.
Future<void> moveTo(Offset location, { Duration timeStamp = Duration.zero }) {
assert(_pointer.kind != PointerDeviceKind.trackpad);
return TestAsyncUtils.guard<void>(() {
if (_pointer._isDown) {
return _dispatcher(_pointer.move(location, timeStamp: timeStamp));
......@@ -530,12 +541,19 @@ class TestGesture {
});
}
/// End the gesture by releasing the pointer.
/// End the gesture by releasing the pointer. For trackpad pointers this
/// will send a panZoomEnd event instead of an up event.
Future<void> up({ Duration timeStamp = Duration.zero }) {
return TestAsyncUtils.guard<void>(() async {
assert(_pointer._isDown);
await _dispatcher(_pointer.up(timeStamp: timeStamp));
assert(!_pointer._isDown);
if (_pointer.kind == PointerDeviceKind.trackpad) {
assert(_pointer._isPanZoomActive);
await _dispatcher(_pointer.panZoomEnd(timeStamp: timeStamp));
assert(!_pointer._isPanZoomActive);
} else {
assert(_pointer._isDown);
await _dispatcher(_pointer.up(timeStamp: timeStamp));
assert(!_pointer._isDown);
}
});
}
......@@ -543,6 +561,7 @@ class TestGesture {
/// system showed a modal dialog on top of the Flutter application,
/// for instance).
Future<void> cancel({ Duration timeStamp = Duration.zero }) {
assert(_pointer.kind != PointerDeviceKind.trackpad, 'Trackpads do not send cancel events.');
return TestAsyncUtils.guard<void>(() async {
assert(_pointer._isDown);
await _dispatcher(_pointer.cancel(timeStamp: timeStamp));
......@@ -553,6 +572,7 @@ class TestGesture {
/// Dispatch a pointer pan zoom start event at the given `location`, caching the
/// hit test result.
Future<void> panZoomStart(Offset location, { Duration timeStamp = Duration.zero }) async {
assert(_pointer.kind == PointerDeviceKind.trackpad, 'Only trackpads can send PointerPanZoom events.');
return TestAsyncUtils.guard<void>(() async {
return _dispatcher(_pointer.panZoomStart(location, timeStamp: timeStamp));
});
......@@ -566,6 +586,7 @@ class TestGesture {
double rotation = 0,
Duration timeStamp = Duration.zero
}) async {
assert(_pointer.kind == PointerDeviceKind.trackpad, 'Only trackpads can send PointerPanZoom events.');
return TestAsyncUtils.guard<void>(() async {
return _dispatcher(_pointer.panZoomUpdate(location,
pan: pan,
......@@ -580,6 +601,7 @@ class TestGesture {
Future<void> panZoomEnd({
Duration timeStamp = Duration.zero
}) async {
assert(_pointer.kind == PointerDeviceKind.trackpad, 'Only trackpads can send PointerPanZoom events.');
return TestAsyncUtils.guard<void>(() async {
return _dispatcher(_pointer.panZoomEnd(
timeStamp: timeStamp
......
......@@ -385,6 +385,40 @@ void main() {
},
);
testWidgets(
'WidgetTester.drag works with trackpad kind',
(WidgetTester tester) async {
final List<String> logs = <String>[];
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Listener(
onPointerDown: (PointerDownEvent event) => logs.add('down ${event.buttons}'),
onPointerMove: (PointerMoveEvent event) => logs.add('move ${event.buttons}'),
onPointerUp: (PointerUpEvent event) => logs.add('up ${event.buttons}'),
onPointerPanZoomStart: (PointerPanZoomStartEvent event) => logs.add('panZoomStart'),
onPointerPanZoomUpdate: (PointerPanZoomUpdateEvent event) => logs.add('panZoomUpdate ${event.pan}'),
onPointerPanZoomEnd: (PointerPanZoomEndEvent event) => logs.add('panZoomEnd'),
child: const Text('test'),
),
),
);
await tester.drag(find.text('test'), const Offset(-150.0, 200.0), kind: PointerDeviceKind.trackpad);
for(int i = 0; i < logs.length; i++) {
if (i == 0) {
expect(logs[i], 'panZoomStart');
} else if (i != logs.length - 1) {
expect(logs[i], startsWith('panZoomUpdate'));
} else {
expect(logs[i], 'panZoomEnd');
}
}
},
);
testWidgets(
'WidgetTester.fling must respect buttons',
(WidgetTester tester) async {
......
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