Skip to content

Commit

Permalink
Text selection via mouse (flutter#28290)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdebbar committed Mar 1, 2019
1 parent 1df28e8 commit b94bf87
Show file tree
Hide file tree
Showing 20 changed files with 833 additions and 51 deletions.
7 changes: 6 additions & 1 deletion packages/flutter/lib/src/gestures/eager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ import 'recognizer.dart';
/// all touch events inside the view bounds to the embedded Android view.
/// See [AndroidView.gestureRecognizers] for more details.
class EagerGestureRecognizer extends OneSequenceGestureRecognizer {
/// Create an eager gesture recognizer.
///
/// {@macro flutter.gestures.gestureRecognizer.kind}
EagerGestureRecognizer({ PointerDeviceKind kind }): super(kind: kind);

@override
void addPointer(PointerDownEvent event) {
void addAllowedPointer(PointerDownEvent event) {
// We call startTrackingPointer as this is where OneSequenceGestureRecognizer joins the arena.
startTrackingPointer(event.pointer);
resolve(GestureDisposition.accepted);
Expand Down
7 changes: 5 additions & 2 deletions packages/flutter/lib/src/gestures/force_press.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,19 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
/// The [interpolation] callback must always return a value in the range 0.0
/// to 1.0 for values of `pressure` that are between `pressureMin` and
/// `pressureMax`.
///
/// {@macro flutter.gestures.gestureRecognizer.kind}
ForcePressGestureRecognizer({
this.startPressure = 0.4,
this.peakPressure = 0.85,
this.interpolation = _inverseLerp,
Object debugOwner,
PointerDeviceKind kind,
}) : assert(startPressure != null),
assert(peakPressure != null),
assert(interpolation != null),
assert(peakPressure > startPressure),
super(debugOwner: debugOwner);
super(debugOwner: debugOwner, kind: kind);

/// A pointer is in contact with the screen and has just pressed with a force
/// exceeding the [startPressure]. Consequently, if there were other gesture
Expand Down Expand Up @@ -205,7 +208,7 @@ class ForcePressGestureRecognizer extends OneSequenceGestureRecognizer {
_ForceState _state = _ForceState.ready;

@override
void addPointer(PointerEvent event) {
void addAllowedPointer(PointerEvent event) {
// If the device has a maximum pressure of less than or equal to 1, it
// doesn't have touch pressure sensing capabilities. Do not participate
// in the gesture arena.
Expand Down
2 changes: 2 additions & 0 deletions packages/flutter/lib/src/gestures/long_press.dart
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,12 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
/// can be moved without limit once the long press is accepted.
LongPressGestureRecognizer({
double postAcceptSlopTolerance,
PointerDeviceKind kind,
Object debugOwner,
}) : super(
deadline: kLongPressTimeout,
postAcceptSlopTolerance: postAcceptSlopTolerance,
kind: kind,
debugOwner: debugOwner,
);

Expand Down
21 changes: 17 additions & 4 deletions packages/flutter/lib/src/gestures/monodrag.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,14 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
/// Initialize the object.
///
/// [dragStartBehavior] must not be null.
///
/// {@macro flutter.gestures.gestureRecognizer.kind}
DragGestureRecognizer({
Object debugOwner,
PointerDeviceKind kind,
this.dragStartBehavior = DragStartBehavior.start,
}) : assert(dragStartBehavior != null),
super(debugOwner: debugOwner);
super(debugOwner: debugOwner, kind: kind);

/// Configure the behavior of offsets sent to [onStart].
///
Expand Down Expand Up @@ -147,7 +150,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
final Map<int, VelocityTracker> _velocityTrackers = <int, VelocityTracker>{};

@override
void addPointer(PointerEvent event) {
void addAllowedPointer(PointerEvent event) {
startTrackingPointer(event.pointer);
_velocityTrackers[event.pointer] = VelocityTracker();
if (_state == _DragState.ready) {
Expand Down Expand Up @@ -296,7 +299,12 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
/// track each touch point independently.
class VerticalDragGestureRecognizer extends DragGestureRecognizer {
/// Create a gesture recognizer for interactions in the vertical axis.
VerticalDragGestureRecognizer({ Object debugOwner }) : super(debugOwner: debugOwner);
///
/// {@macro flutter.gestures.gestureRecognizer.kind}
VerticalDragGestureRecognizer({
Object debugOwner,
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

@override
bool _isFlingGesture(VelocityEstimate estimate) {
Expand Down Expand Up @@ -330,7 +338,12 @@ class VerticalDragGestureRecognizer extends DragGestureRecognizer {
/// track each touch point independently.
class HorizontalDragGestureRecognizer extends DragGestureRecognizer {
/// Create a gesture recognizer for interactions in the horizontal axis.
HorizontalDragGestureRecognizer({ Object debugOwner }) : super(debugOwner: debugOwner);
///
/// {@macro flutter.gestures.gestureRecognizer.kind}
HorizontalDragGestureRecognizer({
Object debugOwner,
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

@override
bool _isFlingGesture(VelocityEstimate estimate) {
Expand Down
25 changes: 19 additions & 6 deletions packages/flutter/lib/src/gestures/multidrag.dart
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,10 @@ abstract class MultiDragPointerState {
/// start after a long-press gesture.
abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> extends GestureRecognizer {
/// Initialize the object.
MultiDragGestureRecognizer({ @required Object debugOwner }) : super(debugOwner: debugOwner);
MultiDragGestureRecognizer({
@required Object debugOwner,
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

/// Called when this class recognizes the start of a drag gesture.
///
Expand All @@ -200,7 +203,7 @@ abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> exten
Map<int, T> _pointers = <int, T>{};

@override
void addPointer(PointerDownEvent event) {
void addAllowedPointer(PointerDownEvent event) {
assert(_pointers != null);
assert(event.pointer != null);
assert(event.position != null);
Expand Down Expand Up @@ -334,7 +337,10 @@ class _ImmediatePointerState extends MultiDragPointerState {
/// start after a long-press gesture.
class ImmediateMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_ImmediatePointerState> {
/// Create a gesture recognizer for tracking multiple pointers at once.
ImmediateMultiDragGestureRecognizer({ Object debugOwner }) : super(debugOwner: debugOwner);
ImmediateMultiDragGestureRecognizer({
Object debugOwner,
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

@override
_ImmediatePointerState createNewPointerState(PointerDownEvent event) {
Expand Down Expand Up @@ -380,7 +386,10 @@ class _HorizontalPointerState extends MultiDragPointerState {
class HorizontalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_HorizontalPointerState> {
/// Create a gesture recognizer for tracking multiple pointers at once
/// but only if they first move horizontally.
HorizontalMultiDragGestureRecognizer({ Object debugOwner }) : super(debugOwner: debugOwner);
HorizontalMultiDragGestureRecognizer({
Object debugOwner,
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

@override
_HorizontalPointerState createNewPointerState(PointerDownEvent event) {
Expand Down Expand Up @@ -426,7 +435,10 @@ class _VerticalPointerState extends MultiDragPointerState {
class VerticalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_VerticalPointerState> {
/// Create a gesture recognizer for tracking multiple pointers at once
/// but only if they first move vertically.
VerticalMultiDragGestureRecognizer({ Object debugOwner }) : super(debugOwner: debugOwner);
VerticalMultiDragGestureRecognizer({
Object debugOwner,
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

@override
_VerticalPointerState createNewPointerState(PointerDownEvent event) {
Expand Down Expand Up @@ -528,8 +540,9 @@ class DelayedMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_Dela
DelayedMultiDragGestureRecognizer({
this.delay = kLongPressTimeout,
Object debugOwner,
PointerDeviceKind kind,
}) : assert(delay != null),
super(debugOwner: debugOwner);
super(debugOwner: debugOwner, kind: kind);

/// The amount of time the pointer must remain in the same place for the drag
/// to be recognized.
Expand Down
14 changes: 10 additions & 4 deletions packages/flutter/lib/src/gestures/multitap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,12 @@ class _TapTracker {
/// quick succession.
class DoubleTapGestureRecognizer extends GestureRecognizer {
/// Create a gesture recognizer for double taps.
DoubleTapGestureRecognizer({ Object debugOwner }) : super(debugOwner: debugOwner);
///
/// {@macro flutter.gestures.gestureRecognizer.kind}
DoubleTapGestureRecognizer({
Object debugOwner,
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

// Implementation notes:
// The double tap recognizer can be in one of four states. There's no
Expand Down Expand Up @@ -100,7 +105,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
final Map<int, _TapTracker> _trackers = <int, _TapTracker>{};

@override
void addPointer(PointerEvent event) {
void addAllowedPointer(PointerEvent event) {
// Ignore out-of-bounds second taps.
if (_firstTap != null &&
!_firstTap.isWithinTolerance(event, kDoubleTapSlop))
Expand Down Expand Up @@ -318,7 +323,8 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
MultiTapGestureRecognizer({
this.longTapDelay = Duration.zero,
Object debugOwner,
}) : super(debugOwner: debugOwner);
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

/// A pointer that might cause a tap has contacted the screen at a particular
/// location.
Expand All @@ -345,7 +351,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
final Map<int, _TapGesture> _gestureMap = <int, _TapGesture>{};

@override
void addPointer(PointerEvent event) {
void addAllowedPointer(PointerEvent event) {
assert(!_gestureMap.containsKey(event.pointer));
_gestureMap[event.pointer] = _TapGesture(
gestureRecognizer: this,
Expand Down
71 changes: 65 additions & 6 deletions packages/flutter/lib/src/gestures/recognizer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ typedef RecognizerCallback<T> = T Function();
///
/// * [DragGestureRecognizer.dragStartBehavior], which gives an example for the different behaviors.
enum DragStartBehavior {
/// Set the initial offset, at the position where the first down even was
/// Set the initial offset, at the position where the first down event was
/// detected.
down,

Expand All @@ -58,14 +58,24 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
///
/// The argument is optional and is only used for debug purposes (e.g. in the
/// [toString] serialization).
GestureRecognizer({ this.debugOwner });
///
/// {@template flutter.gestures.gestureRecognizer.kind}
/// It's possible to limit this recognizer to a specific [PointerDeviceKind]
/// by providing the optional [kind] argument. If [kind] is null,
/// the recognizer will accept pointer events from all device kinds.
/// {@endtemplate}
GestureRecognizer({ this.debugOwner, PointerDeviceKind kind }) : _kind = kind;

/// The recognizer's owner.
///
/// This is used in the [toString] serialization to report the object for which
/// this gesture recognizer was created, to aid in debugging.
final Object debugOwner;

/// The kind of device that's allowed to be recognized. If null, events from
/// all device kinds will be tracked and recognized.
final PointerDeviceKind _kind;

/// Registers a new pointer that might be relevant to this gesture
/// detector.
///
Expand All @@ -78,7 +88,43 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
/// subsequent events for this pointer, and to add the pointer to
/// the global gesture arena manager (see [GestureArenaManager]) to track
/// that pointer.
void addPointer(PointerDownEvent event);
///
/// This method is called for each and all pointers being added. In
/// most cases, you want to override [addAllowedPointer] instead.
void addPointer(PointerDownEvent event) {
if (isPointerAllowed(event)) {
addAllowedPointer(event);
} else {
handleNonAllowedPointer(event);
}
}

/// Registers a new pointer that's been checked to be allowed by this gesture
/// recognizer.
///
/// Subclasses of [GestureRecognizer] are supposed to override this method
/// instead of [addPointer] because [addPointer] will be called for each
/// pointer being added while [addAllowedPointer] is only called for pointers
/// that are allowed by this recognizer.
@protected
void addAllowedPointer(PointerDownEvent event) { }

/// Handles a pointer being added that's not allowed by this recognizer.
///
/// Subclasses can override this method and reject the gesture.
///
/// See:
/// - [OneSequenceGestureRecognizer.handleNonAllowedPointer].
@protected
void handleNonAllowedPointer(PointerDownEvent event) { }

/// Checks whether or not a pointer is allowed to be tracked by this recognizer.
@protected
bool isPointerAllowed(PointerDownEvent event) {
// Currently, it only checks for device kind. But in the future we could check
// for other things e.g. mouse button.
return _kind == null || _kind == event.kind;
}

/// Releases any resources used by the object.
///
Expand Down Expand Up @@ -151,11 +197,21 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
/// simultaneous touches to each result in a separate tap.
abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
/// Initialize the object.
OneSequenceGestureRecognizer({ Object debugOwner }) : super(debugOwner: debugOwner);
///
/// {@macro flutter.gestures.gestureRecognizer.kind}
OneSequenceGestureRecognizer({
Object debugOwner,
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

final Map<int, GestureArenaEntry> _entries = <int, GestureArenaEntry>{};
final Set<int> _trackedPointers = HashSet<int>();

@override
void handleNonAllowedPointer(PointerDownEvent event) {
resolve(GestureDisposition.rejected);
}

/// Called when a pointer event is routed to this recognizer.
@protected
void handleEvent(PointerEvent event);
Expand Down Expand Up @@ -291,11 +347,14 @@ enum GestureRecognizerState {
/// in the gesture arena, the gesture will be rejected.
abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecognizer {
/// Initializes the [deadline] field during construction of subclasses.
///
/// {@macro flutter.gestures.gestureRecognizer.kind}
PrimaryPointerGestureRecognizer({
this.deadline,
this.preAcceptSlopTolerance = kTouchSlop,
this.postAcceptSlopTolerance = kTouchSlop,
Object debugOwner,
PointerDeviceKind kind,
}) : assert(
preAcceptSlopTolerance == null || preAcceptSlopTolerance >= 0,
'The preAcceptSlopTolerance must be positive or null',
Expand All @@ -304,7 +363,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
postAcceptSlopTolerance == null || postAcceptSlopTolerance >= 0,
'The postAcceptSlopTolerance must be positive or null',
),
super(debugOwner: debugOwner);
super(debugOwner: debugOwner, kind: kind);

/// If non-null, the recognizer will call [didExceedDeadline] after this
/// amount of time has elapsed since starting to track the primary pointer.
Expand Down Expand Up @@ -346,7 +405,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
Timer _timer;

@override
void addPointer(PointerDownEvent event) {
void addAllowedPointer(PointerDownEvent event) {
startTrackingPointer(event.pointer);
if (state == GestureRecognizerState.ready) {
state = GestureRecognizerState.possible;
Expand Down
9 changes: 7 additions & 2 deletions packages/flutter/lib/src/gestures/scale.dart
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,12 @@ class _LineBetweenPointers{
/// are no longer in contact with the screen, the recognizer calls [onEnd].
class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
/// Create a gesture recognizer for interactions intended for scaling content.
ScaleGestureRecognizer({ Object debugOwner }) : super(debugOwner: debugOwner);
///
/// {@macro flutter.gestures.gestureRecognizer.kind}
ScaleGestureRecognizer({
Object debugOwner,
PointerDeviceKind kind,
}) : super(debugOwner: debugOwner, kind: kind);

/// The pointers in contact with the screen have established a focal point and
/// initial scale of 1.0.
Expand Down Expand Up @@ -239,7 +244,7 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
}

@override
void addPointer(PointerEvent event) {
void addAllowedPointer(PointerEvent event) {
startTrackingPointer(event.pointer);
_velocityTrackers[event.pointer] = VelocityTracker();
if (_state == _ScaleState.ready) {
Expand Down
Loading

0 comments on commit b94bf87

Please sign in to comment.