Unverified Commit e4e9dde4 authored by Tomasz Gucio's avatar Tomasz Gucio Committed by GitHub

Move TapAndDragGestureRecognizer code under gestures (#119508)

parent 3213588c
...@@ -30,5 +30,6 @@ export 'src/gestures/recognizer.dart'; ...@@ -30,5 +30,6 @@ export 'src/gestures/recognizer.dart';
export 'src/gestures/resampler.dart'; export 'src/gestures/resampler.dart';
export 'src/gestures/scale.dart'; export 'src/gestures/scale.dart';
export 'src/gestures/tap.dart'; export 'src/gestures/tap.dart';
export 'src/gestures/tap_and_drag.dart';
export 'src/gestures/team.dart'; export 'src/gestures/team.dart';
export 'src/gestures/velocity_tracker.dart'; export 'src/gestures/velocity_tracker.dart';
...@@ -5,11 +5,13 @@ ...@@ -5,11 +5,13 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart' show HardwareKeyboard, LogicalKeyboardKey;
import 'framework.dart'; import 'constants.dart';
import 'gesture_detector.dart'; import 'events.dart';
import 'monodrag.dart';
import 'recognizer.dart';
import 'scale.dart';
import 'tap.dart';
// Examples can assume: // Examples can assume:
// void setState(VoidCallback fn) { } // void setState(VoidCallback fn) { }
...@@ -75,14 +77,13 @@ typedef GestureTapDragDownCallback = void Function(TapDragDownDetails details); ...@@ -75,14 +77,13 @@ typedef GestureTapDragDownCallback = void Function(TapDragDownDetails details);
class TapDragDownDetails with Diagnosticable { class TapDragDownDetails with Diagnosticable {
/// Creates details for a [GestureTapDragDownCallback]. /// Creates details for a [GestureTapDragDownCallback].
/// ///
/// The [globalPosition], [localPosition], [consecutiveTapCount], and /// The [globalPosition], [localPosition], and [consecutiveTapCount]
/// [keysPressedOnDown] arguments must be provided and must not be null. /// arguments must be provided and must not be null.
TapDragDownDetails({ TapDragDownDetails({
required this.globalPosition, required this.globalPosition,
required this.localPosition, required this.localPosition,
this.kind, this.kind,
required this.consecutiveTapCount, required this.consecutiveTapCount,
required this.keysPressedOnDown,
}); });
/// The global position at which the pointer contacted the screen. /// The global position at which the pointer contacted the screen.
...@@ -98,9 +99,6 @@ class TapDragDownDetails with Diagnosticable { ...@@ -98,9 +99,6 @@ class TapDragDownDetails with Diagnosticable {
/// the number in the series this tap is. /// the number in the series this tap is.
final int consecutiveTapCount; final int consecutiveTapCount;
/// The keys that were pressed when the most recent [PointerDownEvent] occurred.
final Set<LogicalKeyboardKey> keysPressedOnDown;
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
...@@ -108,7 +106,6 @@ class TapDragDownDetails with Diagnosticable { ...@@ -108,7 +106,6 @@ class TapDragDownDetails with Diagnosticable {
properties.add(DiagnosticsProperty<Offset>('localPosition', localPosition)); properties.add(DiagnosticsProperty<Offset>('localPosition', localPosition));
properties.add(DiagnosticsProperty<PointerDeviceKind?>('kind', kind)); properties.add(DiagnosticsProperty<PointerDeviceKind?>('kind', kind));
properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount)); properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount));
properties.add(DiagnosticsProperty<Set<LogicalKeyboardKey>>('keysPressedOnDown', keysPressedOnDown));
} }
} }
...@@ -134,14 +131,13 @@ typedef GestureTapDragUpCallback = void Function(TapDragUpDetails details); ...@@ -134,14 +131,13 @@ typedef GestureTapDragUpCallback = void Function(TapDragUpDetails details);
class TapDragUpDetails with Diagnosticable { class TapDragUpDetails with Diagnosticable {
/// Creates details for a [GestureTapDragUpCallback]. /// Creates details for a [GestureTapDragUpCallback].
/// ///
/// The [kind], [globalPosition], [localPosition], [consecutiveTapCount], and /// The [kind], [globalPosition], [localPosition], and [consecutiveTapCount]
/// [keysPressedOnDown] arguments must be provided and must not be null. /// arguments must be provided and must not be null.
TapDragUpDetails({ TapDragUpDetails({
required this.kind, required this.kind,
required this.globalPosition, required this.globalPosition,
required this.localPosition, required this.localPosition,
required this.consecutiveTapCount, required this.consecutiveTapCount,
required this.keysPressedOnDown,
}); });
/// The global position at which the pointer contacted the screen. /// The global position at which the pointer contacted the screen.
...@@ -157,9 +153,6 @@ class TapDragUpDetails with Diagnosticable { ...@@ -157,9 +153,6 @@ class TapDragUpDetails with Diagnosticable {
/// the number in the series this tap is. /// the number in the series this tap is.
final int consecutiveTapCount; final int consecutiveTapCount;
/// The keys that were pressed when the most recent [PointerDownEvent] occurred.
final Set<LogicalKeyboardKey> keysPressedOnDown;
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
...@@ -167,7 +160,6 @@ class TapDragUpDetails with Diagnosticable { ...@@ -167,7 +160,6 @@ class TapDragUpDetails with Diagnosticable {
properties.add(DiagnosticsProperty<Offset>('localPosition', localPosition)); properties.add(DiagnosticsProperty<Offset>('localPosition', localPosition));
properties.add(DiagnosticsProperty<PointerDeviceKind?>('kind', kind)); properties.add(DiagnosticsProperty<PointerDeviceKind?>('kind', kind));
properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount)); properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount));
properties.add(DiagnosticsProperty<Set<LogicalKeyboardKey>>('keysPressedOnDown', keysPressedOnDown));
} }
} }
...@@ -193,15 +185,14 @@ typedef GestureTapDragStartCallback = void Function(TapDragStartDetails details) ...@@ -193,15 +185,14 @@ typedef GestureTapDragStartCallback = void Function(TapDragStartDetails details)
class TapDragStartDetails with Diagnosticable { class TapDragStartDetails with Diagnosticable {
/// Creates details for a [GestureTapDragStartCallback]. /// Creates details for a [GestureTapDragStartCallback].
/// ///
/// The [globalPosition], [localPosition], [consecutiveTapCount], and /// The [globalPosition], [localPosition], and [consecutiveTapCount]
/// [keysPressedOnDown] arguments must be provided and must not be null. /// arguments must be provided and must not be null.
TapDragStartDetails({ TapDragStartDetails({
this.sourceTimeStamp, this.sourceTimeStamp,
required this.globalPosition, required this.globalPosition,
required this.localPosition, required this.localPosition,
this.kind, this.kind,
required this.consecutiveTapCount, required this.consecutiveTapCount,
required this.keysPressedOnDown,
}); });
/// Recorded timestamp of the source pointer event that triggered the drag /// Recorded timestamp of the source pointer event that triggered the drag
...@@ -229,9 +220,6 @@ class TapDragStartDetails with Diagnosticable { ...@@ -229,9 +220,6 @@ class TapDragStartDetails with Diagnosticable {
/// the number in the series this tap is. /// the number in the series this tap is.
final int consecutiveTapCount; final int consecutiveTapCount;
/// The keys that were pressed when the most recent [PointerDownEvent] occurred.
final Set<LogicalKeyboardKey> keysPressedOnDown;
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
...@@ -240,7 +228,6 @@ class TapDragStartDetails with Diagnosticable { ...@@ -240,7 +228,6 @@ class TapDragStartDetails with Diagnosticable {
properties.add(DiagnosticsProperty<Offset>('localPosition', localPosition)); properties.add(DiagnosticsProperty<Offset>('localPosition', localPosition));
properties.add(DiagnosticsProperty<PointerDeviceKind?>('kind', kind)); properties.add(DiagnosticsProperty<PointerDeviceKind?>('kind', kind));
properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount)); properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount));
properties.add(DiagnosticsProperty<Set<LogicalKeyboardKey>>('keysPressedOnDown', keysPressedOnDown));
} }
} }
...@@ -272,8 +259,7 @@ class TapDragUpdateDetails with Diagnosticable { ...@@ -272,8 +259,7 @@ class TapDragUpdateDetails with Diagnosticable {
/// coordinates of [delta] and the other coordinate must be zero. /// coordinates of [delta] and the other coordinate must be zero.
/// ///
/// The [globalPosition], [localPosition], [offsetFromOrigin], [localOffsetFromOrigin], /// The [globalPosition], [localPosition], [offsetFromOrigin], [localOffsetFromOrigin],
/// [consecutiveTapCount], and [keysPressedOnDown] arguments must be provided and must /// and [consecutiveTapCount] arguments must be provided and must not be null.
/// not be null.
TapDragUpdateDetails({ TapDragUpdateDetails({
this.sourceTimeStamp, this.sourceTimeStamp,
this.delta = Offset.zero, this.delta = Offset.zero,
...@@ -284,7 +270,6 @@ class TapDragUpdateDetails with Diagnosticable { ...@@ -284,7 +270,6 @@ class TapDragUpdateDetails with Diagnosticable {
required this.offsetFromOrigin, required this.offsetFromOrigin,
required this.localOffsetFromOrigin, required this.localOffsetFromOrigin,
required this.consecutiveTapCount, required this.consecutiveTapCount,
required this.keysPressedOnDown,
}) : assert( }) : assert(
primaryDelta == null primaryDelta == null
|| (primaryDelta == delta.dx && delta.dy == 0.0) || (primaryDelta == delta.dx && delta.dy == 0.0)
...@@ -357,9 +342,6 @@ class TapDragUpdateDetails with Diagnosticable { ...@@ -357,9 +342,6 @@ class TapDragUpdateDetails with Diagnosticable {
/// the number in the series this tap is. /// the number in the series this tap is.
final int consecutiveTapCount; final int consecutiveTapCount;
/// The keys that were pressed when the most recent [PointerDownEvent] occurred.
final Set<LogicalKeyboardKey> keysPressedOnDown;
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
...@@ -372,7 +354,6 @@ class TapDragUpdateDetails with Diagnosticable { ...@@ -372,7 +354,6 @@ class TapDragUpdateDetails with Diagnosticable {
properties.add(DiagnosticsProperty<Offset>('offsetFromOrigin', offsetFromOrigin)); properties.add(DiagnosticsProperty<Offset>('offsetFromOrigin', offsetFromOrigin));
properties.add(DiagnosticsProperty<Offset>('localOffsetFromOrigin', localOffsetFromOrigin)); properties.add(DiagnosticsProperty<Offset>('localOffsetFromOrigin', localOffsetFromOrigin));
properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount)); properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount));
properties.add(DiagnosticsProperty<Set<LogicalKeyboardKey>>('keysPressedOnDown', keysPressedOnDown));
} }
} }
...@@ -400,13 +381,11 @@ class TapDragEndDetails with Diagnosticable { ...@@ -400,13 +381,11 @@ class TapDragEndDetails with Diagnosticable {
/// ///
/// The [velocity] argument must not be null. /// The [velocity] argument must not be null.
/// ///
/// The [consecutiveTapCount], and [keysPressedOnDown] arguments must /// The [consecutiveTapCount] argument must be provided and must not be null.
/// be provided and must not be null.
TapDragEndDetails({ TapDragEndDetails({
this.velocity = Velocity.zero, this.velocity = Velocity.zero,
this.primaryVelocity, this.primaryVelocity,
required this.consecutiveTapCount, required this.consecutiveTapCount,
required this.keysPressedOnDown,
}) : assert( }) : assert(
primaryVelocity == null primaryVelocity == null
|| primaryVelocity == velocity.pixelsPerSecond.dx || primaryVelocity == velocity.pixelsPerSecond.dx
...@@ -434,16 +413,12 @@ class TapDragEndDetails with Diagnosticable { ...@@ -434,16 +413,12 @@ class TapDragEndDetails with Diagnosticable {
/// the number in the series this tap is. /// the number in the series this tap is.
final int consecutiveTapCount; final int consecutiveTapCount;
/// The keys that were pressed when the most recent [PointerDownEvent] occurred.
final Set<LogicalKeyboardKey> keysPressedOnDown;
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Velocity>('velocity', velocity)); properties.add(DiagnosticsProperty<Velocity>('velocity', velocity));
properties.add(DiagnosticsProperty<double?>('primaryVelocity', primaryVelocity)); properties.add(DiagnosticsProperty<double?>('primaryVelocity', primaryVelocity));
properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount)); properties.add(DiagnosticsProperty<int>('consecutiveTapCount', consecutiveTapCount));
properties.add(DiagnosticsProperty<Set<LogicalKeyboardKey>>('keysPressedOnDown', keysPressedOnDown));
} }
} }
...@@ -506,15 +481,6 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer { ...@@ -506,15 +481,6 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer {
// this value will be set to `0`, and a new series will begin. // this value will be set to `0`, and a new series will begin.
int get consecutiveTapCount => _consecutiveTapCount; int get consecutiveTapCount => _consecutiveTapCount;
// The set of [LogicalKeyboardKey]s pressed when the most recent [PointerDownEvent]
// was tracked in [addAllowedPointer].
//
// This value defaults to an empty set.
//
// When the timer between two taps elapses, the recognizer loses the arena, the gesture is cancelled
// or the recognizer is disposed of then this value is reset.
Set<LogicalKeyboardKey> get keysPressedOnDown => _keysPressedOnDown ?? <LogicalKeyboardKey>{};
// The upper limit for the [consecutiveTapCount]. When this limit is reached // The upper limit for the [consecutiveTapCount]. When this limit is reached
// all tap related state is reset and a new tap series is tracked. // all tap related state is reset and a new tap series is tracked.
// //
...@@ -525,7 +491,6 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer { ...@@ -525,7 +491,6 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer {
PointerDownEvent? _down; PointerDownEvent? _down;
PointerUpEvent? _up; PointerUpEvent? _up;
int _consecutiveTapCount = 0; int _consecutiveTapCount = 0;
Set<LogicalKeyboardKey>? _keysPressedOnDown;
OffsetPair? _originPosition; OffsetPair? _originPosition;
int? _previousButtons; int? _previousButtons;
...@@ -534,6 +499,21 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer { ...@@ -534,6 +499,21 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer {
Timer? _consecutiveTapTimer; Timer? _consecutiveTapTimer;
Offset? _lastTapOffset; Offset? _lastTapOffset;
/// {@template flutter.gestures.selectionrecognizers.BaseTapAndDragGestureRecognizer.onTapTrackStart}
/// Callback used to indicate that a tap tracking has started upon
/// a [PointerDownEvent].
/// {@endtemplate}
VoidCallback? onTapTrackStart;
/// {@template flutter.gestures.selectionrecognizers.BaseTapAndDragGestureRecognizer.onTapTrackReset}
/// Callback used to indicate that a tap tracking has been reset which
/// happens on the next [PointerDownEvent] after the timer between two taps
/// elapses, the recognizer loses the arena, the gesture is cancelled or
/// the recognizer is disposed of.
/// {@endtemplate}
VoidCallback? onTapTrackReset;
// When tracking a tap, the [consecutiveTapCount] is incremented if the given tap // When tracking a tap, the [consecutiveTapCount] is incremented if the given tap
// falls under the tolerance specifications and reset to 1 if not. // falls under the tolerance specifications and reset to 1 if not.
@override @override
...@@ -595,10 +575,10 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer { ...@@ -595,10 +575,10 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer {
void _trackTap(PointerDownEvent event) { void _trackTap(PointerDownEvent event) {
_down = event; _down = event;
_keysPressedOnDown = HardwareKeyboard.instance.logicalKeysPressed;
_previousButtons = event.buttons; _previousButtons = event.buttons;
_lastTapOffset = event.position; _lastTapOffset = event.position;
_originPosition = OffsetPair(local: event.localPosition, global: event.position); _originPosition = OffsetPair(local: event.localPosition, global: event.position);
onTapTrackStart?.call();
} }
bool _hasSameButton(int buttons) { bool _hasSameButton(int buttons) {
...@@ -653,9 +633,9 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer { ...@@ -653,9 +633,9 @@ mixin _TapStatusTrackerMixin on OneSequenceGestureRecognizer {
_originPosition = null; _originPosition = null;
_lastTapOffset = null; _lastTapOffset = null;
_consecutiveTapCount = 0; _consecutiveTapCount = 0;
_keysPressedOnDown = null;
_down = null; _down = null;
_up = null; _up = null;
onTapTrackReset?.call();
} }
} }
...@@ -1204,7 +1184,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize ...@@ -1204,7 +1184,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize
localPosition: event.localPosition, localPosition: event.localPosition,
kind: getKindForPointer(event.pointer), kind: getKindForPointer(event.pointer),
consecutiveTapCount: consecutiveTapCount, consecutiveTapCount: consecutiveTapCount,
keysPressedOnDown: keysPressedOnDown,
); );
if (onTapDown != null) { if (onTapDown != null) {
...@@ -1224,7 +1203,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize ...@@ -1224,7 +1203,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize
globalPosition: event.position, globalPosition: event.position,
localPosition: event.localPosition, localPosition: event.localPosition,
consecutiveTapCount: consecutiveTapCount, consecutiveTapCount: consecutiveTapCount,
keysPressedOnDown: keysPressedOnDown,
); );
if (onTapUp != null) { if (onTapUp != null) {
...@@ -1245,7 +1223,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize ...@@ -1245,7 +1223,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize
localPosition: _initialPosition.local, localPosition: _initialPosition.local,
kind: getKindForPointer(event.pointer), kind: getKindForPointer(event.pointer),
consecutiveTapCount: consecutiveTapCount, consecutiveTapCount: consecutiveTapCount,
keysPressedOnDown: keysPressedOnDown,
); );
invokeCallback<void>('onDragStart', () => onDragStart!(details)); invokeCallback<void>('onDragStart', () => onDragStart!(details));
...@@ -1267,7 +1244,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize ...@@ -1267,7 +1244,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize
offsetFromOrigin: globalPosition - _initialPosition.global, offsetFromOrigin: globalPosition - _initialPosition.global,
localOffsetFromOrigin: localPosition - _initialPosition.local, localOffsetFromOrigin: localPosition - _initialPosition.local,
consecutiveTapCount: consecutiveTapCount, consecutiveTapCount: consecutiveTapCount,
keysPressedOnDown: keysPressedOnDown,
); );
if (dragUpdateThrottleFrequency != null) { if (dragUpdateThrottleFrequency != null) {
...@@ -1293,7 +1269,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize ...@@ -1293,7 +1269,6 @@ sealed class BaseTapAndDragGestureRecognizer extends OneSequenceGestureRecognize
TapDragEndDetails( TapDragEndDetails(
primaryVelocity: 0.0, primaryVelocity: 0.0,
consecutiveTapCount: consecutiveTapCount, consecutiveTapCount: consecutiveTapCount,
keysPressedOnDown: keysPressedOnDown,
); );
if (onDragEnd != null) { if (onDragEnd != null) {
......
...@@ -24,7 +24,6 @@ import 'gesture_detector.dart'; ...@@ -24,7 +24,6 @@ import 'gesture_detector.dart';
import 'magnifier.dart'; import 'magnifier.dart';
import 'overlay.dart'; import 'overlay.dart';
import 'scrollable.dart'; import 'scrollable.dart';
import 'tap_and_drag_gestures.dart';
import 'tap_region.dart'; import 'tap_region.dart';
import 'ticker_provider.dart'; import 'ticker_provider.dart';
import 'transitions.dart'; import 'transitions.dart';
...@@ -1993,11 +1992,6 @@ class TextSelectionGestureDetectorBuilder { ...@@ -1993,11 +1992,6 @@ class TextSelectionGestureDetectorBuilder {
&& targetSelection.end >= textPosition.offset; && targetSelection.end >= textPosition.offset;
} }
/// Returns true if shift left or right is contained in the given set.
static bool _containsShift(Set<LogicalKeyboardKey> keysPressed) {
return keysPressed.any(<LogicalKeyboardKey>{ LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.shiftRight }.contains);
}
// Expand the selection to the given global position. // Expand the selection to the given global position.
// //
// Either base or extent will be moved to the last tapped position, whichever // Either base or extent will be moved to the last tapped position, whichever
...@@ -2074,6 +2068,10 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2074,6 +2068,10 @@ class TextSelectionGestureDetectorBuilder {
@protected @protected
RenderEditable get renderEditable => editableText.renderEditable; RenderEditable get renderEditable => editableText.renderEditable;
/// Whether the Shift key was pressed when the most recent [PointerDownEvent]
/// was tracked by the [BaseTapAndDragGestureRecognizer].
bool _isShiftPressed = false;
/// The viewport offset pixels of any [Scrollable] containing the /// The viewport offset pixels of any [Scrollable] containing the
/// [RenderEditable] at the last drag start. /// [RenderEditable] at the last drag start.
double _dragStartScrollOffset = 0.0; double _dragStartScrollOffset = 0.0;
...@@ -2113,6 +2111,30 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2113,6 +2111,30 @@ class TextSelectionGestureDetectorBuilder {
// focused, the cursor moves to the long press position. // focused, the cursor moves to the long press position.
bool _longPressStartedWithoutFocus = false; bool _longPressStartedWithoutFocus = false;
/// Handler for [TextSelectionGestureDetector.onTapTrackStart].
///
/// See also:
///
/// * [TextSelectionGestureDetector.onTapTrackStart], which triggers this
/// callback.
@protected
void onTapTrackStart() {
_isShiftPressed = HardwareKeyboard.instance.logicalKeysPressed
.intersection(<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.shiftRight})
.isNotEmpty;
}
/// Handler for [TextSelectionGestureDetector.onTapTrackReset].
///
/// See also:
///
/// * [TextSelectionGestureDetector.onTapTrackReset], which triggers this
/// callback.
@protected
void onTapTrackReset() {
_isShiftPressed = false;
}
/// Handler for [TextSelectionGestureDetector.onTapDown]. /// Handler for [TextSelectionGestureDetector.onTapDown].
/// ///
/// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets /// By default, it forwards the tap to [RenderEditable.handleTapDown] and sets
...@@ -2145,11 +2167,9 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2145,11 +2167,9 @@ class TextSelectionGestureDetectorBuilder {
|| kind == PointerDeviceKind.touch || kind == PointerDeviceKind.touch
|| kind == PointerDeviceKind.stylus; || kind == PointerDeviceKind.stylus;
// Handle shift + click selection if needed.
final bool isShiftPressed = _containsShift(details.keysPressedOnDown);
// It is impossible to extend the selection when the shift key is pressed, if the // It is impossible to extend the selection when the shift key is pressed, if the
// renderEditable.selection is invalid. // renderEditable.selection is invalid.
final bool isShiftPressedValid = isShiftPressed && renderEditable.selection?.baseOffset != null; final bool isShiftPressedValid = _isShiftPressed && renderEditable.selection?.baseOffset != null;
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.android: case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
...@@ -2246,11 +2266,9 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2246,11 +2266,9 @@ class TextSelectionGestureDetectorBuilder {
@protected @protected
void onSingleTapUp(TapDragUpDetails details) { void onSingleTapUp(TapDragUpDetails details) {
if (delegate.selectionEnabled) { if (delegate.selectionEnabled) {
// Handle shift + click selection if needed.
final bool isShiftPressed = _containsShift(details.keysPressedOnDown);
// It is impossible to extend the selection when the shift key is pressed, if the // It is impossible to extend the selection when the shift key is pressed, if the
// renderEditable.selection is invalid. // renderEditable.selection is invalid.
final bool isShiftPressedValid = isShiftPressed && renderEditable.selection?.baseOffset != null; final bool isShiftPressedValid = _isShiftPressed && renderEditable.selection?.baseOffset != null;
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.linux: case TargetPlatform.linux:
case TargetPlatform.macOS: case TargetPlatform.macOS:
...@@ -2641,9 +2659,7 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2641,9 +2659,7 @@ class TextSelectionGestureDetectorBuilder {
return; return;
} }
final bool isShiftPressed = _containsShift(details.keysPressedOnDown); if (_isShiftPressed && renderEditable.selection != null && renderEditable.selection!.isValid) {
if (isShiftPressed && renderEditable.selection != null && renderEditable.selection!.isValid) {
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
case TargetPlatform.macOS: case TargetPlatform.macOS:
...@@ -2730,9 +2746,7 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2730,9 +2746,7 @@ class TextSelectionGestureDetectorBuilder {
return; return;
} }
final bool isShiftPressed = _containsShift(details.keysPressedOnDown); if (!_isShiftPressed) {
if (!isShiftPressed) {
// Adjust the drag start offset for possible viewport offset changes. // Adjust the drag start offset for possible viewport offset changes.
final Offset editableOffset = renderEditable.maxLines == 1 final Offset editableOffset = renderEditable.maxLines == 1
? Offset(renderEditable.offset.pixels - _dragStartViewportOffset, 0.0) ? Offset(renderEditable.offset.pixels - _dragStartViewportOffset, 0.0)
...@@ -2931,14 +2945,13 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2931,14 +2945,13 @@ class TextSelectionGestureDetectorBuilder {
/// callback. /// callback.
@protected @protected
void onDragSelectionEnd(TapDragEndDetails details) { void onDragSelectionEnd(TapDragEndDetails details) {
final bool isShiftPressed = _containsShift(details.keysPressedOnDown);
_dragBeganOnPreviousSelection = null; _dragBeganOnPreviousSelection = null;
if (_shouldShowSelectionToolbar && _TextSelectionGestureDetectorState._getEffectiveConsecutiveTapCount(details.consecutiveTapCount) == 2) { if (_shouldShowSelectionToolbar && _TextSelectionGestureDetectorState._getEffectiveConsecutiveTapCount(details.consecutiveTapCount) == 2) {
editableText.showToolbar(); editableText.showToolbar();
} }
if (isShiftPressed) { if (_isShiftPressed) {
_dragStartSelection = null; _dragStartSelection = null;
} }
...@@ -2956,6 +2969,8 @@ class TextSelectionGestureDetectorBuilder { ...@@ -2956,6 +2969,8 @@ class TextSelectionGestureDetectorBuilder {
}) { }) {
return TextSelectionGestureDetector( return TextSelectionGestureDetector(
key: key, key: key,
onTapTrackStart: onTapTrackStart,
onTapTrackReset: onTapTrackReset,
onTapDown: onTapDown, onTapDown: onTapDown,
onForcePressStart: delegate.forcePressEnabled ? onForcePressStart : null, onForcePressStart: delegate.forcePressEnabled ? onForcePressStart : null,
onForcePressEnd: delegate.forcePressEnabled ? onForcePressEnd : null, onForcePressEnd: delegate.forcePressEnabled ? onForcePressEnd : null,
...@@ -2996,6 +3011,8 @@ class TextSelectionGestureDetector extends StatefulWidget { ...@@ -2996,6 +3011,8 @@ class TextSelectionGestureDetector extends StatefulWidget {
/// The [child] parameter must not be null. /// The [child] parameter must not be null.
const TextSelectionGestureDetector({ const TextSelectionGestureDetector({
super.key, super.key,
this.onTapTrackStart,
this.onTapTrackReset,
this.onTapDown, this.onTapDown,
this.onForcePressStart, this.onForcePressStart,
this.onForcePressEnd, this.onForcePressEnd,
...@@ -3015,6 +3032,12 @@ class TextSelectionGestureDetector extends StatefulWidget { ...@@ -3015,6 +3032,12 @@ class TextSelectionGestureDetector extends StatefulWidget {
required this.child, required this.child,
}); });
/// {@macro flutter.gestures.selectionrecognizers.BaseTapAndDragGestureRecognizer.onTapTrackStart}
final VoidCallback? onTapTrackStart;
/// {@macro flutter.gestures.selectionrecognizers.BaseTapAndDragGestureRecognizer.onTapTrackReset}
final VoidCallback? onTapTrackReset;
/// Called for every tap down including every tap down that's part of a /// Called for every tap down including every tap down that's part of a
/// double click or a long press, except touches that include enough movement /// double click or a long press, except touches that include enough movement
/// to not qualify as taps (e.g. pans and flings). /// to not qualify as taps (e.g. pans and flings).
...@@ -3125,6 +3148,14 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec ...@@ -3125,6 +3148,14 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec
} }
} }
void _handleTapTrackStart() {
widget.onTapTrackStart?.call();
}
void _handleTapTrackReset() {
widget.onTapTrackReset?.call();
}
// The down handler is force-run on success of a single tap and optimistically // The down handler is force-run on success of a single tap and optimistically
// run before a long press success. // run before a long press success.
void _handleTapDown(TapDragDownDetails details) { void _handleTapDown(TapDragDownDetails details) {
...@@ -3231,6 +3262,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec ...@@ -3231,6 +3262,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec
// Text selection should start from the position of the first pointer // Text selection should start from the position of the first pointer
// down event. // down event.
..dragStartBehavior = DragStartBehavior.down ..dragStartBehavior = DragStartBehavior.down
..onTapTrackStart = _handleTapTrackStart
..onTapTrackReset = _handleTapTrackReset
..onTapDown = _handleTapDown ..onTapDown = _handleTapDown
..onDragStart = _handleDragStart ..onDragStart = _handleDragStart
..onDragUpdate = _handleDragUpdate ..onDragUpdate = _handleDragUpdate
...@@ -3249,6 +3282,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec ...@@ -3249,6 +3282,8 @@ class _TextSelectionGestureDetectorState extends State<TextSelectionGestureDetec
// Text selection should start from the position of the first pointer // Text selection should start from the position of the first pointer
// down event. // down event.
..dragStartBehavior = DragStartBehavior.down ..dragStartBehavior = DragStartBehavior.down
..onTapTrackStart = _handleTapTrackStart
..onTapTrackReset = _handleTapTrackReset
..onTapDown = _handleTapDown ..onTapDown = _handleTapDown
..onDragStart = _handleDragStart ..onDragStart = _handleDragStart
..onDragUpdate = _handleDragUpdate ..onDragUpdate = _handleDragUpdate
......
...@@ -140,7 +140,6 @@ export 'src/widgets/spacer.dart'; ...@@ -140,7 +140,6 @@ export 'src/widgets/spacer.dart';
export 'src/widgets/spell_check.dart'; export 'src/widgets/spell_check.dart';
export 'src/widgets/status_transitions.dart'; export 'src/widgets/status_transitions.dart';
export 'src/widgets/table.dart'; export 'src/widgets/table.dart';
export 'src/widgets/tap_and_drag_gestures.dart';
export 'src/widgets/tap_region.dart'; export 'src/widgets/tap_region.dart';
export 'src/widgets/text.dart'; export 'src/widgets/text.dart';
export 'src/widgets/text_editing_intents.dart'; export 'src/widgets/text_editing_intents.dart';
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import '../gestures/gesture_tester.dart'; import '../gestures/gesture_tester.dart';
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/foundation.dart' show ValueListenable, defaultTargetPlatform; import 'package:flutter/foundation.dart' show ValueListenable, defaultTargetPlatform;
import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
......
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