mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

* Roll engine to b6df7a637498ca9beda1fa9cd7210e3202ea599f. Changes since last roll: ``` b6df7a637 Roll dart to 290c576264faa096a0b3206c71b2435309d9f904. (#4771) a6764dbd5 Add sources for Fuchsia target. (#4763) 2d5900615 [fuchsia] Remove unused header file. (#4769) 9717063b7 Revert "Roll dart to c080951d45e79cd25df98036c4be835b284a269c. (#4767)" (#4768) 9a9814312 Roll dart to c080951d45e79cd25df98036c4be835b284a269c. (#4767) e74e8b35c [async] Update includes of async headers to new path (#4760) e2c4b2760 Use Dart 2 camel case constants in the engine Dart libraries (#4766) 9c1e48434 Updates for Fuchsia roll. (#4765) 14c940e27 Switch from fxl::Mutex to std::mutex (#4764) debf82c0b Roll Garnet (#4759) 5bffdefbb Use weak pointers to the accesibility bridge from objects vended to the UIKit accessibility framework. (#4761) ```
205 lines
6.7 KiB
Dart
205 lines
6.7 KiB
Dart
// Copyright 2015 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/gestures.dart';
|
|
|
|
import 'test_async_utils.dart';
|
|
|
|
export 'dart:ui' show Offset;
|
|
|
|
/// A class for generating coherent artificial pointer events.
|
|
///
|
|
/// You can use this to manually simulate individual events, but the
|
|
/// simplest way to generate coherent gestures is to use [TestGesture].
|
|
class TestPointer {
|
|
/// Creates a [TestPointer]. By default, the pointer identifier used is 1,
|
|
/// however this can be overridden by providing an argument to the
|
|
/// constructor.
|
|
///
|
|
/// Multiple [TestPointer]s created with the same pointer identifier will
|
|
/// interfere with each other if they are used in parallel.
|
|
TestPointer([ this.pointer = 1 ]);
|
|
|
|
/// The pointer identifier used for events generated by this object.
|
|
///
|
|
/// Set when the object is constructed. Defaults to 1.
|
|
final int pointer;
|
|
|
|
/// Whether the pointer simulated by this object is currently down.
|
|
///
|
|
/// A pointer is released (goes up) by calling [up] or [cancel].
|
|
///
|
|
/// Once a pointer is released, it can no longer generate events.
|
|
bool get isDown => _isDown;
|
|
bool _isDown = false;
|
|
|
|
/// The position of the last event sent by this object.
|
|
///
|
|
/// If no event has ever been sent by this object, returns null.
|
|
Offset get location => _location;
|
|
Offset _location;
|
|
|
|
/// Create a [PointerDownEvent] at the given location.
|
|
///
|
|
/// By default, the time stamp on the event is [Duration.zero]. You
|
|
/// can give a specific time stamp by passing the `timeStamp`
|
|
/// argument.
|
|
PointerDownEvent down(Offset newLocation, { Duration timeStamp: Duration.zero }) {
|
|
assert(!isDown);
|
|
_isDown = true;
|
|
_location = newLocation;
|
|
return new PointerDownEvent(
|
|
timeStamp: timeStamp,
|
|
pointer: pointer,
|
|
position: location
|
|
);
|
|
}
|
|
|
|
/// Create a [PointerMoveEvent] to the given location.
|
|
///
|
|
/// By default, the time stamp on the event is [Duration.zero]. You
|
|
/// can give a specific time stamp by passing the `timeStamp`
|
|
/// argument.
|
|
PointerMoveEvent move(Offset newLocation, { Duration timeStamp: Duration.zero }) {
|
|
assert(isDown);
|
|
final Offset delta = newLocation - location;
|
|
_location = newLocation;
|
|
return new PointerMoveEvent(
|
|
timeStamp: timeStamp,
|
|
pointer: pointer,
|
|
position: newLocation,
|
|
delta: delta
|
|
);
|
|
}
|
|
|
|
/// Create a [PointerUpEvent].
|
|
///
|
|
/// By default, the time stamp on the event is [Duration.zero]. You
|
|
/// can give a specific time stamp by passing the `timeStamp`
|
|
/// argument.
|
|
///
|
|
/// The object is no longer usable after this method has been called.
|
|
PointerUpEvent up({ Duration timeStamp: Duration.zero }) {
|
|
assert(isDown);
|
|
_isDown = false;
|
|
return new PointerUpEvent(
|
|
timeStamp: timeStamp,
|
|
pointer: pointer,
|
|
position: location
|
|
);
|
|
}
|
|
|
|
/// Create a [PointerCancelEvent].
|
|
///
|
|
/// By default, the time stamp on the event is [Duration.zero]. You
|
|
/// can give a specific time stamp by passing the `timeStamp`
|
|
/// argument.
|
|
///
|
|
/// The object is no longer usable after this method has been called.
|
|
PointerCancelEvent cancel({ Duration timeStamp: Duration.zero }) {
|
|
assert(isDown);
|
|
_isDown = false;
|
|
return new PointerCancelEvent(
|
|
timeStamp: timeStamp,
|
|
pointer: pointer,
|
|
position: location
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Signature for a callback that can dispatch events and returns a future that
|
|
/// completes when the event dispatch is complete.
|
|
typedef Future<Null> EventDispatcher(PointerEvent event, HitTestResult result);
|
|
|
|
/// Signature for callbacks that perform hit-testing at a given location.
|
|
typedef HitTestResult HitTester(Offset location);
|
|
|
|
/// A class for performing gestures in tests.
|
|
///
|
|
/// The simplest way to create a [TestGesture] is to call
|
|
/// [WidgetTester.startGesture].
|
|
class TestGesture {
|
|
TestGesture._(this._dispatcher, this._result, this._pointer);
|
|
|
|
/// Create a [TestGesture] by starting with a pointerDown at the
|
|
/// given point.
|
|
///
|
|
/// By default, the pointer identifier used is 1. This can be overridden by
|
|
/// providing the `pointer` argument.
|
|
///
|
|
/// A function to use for hit testing should be provided via the `hitTester`
|
|
/// argument, and a function to use for dispatching events should be provided
|
|
/// via the `dispatcher` argument.
|
|
static Future<TestGesture> down(Offset downLocation, {
|
|
int pointer: 1,
|
|
@required HitTester hitTester,
|
|
@required EventDispatcher dispatcher,
|
|
}) async {
|
|
assert(hitTester != null);
|
|
assert(dispatcher != null);
|
|
TestGesture result;
|
|
return TestAsyncUtils.guard(() async {
|
|
// dispatch down event
|
|
final HitTestResult hitTestResult = hitTester(downLocation);
|
|
final TestPointer testPointer = new TestPointer(pointer);
|
|
await dispatcher(testPointer.down(downLocation), hitTestResult);
|
|
|
|
// create a TestGesture
|
|
result = new TestGesture._(dispatcher, hitTestResult, testPointer);
|
|
return null;
|
|
}).then<TestGesture>((Null value) {
|
|
return result;
|
|
}, onError: (dynamic error, StackTrace stack) {
|
|
return new Future<TestGesture>.error(error, stack);
|
|
});
|
|
}
|
|
|
|
final EventDispatcher _dispatcher;
|
|
final HitTestResult _result;
|
|
final TestPointer _pointer;
|
|
|
|
/// Send a move event moving the pointer by the given offset.
|
|
Future<Null> moveBy(Offset offset, { Duration timeStamp: Duration.zero }) {
|
|
assert(_pointer._isDown);
|
|
return moveTo(_pointer.location + offset, timeStamp: timeStamp);
|
|
}
|
|
|
|
/// Send a move event moving the pointer to the given location.
|
|
Future<Null> moveTo(Offset location, { Duration timeStamp: Duration.zero }) {
|
|
return TestAsyncUtils.guard(() {
|
|
assert(_pointer._isDown);
|
|
return _dispatcher(_pointer.move(location, timeStamp: timeStamp), _result);
|
|
});
|
|
}
|
|
|
|
/// End the gesture by releasing the pointer.
|
|
///
|
|
/// The object is no longer usable after this method has been called.
|
|
Future<Null> up() {
|
|
return TestAsyncUtils.guard(() async {
|
|
assert(_pointer._isDown);
|
|
await _dispatcher(_pointer.up(), _result);
|
|
assert(!_pointer._isDown);
|
|
return null;
|
|
});
|
|
}
|
|
|
|
/// End the gesture by canceling the pointer (as would happen if the
|
|
/// system showed a modal dialog on top of the Flutter application,
|
|
/// for instance).
|
|
///
|
|
/// The object is no longer usable after this method has been called.
|
|
Future<Null> cancel() {
|
|
return TestAsyncUtils.guard(() async {
|
|
assert(_pointer._isDown);
|
|
await _dispatcher(_pointer.cancel(), _result);
|
|
assert(!_pointer._isDown);
|
|
return null;
|
|
});
|
|
}
|
|
}
|